aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar smitsohu <smitsohu@gmail.com>2021-06-08 16:00:19 +0200
committerLibravatar smitsohu <smitsohu@gmail.com>2021-06-08 18:15:12 +0200
commit5b921120a3615534b8cfce39090224c1e22edb47 (patch)
tree0852f5402f9785dc1ebdd236eb31a9c40b02adf4
parentrefactor mounting (diff)
downloadfirejail-5b921120a3615534b8cfce39090224c1e22edb47.tar.gz
firejail-5b921120a3615534b8cfce39090224c1e22edb47.tar.zst
firejail-5b921120a3615534b8cfce39090224c1e22edb47.zip
add more EUID switching
always access files under control of the user with effective user id of the user
-rw-r--r--src/firejail/checkcfg.c3
-rw-r--r--src/firejail/chroot.c2
-rw-r--r--src/firejail/firejail.h3
-rw-r--r--src/firejail/fs.c47
-rw-r--r--src/firejail/fs_dev.c2
-rw-r--r--src/firejail/fs_home.c41
-rw-r--r--src/firejail/fs_lib.c7
-rw-r--r--src/firejail/fs_whitelist.c1
-rw-r--r--src/firejail/macros.c1
-rw-r--r--src/firejail/mountinfo.c5
-rw-r--r--src/firejail/paths.c2
-rw-r--r--src/firejail/sbox.c2
-rw-r--r--src/firejail/util.c89
-rw-r--r--src/firejail/x11.c15
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) {
134 *end = '\0'; 134 *end = '\0';
135 135
136 // is the file present? 136 // is the file present?
137 struct stat s; 137 if (access(fname, F_OK) == -1) {
138 if (stat(fname, &s) == -1) {
139 fprintf(stderr, "Error: netfilter-default file %s not available\n", fname); 138 fprintf(stderr, "Error: netfilter-default file %s not available\n", fname);
140 exit(1); 139 exit(1);
141 } 140 }
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) {
219 exit(1); 219 exit(1);
220 } 220 }
221 if (bind_mount_by_fd(src, dst)) 221 if (bind_mount_by_fd(src, dst))
222 errExit("mounting pulseaudio") 222 errExit("mounting pulseaudio");
223 close(src); 223 close(src);
224 close(dst); 224 close(dst);
225 free(pulse); 225 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_
503void touch_file_as_user(const char *fname, mode_t mode); 503void touch_file_as_user(const char *fname, mode_t mode);
504int is_dir(const char *fname); 504int is_dir(const char *fname);
505int is_link(const char *fname); 505int is_link(const char *fname);
506char *realpath_as_user(const char *fname);
507int stat_as_user(const char *fname, struct stat *s);
508int lstat_as_user(const char *fname, struct stat *s);
506void trim_trailing_slash_or_dot(char *path); 509void trim_trailing_slash_or_dot(char *path);
507char *line_remove_spaces(const char *buf); 510char *line_remove_spaces(const char *buf);
508char *split_comma(char *str); 511char *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[] = {
57static void disable_file(OPERATION op, const char *filename) { 57static void disable_file(OPERATION op, const char *filename) {
58 assert(filename); 58 assert(filename);
59 assert(op <OPERATION_MAX); 59 assert(op <OPERATION_MAX);
60 EUID_ASSERT();
60 61
61 // Resolve all symlinks 62 // Resolve all symlinks
62 char* fname = realpath(filename, NULL); 63 char* fname = realpath(filename, NULL);
@@ -74,9 +75,11 @@ static void disable_file(OPERATION op, const char *filename) {
74 return; 75 return;
75 } 76 }
76 77
78 EUID_ROOT();
77 int err = bind_mount_path_to_fd(RUN_RO_DIR, fd); 79 int err = bind_mount_path_to_fd(RUN_RO_DIR, fd);
78 if (err < 0) 80 if (err < 0)
79 err = bind_mount_path_to_fd(RUN_RO_FILE, fd); 81 err = bind_mount_path_to_fd(RUN_RO_FILE, fd);
82 EUID_USER();
80 close(fd); 83 close(fd);
81 84
82 if (err == 0) { 85 if (err == 0) {
@@ -142,6 +145,7 @@ static void disable_file(OPERATION op, const char *filename) {
142 free(fname); 145 free(fname);
143 return; 146 return;
144 } 147 }
148 EUID_ROOT();
145 if (S_ISDIR(s.st_mode)) { 149 if (S_ISDIR(s.st_mode)) {
146 if (bind_mount_path_to_fd(RUN_RO_DIR, fd) < 0) 150 if (bind_mount_path_to_fd(RUN_RO_DIR, fd) < 0)
147 errExit("disable file"); 151 errExit("disable file");
@@ -150,6 +154,7 @@ static void disable_file(OPERATION op, const char *filename) {
150 if (bind_mount_path_to_fd(RUN_RO_FILE, fd) < 0) 154 if (bind_mount_path_to_fd(RUN_RO_FILE, fd) < 0)
151 errExit("disable file"); 155 errExit("disable file");
152 } 156 }
157 EUID_USER();
153 close(fd); 158 close(fd);
154 159
155 if (op == BLACKLIST_FILE) 160 if (op == BLACKLIST_FILE)
@@ -170,8 +175,10 @@ static void disable_file(OPERATION op, const char *filename) {
170 exit(1); 175 exit(1);
171 } 176 }
172 } 177 }
178 // fs_tmpfs returns with EUID 0
173 fs_tmpfs(fname, getuid()); 179 fs_tmpfs(fname, getuid());
174 selinux_relabel_path(fname, fname); 180 selinux_relabel_path(fname, fname);
181 EUID_USER();
175 } 182 }
176 else 183 else
177 fwarning("%s is not a directory; cannot mount a tmpfs on top of it.\n", fname); 184 fwarning("%s is not a directory; cannot mount a tmpfs on top of it.\n", fname);
@@ -191,6 +198,7 @@ static int *nbcheck = NULL;
191// Treat pattern as a shell glob pattern and blacklist matching files 198// Treat pattern as a shell glob pattern and blacklist matching files
192static void globbing(OPERATION op, const char *pattern, const char *noblacklist[], size_t noblacklist_len) { 199static void globbing(OPERATION op, const char *pattern, const char *noblacklist[], size_t noblacklist_len) {
193 assert(pattern); 200 assert(pattern);
201 EUID_ASSERT();
194 202
195#ifdef TEST_NO_BLACKLIST_MATCHING 203#ifdef TEST_NO_BLACKLIST_MATCHING
196 if (nbcheck_start == 0) { 204 if (nbcheck_start == 0) {
@@ -264,6 +272,7 @@ void fs_blacklist(void) {
264 if (noblacklist == NULL) 272 if (noblacklist == NULL)
265 errExit("failed allocating memory for noblacklist entries"); 273 errExit("failed allocating memory for noblacklist entries");
266 274
275 EUID_USER();
267 while (entry) { 276 while (entry) {
268 OPERATION op = OPERATION_MAX; 277 OPERATION op = OPERATION_MAX;
269 char *ptr; 278 char *ptr;
@@ -294,11 +303,13 @@ void fs_blacklist(void) {
294 if (arg_debug) 303 if (arg_debug)
295 printf("Mount-bind %s on top of %s\n", dname1, dname2); 304 printf("Mount-bind %s on top of %s\n", dname1, dname2);
296 // preserve dname2 mode and ownership 305 // preserve dname2 mode and ownership
306 // EUID_ROOT(); - option not accessible to non-root users
297 if (mount(dname1, dname2, NULL, MS_BIND|MS_REC, NULL) < 0) 307 if (mount(dname1, dname2, NULL, MS_BIND|MS_REC, NULL) < 0)
298 errExit("mount bind"); 308 errExit("mount bind");
299 /* coverity[toctou] */ 309 /* coverity[toctou] */
300 if (set_perms(dname2, s.st_uid, s.st_gid,s.st_mode)) 310 if (set_perms(dname2, s.st_uid, s.st_gid,s.st_mode))
301 errExit("set_perms"); 311 errExit("set_perms");
312 // EUID_USER();
302 313
303 entry = entry->next; 314 entry = entry->next;
304 continue; 315 continue;
@@ -376,16 +387,12 @@ void fs_blacklist(void) {
376 op = MOUNT_TMPFS; 387 op = MOUNT_TMPFS;
377 } 388 }
378 else if (strncmp(entry->data, "mkdir ", 6) == 0) { 389 else if (strncmp(entry->data, "mkdir ", 6) == 0) {
379 EUID_USER();
380 fs_mkdir(entry->data + 6); 390 fs_mkdir(entry->data + 6);
381 EUID_ROOT();
382 entry = entry->next; 391 entry = entry->next;
383 continue; 392 continue;
384 } 393 }
385 else if (strncmp(entry->data, "mkfile ", 7) == 0) { 394 else if (strncmp(entry->data, "mkfile ", 7) == 0) {
386 EUID_USER();
387 fs_mkfile(entry->data + 7); 395 fs_mkfile(entry->data + 7);
388 EUID_ROOT();
389 entry = entry->next; 396 entry = entry->next;
390 continue; 397 continue;
391 } 398 }
@@ -441,6 +448,8 @@ void fs_blacklist(void) {
441 for (i = 0; i < noblacklist_c; i++) 448 for (i = 0; i < noblacklist_c; i++)
442 free(noblacklist[i]); 449 free(noblacklist[i]);
443 free(noblacklist); 450 free(noblacklist);
451
452 EUID_ROOT();
444} 453}
445 454
446//*********************************************** 455//***********************************************
@@ -449,6 +458,7 @@ void fs_blacklist(void) {
449 458
450// mount a writable tmpfs on directory; requires a resolved path 459// mount a writable tmpfs on directory; requires a resolved path
451void fs_tmpfs(const char *dir, unsigned check_owner) { 460void fs_tmpfs(const char *dir, unsigned check_owner) {
461 EUID_USER();
452 assert(dir); 462 assert(dir);
453 if (arg_debug) 463 if (arg_debug)
454 printf("Mounting tmpfs on %s, check owner: %s\n", dir, (check_owner)? "yes": "no"); 464 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) {
473 errExit("fstatvfs"); 483 errExit("fstatvfs");
474 unsigned long flags = buf.f_flag & ~(MS_RDONLY|MS_BIND); 484 unsigned long flags = buf.f_flag & ~(MS_RDONLY|MS_BIND);
475 // mount via the symbolic link in /proc/self/fd 485 // mount via the symbolic link in /proc/self/fd
486 EUID_ROOT();
476 char *proc; 487 char *proc;
477 if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1) 488 if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1)
478 errExit("asprintf"); 489 errExit("asprintf");
@@ -490,6 +501,7 @@ void fs_tmpfs(const char *dir, unsigned check_owner) {
490 501
491// remount path, preserving other mount flags; requires a resolved path 502// remount path, preserving other mount flags; requires a resolved path
492static void fs_remount_simple(const char *path, OPERATION op) { 503static void fs_remount_simple(const char *path, OPERATION op) {
504 EUID_ASSERT();
493 assert(path); 505 assert(path);
494 506
495 // open path without following symbolic links 507 // open path without following symbolic links
@@ -555,7 +567,9 @@ static void fs_remount_simple(const char *path, OPERATION op) {
555 567
556 // make path a mount point: 568 // make path a mount point:
557 // mount --bind path path 569 // mount --bind path path
570 EUID_ROOT();
558 int err = bind_mount_by_fd(fd, fd); 571 int err = bind_mount_by_fd(fd, fd);
572 EUID_USER();
559 if (err) { 573 if (err) {
560 close(fd); 574 close(fd);
561 goto out; 575 goto out;
@@ -575,7 +589,9 @@ static void fs_remount_simple(const char *path, OPERATION op) {
575 if (s.st_dev != s2.st_dev || s.st_ino != s2.st_ino) 589 if (s.st_dev != s2.st_dev || s.st_ino != s2.st_ino)
576 errLogExit("invalid %s mount", opstr[op]); 590 errLogExit("invalid %s mount", opstr[op]);
577 591
592 EUID_ROOT();
578 err = remount_by_fd(fd2, flags); 593 err = remount_by_fd(fd2, flags);
594 EUID_USER();
579 close(fd2); 595 close(fd2);
580 if (err) 596 if (err)
581 goto out; 597 goto out;
@@ -599,7 +615,9 @@ out:
599 615
600// remount recursively; requires a resolved path 616// remount recursively; requires a resolved path
601static void fs_remount_rec(const char *dir, OPERATION op) { 617static void fs_remount_rec(const char *dir, OPERATION op) {
618 EUID_ASSERT();
602 assert(dir); 619 assert(dir);
620
603 struct stat s; 621 struct stat s;
604 if (stat(dir, &s) != 0) 622 if (stat(dir, &s) != 0)
605 return; 623 return;
@@ -637,6 +655,9 @@ static void fs_remount_rec(const char *dir, OPERATION op) {
637// resolve a path and remount it 655// resolve a path and remount it
638void fs_remount(const char *path, OPERATION op, int rec) { 656void fs_remount(const char *path, OPERATION op, int rec) {
639 assert(path); 657 assert(path);
658 assert(geteuid() == 0);
659 EUID_USER();
660
640 char *rpath = realpath(path, NULL); 661 char *rpath = realpath(path, NULL);
641 if (rpath) { 662 if (rpath) {
642 if (rec) 663 if (rec)
@@ -645,10 +666,12 @@ void fs_remount(const char *path, OPERATION op, int rec) {
645 fs_remount_simple(rpath, op); 666 fs_remount_simple(rpath, op);
646 free(rpath); 667 free(rpath);
647 } 668 }
669 EUID_ROOT();
648} 670}
649 671
650// Disable /mnt, /media, /run/mount and /run/media access 672// Disable /mnt, /media, /run/mount and /run/media access
651void fs_mnt(const int enforce) { 673void fs_mnt(const int enforce) {
674 EUID_USER();
652 if (enforce) { 675 if (enforce) {
653 // disable-mnt set in firejail.config 676 // disable-mnt set in firejail.config
654 // overriding with noblacklist is not possible in this case 677 // overriding with noblacklist is not possible in this case
@@ -658,13 +681,12 @@ void fs_mnt(const int enforce) {
658 disable_file(BLACKLIST_FILE, "/run/media"); 681 disable_file(BLACKLIST_FILE, "/run/media");
659 } 682 }
660 else { 683 else {
661 EUID_USER();
662 profile_add("blacklist /mnt"); 684 profile_add("blacklist /mnt");
663 profile_add("blacklist /media"); 685 profile_add("blacklist /media");
664 profile_add("blacklist /run/mount"); 686 profile_add("blacklist /run/mount");
665 profile_add("blacklist /run/media"); 687 profile_add("blacklist /run/media");
666 EUID_ROOT();
667 } 688 }
689 EUID_ROOT();
668} 690}
669 691
670 692
@@ -679,7 +701,6 @@ void fs_proc_sys_dev_boot(void) {
679 errExit("mounting /proc/sys"); 701 errExit("mounting /proc/sys");
680 fs_logger("read-only /proc/sys"); 702 fs_logger("read-only /proc/sys");
681 703
682
683 /* Mount a version of /sys that describes the network namespace */ 704 /* Mount a version of /sys that describes the network namespace */
684 if (arg_debug) 705 if (arg_debug)
685 printf("Remounting /sys directory\n"); 706 printf("Remounting /sys directory\n");
@@ -694,13 +715,13 @@ void fs_proc_sys_dev_boot(void) {
694 else 715 else
695 fs_logger("remount /sys"); 716 fs_logger("remount /sys");
696 717
718 EUID_USER();
719
697 disable_file(BLACKLIST_FILE, "/sys/firmware"); 720 disable_file(BLACKLIST_FILE, "/sys/firmware");
698 disable_file(BLACKLIST_FILE, "/sys/hypervisor"); 721 disable_file(BLACKLIST_FILE, "/sys/hypervisor");
699 { // allow user access to some directories in /sys/ by specifying 'noblacklist' option 722 { // allow user access to some directories in /sys/ by specifying 'noblacklist' option
700 EUID_USER();
701 profile_add("blacklist /sys/fs"); 723 profile_add("blacklist /sys/fs");
702 profile_add("blacklist /sys/module"); 724 profile_add("blacklist /sys/module");
703 EUID_ROOT();
704 } 725 }
705 disable_file(BLACKLIST_FILE, "/sys/power"); 726 disable_file(BLACKLIST_FILE, "/sys/power");
706 disable_file(BLACKLIST_FILE, "/sys/kernel/debug"); 727 disable_file(BLACKLIST_FILE, "/sys/kernel/debug");
@@ -744,8 +765,6 @@ void fs_proc_sys_dev_boot(void) {
744 // disable /dev/port 765 // disable /dev/port
745 disable_file(BLACKLIST_FILE, "/dev/port"); 766 disable_file(BLACKLIST_FILE, "/dev/port");
746 767
747
748
749 // disable various ipc sockets in /run/user 768 // disable various ipc sockets in /run/user
750 if (!arg_writable_run_user) { 769 if (!arg_writable_run_user) {
751 char *fname; 770 char *fname;
@@ -778,10 +797,13 @@ void fs_proc_sys_dev_boot(void) {
778 disable_file(BLACKLIST_FILE, "/dev/kmsg"); 797 disable_file(BLACKLIST_FILE, "/dev/kmsg");
779 disable_file(BLACKLIST_FILE, "/proc/kmsg"); 798 disable_file(BLACKLIST_FILE, "/proc/kmsg");
780 } 799 }
800
801 EUID_ROOT();
781} 802}
782 803
783// disable firejail configuration in ~/.config/firejail 804// disable firejail configuration in ~/.config/firejail
784void disable_config(void) { 805void disable_config(void) {
806 EUID_USER();
785 char *fname; 807 char *fname;
786 if (asprintf(&fname, "%s/.config/firejail", cfg.homedir) == -1) 808 if (asprintf(&fname, "%s/.config/firejail", cfg.homedir) == -1)
787 errExit("asprintf"); 809 errExit("asprintf");
@@ -794,6 +816,7 @@ void disable_config(void) {
794 disable_file(BLACKLIST_FILE, RUN_FIREJAIL_NAME_DIR); 816 disable_file(BLACKLIST_FILE, RUN_FIREJAIL_NAME_DIR);
795 disable_file(BLACKLIST_FILE, RUN_FIREJAIL_PROFILE_DIR); 817 disable_file(BLACKLIST_FILE, RUN_FIREJAIL_PROFILE_DIR);
796 disable_file(BLACKLIST_FILE, RUN_FIREJAIL_X11_DIR); 818 disable_file(BLACKLIST_FILE, RUN_FIREJAIL_X11_DIR);
819 EUID_ROOT();
797} 820}
798 821
799 822
@@ -855,6 +878,7 @@ void fs_basic_fs(void) {
855#ifdef HAVE_OVERLAYFS 878#ifdef HAVE_OVERLAYFS
856char *fs_check_overlay_dir(const char *subdirname, int allow_reuse) { 879char *fs_check_overlay_dir(const char *subdirname, int allow_reuse) {
857 assert(subdirname); 880 assert(subdirname);
881 EUID_ASSERT();
858 struct stat s; 882 struct stat s;
859 char *dirname; 883 char *dirname;
860 884
@@ -1214,6 +1238,7 @@ void fs_overlayfs(void) {
1214 1238
1215// this function is called from sandbox.c before blacklist/whitelist functions 1239// this function is called from sandbox.c before blacklist/whitelist functions
1216void fs_private_tmp(void) { 1240void fs_private_tmp(void) {
1241 EUID_ASSERT();
1217 if (arg_debug) 1242 if (arg_debug)
1218 printf("Generate private-tmp whitelist commands\n"); 1243 printf("Generate private-tmp whitelist commands\n");
1219 1244
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) {
187static void process_dev_shm(void) { 187static void process_dev_shm(void) {
188 // Jack audio keeps an Unix socket under (/dev/shm/jack_default_1000_0 or /dev/shm/jack/...) 188 // Jack audio keeps an Unix socket under (/dev/shm/jack_default_1000_0 or /dev/shm/jack/...)
189 // looking for jack socket 189 // looking for jack socket
190 EUID_USER();
190 glob_t globbuf; 191 glob_t globbuf;
191 int globerr = glob(RUN_DEV_DIR "/shm/jack*", GLOB_NOSORT, NULL, &globbuf); 192 int globerr = glob(RUN_DEV_DIR "/shm/jack*", GLOB_NOSORT, NULL, &globbuf);
193 EUID_ROOT();
192 if (globerr && !arg_keep_dev_shm) { 194 if (globerr && !arg_keep_dev_shm) {
193 empty_dev_shm(); 195 empty_dev_shm();
194 return; 196 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) {
42 // copy skel files 42 // copy skel files
43 if (asprintf(&fname, "%s/.zshrc", homedir) == -1) 43 if (asprintf(&fname, "%s/.zshrc", homedir) == -1)
44 errExit("asprintf"); 44 errExit("asprintf");
45 struct stat s;
46 // don't copy it if we already have the file 45 // don't copy it if we already have the file
47 if (stat(fname, &s) == 0) 46 if (access(fname, F_OK) == 0)
48 return; 47 return;
49 if (is_link(fname)) { // stat on dangling symlinks fails, try again using lstat 48 if (is_link(fname)) { // access(3) on dangling symlinks fails, try again using lstat
50 fprintf(stderr, "Error: invalid %s file\n", fname); 49 fprintf(stderr, "Error: invalid %s file\n", fname);
51 exit(1); 50 exit(1);
52 } 51 }
53 if (stat("/etc/skel/.zshrc", &s) == 0) { 52 if (access("/etc/skel/.zshrc", R_OK) == 0) {
54 copy_file_as_user("/etc/skel/.zshrc", fname, u, g, 0644); // regular user 53 copy_file_as_user("/etc/skel/.zshrc", fname, u, g, 0644); // regular user
55 fs_logger("clone /etc/skel/.zshrc"); 54 fs_logger("clone /etc/skel/.zshrc");
56 fs_logger2("clone", fname); 55 fs_logger2("clone", fname);
@@ -67,16 +66,14 @@ static void skel(const char *homedir, uid_t u, gid_t g) {
67 // copy skel files 66 // copy skel files
68 if (asprintf(&fname, "%s/.cshrc", homedir) == -1) 67 if (asprintf(&fname, "%s/.cshrc", homedir) == -1)
69 errExit("asprintf"); 68 errExit("asprintf");
70 struct stat s;
71
72 // don't copy it if we already have the file 69 // don't copy it if we already have the file
73 if (stat(fname, &s) == 0) 70 if (access(fname, F_OK) == 0)
74 return; 71 return;
75 if (is_link(fname)) { // stat on dangling symlinks fails, try again using lstat 72 if (is_link(fname)) { // access(3) on dangling symlinks fails, try again using lstat
76 fprintf(stderr, "Error: invalid %s file\n", fname); 73 fprintf(stderr, "Error: invalid %s file\n", fname);
77 exit(1); 74 exit(1);
78 } 75 }
79 if (stat("/etc/skel/.cshrc", &s) == 0) { 76 if (access("/etc/skel/.cshrc", R_OK) == 0) {
80 copy_file_as_user("/etc/skel/.cshrc", fname, u, g, 0644); // regular user 77 copy_file_as_user("/etc/skel/.cshrc", fname, u, g, 0644); // regular user
81 fs_logger("clone /etc/skel/.cshrc"); 78 fs_logger("clone /etc/skel/.cshrc");
82 fs_logger2("clone", fname); 79 fs_logger2("clone", fname);
@@ -93,15 +90,14 @@ static void skel(const char *homedir, uid_t u, gid_t g) {
93 // copy skel files 90 // copy skel files
94 if (asprintf(&fname, "%s/.bashrc", homedir) == -1) 91 if (asprintf(&fname, "%s/.bashrc", homedir) == -1)
95 errExit("asprintf"); 92 errExit("asprintf");
96 struct stat s;
97 // don't copy it if we already have the file 93 // don't copy it if we already have the file
98 if (stat(fname, &s) == 0) 94 if (access(fname, F_OK) == 0)
99 return; 95 return;
100 if (is_link(fname)) { // stat on dangling symlinks fails, try again using lstat 96 if (is_link(fname)) { // access(3) on dangling symlinks fails, try again using lstat
101 fprintf(stderr, "Error: invalid %s file\n", fname); 97 fprintf(stderr, "Error: invalid %s file\n", fname);
102 exit(1); 98 exit(1);
103 } 99 }
104 if (stat("/etc/skel/.bashrc", &s) == 0) { 100 if (access("/etc/skel/.bashrc", R_OK) == 0) {
105 copy_file_as_user("/etc/skel/.bashrc", fname, u, g, 0644); // regular user 101 copy_file_as_user("/etc/skel/.bashrc", fname, u, g, 0644); // regular user
106 fs_logger("clone /etc/skel/.bashrc"); 102 fs_logger("clone /etc/skel/.bashrc");
107 fs_logger2("clone", fname); 103 fs_logger2("clone", fname);
@@ -122,8 +118,8 @@ static int store_xauthority(void) {
122 errExit("asprintf"); 118 errExit("asprintf");
123 119
124 struct stat s; 120 struct stat s;
125 if (stat(src, &s) == 0) { 121 if (lstat_as_user(src, &s) == 0) {
126 if (is_link(src)) { 122 if (S_ISLNK(s.st_mode)) {
127 fwarning("invalid .Xauthority file\n"); 123 fwarning("invalid .Xauthority file\n");
128 free(src); 124 free(src);
129 return 0; 125 return 0;
@@ -161,11 +157,11 @@ static int store_asoundrc(void) {
161 errExit("asprintf"); 157 errExit("asprintf");
162 158
163 struct stat s; 159 struct stat s;
164 if (stat(src, &s) == 0) { 160 if (lstat_as_user(src, &s) == 0) {
165 if (is_link(src)) { 161 if (S_ISLNK(s.st_mode)) {
166 // make sure the real path of the file is inside the home directory 162 // make sure the real path of the file is inside the home directory
167 /* coverity[toctou] */ 163 /* coverity[toctou] */
168 char* rp = realpath(src, NULL); 164 char *rp = realpath_as_user(src);
169 if (!rp) { 165 if (!rp) {
170 fprintf(stderr, "Error: Cannot access %s\n", src); 166 fprintf(stderr, "Error: Cannot access %s\n", src);
171 exit(1); 167 exit(1);
@@ -263,6 +259,7 @@ void fs_private_homedir(void) {
263 if (arg_debug) 259 if (arg_debug)
264 printf("Mount-bind %s on top of %s\n", private_homedir, homedir); 260 printf("Mount-bind %s on top of %s\n", private_homedir, homedir);
265 // get file descriptors for homedir and private_homedir, fails if there is any symlink 261 // get file descriptors for homedir and private_homedir, fails if there is any symlink
262 EUID_USER();
266 int src = safer_openat(-1, private_homedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); 263 int src = safer_openat(-1, private_homedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
267 if (src == -1) 264 if (src == -1)
268 errExit("opening private directory"); 265 errExit("opening private directory");
@@ -287,6 +284,7 @@ void fs_private_homedir(void) {
287 exit(1); 284 exit(1);
288 } 285 }
289 // mount via the links in /proc/self/fd 286 // mount via the links in /proc/self/fd
287 EUID_ROOT();
290 if (bind_mount_by_fd(src, dst)) 288 if (bind_mount_by_fd(src, dst))
291 errExit("mount bind"); 289 errExit("mount bind");
292 290
@@ -433,6 +431,7 @@ void fs_check_private_cwd(const char *dir) {
433// --private-home 431// --private-home
434//*********************************************************************************** 432//***********************************************************************************
435static char *check_dir_or_file(const char *name) { 433static char *check_dir_or_file(const char *name) {
434 EUID_ASSERT();
436 assert(name); 435 assert(name);
437 436
438 // basic checks 437 // basic checks
@@ -493,6 +492,7 @@ errexit:
493} 492}
494 493
495static void duplicate(char *name) { 494static void duplicate(char *name) {
495 EUID_ASSERT();
496 char *fname = check_dir_or_file(name); 496 char *fname = check_dir_or_file(name);
497 497
498 if (arg_debug) 498 if (arg_debug)
@@ -548,10 +548,10 @@ void fs_private_home_list(void) {
548 selinux_relabel_path(RUN_HOME_DIR, homedir); 548 selinux_relabel_path(RUN_HOME_DIR, homedir);
549 fs_logger_print(); // save the current log 549 fs_logger_print(); // save the current log
550 550
551 // copy the list of files in the new home directory
552 EUID_USER();
551 if (arg_debug) 553 if (arg_debug)
552 printf("Copying files in the new home:\n"); 554 printf("Copying files in the new home:\n");
553
554 // copy the list of files in the new home directory
555 char *dlist = strdup(cfg.home_private_keep); 555 char *dlist = strdup(cfg.home_private_keep);
556 if (!dlist) 556 if (!dlist)
557 errExit("strdup"); 557 errExit("strdup");
@@ -584,6 +584,7 @@ void fs_private_home_list(void) {
584 exit(1); 584 exit(1);
585 } 585 }
586 // mount using the file descriptor 586 // mount using the file descriptor
587 EUID_ROOT();
587 if (bind_mount_path_to_fd(RUN_HOME_DIR, fd)) 588 if (bind_mount_path_to_fd(RUN_HOME_DIR, fd))
588 errExit("mount bind"); 589 errExit("mount bind");
589 close(fd); 590 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) {
178 178
179 if (*full_path == '\0' || 179 if (*full_path == '\0' ||
180 !valid_full_path(full_path) || 180 !valid_full_path(full_path) ||
181 access(full_path, F_OK) != 0 || 181 stat_as_user(full_path, &s) != 0 ||
182 stat(full_path, &s) != 0 ||
183 s.st_uid != 0) 182 s.st_uid != 0)
184 return; 183 return;
185 184
@@ -246,7 +245,7 @@ static void load_library(const char *fname) {
246 245
247 // existing file owned by root 246 // existing file owned by root
248 struct stat s; 247 struct stat s;
249 if (!access(fname, F_OK) && stat(fname, &s) == 0 && s.st_uid == 0) { 248 if (stat_as_user(fname, &s) == 0 && s.st_uid == 0) {
250 // load directories, regular 64 bit libraries, and 64 bit executables 249 // load directories, regular 64 bit libraries, and 64 bit executables
251 if (S_ISDIR(s.st_mode)) 250 if (S_ISDIR(s.st_mode))
252 fslib_mount(fname); 251 fslib_mount(fname);
@@ -286,12 +285,14 @@ static void install_list_entry(const char *lib) {
286#define DO_GLOBBING 285#define DO_GLOBBING
287#ifdef DO_GLOBBING 286#ifdef DO_GLOBBING
288 // globbing 287 // globbing
288 EUID_USER();
289 glob_t globbuf; 289 glob_t globbuf;
290 int globerr = glob(fname, GLOB_NOCHECK | GLOB_NOSORT | GLOB_PERIOD, NULL, &globbuf); 290 int globerr = glob(fname, GLOB_NOCHECK | GLOB_NOSORT | GLOB_PERIOD, NULL, &globbuf);
291 if (globerr) { 291 if (globerr) {
292 fprintf(stderr, "Error: failed to glob private-lib pattern %s\n", fname); 292 fprintf(stderr, "Error: failed to glob private-lib pattern %s\n", fname);
293 exit(1); 293 exit(1);
294 } 294 }
295 EUID_ROOT();
295 size_t j; 296 size_t j;
296 for (j = 0; j < globbuf.gl_pathc; j++) { 297 for (j = 0; j < globbuf.gl_pathc; j++) {
297 assert(globbuf.gl_pathv[j]); 298 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) {
257} 257}
258 258
259static void globbing(const char *pattern) { 259static void globbing(const char *pattern) {
260 EUID_ASSERT();
260 assert(pattern); 261 assert(pattern);
261 262
262 // globbing 263 // 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) {
149 149
150// returns mallocated memory 150// returns mallocated memory
151static char *resolve_hardcoded(char *entries[]) { 151static char *resolve_hardcoded(char *entries[]) {
152 EUID_ASSERT();
152 char *fname; 153 char *fname;
153 struct stat s; 154 struct stat s;
154 155
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 @@
22 22
23#include <fcntl.h> 23#include <fcntl.h>
24#ifndef O_PATH 24#ifndef O_PATH
25# define O_PATH 010000000 25#define O_PATH 010000000
26#endif 26#endif
27 27
28#define MAX_BUF 4096 28#define MAX_BUF 4096
@@ -153,6 +153,7 @@ MountData *get_last_mount(void) {
153 153
154// Extract the mount id from /proc/self/fdinfo and return it. 154// Extract the mount id from /proc/self/fdinfo and return it.
155int get_mount_id(const char *path) { 155int get_mount_id(const char *path) {
156 EUID_ASSERT();
156 assert(path); 157 assert(path);
157 158
158 int fd = open(path, O_PATH|O_CLOEXEC); 159 int fd = open(path, O_PATH|O_CLOEXEC);
@@ -162,7 +163,9 @@ int get_mount_id(const char *path) {
162 char *fdinfo; 163 char *fdinfo;
163 if (asprintf(&fdinfo, "/proc/self/fdinfo/%d", fd) == -1) 164 if (asprintf(&fdinfo, "/proc/self/fdinfo/%d", fd) == -1)
164 errExit("asprintf"); 165 errExit("asprintf");
166 EUID_ROOT();
165 FILE *fp = fopen(fdinfo, "re"); 167 FILE *fp = fopen(fdinfo, "re");
168 EUID_USER();
166 free(fdinfo); 169 free(fdinfo);
167 if (!fp) 170 if (!fp)
168 goto errexit; 171 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) {
136 // ('x' permission means something different for directories). 136 // ('x' permission means something different for directories).
137 // exec follows symlinks, so use stat, not lstat. 137 // exec follows symlinks, so use stat, not lstat.
138 struct stat st; 138 struct stat st;
139 if (stat(scratch, &st)) { 139 if (stat_as_user(scratch, &st)) {
140 perror(scratch); 140 perror(scratch);
141 exit(1); 141 exit(1);
142 } 142 }
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, ...) {
265} 265}
266 266
267int sbox_run_v(unsigned filtermask, char * const arg[]) { 267int sbox_run_v(unsigned filtermask, char * const arg[]) {
268 EUID_ROOT();
269 assert(arg); 268 assert(arg);
270 269
271 if (arg_debug) { 270 if (arg_debug) {
@@ -285,6 +284,7 @@ int sbox_run_v(unsigned filtermask, char * const arg[]) {
285 if (child < 0) 284 if (child < 0)
286 errExit("fork"); 285 errExit("fork");
287 if (child == 0) { 286 if (child == 0) {
287 EUID_ROOT();
288 sbox_do_exec_v(filtermask, arg); 288 sbox_do_exec_v(filtermask, arg);
289 } 289 }
290 290
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) {
417 if (*fname == '\0') 417 if (*fname == '\0')
418 return 0; 418 return 0;
419 419
420 int called_as_root = 0;
421 if (geteuid() == 0)
422 called_as_root = 1;
423
424 if (called_as_root)
425 EUID_USER();
426
420 // if fname doesn't end in '/', add one 427 // if fname doesn't end in '/', add one
421 int rv; 428 int rv;
422 struct stat s; 429 struct stat s;
@@ -432,6 +439,9 @@ int is_dir(const char *fname) {
432 free(tmp); 439 free(tmp);
433 } 440 }
434 441
442 if (called_as_root)
443 EUID_ROOT();
444
435 if (rv == -1) 445 if (rv == -1)
436 return 0; 446 return 0;
437 447
@@ -447,6 +457,14 @@ int is_link(const char *fname) {
447 if (*fname == '\0') 457 if (*fname == '\0')
448 return 0; 458 return 0;
449 459
460 int called_as_root = 0;
461 if (geteuid() == 0)
462 called_as_root = 1;
463
464 if (called_as_root)
465 EUID_USER();
466
467 // remove trailing '/' if any
450 char *tmp = strdup(fname); 468 char *tmp = strdup(fname);
451 if (!tmp) 469 if (!tmp)
452 errExit("strdup"); 470 errExit("strdup");
@@ -456,9 +474,66 @@ int is_link(const char *fname) {
456 ssize_t rv = readlink(tmp, &c, 1); 474 ssize_t rv = readlink(tmp, &c, 1);
457 free(tmp); 475 free(tmp);
458 476
477 if (called_as_root)
478 EUID_ROOT();
479
459 return (rv != -1); 480 return (rv != -1);
460} 481}
461 482
483char *realpath_as_user(const char *fname) {
484 assert(fname);
485
486 int called_as_root = 0;
487 if (geteuid() == 0)
488 called_as_root = 1;
489
490 if (called_as_root)
491 EUID_USER();
492
493 char *rv = realpath(fname, NULL);
494
495 if (called_as_root)
496 EUID_ROOT();
497
498 return rv;
499}
500
501int stat_as_user(const char *fname, struct stat *s) {
502 assert(fname);
503
504 int called_as_root = 0;
505 if (geteuid() == 0)
506 called_as_root = 1;
507
508 if (called_as_root)
509 EUID_USER();
510
511 int rv = stat(fname, s);
512
513 if (called_as_root)
514 EUID_ROOT();
515
516 return rv;
517}
518
519int lstat_as_user(const char *fname, struct stat *s) {
520 assert(fname);
521
522 int called_as_root = 0;
523 if (geteuid() == 0)
524 called_as_root = 1;
525
526 if (called_as_root)
527 EUID_USER();
528
529 int rv = lstat(fname, s);
530
531 if (called_as_root)
532 EUID_ROOT();
533
534 return rv;
535}
536
462// remove all slashes and single dots from the end of a path 537// remove all slashes and single dots from the end of a path
463// for example /foo/bar///././. -> /foo/bar 538// for example /foo/bar///././. -> /foo/bar
464void trim_trailing_slash_or_dot(char *path) { 539void trim_trailing_slash_or_dot(char *path) {
@@ -891,14 +966,13 @@ static int remove_callback(const char *fpath, const struct stat *sb, int typefla
891 966
892int remove_overlay_directory(void) { 967int remove_overlay_directory(void) {
893 EUID_ASSERT(); 968 EUID_ASSERT();
894 struct stat s;
895 sleep(1); 969 sleep(1);
896 970
897 char *path; 971 char *path;
898 if (asprintf(&path, "%s/.firejail", cfg.homedir) == -1) 972 if (asprintf(&path, "%s/.firejail", cfg.homedir) == -1)
899 errExit("asprintf"); 973 errExit("asprintf");
900 974
901 if (lstat(path, &s) == 0) { 975 if (access(path, F_OK) == 0) {
902 pid_t child = fork(); 976 pid_t child = fork();
903 if (child < 0) 977 if (child < 0)
904 errExit("fork"); 978 errExit("fork");
@@ -909,6 +983,7 @@ int remove_overlay_directory(void) {
909 fprintf(stderr, "Error: cannot open %s\n", path); 983 fprintf(stderr, "Error: cannot open %s\n", path);
910 _exit(1); 984 _exit(1);
911 } 985 }
986 struct stat s;
912 if (fstat(fd, &s) == -1) 987 if (fstat(fd, &s) == -1)
913 errExit("fstat"); 988 errExit("fstat");
914 if (!S_ISDIR(s.st_mode)) { 989 if (!S_ISDIR(s.st_mode)) {
@@ -944,7 +1019,7 @@ int remove_overlay_directory(void) {
944 // wait for the child to finish 1019 // wait for the child to finish
945 waitpid(child, NULL, 0); 1020 waitpid(child, NULL, 0);
946 // check if ~/.firejail was deleted 1021 // check if ~/.firejail was deleted
947 if (stat(path, &s) == 0) 1022 if (access(path, F_OK) == 0)
948 return 1; 1023 return 1;
949 } 1024 }
950 return 0; 1025 return 0;
@@ -977,9 +1052,8 @@ void flush_stdin(void) {
977int create_empty_dir_as_user(const char *dir, mode_t mode) { 1052int create_empty_dir_as_user(const char *dir, mode_t mode) {
978 assert(dir); 1053 assert(dir);
979 mode &= 07777; 1054 mode &= 07777;
980 struct stat s;
981 1055
982 if (stat(dir, &s)) { 1056 if (access(dir, F_OK) != 0) {
983 if (arg_debug) 1057 if (arg_debug)
984 printf("Creating empty %s directory\n", dir); 1058 printf("Creating empty %s directory\n", dir);
985 pid_t child = fork(); 1059 pid_t child = fork();
@@ -1001,7 +1075,7 @@ int create_empty_dir_as_user(const char *dir, mode_t mode) {
1001 _exit(0); 1075 _exit(0);
1002 } 1076 }
1003 waitpid(child, NULL, 0); 1077 waitpid(child, NULL, 0);
1004 if (stat(dir, &s) == 0) 1078 if (access(dir, F_OK) == 0)
1005 return 1; 1079 return 1;
1006 } 1080 }
1007 return 0; 1081 return 0;
@@ -1113,8 +1187,11 @@ unsigned extract_timeout(const char *str) {
1113 1187
1114void disable_file_or_dir(const char *fname) { 1188void disable_file_or_dir(const char *fname) {
1115 assert(fname); 1189 assert(fname);
1190 assert(geteuid() == 0);
1116 1191
1192 EUID_USER();
1117 int fd = open(fname, O_PATH|O_CLOEXEC); 1193 int fd = open(fname, O_PATH|O_CLOEXEC);
1194 EUID_ROOT();
1118 if (fd < 0) 1195 if (fd < 0)
1119 return; 1196 return;
1120 1197
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) {
204void x11_start_xvfb(int argc, char **argv) { 204void x11_start_xvfb(int argc, char **argv) {
205 EUID_ASSERT(); 205 EUID_ASSERT();
206 int i; 206 int i;
207 struct stat s;
208 pid_t jail = 0; 207 pid_t jail = 0;
209 pid_t server = 0; 208 pid_t server = 0;
210 209
@@ -348,7 +347,7 @@ void x11_start_xvfb(int argc, char **argv) {
348 // wait for x11 server to start 347 // wait for x11 server to start
349 while (++n < 10) { 348 while (++n < 10) {
350 sleep(1); 349 sleep(1);
351 if (stat(fname, &s) == 0) 350 if (access(fname, F_OK) == 0)
352 break; 351 break;
353 }; 352 };
354 353
@@ -427,7 +426,6 @@ static char *extract_setting(int argc, char **argv, const char *argument) {
427void x11_start_xephyr(int argc, char **argv) { 426void x11_start_xephyr(int argc, char **argv) {
428 EUID_ASSERT(); 427 EUID_ASSERT();
429 int i; 428 int i;
430 struct stat s;
431 pid_t jail = 0; 429 pid_t jail = 0;
432 pid_t server = 0; 430 pid_t server = 0;
433 431
@@ -586,7 +584,7 @@ void x11_start_xephyr(int argc, char **argv) {
586 // wait for x11 server to start 584 // wait for x11 server to start
587 while (++n < 10) { 585 while (++n < 10) {
588 sleep(1); 586 sleep(1);
589 if (stat(fname, &s) == 0) 587 if (access(fname, F_OK) == 0)
590 break; 588 break;
591 }; 589 };
592 590
@@ -701,7 +699,6 @@ static char * get_title_arg_str() {
701static void __attribute__((noreturn)) x11_start_xpra_old(int argc, char **argv, int display, char *display_str) { 699static void __attribute__((noreturn)) x11_start_xpra_old(int argc, char **argv, int display, char *display_str) {
702 EUID_ASSERT(); 700 EUID_ASSERT();
703 int i; 701 int i;
704 struct stat s;
705 pid_t client = 0; 702 pid_t client = 0;
706 pid_t server = 0; 703 pid_t server = 0;
707 704
@@ -818,7 +815,7 @@ static void __attribute__((noreturn)) x11_start_xpra_old(int argc, char **argv,
818 // wait for x11 server to start 815 // wait for x11 server to start
819 while (++n < 10) { 816 while (++n < 10) {
820 sleep(1); 817 sleep(1);
821 if (stat(fname, &s) == 0) 818 if (access(fname, F_OK) == 0)
822 break; 819 break;
823 } 820 }
824 821
@@ -1231,9 +1228,9 @@ void x11_xorg(void) {
1231 char *dest; 1228 char *dest;
1232 if (asprintf(&dest, "%s/.Xauthority", cfg.homedir) == -1) 1229 if (asprintf(&dest, "%s/.Xauthority", cfg.homedir) == -1)
1233 errExit("asprintf"); 1230 errExit("asprintf");
1234 if (lstat(dest, &s) == -1) { 1231 if (access(dest, F_OK) == -1) {
1235 touch_file_as_user(dest, 0600); 1232 touch_file_as_user(dest, 0600);
1236 if (stat(dest, &s) == -1) { 1233 if (access(dest, F_OK) == -1) {
1237 fprintf(stderr, "Error: cannot create %s\n", dest); 1234 fprintf(stderr, "Error: cannot create %s\n", dest);
1238 exit(1); 1235 exit(1);
1239 } 1236 }
@@ -1292,7 +1289,7 @@ void x11_xorg(void) {
1292 // blacklist user .Xauthority file if it is not masked already 1289 // blacklist user .Xauthority file if it is not masked already
1293 const char *envar = env_get("XAUTHORITY"); 1290 const char *envar = env_get("XAUTHORITY");
1294 if (envar) { 1291 if (envar) {
1295 char *rp = realpath(envar, NULL); 1292 char *rp = realpath_as_user(envar);
1296 if (rp) { 1293 if (rp) {
1297 if (strcmp(rp, dest) != 0) 1294 if (strcmp(rp, dest) != 0)
1298 disable_file_or_dir(rp); 1295 disable_file_or_dir(rp);