aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2024-12-29 17:14:11 +0100
committerdec05eba <dec05eba@protonmail.com>2024-12-29 17:14:11 +0100
commitd90b3174d28504bb4b95724c39ec93fb0bebd7dc (patch)
tree56faeb9c64a6c00071699e911c6069c96622fb7a
parent12bb4a75dbc19e2650eb7a3155ee44ae1048ae79 (diff)
Add option to install gsr-global-hotkeys as well
-rw-r--r--README.md2
-rw-r--r--main.c93
2 files changed, 67 insertions, 28 deletions
diff --git a/README.md b/README.md
index a927133..2188697 100644
--- a/README.md
+++ b/README.md
@@ -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
diff --git a/main.c b/main.c
index 8084021..4a46f54 100644
--- a/main.c
+++ b/main.c
@@ -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();
+ }
+}