diff options
Diffstat (limited to 'main.c')
-rw-r--r-- | main.c | 68 |
1 files changed, 59 insertions, 9 deletions
@@ -120,6 +120,7 @@ static int copy_file_atomic_set_capabilities(const char *source_path, const char static void usage(void) { fprintf(stderr, "usage alt.1: kms-server-proxy <initial_socket_path> <card_path> <user_homepath>\n"); fprintf(stderr, "usage alt.2: kms-server-proxy setup-gsr-ui [user_homepath]\n"); + fprintf(stderr, "usage alt.3: kms-server-proxy launch-gsr-global-hotkeys <user_homepath> [args...]\n"); exit(1); } @@ -140,14 +141,14 @@ static int setup_gsr_ui(const char *user_homepath) { /* Update kms-server-proxy-N to kms-server-proxy-N+1 on update (update that needs to run before this program launches itself) */ snprintf(kms_server_proxy_local_filepath, sizeof(kms_server_proxy_local_filepath), "%s/.local/share/gpu-screen-recorder/kms-server-proxy-1", user_homepath); - char gsr_global_hotkeys_local_filepath[PATH_MAX]; - snprintf(gsr_global_hotkeys_local_filepath, sizeof(gsr_global_hotkeys_local_filepath), "%s/.local/share/gpu-screen-recorder/gsr-global-hotkeys", user_homepath); + //char gsr_global_hotkeys_local_filepath[PATH_MAX]; + //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(GSR_KMS_SERVER_FILEPATH, (const cap_value_t[]){ CAP_SYS_ADMIN }, 1) == 1); - success &= (copy_file_atomic_set_capabilities(self_path, kms_server_proxy_local_filepath, (const cap_value_t[]){ CAP_SYS_ADMIN, CAP_SETFCAP }, 2) == 1); - success &= (copy_file_atomic_set_capabilities(GSR_GLOBAL_HOTKEYS_FILEPATH, gsr_global_hotkeys_local_filepath, (const cap_value_t[]){ CAP_SETUID }, 1) == 1); + success &= (copy_file_atomic_set_capabilities(self_path, kms_server_proxy_local_filepath, (const cap_value_t[]){ CAP_SYS_ADMIN, CAP_SETFCAP, CAP_SETUID }, 3) == 1); + //success &= (copy_file_atomic_set_capabilities(GSR_GLOBAL_HOTKEYS_FILEPATH, gsr_global_hotkeys_local_filepath, (const cap_value_t[]){ CAP_SETUID }, 1) == 1); return success ? 0 : 1; } else { if(create_local_kms_server_proxy_directory(user_homepath) != 1) @@ -199,7 +200,7 @@ static int launch_gsr_kms_server(const char *initial_socket_path, const char *ca return execvp(args[0], (char *const*)args); } else if(geteuid() == 0) { /* is current user root? */ file_set_capabilities(GSR_KMS_SERVER_FILEPATH, (const cap_value_t[]){ CAP_SYS_ADMIN }, 1); - copy_file_atomic_set_capabilities(self_path, kms_server_proxy_local_filepath, (const cap_value_t[]){ CAP_SYS_ADMIN, CAP_SETFCAP }, 2); + copy_file_atomic_set_capabilities(self_path, kms_server_proxy_local_filepath, (const cap_value_t[]){ CAP_SYS_ADMIN, CAP_SETFCAP, CAP_SETUID }, 3); const char *args[] = { GSR_KMS_SERVER_FILEPATH, initial_socket_path, card_path, NULL }; return execv(args[0], (char *const*)args); @@ -211,18 +212,67 @@ static int launch_gsr_kms_server(const char *initial_socket_path, const char *ca } } +static int launch_gsr_global_hotkeys(char **argv) { + char self_path[PATH_MAX]; + if(!readlink_realpath("/proc/self/exe", self_path)) { + fprintf(stderr, "failed to resolve /proc/self/exe\n"); + return 1; + } + + const char *user_homepath = argv[2]; + + char kms_server_proxy_local_filepath[PATH_MAX]; + /* Update kms-server-proxy-N to kms-server-proxy-N+1 on update (update that needs to run before this program launches itself) */ + snprintf(kms_server_proxy_local_filepath, sizeof(kms_server_proxy_local_filepath), "%s/.local/share/gpu-screen-recorder/kms-server-proxy-1", user_homepath); + + if(!file_has_sys_admin_capability(kms_server_proxy_local_filepath)) { + fprintf(stderr, "Error: kms-server-proxy is missing cap sys admin capability\n"); + return 1; + } + + /* Need to resolve kms_server_proxy_local_filepath because /home can be a symlink to another location */ + char kms_server_proxy_local_filepath_full[PATH_MAX]; + if(!readlink_realpath(kms_server_proxy_local_filepath, kms_server_proxy_local_filepath_full)) { + fprintf(stderr, "failed to resolve %s\n", kms_server_proxy_local_filepath); + return 1; + } + + /* + Run cached ~/.local/share/gpu-screen-recorder/kms-server-proxy which has sys admin capability. + The one in flatpak location gets capabilities overwritten on flatpak update. + */ + if(strcmp(self_path, kms_server_proxy_local_filepath_full) != 0) { + argv[0] = kms_server_proxy_local_filepath_full; + return execv(argv[0], (char *const*)argv); + } + + if(setuid(0) == -1) { + fprintf(stderr, "Error: failed to switch to root user to launch gsr-global-hotkeys\n"); + return 1; + } + + argv[2] = GSR_GLOBAL_HOTKEYS_FILEPATH; + return execv(argv[2], argv + 3); +} + int main(int argc, char **argv) { - if(argc == 2 || argc == 3) { + if(argc < 2) + usage(); + + if(strcmp(argv[1], "setup-gsr-ui") == 0) { const char *user_homepath = argc == 3 ? argv[2] : NULL; - if(strcmp(argv[1], "setup-gsr-ui") == 0) { - return setup_gsr_ui(user_homepath); + return setup_gsr_ui(user_homepath); + } else if(strcmp(argv[1], "launch-gsr-global-hotkeys") == 0) { + if(argc >= 3) { + return launch_gsr_global_hotkeys(argv); } else { - fprintf(stderr, "error: invalid option \"%s\".\n", argv[1]); + fprintf(stderr, "Error: missing user_homepath argument to launch-gsr-global-hotkeys\n"); usage(); } } else if(argc == 4) { return launch_gsr_kms_server(argv[1], argv[2], argv[3]); } else { + fprintf(stderr, "error: invalid option \"%s\".\n", argv[1]); usage(); } } |