Added performance tests and creation permission flags

This commit is contained in:
fedir 2025-05-21 16:21:33 +02:00
parent 448c862731
commit 467087d76e
Signed by: fedir
GPG Key ID: C959EE85F0C9362C
10 changed files with 175 additions and 82 deletions

View File

@ -13,6 +13,7 @@
#include "process_info.h" #include "process_info.h"
#include "real_filename.h" #include "real_filename.h"
#include "set_mode_t.h"
#include <assert.h> #include <assert.h>
#include <stddef.h> #include <stddef.h>
#define FUSE_USE_VERSION 31 #define FUSE_USE_VERSION 31
@ -45,6 +46,10 @@
#include "temp_permissions_table.h" #include "temp_permissions_table.h"
#include "ui-socket.h" #include "ui-socket.h"
int auto_create_perm = GRANT_PERM;
void set_auto_create_perm(int val) { auto_create_perm = val; }
static void *xmp_init(struct fuse_conn_info *conn, struct fuse_config *cfg) { static void *xmp_init(struct fuse_conn_info *conn, struct fuse_config *cfg) {
(void)conn; (void)conn;
cfg->use_ino = 1; cfg->use_ino = 1;
@ -85,7 +90,7 @@ static int xmp_getattr(const char *path, struct stat *stbuf,
else else
res = source_stat(path, stbuf); res = source_stat(path, stbuf);
if (res == -1) { if (res == -1) {
perror("Stat failed"); perror("[ICFS] Stat failed");
return -errno; return -errno;
} }
@ -149,7 +154,7 @@ static int xmp_opendir(const char *path, struct fuse_file_info *fi) {
d->dp = source_opendir(path); d->dp = source_opendir(path);
if (d->dp == NULL) { if (d->dp == NULL) {
perror("Opendir failed"); perror("[ICFS] Opendir failed");
res = -errno; res = -errno;
free(d); free(d);
return res; return res;
@ -461,7 +466,7 @@ static int xmp_create(const char *path, mode_t mode,
// fprintf(stderr, "%s, %d\n", path, ask_access(path, pi)); // fprintf(stderr, "%s, %d\n", path, ask_access(path, pi));
if (!interactive_access(path, pi, GRANT_PERM)) { if (!interactive_access(path, pi, auto_create_perm)) {
free(pi.name); free(pi.name);
return -EACCES; return -EACCES;
} }

View File

@ -14,5 +14,6 @@
#include <fuse3/fuse.h> #include <fuse3/fuse.h>
const struct fuse_operations *get_fuse_operations(); const struct fuse_operations *get_fuse_operations();
void set_auto_create_perm(int val);
#endif #endif

View File

@ -10,6 +10,7 @@
See the file LICENSE. See the file LICENSE.
*/ */
#include <string.h>
#define FUSE_USE_VERSION 31 #define FUSE_USE_VERSION 31
#define _GNU_SOURCE #define _GNU_SOURCE
@ -29,7 +30,26 @@ const char *mountpoint = NULL;
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
if (argc < 3) { if (argc < 3) {
fprintf(stderr, "Usage: icfs <FUSE arguments> [target directory] [path to " fprintf(stderr, "Usage: icfs <FUSE arguments> [target directory] [path to "
"the permanent permissions database\n"); "the permanent permissions database] <ICFS "
"arguments>\n\t--no-perm-on-create - do not give permanent "
"permissions to files a process creates automatically "
"(incompatible with --temp-on-create)\n\t--temp-on-create "
"- give temporary permissions to files a process creates "
"automatically (incompatible with --no-perm-on-create)\n");
return EXIT_FAILURE;
}
if ((0 == strcmp(argv[argc - 1], "--no-perm-on-create") &&
0 == strcmp(argv[argc - 2], "--temp-on-create")) ||
(0 == strcmp(argv[argc - 2], "--no-perm-on-create") &&
0 == strcmp(argv[argc - 1], "--temp-on-create"))) {
fprintf(stderr, "Usage: icfs <FUSE arguments> [target directory] [path to "
"the permanent permissions database] <ICFS "
"arguments>\n\t--no-perm-on-create - do not give permanent "
"permissions to files a process creates automatically "
"(incompatible with --temp-on-create)\n\t--temp-on-create "
"- give temporary permissions to files a process creates "
"automatically (incompatible with --no-perm-on-create)\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -37,11 +57,20 @@ int main(int argc, char *argv[]) {
// permissions than it's caller reqested // permissions than it's caller reqested
umask(0); umask(0);
if (0 == strcmp(argv[argc - 1], "--no-perm-on-create")) {
set_auto_create_perm(0);
argc--;
}
if (0 == strcmp(argv[argc - 1], "--temp-on-create")) {
set_auto_create_perm(GRANT_TEMP);
argc--;
}
// ui socket should always be initialized before anything else, since it // ui socket should always be initialized before anything else, since it
// handles the setuid bits! // handles the setuid bits!
int ret = init_ui_socket(argv[argc - 1]); int ret = init_ui_socket(argv[argc - 1]);
if (ret != 0) { if (ret != 0) {
fprintf(stderr, "Could not initalize ui-socket.\n"); fprintf(stderr, "[ICFS] Could not initalize ui-socket.\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -49,7 +78,7 @@ int main(int argc, char *argv[]) {
ret = source_init(mountpoint); ret = source_init(mountpoint);
if (ret != 0) { if (ret != 0) {
perror("source_init"); perror("[ICFS] source_init");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }

View File

@ -41,7 +41,7 @@ void set_db_fsuid() {
status = setfsuid(ruid); status = setfsuid(ruid);
if (status < 0) { if (status < 0) {
fprintf(stderr, "Couldn't set uid to %d.\n", ruid); fprintf(stderr, "[ICFS] Couldn't set uid to %d.\n", ruid);
exit(status); exit(status);
} }
pthread_mutex_unlock(&uid_switch); pthread_mutex_unlock(&uid_switch);
@ -56,7 +56,7 @@ void set_real_fsuid() {
status = setfsuid(ruid); status = setfsuid(ruid);
if (status < 0) { if (status < 0) {
fprintf(stderr, "Couldn't set uid to %d.\n", euid); fprintf(stderr, "[ICFS] Couldn't set uid to %d.\n", euid);
exit(status); exit(status);
} }
pthread_mutex_unlock(&uid_switch); pthread_mutex_unlock(&uid_switch);
@ -67,12 +67,13 @@ static int check_table_col_schema(void *notused, int argc, char **argv,
(void)notused; (void)notused;
(void)colname; (void)colname;
if (argc < 3) { if (argc < 3) {
fprintf(stderr, "Unexpected amount of arguments given to the callback.\n"); fprintf(stderr,
"[ICFS] Unexpected amount of arguments given to the callback.\n");
return 1; return 1;
} }
int column_num = atoi(argv[0]); int column_num = atoi(argv[0]);
if (column_num >= column_count) { if (column_num >= column_count) {
fprintf(stderr, "Table contains unexpected amount of columns.\n"); fprintf(stderr, "[ICFS] Table contains unexpected amount of columns.\n");
return 1; return 1;
} }
@ -80,7 +81,8 @@ static int check_table_col_schema(void *notused, int argc, char **argv,
strcmp(types[column_num], argv[2]) == 0) { strcmp(types[column_num], argv[2]) == 0) {
return 0; return 0;
} }
fprintf(stderr, "Column %d does not conform to the schema.\n", column_num); fprintf(stderr, "[ICFS] Column %d does not conform to the schema.\n",
column_num);
return 1; return 1;
} }
@ -88,14 +90,15 @@ static int set_flag(void *flag, int argc, char **argv, char **colname) {
(void)colname; (void)colname;
if (argc < 3) { if (argc < 3) {
fprintf(stderr, fprintf(
"Unexpected amount of arguments given to the callback: %d.\n", stderr,
"[ICFS] Unexpected amount of arguments given to the callback: %d.\n",
argc); argc);
return 1; return 1;
} }
if (atoi(argv[2])) { if (atoi(argv[2])) {
fprintf(stderr, "Third column was: %s\n", argv[2]); fprintf(stderr, "[ICFS] Third column was: %s\n", argv[2]);
*(int *)flag = 1; *(int *)flag = 1;
} else { } else {
*(int *)flag = -1; *(int *)flag = -1;
@ -104,7 +107,7 @@ static int set_flag(void *flag, int argc, char **argv, char **colname) {
} }
int create_database_schema() { int create_database_schema() {
fprintf(stderr, "Creating table 'permissions'.\n"); fprintf(stderr, "[ICFS] Creating table 'permissions'.\n");
const char *create_query = const char *create_query =
"CREATE TABLE permissions(executable TEXT NOT " "CREATE TABLE permissions(executable TEXT NOT "
"NULL, filename TEXT NOT NULL, mode INTEGER NOT NULL);"; "NULL, filename TEXT NOT NULL, mode INTEGER NOT NULL);";
@ -112,12 +115,12 @@ int create_database_schema() {
int ret = sqlite3_exec(perm_database, create_query, NULL, NULL, &err); int ret = sqlite3_exec(perm_database, create_query, NULL, NULL, &err);
if (ret != SQLITE_OK) { if (ret != SQLITE_OK) {
fprintf(stderr, "sqlite3 error: %s\n", err); fprintf(stderr, "[ICFS] sqlite3 error: %s\n", err);
sqlite3_free(err); sqlite3_free(err);
return 1; return 1;
} }
fprintf(stderr, "Database created successfully\n"); fprintf(stderr, "[ICFS] Database created successfully\n");
return 0; return 0;
} }
@ -131,14 +134,14 @@ int ensure_database_schema() {
int result = sqlite3_table_column_metadata( int result = sqlite3_table_column_metadata(
perm_database, NULL, table_name, NULL, NULL, NULL, NULL, NULL, NULL); perm_database, NULL, table_name, NULL, NULL, NULL, NULL, NULL, NULL);
if (result == SQLITE_ERROR) { if (result == SQLITE_ERROR) {
fprintf(stderr, "Table '%s' does not exist.\n", table_name); fprintf(stderr, "[ICFS] Table '%s' does not exist.\n", table_name);
if (create_database_schema()) { if (create_database_schema()) {
fprintf(stderr, "Table could not be created.\n"); fprintf(stderr, "[ICFS] Table could not be created.\n");
return 1; return 1;
} }
return 0; return 0;
} else if (result != SQLITE_OK) { } else if (result != SQLITE_OK) {
fprintf(stderr, "Database metadata could not be retrieved.\n"); fprintf(stderr, "[ICFS] Database metadata could not be retrieved.\n");
return 1; return 1;
} }
@ -148,12 +151,12 @@ int ensure_database_schema() {
sqlite3_exec(perm_database, pragma, check_table_col_schema, NULL, &err); sqlite3_exec(perm_database, pragma, check_table_col_schema, NULL, &err);
if (ret != SQLITE_OK) { if (ret != SQLITE_OK) {
fprintf(stderr, "sqlite3 error: %s\n", err); fprintf(stderr, "[ICFS] sqlite3 error: %s\n", err);
sqlite3_free(err); sqlite3_free(err);
return 1; return 1;
} }
fprintf(stderr, "Schema is correct.\n"); fprintf(stderr, "[ICFS] Schema is correct.\n");
return 0; return 0;
} }
@ -168,24 +171,25 @@ int init_perm_permissions_table(const char *db_filename) {
umask(0077); umask(0077);
ruid = getuid(); ruid = getuid();
euid = geteuid(); euid = geteuid();
fprintf(stderr, "Running with uid: %d, gid: %d\n", euid, getegid()); fprintf(stderr, "[ICFS] Running with uid: %d, gid: %d\n", euid, getegid());
if (sqlite3_open_v2(db_filename, &perm_database, if (sqlite3_open_v2(db_filename, &perm_database,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
SQLITE_OPEN_FULLMUTEX, SQLITE_OPEN_FULLMUTEX,
NULL)) { NULL)) {
perror("Can't open permanent permissions database"); perror("[ICFS] Can't open permanent permissions database");
return -1; return -1;
} }
umask(0); umask(0);
if (ensure_database_schema()) { if (ensure_database_schema()) {
fprintf(stderr, "Database schema is not correct.\n"); fprintf(stderr, "[ICFS] Database schema is not correct.\n");
return -1; return -1;
} }
int status = seteuid(ruid); int status = seteuid(ruid);
if (status < 0) { if (status < 0) {
fprintf(stderr, "Couldn't set euid to ruid during database setup.\n"); fprintf(stderr,
"[ICFS] Couldn't set euid to ruid during database setup.\n");
exit(status); exit(status);
} }
@ -222,7 +226,7 @@ access_t check_perm_access_noparent(const char *filename,
int step_ret = sqlite3_step(stmt); int step_ret = sqlite3_step(stmt);
if (step_ret != SQLITE_ROW && step_ret != SQLITE_DONE) { if (step_ret != SQLITE_ROW && step_ret != SQLITE_DONE) {
fprintf(stderr, "SQLite error: %s\n", sqlite3_errstr(step_ret)); fprintf(stderr, "[ICFS] SQLite error: %s\n", sqlite3_errstr(step_ret));
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
return ret; return ret;
} }
@ -304,7 +308,7 @@ int set_perm_access(const char *filename, struct process_info pi,
// asprintf). That does not explicitly rule out that query will be a valid // asprintf). That does not explicitly rule out that query will be a valid
// pointer. But the risk of freeing a non-allocated pointer is too much to // pointer. But the risk of freeing a non-allocated pointer is too much to
// justify preparing for this. // justify preparing for this.
fprintf(stderr, "Could not create query on rule insertion\n"); fprintf(stderr, "[ICFS] Could not create query on rule insertion\n");
perror(""); perror("");
return 1; return 1;
} }
@ -313,7 +317,7 @@ int set_perm_access(const char *filename, struct process_info pi,
ret = sqlite3_exec(perm_database, query, NULL, NULL, &sqlite_error); ret = sqlite3_exec(perm_database, query, NULL, NULL, &sqlite_error);
free(query); free(query);
if (ret != SQLITE_OK) { if (ret != SQLITE_OK) {
fprintf(stderr, "SQLite returned an error: %s\n", sqlite_error); fprintf(stderr, "[ICFS] SQLite returned an error: %s\n", sqlite_error);
sqlite3_free(sqlite_error); sqlite3_free(sqlite_error);
return 1; return 1;
} }

View File

@ -46,7 +46,8 @@ pid_t get_main_thread_pid(pid_t tid) {
fclose(fp); fclose(fp);
if (tgid != tid) { if (tgid != tid) {
fprintf(stderr, "The tid and and pid wasn't equal. tid:%d, pid:%d.\n", tid, fprintf(stderr,
"[ICFS] The tid and and pid wasn't equal. tid:%d, pid:%d.\n", tid,
tgid); tgid);
} }
return tgid; return tgid;
@ -59,7 +60,7 @@ char *get_process_name_by_pid(const int pid) {
size_t size = 128; size_t size = 128;
char *name = malloc(size); char *name = malloc(size);
if (name == NULL) { if (name == NULL) {
fprintf(stderr, "Could not get process name by pid %d", pid); fprintf(stderr, "[ICFS] Could not get process name by pid %d", pid);
perror(""); perror("");
return NULL; return NULL;
} }
@ -68,7 +69,7 @@ char *get_process_name_by_pid(const int pid) {
ssize_t len = readlink(path, name, size); ssize_t len = readlink(path, name, size);
if (len == -1) { if (len == -1) {
fprintf(stderr, "Could not get process name by pid %d", pid); fprintf(stderr, "[ICFS] Could not get process name by pid %d", pid);
perror(""); perror("");
free(name); free(name);
return NULL; return NULL;
@ -105,7 +106,7 @@ pid_t get_parent_pid(pid_t pid) {
FILE *file = fopen(path, "r"); FILE *file = fopen(path, "r");
if (file == NULL) { if (file == NULL) {
perror("Failed to open /proc/<pid>/status"); perror("[ICFS] Failed to open /proc/<pid>/status");
return 0; return 0;
} }

View File

@ -32,7 +32,7 @@ const char *source_filename_translate(const char *filename) {
int source_init(const char *root_path) { int source_init(const char *root_path) {
handle.mountpoint = malloc(strlen(root_path) + 1); handle.mountpoint = malloc(strlen(root_path) + 1);
if (handle.mountpoint == NULL) { if (handle.mountpoint == NULL) {
perror("Malloc failed"); perror("[ICFS] Malloc failed");
return -1; return -1;
} }
@ -41,7 +41,8 @@ int source_init(const char *root_path) {
int root_fd = open(root_path, O_PATH); int root_fd = open(root_path, O_PATH);
if (root_fd == -1) { if (root_fd == -1) {
fprintf(stderr, "Could not initialize source file system at %s", root_path); fprintf(stderr, "[ICFS] Could not initialize source file system at %s",
root_path);
perror(""); perror("");
return -1; return -1;
} }
@ -65,7 +66,7 @@ const char *real_filename(const char *filename) {
// Allocate memory (+1 for null terminator) // Allocate memory (+1 for null terminator)
char *result = malloc(total_len + 1); char *result = malloc(total_len + 1);
if (result == NULL) { if (result == NULL) {
fprintf(stderr, "Memory allocation failed"); fprintf(stderr, "[ICFS] Memory allocation failed");
perror(""); perror("");
return NULL; return NULL;
} }
@ -111,7 +112,7 @@ DIR *source_opendir(const char *filename) {
const char *relative_filename = source_filename_translate(filename); const char *relative_filename = source_filename_translate(filename);
int fd = openat(handle.root_fd, relative_filename, 0); int fd = openat(handle.root_fd, relative_filename, 0);
if (fd < 0) { if (fd < 0) {
perror("Openat failed"); perror("[ICFS] Openat failed");
return NULL; return NULL;
} }
DIR *dir_pointer = fdopendir(fd); DIR *dir_pointer = fdopendir(fd);
@ -148,7 +149,7 @@ int source_truncate(const char *filename, off_t length) {
const char *relative_filename = source_filename_translate(filename); const char *relative_filename = source_filename_translate(filename);
int fd = openat(handle.root_fd, relative_filename, 0); int fd = openat(handle.root_fd, relative_filename, 0);
if (fd < 0) { if (fd < 0) {
perror("Openat failed"); perror("[ICFS] Openat failed");
return -1; return -1;
} }
return ftruncate(fd, length); return ftruncate(fd, length);

View File

@ -52,20 +52,21 @@ unsigned long long get_process_creation_time(pid_t pid) {
// Open the status file // Open the status file
fp = fopen(path, "r"); fp = fopen(path, "r");
if (fp == NULL) { if (fp == NULL) {
perror("fopen"); perror("[ICFS] fopen");
return 0; return 0;
} }
// Read the creation time (the 22nd field in the stat file) // Read the creation time (the 22nd field in the stat file)
for (int i = 1; i < 22; i++) { for (int i = 1; i < 22; i++) {
if (fscanf(fp, "%*s") == EOF) { if (fscanf(fp, "%*s") == EOF) {
fprintf(stderr, "Error reading process stat file on the number %d\n", i); fprintf(stderr,
"[ICFS] Error reading process stat file on the number %d\n", i);
fclose(fp); fclose(fp);
return 0; return 0;
} }
} }
if (fscanf(fp, "%llu", &creation_time) != 1) { if (fscanf(fp, "%llu", &creation_time) != 1) {
fprintf(stderr, "Error reading creation time\n"); fprintf(stderr, "[ICFS] Error reading creation time\n");
fclose(fp); fclose(fp);
return 0; return 0;
} }
@ -183,7 +184,7 @@ access_t check_temp_access_noparent(const char *filename, pid_t pid) {
if (permission_entry != NULL) { if (permission_entry != NULL) {
unsigned long long process_creation_time = get_process_creation_time(pid); unsigned long long process_creation_time = get_process_creation_time(pid);
if (process_creation_time == 0) { if (process_creation_time == 0) {
perror("Could not retrieve process creation time"); perror("[ICFS] Could not retrieve process creation time");
pthread_rwlock_unlock(&temp_permissions_table_lock); pthread_rwlock_unlock(&temp_permissions_table_lock);
return NDEF; return NDEF;
} }
@ -271,7 +272,7 @@ int set_temp_access(const char *filename, struct process_info pi,
unsigned long long process_creation_time = unsigned long long process_creation_time =
get_process_creation_time(pi.PID); get_process_creation_time(pi.PID);
if (process_creation_time == 0) { if (process_creation_time == 0) {
perror("Could not retrieve process creation time"); perror("[ICFS] Could not retrieve process creation time");
pthread_rwlock_unlock(&temp_permissions_table_lock); pthread_rwlock_unlock(&temp_permissions_table_lock);
return -1; return -1;
} }

View File

@ -45,19 +45,21 @@ int init_ui_socket(const char *perm_permissions_db_filename) {
access_log = fopen("/etc/icfs-log", "a+"); access_log = fopen("/etc/icfs-log", "a+");
if (init_temp_permissions_table()) { if (init_temp_permissions_table()) {
fprintf(stderr, "Could not initialize temporary permissions table.\n"); fprintf(stderr,
"[ICFS] Could not initialize temporary permissions table.\n");
return 1; return 1;
} }
if (init_perm_permissions_table(perm_permissions_db_filename)) { if (init_perm_permissions_table(perm_permissions_db_filename)) {
fprintf(stderr, "Could not initialize permanent permissions table.\n"); fprintf(stderr,
"[ICFS] Could not initialize permanent permissions table.\n");
return 1; return 1;
} }
// Test if dialogue is installed (get version) // Test if dialogue is installed (get version)
fp = popen("icfs_dialogue --version", "r"); fp = popen("icfs_dialogue --version", "r");
if (fp == NULL) { if (fp == NULL) {
perror("Pipe returned an error"); perror("[ICFS] Pipe returned an error");
return 1; return 1;
} }
@ -96,7 +98,7 @@ struct dialogue_response ask_access(const char *filename,
// asprintf). That does not explicitly rule out that command will be a valid // asprintf). That does not explicitly rule out that command will be a valid
// pointer. But the risk of freeing a non-allocated pointer is too much to // pointer. But the risk of freeing a non-allocated pointer is too much to
// justify preparing for this. // justify preparing for this.
fprintf(stderr, "Could not create query on rule insertion"); fprintf(stderr, "[ICFS] Could not create query on rule insertion");
perror(""); perror("");
response.decision = DENY; response.decision = DENY;
response.filename = malloc(2); response.filename = malloc(2);
@ -110,7 +112,7 @@ struct dialogue_response ask_access(const char *filename,
free(command); free(command);
if (fp == NULL) { if (fp == NULL) {
perror("Pipe returned a error"); perror("[ICFS] Pipe returned a error");
response.decision = DENY; response.decision = DENY;
response.filename = malloc(2); response.filename = malloc(2);
response.filename[0] = '/'; response.filename[0] = '/';
@ -130,8 +132,8 @@ struct dialogue_response ask_access(const char *filename,
int dialogue_exit_code = WEXITSTATUS(pclose(fp)); int dialogue_exit_code = WEXITSTATUS(pclose(fp));
fprintf(stderr, "dialogue wrote out %s\n", first(&dialogue_output)); fprintf(stderr, "[ICFS] dialogue wrote out %s\n", first(&dialogue_output));
fprintf(stderr, "dialogue returned %d\n", dialogue_exit_code); fprintf(stderr, "[ICFS] dialogue returned %d\n", dialogue_exit_code);
if (size(&dialogue_output) == 0) { if (size(&dialogue_output) == 0) {
push(&dialogue_output, '/'); push(&dialogue_output, '/');
@ -146,7 +148,7 @@ struct dialogue_response ask_access(const char *filename,
// assert(0 == strcmp(response.filename, first(&dialogue_output))); // assert(0 == strcmp(response.filename, first(&dialogue_output)));
cleanup(&dialogue_output); cleanup(&dialogue_output);
time_t now = time(0); time_t now = time(0);
fprintf(access_log, "%ld\n", now); fprintf(access_log, "[ICFS] wrote to access log: %ld\n", now);
if (dialogue_exit_code == (DIALOGUE_YES | DIALOGUE_PERM)) { if (dialogue_exit_code == (DIALOGUE_YES | DIALOGUE_PERM)) {
response.decision = ALLOW; response.decision = ALLOW;
@ -179,8 +181,9 @@ int interactive_access(const char *filename, struct process_info proc_info,
access_t access = check_temp_access(real_path, proc_info); access_t access = check_temp_access(real_path, proc_info);
if (access == ALLOW) { if (access == ALLOW) {
fprintf(stderr, fprintf(
"Permission allowed to %s based on a rule present in the temp " stderr,
"[ICFS] Permission allowed to %s based on a rule present in the temp "
"permission table.\n", "permission table.\n",
proc_info.name); proc_info.name);
free(real_path); free(real_path);
@ -188,8 +191,9 @@ int interactive_access(const char *filename, struct process_info proc_info,
return 1; return 1;
} }
if (access == DENY) { if (access == DENY) {
fprintf(stderr, fprintf(
"Permission denied to %s based on a rule present in the temp " stderr,
"[ICFS] Permission denied to %s based on a rule present in the temp "
"permission table.\n", "permission table.\n",
proc_info.name); proc_info.name);
free(real_path); free(real_path);
@ -199,8 +203,9 @@ int interactive_access(const char *filename, struct process_info proc_info,
access = check_perm_access(real_path, proc_info); access = check_perm_access(real_path, proc_info);
if (access == ALLOW) { if (access == ALLOW) {
fprintf(stderr, fprintf(
"Permission allowed to %s based on a rule present in the perm " stderr,
"[ICFS] Permission allowed to %s based on a rule present in the perm "
"permission table.\n", "permission table.\n",
proc_info.name); proc_info.name);
free(real_path); free(real_path);
@ -208,8 +213,9 @@ int interactive_access(const char *filename, struct process_info proc_info,
return 1; return 1;
} }
if (access == DENY) { if (access == DENY) {
fprintf(stderr, fprintf(
"Permission denied to %s based on a rule present in the perm " stderr,
"[ICFS] Permission denied to %s based on a rule present in the perm "
"permission table.\n", "permission table.\n",
proc_info.name); proc_info.name);
free(real_path); free(real_path);
@ -221,14 +227,16 @@ int interactive_access(const char *filename, struct process_info proc_info,
// permissions are granted // permissions are granted
if (opts & GRANT_PERM) { if (opts & GRANT_PERM) {
fprintf(stderr, "Permission granted permanently to %s.\n", proc_info.name); fprintf(stderr, "[ICFS] Permission granted permanently to %s.\n",
proc_info.name);
set_perm_access(real_path, proc_info, SET_ALLOW); set_perm_access(real_path, proc_info, SET_ALLOW);
free(real_path); free(real_path);
pthread_mutex_unlock(&access_check_mutex); pthread_mutex_unlock(&access_check_mutex);
return 1; return 1;
} }
if (opts & GRANT_TEMP) { if (opts & GRANT_TEMP) {
fprintf(stderr, "Permission granted temporarily to %s.\n", proc_info.name); fprintf(stderr, "[ICFS] Permission granted temporarily to %s.\n",
proc_info.name);
set_temp_access(real_path, proc_info, SET_ALLOW); set_temp_access(real_path, proc_info, SET_ALLOW);
free(real_path); free(real_path);
pthread_mutex_unlock(&access_check_mutex); pthread_mutex_unlock(&access_check_mutex);
@ -244,7 +252,7 @@ int interactive_access(const char *filename, struct process_info proc_info,
while (source_access(response.filename, F_OK)) { while (source_access(response.filename, F_OK)) {
// if it is invalid, just ask again. // if it is invalid, just ask again.
fprintf(stderr, "Filename returned by zenty wasn't correct: %s\n", fprintf(stderr, "[ICFS] Filename returned by zenty wasn't correct: %s\n",
response.filename); response.filename);
free(response.filename); free(response.filename);
response = ask_access(filename, proc_info); response = ask_access(filename, proc_info);
@ -259,25 +267,29 @@ int interactive_access(const char *filename, struct process_info proc_info,
if (response.decision == ALLOW) { if (response.decision == ALLOW) {
fprintf(stderr, fprintf(stderr,
"Permission granted permanently to %s based on zenty response.\n", "[ICFS] Permission granted permanently to %s based on zenty "
"response.\n",
proc_info.name); proc_info.name);
set_perm_access(real_path, proc_info, SET_ALLOW); set_perm_access(real_path, proc_info, SET_ALLOW);
ret = 1; ret = 1;
} else if (response.decision == ALLOW_TEMP) { } else if (response.decision == ALLOW_TEMP) {
fprintf(stderr, fprintf(stderr,
"Permission granted temporarily to %s based on zenty response.\n", "[ICFS] Permission granted temporarily to %s based on zenty "
"response.\n",
proc_info.name); proc_info.name);
set_temp_access(real_path, proc_info, SET_ALLOW); set_temp_access(real_path, proc_info, SET_ALLOW);
ret = 1; ret = 1;
} else if (response.decision == DENY_TEMP) { } else if (response.decision == DENY_TEMP) {
fprintf(stderr, fprintf(
"Permission denied temporarily to %s based on zenty response.\n", stderr,
"[ICFS] Permission denied temporarily to %s based on zenty response.\n",
proc_info.name); proc_info.name);
set_temp_access(real_path, proc_info, SET_DENY); set_temp_access(real_path, proc_info, SET_DENY);
ret = 0; ret = 0;
} else if (response.decision == DENY) { } else if (response.decision == DENY) {
fprintf(stderr, fprintf(
"Permission denied permanently to %s based on zenty response.\n", stderr,
"[ICFS] Permission denied permanently to %s based on zenty response.\n",
proc_info.name); proc_info.name);
set_perm_access(real_path, proc_info, SET_DENY); set_perm_access(real_path, proc_info, SET_DENY);
ret = 0; ret = 0;

6
test/stress.bash Executable file
View File

@ -0,0 +1,6 @@
#!/bin/bash
count=$1
for i in $(seq $count); do
$2 ./protected/haystack/
done

View File

@ -10,7 +10,7 @@ chmod 777 ./protected/perm777 ./protected/perm000
echo "Free code, free world." >./protected/motto echo "Free code, free world." >./protected/motto
mkdir protected/haystack mkdir protected/haystack
for i in {1..10}; do for i in {1..100}; do
touch "./protected/haystack/hay$i" touch "./protected/haystack/hay$i"
done done
touch ./protected/haystack/needle touch ./protected/haystack/needle
@ -22,7 +22,7 @@ make -C ./opener || (
echo "Could not make the opener program." echo "Could not make the opener program."
exit 1 exit 1
) )
for i in {1..10}; do for i in {1..12}; do
cp ./opener/opener "./openers/opener$i" cp ./opener/opener "./openers/opener$i"
ln --symbolic "$(realpath "./openers/opener$i")" "./openers/symlinked_opener$i" ln --symbolic "$(realpath "./openers/opener$i")" "./openers/symlinked_opener$i"
done done
@ -43,6 +43,12 @@ if [[ $1 == "--setuid" ]]; then
echo "Valgrind will not be used due to setuid compatibility issues." echo "Valgrind will not be used due to setuid compatibility issues."
../build/icfs -o default_permissions ./protected ./.pt.db & ../build/icfs -o default_permissions ./protected ./.pt.db &
sleep 1 sleep 1
elif [[ $1 == "--performance" ]]; then
echo "Database protection will not be tested due to the lack of setuid capabilites."
echo "To test it, run this script with '--setuid'."
echo "valgrind won't be used to make performance measurements more accurate."
../build/icfs -o default_permissions ./protected ./.pt.db &
sleep 5
else else
echo "Database protection will not be tested due to the lack of setuid capabilites." echo "Database protection will not be tested due to the lack of setuid capabilites."
echo "To test it, run this script with '--setuid'." echo "To test it, run this script with '--setuid'."
@ -205,9 +211,36 @@ else
echo "[ICFS-TEST]: permanent permissions database access was not tested due to the lack of seuid bit setting capabilites. To test this, run the script with '--setuid' flag" echo "[ICFS-TEST]: permanent permissions database access was not tested due to the lack of seuid bit setting capabilites. To test this, run the script with '--setuid' flag"
fi fi
RUNS_NUM=500
if [[ $1 == '--performance' ]]; then
#warmup
icfs_dialogue --set-fake-response yes
parallel -j8 ::: "./stress.bash $RUNS_NUM openers/opener10"
icfs_dialogue --set-fake-response yes
echo "[ICFS-TEST]: temp permissions"
time parallel -j8 ::: "./stress.bash $RUNS_NUM openers/opener7"
icfs_dialogue --set-fake-response yes_perm
echo "[ICFS-TEST]: perm permissions"
time parallel -j8 ::: "./stress.bash $RUNS_NUM openers/opener8"
fi
# unmount # unmount
sleep 0.5 sleep 0.5
#lsof +f -- $(realpath ./protected) #lsof +f -- $(realpath ./protected)
umount "$(realpath ./protected)" umount "$(realpath ./protected)"
sleep 2 sleep 3
if [[ $1 == '--performance' ]]; then
#warmup
parallel -j8 ::: "./stress.bash $RUNS_NUM openers/opener9"
echo "[ICFS-TEST]: bare filesystem"
time parallel -j8 ::: "./stress.bash $RUNS_NUM openers/opener9"
fi