From 5b921120a3615534b8cfce39090224c1e22edb47 Mon Sep 17 00:00:00 2001 From: smitsohu Date: Tue, 8 Jun 2021 16:00:19 +0200 Subject: add more EUID switching always access files under control of the user with effective user id of the user --- src/firejail/checkcfg.c | 3 +- src/firejail/chroot.c | 2 +- src/firejail/firejail.h | 3 ++ src/firejail/fs.c | 47 ++++++++++++++++++------ src/firejail/fs_dev.c | 2 + src/firejail/fs_home.c | 41 +++++++++++---------- src/firejail/fs_lib.c | 7 ++-- src/firejail/fs_whitelist.c | 1 + src/firejail/macros.c | 1 + src/firejail/mountinfo.c | 5 ++- src/firejail/paths.c | 2 +- src/firejail/sbox.c | 2 +- src/firejail/util.c | 89 ++++++++++++++++++++++++++++++++++++++++++--- src/firejail/x11.c | 15 +++----- 14 files changed, 165 insertions(+), 55 deletions(-) diff --git a/src/firejail/checkcfg.c b/src/firejail/checkcfg.c index d7690a4fc..f3ab0a6d8 100644 --- a/src/firejail/checkcfg.c +++ b/src/firejail/checkcfg.c @@ -134,8 +134,7 @@ int checkcfg(int val) { *end = '\0'; // is the file present? - struct stat s; - if (stat(fname, &s) == -1) { + if (access(fname, F_OK) == -1) { fprintf(stderr, "Error: netfilter-default file %s not available\n", fname); exit(1); } diff --git a/src/firejail/chroot.c b/src/firejail/chroot.c index 4125a4130..05d89a866 100644 --- a/src/firejail/chroot.c +++ b/src/firejail/chroot.c @@ -219,7 +219,7 @@ void fs_chroot(const char *rootdir) { exit(1); } if (bind_mount_by_fd(src, dst)) - errExit("mounting pulseaudio") + errExit("mounting pulseaudio"); close(src); close(dst); free(pulse); diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index ab6e44a8a..10133142a 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h @@ -503,6 +503,9 @@ void copy_file_from_user_to_root(const char *srcname, const char *destname, uid_ void touch_file_as_user(const char *fname, mode_t mode); int is_dir(const char *fname); int is_link(const char *fname); +char *realpath_as_user(const char *fname); +int stat_as_user(const char *fname, struct stat *s); +int lstat_as_user(const char *fname, struct stat *s); void trim_trailing_slash_or_dot(char *path); char *line_remove_spaces(const char *buf); char *split_comma(char *str); diff --git a/src/firejail/fs.c b/src/firejail/fs.c index eaf23e603..01182bd2c 100644 --- a/src/firejail/fs.c +++ b/src/firejail/fs.c @@ -57,6 +57,7 @@ static char *opstr[] = { static void disable_file(OPERATION op, const char *filename) { assert(filename); assert(op next; continue; @@ -376,16 +387,12 @@ void fs_blacklist(void) { op = MOUNT_TMPFS; } else if (strncmp(entry->data, "mkdir ", 6) == 0) { - EUID_USER(); fs_mkdir(entry->data + 6); - EUID_ROOT(); entry = entry->next; continue; } else if (strncmp(entry->data, "mkfile ", 7) == 0) { - EUID_USER(); fs_mkfile(entry->data + 7); - EUID_ROOT(); entry = entry->next; continue; } @@ -441,6 +448,8 @@ void fs_blacklist(void) { for (i = 0; i < noblacklist_c; i++) free(noblacklist[i]); free(noblacklist); + + EUID_ROOT(); } //*********************************************** @@ -449,6 +458,7 @@ void fs_blacklist(void) { // mount a writable tmpfs on directory; requires a resolved path void fs_tmpfs(const char *dir, unsigned check_owner) { + EUID_USER(); assert(dir); if (arg_debug) printf("Mounting tmpfs on %s, check owner: %s\n", dir, (check_owner)? "yes": "no"); @@ -473,6 +483,7 @@ void fs_tmpfs(const char *dir, unsigned check_owner) { errExit("fstatvfs"); unsigned long flags = buf.f_flag & ~(MS_RDONLY|MS_BIND); // mount via the symbolic link in /proc/self/fd + EUID_ROOT(); char *proc; if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1) errExit("asprintf"); @@ -490,6 +501,7 @@ void fs_tmpfs(const char *dir, unsigned check_owner) { // remount path, preserving other mount flags; requires a resolved path static void fs_remount_simple(const char *path, OPERATION op) { + EUID_ASSERT(); assert(path); // open path without following symbolic links @@ -555,7 +567,9 @@ static void fs_remount_simple(const char *path, OPERATION op) { // make path a mount point: // mount --bind path path + EUID_ROOT(); int err = bind_mount_by_fd(fd, fd); + EUID_USER(); if (err) { close(fd); goto out; @@ -575,7 +589,9 @@ static void fs_remount_simple(const char *path, OPERATION op) { if (s.st_dev != s2.st_dev || s.st_ino != s2.st_ino) errLogExit("invalid %s mount", opstr[op]); + EUID_ROOT(); err = remount_by_fd(fd2, flags); + EUID_USER(); close(fd2); if (err) goto out; @@ -599,7 +615,9 @@ out: // remount recursively; requires a resolved path static void fs_remount_rec(const char *dir, OPERATION op) { + EUID_ASSERT(); assert(dir); + struct stat s; if (stat(dir, &s) != 0) return; @@ -637,6 +655,9 @@ static void fs_remount_rec(const char *dir, OPERATION op) { // resolve a path and remount it void fs_remount(const char *path, OPERATION op, int rec) { assert(path); + assert(geteuid() == 0); + EUID_USER(); + char *rpath = realpath(path, NULL); if (rpath) { if (rec) @@ -645,10 +666,12 @@ void fs_remount(const char *path, OPERATION op, int rec) { fs_remount_simple(rpath, op); free(rpath); } + EUID_ROOT(); } // Disable /mnt, /media, /run/mount and /run/media access void fs_mnt(const int enforce) { + EUID_USER(); if (enforce) { // disable-mnt set in firejail.config // overriding with noblacklist is not possible in this case @@ -658,13 +681,12 @@ void fs_mnt(const int enforce) { disable_file(BLACKLIST_FILE, "/run/media"); } else { - EUID_USER(); profile_add("blacklist /mnt"); profile_add("blacklist /media"); profile_add("blacklist /run/mount"); profile_add("blacklist /run/media"); - EUID_ROOT(); } + EUID_ROOT(); } @@ -679,7 +701,6 @@ void fs_proc_sys_dev_boot(void) { errExit("mounting /proc/sys"); fs_logger("read-only /proc/sys"); - /* Mount a version of /sys that describes the network namespace */ if (arg_debug) printf("Remounting /sys directory\n"); @@ -694,13 +715,13 @@ void fs_proc_sys_dev_boot(void) { else fs_logger("remount /sys"); + EUID_USER(); + disable_file(BLACKLIST_FILE, "/sys/firmware"); disable_file(BLACKLIST_FILE, "/sys/hypervisor"); { // allow user access to some directories in /sys/ by specifying 'noblacklist' option - EUID_USER(); profile_add("blacklist /sys/fs"); profile_add("blacklist /sys/module"); - EUID_ROOT(); } disable_file(BLACKLIST_FILE, "/sys/power"); disable_file(BLACKLIST_FILE, "/sys/kernel/debug"); @@ -744,8 +765,6 @@ void fs_proc_sys_dev_boot(void) { // disable /dev/port disable_file(BLACKLIST_FILE, "/dev/port"); - - // disable various ipc sockets in /run/user if (!arg_writable_run_user) { char *fname; @@ -778,10 +797,13 @@ void fs_proc_sys_dev_boot(void) { disable_file(BLACKLIST_FILE, "/dev/kmsg"); disable_file(BLACKLIST_FILE, "/proc/kmsg"); } + + EUID_ROOT(); } // disable firejail configuration in ~/.config/firejail void disable_config(void) { + EUID_USER(); char *fname; if (asprintf(&fname, "%s/.config/firejail", cfg.homedir) == -1) errExit("asprintf"); @@ -794,6 +816,7 @@ void disable_config(void) { disable_file(BLACKLIST_FILE, RUN_FIREJAIL_NAME_DIR); disable_file(BLACKLIST_FILE, RUN_FIREJAIL_PROFILE_DIR); disable_file(BLACKLIST_FILE, RUN_FIREJAIL_X11_DIR); + EUID_ROOT(); } @@ -855,6 +878,7 @@ void fs_basic_fs(void) { #ifdef HAVE_OVERLAYFS char *fs_check_overlay_dir(const char *subdirname, int allow_reuse) { assert(subdirname); + EUID_ASSERT(); struct stat s; char *dirname; @@ -1214,6 +1238,7 @@ void fs_overlayfs(void) { // this function is called from sandbox.c before blacklist/whitelist functions void fs_private_tmp(void) { + EUID_ASSERT(); if (arg_debug) printf("Generate private-tmp whitelist commands\n"); diff --git a/src/firejail/fs_dev.c b/src/firejail/fs_dev.c index 8c2870a4d..8cc3ecc62 100644 --- a/src/firejail/fs_dev.c +++ b/src/firejail/fs_dev.c @@ -187,8 +187,10 @@ static void mount_dev_shm(void) { static void process_dev_shm(void) { // Jack audio keeps an Unix socket under (/dev/shm/jack_default_1000_0 or /dev/shm/jack/...) // looking for jack socket + EUID_USER(); glob_t globbuf; int globerr = glob(RUN_DEV_DIR "/shm/jack*", GLOB_NOSORT, NULL, &globbuf); + EUID_ROOT(); if (globerr && !arg_keep_dev_shm) { empty_dev_shm(); return; diff --git a/src/firejail/fs_home.c b/src/firejail/fs_home.c index ec6dab947..eab952eb8 100644 --- a/src/firejail/fs_home.c +++ b/src/firejail/fs_home.c @@ -42,15 +42,14 @@ static void skel(const char *homedir, uid_t u, gid_t g) { // copy skel files if (asprintf(&fname, "%s/.zshrc", homedir) == -1) errExit("asprintf"); - struct stat s; // don't copy it if we already have the file - if (stat(fname, &s) == 0) + if (access(fname, F_OK) == 0) return; - if (is_link(fname)) { // stat on dangling symlinks fails, try again using lstat + if (is_link(fname)) { // access(3) on dangling symlinks fails, try again using lstat fprintf(stderr, "Error: invalid %s file\n", fname); exit(1); } - if (stat("/etc/skel/.zshrc", &s) == 0) { + if (access("/etc/skel/.zshrc", R_OK) == 0) { copy_file_as_user("/etc/skel/.zshrc", fname, u, g, 0644); // regular user fs_logger("clone /etc/skel/.zshrc"); fs_logger2("clone", fname); @@ -67,16 +66,14 @@ static void skel(const char *homedir, uid_t u, gid_t g) { // copy skel files if (asprintf(&fname, "%s/.cshrc", homedir) == -1) errExit("asprintf"); - struct stat s; - // don't copy it if we already have the file - if (stat(fname, &s) == 0) + if (access(fname, F_OK) == 0) return; - if (is_link(fname)) { // stat on dangling symlinks fails, try again using lstat + if (is_link(fname)) { // access(3) on dangling symlinks fails, try again using lstat fprintf(stderr, "Error: invalid %s file\n", fname); exit(1); } - if (stat("/etc/skel/.cshrc", &s) == 0) { + if (access("/etc/skel/.cshrc", R_OK) == 0) { copy_file_as_user("/etc/skel/.cshrc", fname, u, g, 0644); // regular user fs_logger("clone /etc/skel/.cshrc"); fs_logger2("clone", fname); @@ -93,15 +90,14 @@ static void skel(const char *homedir, uid_t u, gid_t g) { // copy skel files if (asprintf(&fname, "%s/.bashrc", homedir) == -1) errExit("asprintf"); - struct stat s; // don't copy it if we already have the file - if (stat(fname, &s) == 0) + if (access(fname, F_OK) == 0) return; - if (is_link(fname)) { // stat on dangling symlinks fails, try again using lstat + if (is_link(fname)) { // access(3) on dangling symlinks fails, try again using lstat fprintf(stderr, "Error: invalid %s file\n", fname); exit(1); } - if (stat("/etc/skel/.bashrc", &s) == 0) { + if (access("/etc/skel/.bashrc", R_OK) == 0) { copy_file_as_user("/etc/skel/.bashrc", fname, u, g, 0644); // regular user fs_logger("clone /etc/skel/.bashrc"); fs_logger2("clone", fname); @@ -122,8 +118,8 @@ static int store_xauthority(void) { errExit("asprintf"); struct stat s; - if (stat(src, &s) == 0) { - if (is_link(src)) { + if (lstat_as_user(src, &s) == 0) { + if (S_ISLNK(s.st_mode)) { fwarning("invalid .Xauthority file\n"); free(src); return 0; @@ -161,11 +157,11 @@ static int store_asoundrc(void) { errExit("asprintf"); struct stat s; - if (stat(src, &s) == 0) { - if (is_link(src)) { + if (lstat_as_user(src, &s) == 0) { + if (S_ISLNK(s.st_mode)) { // make sure the real path of the file is inside the home directory /* coverity[toctou] */ - char* rp = realpath(src, NULL); + char *rp = realpath_as_user(src); if (!rp) { fprintf(stderr, "Error: Cannot access %s\n", src); exit(1); @@ -263,6 +259,7 @@ void fs_private_homedir(void) { if (arg_debug) printf("Mount-bind %s on top of %s\n", private_homedir, homedir); // get file descriptors for homedir and private_homedir, fails if there is any symlink + EUID_USER(); int src = safer_openat(-1, private_homedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); if (src == -1) errExit("opening private directory"); @@ -287,6 +284,7 @@ void fs_private_homedir(void) { exit(1); } // mount via the links in /proc/self/fd + EUID_ROOT(); if (bind_mount_by_fd(src, dst)) errExit("mount bind"); @@ -433,6 +431,7 @@ void fs_check_private_cwd(const char *dir) { // --private-home //*********************************************************************************** static char *check_dir_or_file(const char *name) { + EUID_ASSERT(); assert(name); // basic checks @@ -493,6 +492,7 @@ errexit: } static void duplicate(char *name) { + EUID_ASSERT(); char *fname = check_dir_or_file(name); if (arg_debug) @@ -548,10 +548,10 @@ void fs_private_home_list(void) { selinux_relabel_path(RUN_HOME_DIR, homedir); fs_logger_print(); // save the current log + // copy the list of files in the new home directory + EUID_USER(); if (arg_debug) printf("Copying files in the new home:\n"); - - // copy the list of files in the new home directory char *dlist = strdup(cfg.home_private_keep); if (!dlist) errExit("strdup"); @@ -584,6 +584,7 @@ void fs_private_home_list(void) { exit(1); } // mount using the file descriptor + EUID_ROOT(); if (bind_mount_path_to_fd(RUN_HOME_DIR, fd)) errExit("mount bind"); close(fd); diff --git a/src/firejail/fs_lib.c b/src/firejail/fs_lib.c index 8369e6259..9d7a17cf3 100644 --- a/src/firejail/fs_lib.c +++ b/src/firejail/fs_lib.c @@ -178,8 +178,7 @@ void fslib_mount(const char *full_path) { if (*full_path == '\0' || !valid_full_path(full_path) || - access(full_path, F_OK) != 0 || - stat(full_path, &s) != 0 || + stat_as_user(full_path, &s) != 0 || s.st_uid != 0) return; @@ -246,7 +245,7 @@ static void load_library(const char *fname) { // existing file owned by root struct stat s; - if (!access(fname, F_OK) && stat(fname, &s) == 0 && s.st_uid == 0) { + if (stat_as_user(fname, &s) == 0 && s.st_uid == 0) { // load directories, regular 64 bit libraries, and 64 bit executables if (S_ISDIR(s.st_mode)) fslib_mount(fname); @@ -286,12 +285,14 @@ static void install_list_entry(const char *lib) { #define DO_GLOBBING #ifdef DO_GLOBBING // globbing + EUID_USER(); glob_t globbuf; int globerr = glob(fname, GLOB_NOCHECK | GLOB_NOSORT | GLOB_PERIOD, NULL, &globbuf); if (globerr) { fprintf(stderr, "Error: failed to glob private-lib pattern %s\n", fname); exit(1); } + EUID_ROOT(); size_t j; for (j = 0; j < globbuf.gl_pathc; j++) { assert(globbuf.gl_pathv[j]); diff --git a/src/firejail/fs_whitelist.c b/src/firejail/fs_whitelist.c index ec3fe4c5b..370035a4d 100644 --- a/src/firejail/fs_whitelist.c +++ b/src/firejail/fs_whitelist.c @@ -257,6 +257,7 @@ static void whitelist_symlink(const char *link, const char *target) { } static void globbing(const char *pattern) { + EUID_ASSERT(); assert(pattern); // globbing diff --git a/src/firejail/macros.c b/src/firejail/macros.c index bcac1feb4..cd29d8f85 100644 --- a/src/firejail/macros.c +++ b/src/firejail/macros.c @@ -149,6 +149,7 @@ static char *resolve_xdg(const char *var) { // returns mallocated memory static char *resolve_hardcoded(char *entries[]) { + EUID_ASSERT(); char *fname; struct stat s; diff --git a/src/firejail/mountinfo.c b/src/firejail/mountinfo.c index a700729d3..64a94bd84 100644 --- a/src/firejail/mountinfo.c +++ b/src/firejail/mountinfo.c @@ -22,7 +22,7 @@ #include #ifndef O_PATH -# define O_PATH 010000000 +#define O_PATH 010000000 #endif #define MAX_BUF 4096 @@ -153,6 +153,7 @@ MountData *get_last_mount(void) { // Extract the mount id from /proc/self/fdinfo and return it. int get_mount_id(const char *path) { + EUID_ASSERT(); assert(path); int fd = open(path, O_PATH|O_CLOEXEC); @@ -162,7 +163,9 @@ int get_mount_id(const char *path) { char *fdinfo; if (asprintf(&fdinfo, "/proc/self/fdinfo/%d", fd) == -1) errExit("asprintf"); + EUID_ROOT(); FILE *fp = fopen(fdinfo, "re"); + EUID_USER(); free(fdinfo); if (!fp) goto errexit; diff --git a/src/firejail/paths.c b/src/firejail/paths.c index b800fa944..d58a9d272 100644 --- a/src/firejail/paths.c +++ b/src/firejail/paths.c @@ -136,7 +136,7 @@ int program_in_path(const char *program) { // ('x' permission means something different for directories). // exec follows symlinks, so use stat, not lstat. struct stat st; - if (stat(scratch, &st)) { + if (stat_as_user(scratch, &st)) { perror(scratch); exit(1); } diff --git a/src/firejail/sbox.c b/src/firejail/sbox.c index d2c0bcc19..37111324a 100644 --- a/src/firejail/sbox.c +++ b/src/firejail/sbox.c @@ -265,7 +265,6 @@ int sbox_run(unsigned filtermask, int num, ...) { } int sbox_run_v(unsigned filtermask, char * const arg[]) { - EUID_ROOT(); assert(arg); if (arg_debug) { @@ -285,6 +284,7 @@ int sbox_run_v(unsigned filtermask, char * const arg[]) { if (child < 0) errExit("fork"); if (child == 0) { + EUID_ROOT(); sbox_do_exec_v(filtermask, arg); } diff --git a/src/firejail/util.c b/src/firejail/util.c index 44f1cbd02..b8643ff60 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c @@ -417,6 +417,13 @@ int is_dir(const char *fname) { if (*fname == '\0') return 0; + int called_as_root = 0; + if (geteuid() == 0) + called_as_root = 1; + + if (called_as_root) + EUID_USER(); + // if fname doesn't end in '/', add one int rv; struct stat s; @@ -432,6 +439,9 @@ int is_dir(const char *fname) { free(tmp); } + if (called_as_root) + EUID_ROOT(); + if (rv == -1) return 0; @@ -447,6 +457,14 @@ int is_link(const char *fname) { if (*fname == '\0') return 0; + int called_as_root = 0; + if (geteuid() == 0) + called_as_root = 1; + + if (called_as_root) + EUID_USER(); + + // remove trailing '/' if any char *tmp = strdup(fname); if (!tmp) errExit("strdup"); @@ -456,9 +474,66 @@ int is_link(const char *fname) { ssize_t rv = readlink(tmp, &c, 1); free(tmp); + if (called_as_root) + EUID_ROOT(); + return (rv != -1); } +char *realpath_as_user(const char *fname) { + assert(fname); + + int called_as_root = 0; + if (geteuid() == 0) + called_as_root = 1; + + if (called_as_root) + EUID_USER(); + + char *rv = realpath(fname, NULL); + + if (called_as_root) + EUID_ROOT(); + + return rv; +} + +int stat_as_user(const char *fname, struct stat *s) { + assert(fname); + + int called_as_root = 0; + if (geteuid() == 0) + called_as_root = 1; + + if (called_as_root) + EUID_USER(); + + int rv = stat(fname, s); + + if (called_as_root) + EUID_ROOT(); + + return rv; +} + +int lstat_as_user(const char *fname, struct stat *s) { + assert(fname); + + int called_as_root = 0; + if (geteuid() == 0) + called_as_root = 1; + + if (called_as_root) + EUID_USER(); + + int rv = lstat(fname, s); + + if (called_as_root) + EUID_ROOT(); + + return rv; +} + // remove all slashes and single dots from the end of a path // for example /foo/bar///././. -> /foo/bar void trim_trailing_slash_or_dot(char *path) { @@ -891,14 +966,13 @@ static int remove_callback(const char *fpath, const struct stat *sb, int typefla int remove_overlay_directory(void) { EUID_ASSERT(); - struct stat s; sleep(1); char *path; if (asprintf(&path, "%s/.firejail", cfg.homedir) == -1) errExit("asprintf"); - if (lstat(path, &s) == 0) { + if (access(path, F_OK) == 0) { pid_t child = fork(); if (child < 0) errExit("fork"); @@ -909,6 +983,7 @@ int remove_overlay_directory(void) { fprintf(stderr, "Error: cannot open %s\n", path); _exit(1); } + struct stat s; if (fstat(fd, &s) == -1) errExit("fstat"); if (!S_ISDIR(s.st_mode)) { @@ -944,7 +1019,7 @@ int remove_overlay_directory(void) { // wait for the child to finish waitpid(child, NULL, 0); // check if ~/.firejail was deleted - if (stat(path, &s) == 0) + if (access(path, F_OK) == 0) return 1; } return 0; @@ -977,9 +1052,8 @@ void flush_stdin(void) { int create_empty_dir_as_user(const char *dir, mode_t mode) { assert(dir); mode &= 07777; - struct stat s; - if (stat(dir, &s)) { + if (access(dir, F_OK) != 0) { if (arg_debug) printf("Creating empty %s directory\n", dir); pid_t child = fork(); @@ -1001,7 +1075,7 @@ int create_empty_dir_as_user(const char *dir, mode_t mode) { _exit(0); } waitpid(child, NULL, 0); - if (stat(dir, &s) == 0) + if (access(dir, F_OK) == 0) return 1; } return 0; @@ -1113,8 +1187,11 @@ unsigned extract_timeout(const char *str) { void disable_file_or_dir(const char *fname) { assert(fname); + assert(geteuid() == 0); + EUID_USER(); int fd = open(fname, O_PATH|O_CLOEXEC); + EUID_ROOT(); if (fd < 0) return; diff --git a/src/firejail/x11.c b/src/firejail/x11.c index afe77e246..09956b903 100644 --- a/src/firejail/x11.c +++ b/src/firejail/x11.c @@ -204,7 +204,6 @@ static int random_display_number(void) { void x11_start_xvfb(int argc, char **argv) { EUID_ASSERT(); int i; - struct stat s; pid_t jail = 0; pid_t server = 0; @@ -348,7 +347,7 @@ void x11_start_xvfb(int argc, char **argv) { // wait for x11 server to start while (++n < 10) { sleep(1); - if (stat(fname, &s) == 0) + if (access(fname, F_OK) == 0) break; }; @@ -427,7 +426,6 @@ static char *extract_setting(int argc, char **argv, const char *argument) { void x11_start_xephyr(int argc, char **argv) { EUID_ASSERT(); int i; - struct stat s; pid_t jail = 0; pid_t server = 0; @@ -586,7 +584,7 @@ void x11_start_xephyr(int argc, char **argv) { // wait for x11 server to start while (++n < 10) { sleep(1); - if (stat(fname, &s) == 0) + if (access(fname, F_OK) == 0) break; }; @@ -701,7 +699,6 @@ static char * get_title_arg_str() { static void __attribute__((noreturn)) x11_start_xpra_old(int argc, char **argv, int display, char *display_str) { EUID_ASSERT(); int i; - struct stat s; pid_t client = 0; pid_t server = 0; @@ -818,7 +815,7 @@ static void __attribute__((noreturn)) x11_start_xpra_old(int argc, char **argv, // wait for x11 server to start while (++n < 10) { sleep(1); - if (stat(fname, &s) == 0) + if (access(fname, F_OK) == 0) break; } @@ -1231,9 +1228,9 @@ void x11_xorg(void) { char *dest; if (asprintf(&dest, "%s/.Xauthority", cfg.homedir) == -1) errExit("asprintf"); - if (lstat(dest, &s) == -1) { + if (access(dest, F_OK) == -1) { touch_file_as_user(dest, 0600); - if (stat(dest, &s) == -1) { + if (access(dest, F_OK) == -1) { fprintf(stderr, "Error: cannot create %s\n", dest); exit(1); } @@ -1292,7 +1289,7 @@ void x11_xorg(void) { // blacklist user .Xauthority file if it is not masked already const char *envar = env_get("XAUTHORITY"); if (envar) { - char *rp = realpath(envar, NULL); + char *rp = realpath_as_user(envar); if (rp) { if (strcmp(rp, dest) != 0) disable_file_or_dir(rp); -- cgit v1.2.3-54-g00ecf