diff --git a/src/main.c b/src/main.c index 4bc5faa..8597c98 100644 --- a/src/main.c +++ b/src/main.c @@ -36,7 +36,7 @@ int main(int argc, char *argv[]) { exit(EXIT_FAILURE); } - ret = init_ui_socket("/home/fedir/.icfs-sock"); + ret = init_ui_socket(); if (ret != 0) { perror("init_ui_socket"); exit(EXIT_FAILURE); @@ -45,5 +45,6 @@ int main(int argc, char *argv[]) { ret = fuse_main(argc, argv, get_fuse_operations(), NULL); free(mountpoint); + destroy_ui_socket(); return ret; } diff --git a/src/ui-socket.c b/src/ui-socket.c index fd66dbd..7f676a0 100644 --- a/src/ui-socket.c +++ b/src/ui-socket.c @@ -8,7 +8,9 @@ #include #include +#include #define _GNU_SOURCE +#include "cc.h" #include "ui-socket.h" #include #include @@ -19,7 +21,61 @@ #include #include -int init_ui_socket(const char *filename) { +/** + * Function to get the process creation time (in jiffies) from the proc + * filesystem + * + * @param pid: The process ID of the process to get the creation time of + * @return: The process creation time in jiffies, or 0 on error + * @note: although nothing in the documentation says that the creation time is + * never really equal to 0, it exceptionally unlikely. + */ +unsigned long long get_process_creation_time(pid_t pid) { + char path[32]; + FILE *fp; + unsigned long long creation_time = 0; + + // Construct the path to the process's status file + snprintf(path, sizeof(path), "/proc/%d/stat", pid); + + // Open the status file + fp = fopen(path, "r"); + if (fp == NULL) { + perror("fopen"); + return 0; + } + + // Read the creation time (the 22nd field in the stat file) + for (int i = 1; i < 22; i++) { + if (fscanf(fp, "%*s") != 1) { + fprintf(stderr, "Error reading process stat file\n"); + fclose(fp); + return 0; + } + } + if (fscanf(fp, "%llu", &creation_time) != 1) { + fprintf(stderr, "Error reading creation time\n"); + fclose(fp); + return 0; + } + + // Close the file + fclose(fp); + + return creation_time; +} + +struct temp_process_permissions { + // yes, this is a correct type for start time in jiffies (see + // proc_pid_stat(5)) + unsigned long long creation_time; + vec(char *) allowed_files; +}; + +map(pid_t, struct temp_process_permissions) temp_permissions_table; +pthread_mutex_t temp_permissions_table_lock; + +int init_ui_socket() { char line[256]; FILE *fp; @@ -28,12 +84,24 @@ int init_ui_socket(const char *filename) { if (fp == NULL) { perror("Pipe returned a error"); return 1; - } else { - while (fgets(line, sizeof(line), fp)) - printf("%s", line); - pclose(fp); - return 0; } + pthread_mutex_init(&temp_permissions_table_lock, PTHREAD_MUTEX_DEFAULT); + init(&temp_permissions_table); + + while (fgets(line, sizeof(line), fp)) + printf("%s", line); + pclose(fp); + return 0; +} + +void destroy_ui_socket() { + // free the memory allocated for the table + for_each(&temp_permissions_table, entry) { + for_each(&entry->allowed_files, allowed_file) { free(*allowed_file); } + cleanup(&entry->allowed_files); + } + cleanup(&temp_permissions_table); + pthread_mutex_destroy(&temp_permissions_table_lock); } /** @@ -71,6 +139,7 @@ int ask_access(const char *filename, struct process_info pi) { // to manually check the output. char buffer[1024]; while (fgets(buffer, sizeof(buffer), fp)) { + printf("%s", buffer); if (strcmp(buffer, "Allow this time\n") == 0) { pclose(fp); return 2; @@ -94,7 +163,31 @@ int ask_access(const char *filename, struct process_info pi) { * @return: 0 if access is denied, 1 if access is allowed */ int check_temp_access(const char *filename, struct process_info pi) { - perror("Not implemented"); + // TODO: more efficient locking + pthread_mutex_lock(&temp_permissions_table_lock); + struct temp_process_permissions *permission_entry = + get(&temp_permissions_table, pi.PID); + if (permission_entry != NULL) { + unsigned long long process_creation_time = + get_process_creation_time(pi.PID); + if (process_creation_time == 0) { + perror("Could not retrieve process creation time"); + pthread_mutex_unlock(&temp_permissions_table_lock); + return 0; + } + + if (process_creation_time == permission_entry->creation_time) { + // the process is the same as the one that was granted temporary access + // to the file + for_each(&permission_entry->allowed_files, allowed_file) { + if (strncmp(*allowed_file, filename, strlen(filename)) == 0) { + pthread_mutex_unlock(&temp_permissions_table_lock); + return 1; + } + } + } + } + pthread_mutex_unlock(&temp_permissions_table_lock); return 0; } @@ -110,11 +203,51 @@ int check_perm_access(const char *filename, struct process_info pi) { return 0; } -void give_temp_access(const char *filename, struct process_info pi) { - perror("Not implemented"); +int give_temp_access(const char *filename, struct process_info pi) { + pthread_mutex_lock(&temp_permissions_table_lock); + struct temp_process_permissions *permission_entry = + get(&temp_permissions_table, pi.PID); + + if (permission_entry != NULL) { + + unsigned long long process_creation_time = + get_process_creation_time(pi.PID); + if (process_creation_time == 0) { + perror("Could not retrieve process creation time"); + pthread_mutex_unlock(&temp_permissions_table_lock); + return -1; + } + + if (process_creation_time == permission_entry->creation_time) { + // the process is the same as the one that was granted temporary access + // to the file + push(&permission_entry->allowed_files, strdup(filename)); + pthread_mutex_unlock(&temp_permissions_table_lock); + return 0; + } + // we have an entry for the process, but the process is different + // delete the entry and create a new one + erase(&temp_permissions_table, pi.PID); + permission_entry = NULL; + } + + // no entry is present + // construct the entry + struct temp_process_permissions new_permission_entry; + + new_permission_entry.creation_time = get_process_creation_time(pi.PID); + init(&new_permission_entry.allowed_files); + push(&new_permission_entry.allowed_files, strdup(filename)); + + insert(&temp_permissions_table, pi.PID, new_permission_entry); + + pthread_mutex_unlock(&temp_permissions_table_lock); + return 0; } -void give_perm_access(const char *filename, struct process_info pi) { + +int give_perm_access(const char *filename, struct process_info pi) { perror("Not implemented"); + return -1; } /** diff --git a/src/ui-socket.h b/src/ui-socket.h index 399bc7d..bc51e2a 100644 --- a/src/ui-socket.h +++ b/src/ui-socket.h @@ -21,8 +21,9 @@ struct process_info { uid_t UID; }; -// For default socket location, set socket_path = NULL. -int init_ui_socket(const char *socket_path); +int init_ui_socket(); + +void destroy_ui_socket(); int interactive_access(const char *filename, struct process_info pi);