diff options
author | dec05eba <dec05eba@protonmail.com> | 2024-12-29 17:14:11 +0100 |
---|---|---|
committer | dec05eba <dec05eba@protonmail.com> | 2024-12-29 17:14:11 +0100 |
commit | d90b3174d28504bb4b95724c39ec93fb0bebd7dc (patch) | |
tree | 56faeb9c64a6c00071699e911c6069c96622fb7a | |
parent | 12bb4a75dbc19e2650eb7a3155ee44ae1048ae79 (diff) |
Add option to install gsr-global-hotkeys as well
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | main.c | 93 |
2 files changed, 67 insertions, 28 deletions
@@ -12,4 +12,6 @@ so a password prompt will show up. The reason all of this is needed is because `setcap cap_sys_admin+ep gsr-kms-server` can't be done in the flatpak because of sandboxing so this is only done when you install GPU Screen Recorder from source/aur to workaround that limitation. +This program also installs gsr-global-hotkeys from the GPU Screen Recorder flatpak to ~/.local/share/gpu-screen-recorder. + The depends directory contains libcap from the libcap project, available here: https://mirrors.edge.kernel.org/pub/linux/libs/security/linux-privs/libcap2/. The version used is libcap-2.69.
\ No newline at end of file @@ -9,6 +9,9 @@ #include <sys/sendfile.h> #include <sys/capability.h> +#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) { char symlinked_path[PATH_MAX]; ssize_t bytes_written = readlink(filepath, symlinked_path, sizeof(symlinked_path) - 1); @@ -39,7 +42,7 @@ static int file_has_sys_admin_capability(const char *filepath) { return cap_set; } -static int file_set_sys_admin_capability(const char *filepath, int setfcap) { +static int 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; @@ -50,15 +53,10 @@ static int file_set_sys_admin_capability(const char *filepath, int setfcap) { return 0; } - const cap_value_t cap_to_set[] = { CAP_SYS_ADMIN, CAP_SETFCAP }; - int num_caps = 1; - if(setfcap) - num_caps = 2; - int res = 0; - res |= cap_set_flag(cap, CAP_EFFECTIVE, num_caps, cap_to_set, CAP_SET); - res |= cap_set_flag(cap, CAP_PERMITTED, num_caps, cap_to_set, CAP_SET); - /*cap_set_flag(cap, CAP_INHERITABLE, num_caps, cap_to_set, CAP_SET);*/ + res |= cap_set_flag(cap, CAP_EFFECTIVE, num_caps_to_set, caps_to_set, CAP_SET); + res |= cap_set_flag(cap, CAP_PERMITTED, num_caps_to_set, caps_to_set, CAP_SET); + /*cap_set_flag(cap, CAP_INHERITABLE, num_caps_to_set, caps_to_set, CAP_SET);*/ res |= cap_set_file(filepath, cap); cap_free(cap); return res == 0; @@ -80,7 +78,7 @@ static int create_local_kms_server_proxy_directory(const char *home) { return 1; } -static int create_local_kms_server_proxy_file_atomic(const char *source_path, const char *dest_path) { +static int copy_file_atomic_set_capabilities(const char *source_path, const char *dest_path, const cap_value_t *caps_to_set, int num_caps_to_set) { int in_fd = -1; int out_fd = -1; int res = 0; @@ -111,25 +109,49 @@ static int create_local_kms_server_proxy_file_atomic(const char *source_path, co close(out_fd); if(res) - res = file_set_sys_admin_capability(tmp_filepath, 1); + res = file_set_capabilities(tmp_filepath, caps_to_set, num_caps_to_set); if(res) - rename(tmp_filepath, dest_path); + res = rename(tmp_filepath, dest_path) == 0; return res; } -int main(int argc, char **argv) { - if(argc != 4) { - fprintf(stderr, "usage: kms-server-proxy <initial_socket_path> <card_path> <user_homepath>\n"); +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"); + exit(1); +} + +static int setup_gsr_ui(const char *user_homepath) { + 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 *gsr_kms_server_filepath = "/var/lib/flatpak/app/com.dec05eba.gpu_screen_recorder/current/active/files/bin/gsr-kms-server"; - const char *initial_socket_path = argv[1]; - const char *card_path = argv[2]; - const char *user_homepath = argv[3]; + 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); + + 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); + return success ? 0 : 1; + } else { + create_local_kms_server_proxy_directory(user_homepath); + + const char *args[] = { "pkexec", self_path, "setup-gsr-ui", user_homepath, NULL }; + return execvp(args[0], (char *const*)args); + } +} + +static int launch_gsr_kms_server(const char *initial_socket_path, const char *card_path, const char *user_homepath) { char self_path[PATH_MAX]; if(!readlink_realpath("/proc/self/exe", self_path)) { fprintf(stderr, "failed to resolve /proc/self/exe\n"); @@ -140,8 +162,8 @@ int main(int argc, char **argv) { /* 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(gsr_kms_server_filepath)) { - const char *args[] = { gsr_kms_server_filepath, initial_socket_path, card_path, NULL }; + if(file_has_sys_admin_capability(GSR_KMS_SERVER_FILEPATH)) { + const char *args[] = { GSR_KMS_SERVER_FILEPATH, initial_socket_path, card_path, NULL }; return execv(args[0], (char *const*)args); } else if(file_has_sys_admin_capability(kms_server_proxy_local_filepath)) { /* Need to resolve kms_server_proxy_local_filepath because /home can be a symlink to another location */ @@ -161,18 +183,18 @@ int main(int argc, char **argv) { } /* TODO: Remove the need for this. Instead inherit capabilities */ - if(file_set_sys_admin_capability(gsr_kms_server_filepath, 0)) { - const char *args[] = { gsr_kms_server_filepath, initial_socket_path, card_path, NULL }; + if(file_set_capabilities(GSR_KMS_SERVER_FILEPATH, (const cap_value_t[]){ CAP_SYS_ADMIN }, 1)) { + const char *args[] = { GSR_KMS_SERVER_FILEPATH, initial_socket_path, card_path, NULL }; return execv(args[0], (char *const*)args); } - const char *args[] = { "pkexec", gsr_kms_server_filepath, initial_socket_path, card_path, NULL }; + const char *args[] = { "pkexec", GSR_KMS_SERVER_FILEPATH, initial_socket_path, card_path, NULL }; return execvp(args[0], (char *const*)args); - } else if(geteuid() == 0) { /* is current user root */ - file_set_sys_admin_capability(gsr_kms_server_filepath, 0); - create_local_kms_server_proxy_file_atomic(self_path, kms_server_proxy_local_filepath); + } 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); - const char *args[] = { gsr_kms_server_filepath, initial_socket_path, card_path, NULL }; + const char *args[] = { GSR_KMS_SERVER_FILEPATH, initial_socket_path, card_path, NULL }; return execv(args[0], (char *const*)args); } else { create_local_kms_server_proxy_directory(user_homepath); @@ -181,3 +203,18 @@ int main(int argc, char **argv) { return execvp(args[0], (char *const*)args); } } + +int main(int argc, char **argv) { + if(argc == 3) { + if(strcmp(argv[1], "setup-gsr-ui") == 0) { + return setup_gsr_ui(argv[2]); + } else { + fprintf(stderr, "error: invalid option \"%s\".\n", argv[1]); + usage(); + } + } else if(argc == 4) { + return launch_gsr_kms_server(argv[1], argv[2], argv[3]); + } else { + usage(); + } +} |