diff --git a/src/sourcefs.c b/src/sourcefs.c index cf2b4ee..3117d1e 100644 --- a/src/sourcefs.c +++ b/src/sourcefs.c @@ -22,8 +22,8 @@ * Stores the root directory information to enable relative path operations. */ static struct source_files_handle { - const char *mountpoint; // Absolute path to the mounted filesystem root - int root_fd; // File descriptor for the root directory (O_PATH) + char *mountpoint; // Absolute path to the mounted filesystem root + int root_fd; // File descriptor for the root directory (O_PATH) } handle; /** @@ -128,8 +128,7 @@ int source_mkdir(const char *filename, mode_t mode) { /** * @brief Remove a file from the filesystem * - * Uses unlinkat() with AT_REMOVEDIR flag to safely remove files relative - * to the root directory. + * Uses unlinkat() to safely remove files relative to the root directory. */ int source_unlink(const char *filename) { const char *relative_filename = source_filename_translate(filename); diff --git a/src/ui-socket.c b/src/ui-socket.c index 6bc51b6..b2eab5a 100644 --- a/src/ui-socket.c +++ b/src/ui-socket.c @@ -7,6 +7,7 @@ */ #include "access_t.h" +#include #include #include #include @@ -25,6 +26,7 @@ #include #include #include +#include // Exit status codes for icfs_dialogue process interaction #define DIALOGUE_YES 1 @@ -96,30 +98,64 @@ void destroy_ui_socket(void) { struct dialogue_response ask_access(const char *filename, struct process_info proc_info) { FILE *fp = NULL; - char *command = NULL; - int ret = asprintf(&command, "icfs_dialogue \"%d\" \"%s\" \"%s\" \"%s\"", - proc_info.PID, proc_info.name, get_mountpoint(), filename); struct dialogue_response response; response.decision = DENY; response.filename = NULL; - if (ret < 0) { - // Memory allocation failed - create minimal fallback response - fprintf(stderr, "[ICFS] Could not create query on rule insertion"); - perror(""); + // instead of popeen -------------- + + char pid_str[sizeof(pid_t) * + 8]; // amount of bits should be enough for a decimal + snprintf(pid_str, sizeof(pid_str), "%d", proc_info.PID); + + int pipefd[2]; + if (pipe(pipefd) == -1) { + perror("[ICFS] pipe returned a error"); response.filename = malloc(2); response.filename[0] = '/'; response.filename[1] = 0; return response; } - // Execute permission dialogue - fp = popen(command, "r"); - free(command); + pid_t pid = fork(); + if (pid == -1) { + perror("[ICFS] fork returned a error"); + response.filename = malloc(2); + response.filename[0] = '/'; + response.filename[1] = 0; + return response; + } + + if (pid == 0) { + // Child process + close(pipefd[0]); // Close read end + dup2(pipefd[1], STDOUT_FILENO); // Redirect stdout + close(pipefd[1]); // Close original write end + + // Prepare command and arguments + char *args[] = {"icfs_dialogue", // Command name (looked up in PATH) + pid_str, + (char *)proc_info.name, + (char *)get_mountpoint(), + (char *)filename, + NULL}; + + // Execute the command using execvp (uses PATH) + execvp("icfs_dialogue", args); + + // If execvp fails + perror("execvp failed"); + exit(EXIT_FAILURE); + } + + // instead of popen --------------- + + close(pipefd[1]); // Close write end + fp = fdopen(pipefd[0], "r"); if (fp == NULL) { - perror("[ICFS] Pipe returned a error"); + perror("[ICFS] fdopen returned a error"); response.filename = malloc(2); response.filename[0] = '/'; response.filename[1] = 0; @@ -133,16 +169,42 @@ struct dialogue_response ask_access(const char *filename, // Read entire command output while (fgets(line, sizeof(line), fp)) { - push_fmt(&dialogue_output, line); + if (push_fmt(&dialogue_output, line) == NULL) { + cleanup(&dialogue_output); + perror("[ICFS] not enough memory for dialogue output."); + // kill the dialogue if it's still there + kill(pid, SIGQUIT); + fclose(fp); + response.filename = malloc(2); + response.filename[0] = '/'; + response.filename[1] = 0; + return response; + } } - int dialogue_exit_code = WEXITSTATUS(pclose(fp)); + fclose(fp); + + // Wait for the child to finish + int status; + if (waitpid(pid, &status, 0) == -1) { + cleanup(&dialogue_output); + perror("[ICFS] waitpid error"); + // kill the dialogue if it is still there + kill(pid, SIGQUIT); + response.filename = malloc(2); + response.filename[0] = '/'; + response.filename[1] = 0; + return response; + } + + int dialogue_exit_code = WEXITSTATUS(status); fprintf(stderr, "[ICFS] dialogue wrote out %s\n", first(&dialogue_output)); fprintf(stderr, "[ICFS] dialogue returned %d\n", dialogue_exit_code); // Handle empty output case if (size(&dialogue_output) == 0) { + perror("[ICFS] empty dialogue output."); push(&dialogue_output, '/'); }