Use /usr/bin/gsr-kms-server constant path for pkexec

This commit is contained in:
dec05eba 2023-04-09 16:06:39 +02:00
parent cb82677ae8
commit 7dcf3a68cc
5 changed files with 39 additions and 43 deletions

View File

@ -10,7 +10,6 @@ typedef struct _XDisplay Display;
typedef struct {
Display *dpy;
const char *display_to_capture; /* if this is "screen", then the entire x11 screen is captured (all displays). A copy is made of this */
const char *program_dir; /* ref */
} gsr_capture_kms_vaapi_params;
gsr_capture* gsr_capture_kms_vaapi_create(const gsr_capture_kms_vaapi_params *params);

View File

@ -63,7 +63,7 @@ static int recv_msg_from_server(int server_fd, gsr_kms_response *response) {
return res;
}
int gsr_kms_client_init(gsr_kms_client *self, const char *card_path, const char *program_dir) {
int gsr_kms_client_init(gsr_kms_client *self, const char *card_path) {
self->kms_server_pid = -1;
self->card_path = NULL;
self->socket_fd = -1;
@ -72,37 +72,42 @@ int gsr_kms_client_init(gsr_kms_client *self, const char *card_path, const char
struct sockaddr_un local_addr = {0};
struct sockaddr_un remote_addr = {0};
bool inside_flatpak = is_inside_flatpak();
char server_filepath[PATH_MAX];
snprintf(server_filepath, sizeof(server_filepath), "%s/%s", program_dir, "gsr-kms-server");
if(access(server_filepath, F_OK) != 0 || inside_flatpak)
snprintf(server_filepath, sizeof(server_filepath), "gsr-kms-server"); // Assume gsr-kms-server is in $PATH
// This doesn't work on nixos, but we dont want to use $PATH because we want to make this as safe as possible by running pkexec
// on a path that only root can modify. If we use "gsr-kms-server" instead then $PATH can be modified in ~/.bashrc for example
// which will overwrite the path to gsr-kms-server and the user can end up running a malicious program that pretends to be gsr-kms-server.
// If there is a safe way to do this on nixos, then please tell me; or use gpu-screen-recorder flatpak instead.
const char *server_filepath = "/usr/bin/gsr-kms-server";
bool has_perm = 0;
if(geteuid() == 0) {
has_perm = true;
} else {
cap_t kms_server_cap = cap_get_file(server_filepath);
if(kms_server_cap) {
cap_flag_value_t res = 0;
cap_get_flag(kms_server_cap, CAP_SYS_ADMIN, CAP_PERMITTED, &res);
if(res == CAP_SET) {
//fprintf(stderr, "has permission!\n");
has_perm = true;
} else {
//fprintf(stderr, "No permission:(\n");
}
cap_free(kms_server_cap);
bool inside_flatpak = is_inside_flatpak();
if(!inside_flatpak) {
if(access("/usr/bin/gsr-kms-server", F_OK) != 0) {
fprintf(stderr, "gsr error: gsr_kms_client_init: /usr/bin/gsr-kms-server not found, please install gpu-screen-recorder first\n");
return -1;
}
if(geteuid() == 0) {
has_perm = true;
} else {
if(errno == ENODATA)
fprintf(stderr, "gsr info: gsr_kms_client_init: gsr-kms-server is missing sys_admin cap and will require root authentication. To bypass this automatically, run: sudo setcap cap_sys_admin+ep '%s'\n", server_filepath);
else
fprintf(stderr, "gsr info: gsr_kms_client_init: failed to get cap\n");
cap_t kms_server_cap = cap_get_file(server_filepath);
if(kms_server_cap) {
cap_flag_value_t res = 0;
cap_get_flag(kms_server_cap, CAP_SYS_ADMIN, CAP_PERMITTED, &res);
if(res == CAP_SET) {
//fprintf(stderr, "has permission!\n");
has_perm = true;
} else {
//fprintf(stderr, "No permission:(\n");
}
cap_free(kms_server_cap);
} else {
if(errno == ENODATA)
fprintf(stderr, "gsr info: gsr_kms_client_init: gsr-kms-server is missing sys_admin cap and will require root authentication. To bypass this automatically, run: sudo setcap cap_sys_admin+ep '%s'\n", server_filepath);
else
fprintf(stderr, "gsr info: gsr_kms_client_init: failed to get cap\n");
}
}
}
fprintf(stderr, "gsr info: gsr server path: %s, exists: %s\n", server_filepath, access(server_filepath, F_OK) == 0 ? "yes" : "no");
self->card_path = strdup(card_path);
if(!self->card_path) {
fprintf(stderr, "gsr error: gsr_kms_client_init: failed to duplicate card_path\n");
@ -138,17 +143,17 @@ int gsr_kms_client_init(gsr_kms_client *self, const char *card_path, const char
fprintf(stderr, "gsr error: gsr_kms_client_init: fork failed, error: %s\n", strerror(errno));
goto err;
} else if(pid == 0) { /* child */
if(has_perm) {
const char *args[] = { server_filepath, self->socket_path, NULL };
if(inside_flatpak) {
const char *args[] = { "flatpak-spawn", "--host", "pkexec", "flatpak", "run", "--command=gsr-kms-server", "com.dec05eba.gpu_screen_recorder", self->socket_path, NULL };
execvp(args[0], (char *const*)args);
} else if(inside_flatpak) {
const char *args[] = { "flatpak-spawn", "--host", "pkexec", server_filepath, self->socket_path, NULL };
} else if(has_perm) {
const char *args[] = { server_filepath, self->socket_path, NULL };
execvp(args[0], (char *const*)args);
} else {
const char *args[] = { "pkexec", server_filepath, self->socket_path, NULL };
execvp(args[0], (char *const*)args);
}
perror("execvp");
fprintf(stderr, "gsr error: gsr_kms_client_init: execvp failed, error: %s\n", strerror(errno));
_exit(127);
} else { /* parent */
self->kms_server_pid = pid;

View File

@ -13,7 +13,7 @@ typedef struct {
} gsr_kms_client;
/* |card_path| should be a path to card, for example /dev/dri/card0 */
int gsr_kms_client_init(gsr_kms_client *self, const char *card_path, const char *program_dir);
int gsr_kms_client_init(gsr_kms_client *self, const char *card_path);
void gsr_kms_client_deinit(gsr_kms_client *self);
int gsr_kms_client_get_kms(gsr_kms_client *self, gsr_kms_response *response);

View File

@ -98,7 +98,7 @@ static int gsr_capture_kms_vaapi_start(gsr_capture *cap, AVCodecContext *video_c
gsr_capture_kms_vaapi *cap_kms = cap->priv;
// TODO: Allow specifying another card, and in other places (TODO: Use /dev/dri/renderD128?)
if(gsr_kms_client_init(&cap_kms->kms_client, "/dev/dri/card0", cap_kms->params.program_dir) != 0) {
if(gsr_kms_client_init(&cap_kms->kms_client, "/dev/dri/card0") != 0) {
return -1;
}

View File

@ -19,8 +19,6 @@ extern "C" {
#include <signal.h>
#include <sys/stat.h>
#include <libgen.h>
#include "../include/sound.hpp"
extern "C" {
@ -1111,11 +1109,6 @@ int main(int argc, char **argv) {
if(argc == 0)
usage();
char *program_dir = dirname(argv[0]);
char program_dir_full[PATH_MAX];
program_dir_full[0] = '\0';
realpath(program_dir, program_dir_full);
//av_log_set_level(AV_LOG_TRACE);
std::map<std::string, Arg> args = {
@ -1397,7 +1390,6 @@ int main(int argc, char **argv) {
gsr_capture_kms_vaapi_params kms_params;
kms_params.dpy = dpy;
kms_params.display_to_capture = capture_target;
kms_params.program_dir = program_dir_full;
capture = gsr_capture_kms_vaapi_create(&kms_params);
if(!capture)
return 1;