diff options
author | dec05eba <dec05eba@protonmail.com> | 2025-02-22 14:31:39 +0100 |
---|---|---|
committer | dec05eba <dec05eba@protonmail.com> | 2025-02-22 14:31:39 +0100 |
commit | 8141550b47b7c364dea07c16d7e6264d0d90259c (patch) | |
tree | 09168a8155401341813c0bd4d104609138d23521 | |
parent | 1b141d01b1a80387e5521886631bb54bf53aebf1 (diff) |
-rw-r--r-- | main.c | 121 |
1 files changed, 71 insertions, 50 deletions
@@ -5,6 +5,7 @@ #include <limits.h> #include <errno.h> #include <fcntl.h> +#include <stdbool.h> #include <sys/stat.h> #include <sys/sendfile.h> #include <sys/capability.h> @@ -13,45 +14,45 @@ #define GSR_KMS_SERVER_FILEPATH "/var/lib/flatpak/app/com.dec05eba.gpu_screen_recorder/current/active/files/bin/gsr-kms-server" #define GSR_GLOBAL_HOTKEYS_FILEPATH "/var/lib/flatpak/app/com.dec05eba.gpu_screen_recorder/current/active/files/bin/gsr-global-hotkeys" -static int readlink_realpath(const char *filepath, char *buffer) { +static bool readlink_realpath(const char *filepath, char *buffer) { char symlinked_path[PATH_MAX]; ssize_t bytes_written = readlink(filepath, symlinked_path, sizeof(symlinked_path) - 1); if(bytes_written == -1 && errno == EINVAL) { /* Not a symlink */ strncpy(symlinked_path, filepath, sizeof(symlinked_path)); } else if(bytes_written == -1) { - return 0; + return false; } else { symlinked_path[bytes_written] = '\0'; } if(!realpath(symlinked_path, buffer)) - return 0; + return false; - return 1; + return true; } -static int file_has_sys_admin_capability(const char *filepath) { +static bool file_has_sys_admin_capability(const char *filepath) { cap_t cap = cap_get_file(filepath); if(!cap) - return 0; + return false; cap_flag_value_t res = CAP_CLEAR; cap_get_flag(cap, CAP_SYS_ADMIN, CAP_PERMITTED, &res); - int cap_set = res == CAP_SET; + bool cap_set = res == CAP_SET; cap_free(cap); return cap_set; } -static int file_set_capabilities(const char *filepath, const cap_value_t *caps_to_set, int num_caps_to_set) { +static bool file_set_capabilities(const char *filepath, const cap_value_t *caps_to_set, int num_caps_to_set) { cap_t cap = cap_get_file(filepath); if(!cap && errno != ENODATA) - return 0; + return false; if(!cap) { cap = cap_init(); if(!cap) - return 0; + return false; } int res = 0; @@ -63,7 +64,11 @@ static int file_set_capabilities(const char *filepath, const cap_value_t *caps_t return res == 0; } -static int create_local_kms_server_proxy_directory(const char *home) { +static bool file_set_permissions(const char *filepath, unsigned int permissions) { + return chmod(filepath, permissions) == 0; +} + +static bool create_local_kms_server_proxy_directory(const char *home) { char path[PATH_MAX]; int err; @@ -73,16 +78,16 @@ static int create_local_kms_server_proxy_directory(const char *home) { snprintf(path, sizeof(path), "%s/%s", home, path_part); err = mkdir(path, S_IRWXU); if(err == -1 && errno != EEXIST) - return 0; + return false; } - return 1; + return true; } -static int copy_file_atomic(const char *source_path, const char *dest_path) { +static bool copy_file_atomic(const char *source_path, const char *dest_path) { int in_fd = -1; int out_fd = -1; - int res = 0; + bool res = false; char tmp_filepath[PATH_MAX]; snprintf(tmp_filepath, sizeof(tmp_filepath), "%s.tmp", dest_path); @@ -101,7 +106,7 @@ static int copy_file_atomic(const char *source_path, const char *dest_path) { if(sendfile(out_fd, in_fd, NULL, st.st_size) != st.st_size) goto done; - res = 1; + res = true; done: if(in_fd) @@ -122,6 +127,48 @@ static void usage(void) { exit(1); } +static bool set_kms_server_proxy_permissions_and_capabilities(const char *kms_server_proxy_filepath) { + /* owner: read/write/execute, group: read/execute, public: read/execute */ + if(!file_set_permissions(kms_server_proxy_filepath, 0755)) { + fprintf(stderr, "Error: failed to set kms-server-proxy permissions\n"); + return false; + } + + if(!file_set_capabilities(kms_server_proxy_filepath, (const cap_value_t[]){ CAP_SYS_ADMIN, CAP_SETFCAP, CAP_SETUID }, 3)) { + fprintf(stderr, "Error: failed to set kms-server-proxy capabilities\n"); + return false; + } + + return true; +} + +/* |gsr_global_hotkeys_local_filepath| can be NULL */ +static bool setup_local_files(const char *user_homepath, const char *kms_server_proxy_local_filepath, const char *gsr_kms_server_local_filepath, const char *gsr_global_hotkeys_local_filepath) { + if(!create_local_kms_server_proxy_directory(user_homepath)) { + fprintf(stderr, "Error: failed to create ~/.local/share/gpu-screen-recorder directory\n"); + return false; + } + + if(!copy_file_atomic(KMS_SERVER_PROXY_FILEPATH, kms_server_proxy_local_filepath)) { + fprintf(stderr, "Error: failed to copy kms-server-proxy to %s\n", kms_server_proxy_local_filepath); + return false; + } + + if(!copy_file_atomic(GSR_KMS_SERVER_FILEPATH, gsr_kms_server_local_filepath)) { + fprintf(stderr, "Error: failed to copy gsr-kms-server to %s\n", gsr_kms_server_local_filepath); + return false; + } + + if(gsr_global_hotkeys_local_filepath) { + if(!copy_file_atomic(GSR_GLOBAL_HOTKEYS_FILEPATH, gsr_global_hotkeys_local_filepath)) { + fprintf(stderr, "Error: failed to copy gsr-global-hotkeys to %s\n", gsr_global_hotkeys_local_filepath); + return false; + } + } + + return true; +} + static int setup_gsr_ui(const char *user_homepath) { char self_path[PATH_MAX]; if(!readlink_realpath("/proc/self/exe", self_path)) { @@ -146,29 +193,13 @@ static int setup_gsr_ui(const char *user_homepath) { snprintf(gsr_global_hotkeys_local_filepath, sizeof(gsr_global_hotkeys_local_filepath), "%s/.local/share/gpu-screen-recorder/gsr-global-hotkeys", user_homepath); if(geteuid() == 0) { /* is current user root? */ - int success = 1; - success &= (file_set_capabilities(kms_server_proxy_local_filepath, (const cap_value_t[]){ CAP_SYS_ADMIN, CAP_SETFCAP, CAP_SETUID }, 3) == 1); - return success ? 0 : 1; - } else { - if(create_local_kms_server_proxy_directory(user_homepath) != 1) { - fprintf(stderr, "Error: failed to create ~/.local/share/gpu-screen-recorder directory\n"); - return 1; - } - - if(copy_file_atomic(KMS_SERVER_PROXY_FILEPATH, kms_server_proxy_local_filepath) != 1) { - fprintf(stderr, "Error: failed to copy kms-server-proxy to %s\n", kms_server_proxy_local_filepath); + if(!set_kms_server_proxy_permissions_and_capabilities(kms_server_proxy_local_filepath)) return 1; - } - - if(copy_file_atomic(GSR_KMS_SERVER_FILEPATH, gsr_kms_server_local_filepath) != 1) { - fprintf(stderr, "Error: failed to copy gsr-kms-server to %s\n", gsr_kms_server_local_filepath); - return 1; - } - if(copy_file_atomic(GSR_GLOBAL_HOTKEYS_FILEPATH, gsr_global_hotkeys_local_filepath) != 1) { - fprintf(stderr, "Error: failed to copy gsr-global-hotkeys to %s\n", gsr_global_hotkeys_local_filepath); + return 0; + } else { + if(!setup_local_files(user_homepath, kms_server_proxy_local_filepath, gsr_kms_server_local_filepath, gsr_global_hotkeys_local_filepath)) return 1; - } const char *args[] = { "pkexec", kms_server_proxy_local_filepath, "setup-gsr-ui", user_homepath, NULL }; return execvp(args[0], (char *const*)args); @@ -209,24 +240,14 @@ static int launch_gsr_kms_server(const char *initial_socket_path, const char *ca const char *args[] = { "pkexec", gsr_kms_server_local_filepath, initial_socket_path, card_path, NULL }; return execvp(args[0], (char *const*)args); } else if(geteuid() == 0) { /* is current user root? */ - file_set_capabilities(kms_server_proxy_local_filepath, (const cap_value_t[]){ CAP_SYS_ADMIN, CAP_SETFCAP, CAP_SETUID }, 3); + if(!set_kms_server_proxy_permissions_and_capabilities(kms_server_proxy_local_filepath)) + return 1; + const char *args[] = { gsr_kms_server_local_filepath, initial_socket_path, card_path, NULL }; return execv(args[0], (char *const*)args); } else { - if(create_local_kms_server_proxy_directory(user_homepath) != 1) { - fprintf(stderr, "Error: failed to create ~/.local/share/gpu-screen-recorder directory\n"); + if(!setup_local_files(user_homepath, kms_server_proxy_local_filepath, gsr_kms_server_local_filepath, NULL)) return 1; - } - - if(copy_file_atomic(KMS_SERVER_PROXY_FILEPATH, kms_server_proxy_local_filepath) != 1) { - fprintf(stderr, "Error: failed to copy kms-server-proxy to %s\n", kms_server_proxy_local_filepath); - return 1; - } - - if(copy_file_atomic(GSR_KMS_SERVER_FILEPATH, gsr_kms_server_local_filepath) != 1) { - fprintf(stderr, "Error: failed to copy gsr-kms-server to %s\n", gsr_kms_server_local_filepath); - return 1; - } const char *args[] = { "pkexec", kms_server_proxy_local_filepath, initial_socket_path, card_path, user_homepath, NULL }; return execvp(args[0], (char *const*)args); |