aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar smitsohu <smitsohu@gmail.com>2021-09-29 15:49:52 +0200
committerLibravatar smitsohu <smitsohu@gmail.com>2021-10-01 18:25:18 +0200
commit9e18bf8a10a3b9b948c15853ad716cf8e3673fcf (patch)
tree8ec3c5de5f63ae6975da6862321ef0a11b19d563
parentprivate-lib fixup (diff)
downloadfirejail-9e18bf8a10a3b9b948c15853ad716cf8e3673fcf.tar.gz
firejail-9e18bf8a10a3b9b948c15853ad716cf8e3673fcf.tar.zst
firejail-9e18bf8a10a3b9b948c15853ad716cf8e3673fcf.zip
add more EUID improvements
-rw-r--r--src/fcopy/main.c3
-rw-r--r--src/firejail/fs.c12
-rw-r--r--src/firejail/fs_dev.c2
-rw-r--r--src/firejail/fs_home.c11
-rw-r--r--src/firejail/fs_whitelist.c59
-rw-r--r--src/firejail/sandbox.c2
-rw-r--r--src/firejail/selinux.c21
-rw-r--r--src/firejail/util.c14
8 files changed, 65 insertions, 59 deletions
diff --git a/src/fcopy/main.c b/src/fcopy/main.c
index 31810de9a..f279af89f 100644
--- a/src/fcopy/main.c
+++ b/src/fcopy/main.c
@@ -88,7 +88,8 @@ static void selinux_relabel_path(const char *path, const char *inside_path) {
88 if (arg_debug) 88 if (arg_debug)
89 printf("Relabeling %s as %s (%s)\n", path, inside_path, fcon); 89 printf("Relabeling %s as %s (%s)\n", path, inside_path, fcon);
90 90
91 setfilecon_raw(procfs_path, fcon); 91 if (setfilecon_raw(procfs_path, fcon) != 0 && arg_debug)
92 printf("Cannot relabel %s: %s\n", path, strerror(errno));
92 } 93 }
93 freecon(fcon); 94 freecon(fcon);
94 close: 95 close:
diff --git a/src/firejail/fs.c b/src/firejail/fs.c
index dd4c2139d..6d01b5e5d 100644
--- a/src/firejail/fs.c
+++ b/src/firejail/fs.c
@@ -200,8 +200,6 @@ static void disable_file(OPERATION op, const char *filename) {
200 } 200 }
201 201
202 fs_tmpfs(fname, uid); 202 fs_tmpfs(fname, uid);
203 EUID_USER(); // fs_tmpfs returns with EUID 0
204
205 selinux_relabel_path(fname, fname); 203 selinux_relabel_path(fname, fname);
206 } 204 }
207 else 205 else
@@ -282,6 +280,8 @@ static void globbing(OPERATION op, const char *pattern, const char *noblacklist[
282 280
283// blacklist files or directories by mounting empty files on top of them 281// blacklist files or directories by mounting empty files on top of them
284void fs_blacklist(void) { 282void fs_blacklist(void) {
283 EUID_ASSERT();
284
285 ProfileEntry *entry = cfg.profile; 285 ProfileEntry *entry = cfg.profile;
286 if (!entry) 286 if (!entry)
287 return; 287 return;
@@ -293,7 +293,6 @@ void fs_blacklist(void) {
293 if (noblacklist == NULL) 293 if (noblacklist == NULL)
294 errExit("failed allocating memory for noblacklist entries"); 294 errExit("failed allocating memory for noblacklist entries");
295 295
296 EUID_USER();
297 while (entry) { 296 while (entry) {
298 OPERATION op = OPERATION_MAX; 297 OPERATION op = OPERATION_MAX;
299 char *ptr; 298 char *ptr;
@@ -469,8 +468,6 @@ void fs_blacklist(void) {
469 for (i = 0; i < noblacklist_c; i++) 468 for (i = 0; i < noblacklist_c; i++)
470 free(noblacklist[i]); 469 free(noblacklist[i]);
471 free(noblacklist); 470 free(noblacklist);
472
473 EUID_ROOT();
474} 471}
475 472
476//*********************************************** 473//***********************************************
@@ -479,7 +476,7 @@ void fs_blacklist(void) {
479 476
480// mount a writable tmpfs on directory; requires a resolved path 477// mount a writable tmpfs on directory; requires a resolved path
481void fs_tmpfs(const char *dir, unsigned check_owner) { 478void fs_tmpfs(const char *dir, unsigned check_owner) {
482 EUID_USER(); 479 EUID_ASSERT();
483 assert(dir); 480 assert(dir);
484 if (arg_debug) 481 if (arg_debug)
485 printf("Mounting tmpfs on %s, check owner: %s\n", dir, (check_owner)? "yes": "no"); 482 printf("Mounting tmpfs on %s, check owner: %s\n", dir, (check_owner)? "yes": "no");
@@ -504,12 +501,13 @@ void fs_tmpfs(const char *dir, unsigned check_owner) {
504 errExit("fstatvfs"); 501 errExit("fstatvfs");
505 unsigned long flags = buf.f_flag & ~(MS_RDONLY|MS_BIND|MS_REMOUNT); 502 unsigned long flags = buf.f_flag & ~(MS_RDONLY|MS_BIND|MS_REMOUNT);
506 // mount via the symbolic link in /proc/self/fd 503 // mount via the symbolic link in /proc/self/fd
507 EUID_ROOT();
508 char *proc; 504 char *proc;
509 if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1) 505 if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1)
510 errExit("asprintf"); 506 errExit("asprintf");
507 EUID_ROOT();
511 if (mount("tmpfs", proc, "tmpfs", flags|MS_NOSUID|MS_NODEV, options) < 0) 508 if (mount("tmpfs", proc, "tmpfs", flags|MS_NOSUID|MS_NODEV, options) < 0)
512 errExit("mounting tmpfs"); 509 errExit("mounting tmpfs");
510 EUID_USER();
513 // check the last mount operation 511 // check the last mount operation
514 MountData *mdata = get_last_mount(); 512 MountData *mdata = get_last_mount();
515 if (strcmp(mdata->fstype, "tmpfs") != 0 || strcmp(mdata->dir, dir) != 0) 513 if (strcmp(mdata->fstype, "tmpfs") != 0 || strcmp(mdata->dir, dir) != 0)
diff --git a/src/firejail/fs_dev.c b/src/firejail/fs_dev.c
index 8cc3ecc62..a43b18344 100644
--- a/src/firejail/fs_dev.c
+++ b/src/firejail/fs_dev.c
@@ -330,8 +330,10 @@ void fs_dev_disable_sound(void) {
330 } 330 }
331 331
332 // disable all jack sockets in /dev/shm 332 // disable all jack sockets in /dev/shm
333 EUID_USER();
333 glob_t globbuf; 334 glob_t globbuf;
334 int globerr = glob("/dev/shm/jack*", GLOB_NOSORT, NULL, &globbuf); 335 int globerr = glob("/dev/shm/jack*", GLOB_NOSORT, NULL, &globbuf);
336 EUID_ROOT();
335 if (globerr) 337 if (globerr)
336 return; 338 return;
337 339
diff --git a/src/firejail/fs_home.c b/src/firejail/fs_home.c
index 0ed476063..590337da1 100644
--- a/src/firejail/fs_home.c
+++ b/src/firejail/fs_home.c
@@ -395,14 +395,16 @@ void fs_private(void) {
395 } 395 }
396 if (chown(homedir, u, g) < 0) 396 if (chown(homedir, u, g) < 0)
397 errExit("chown"); 397 errExit("chown");
398
399 fs_logger2("mkdir", homedir); 398 fs_logger2("mkdir", homedir);
400 fs_logger2("tmpfs", homedir); 399 fs_logger2("tmpfs", homedir);
401 } 400 }
402 else 401 else {
403 // mask user home directory 402 // mask user home directory
404 // the directory should be owned by the current user 403 // the directory should be owned by the current user
404 EUID_USER();
405 fs_tmpfs(homedir, 1); 405 fs_tmpfs(homedir, 1);
406 EUID_ROOT();
407 }
406 408
407 selinux_relabel_path(homedir, homedir); 409 selinux_relabel_path(homedir, homedir);
408 } 410 }
@@ -564,12 +566,13 @@ void fs_private_home_list(void) {
564 int xflag = store_xauthority(); 566 int xflag = store_xauthority();
565 int aflag = store_asoundrc(); 567 int aflag = store_asoundrc();
566 568
567 // create /run/firejail/mnt/home directory
568 EUID_ROOT(); 569 EUID_ROOT();
570 // create /run/firejail/mnt/home directory
569 mkdir_attr(RUN_HOME_DIR, 0755, uid, gid); 571 mkdir_attr(RUN_HOME_DIR, 0755, uid, gid);
570 selinux_relabel_path(RUN_HOME_DIR, homedir); 572 selinux_relabel_path(RUN_HOME_DIR, homedir);
571 573
572 fs_logger_print(); // save the current log 574 // save the current log
575 fs_logger_print();
573 EUID_USER(); 576 EUID_USER();
574 577
575 // copy the list of files in the new home directory 578 // copy the list of files in the new home directory
diff --git a/src/firejail/fs_whitelist.c b/src/firejail/fs_whitelist.c
index 943f275de..7afebed1f 100644
--- a/src/firejail/fs_whitelist.c
+++ b/src/firejail/fs_whitelist.c
@@ -105,6 +105,7 @@ static int whitelist_mkpath(const char* path, mode_t mode) {
105} 105}
106 106
107static void whitelist_file(int dirfd, const char *relpath, const char *path) { 107static void whitelist_file(int dirfd, const char *relpath, const char *path) {
108 EUID_ASSERT();
108 assert(relpath && path); 109 assert(relpath && path);
109 110
110 // open mount source, using a file descriptor that refers to the 111 // open mount source, using a file descriptor that refers to the
@@ -130,12 +131,9 @@ static void whitelist_file(int dirfd, const char *relpath, const char *path) {
130 } 131 }
131 132
132 // create mount target as root, except if inside home or run/user/$UID directory 133 // create mount target as root, except if inside home or run/user/$UID directory
133 int userprivs = 0; 134 if ((strncmp(path, cfg.homedir, homedir_len) != 0 || path[homedir_len] != '/') &&
134 if ((strncmp(path, cfg.homedir, homedir_len) == 0 && path[homedir_len] == '/') || 135 (strncmp(path, runuser, runuser_len) != 0 || path[runuser_len] != '/'))
135 (strncmp(path, runuser, runuser_len) == 0 && path[runuser_len] == '/')) { 136 EUID_ROOT();
136 EUID_USER();
137 userprivs = 1;
138 }
139 137
140 // create path of the mount target 138 // create path of the mount target
141 int fd2 = whitelist_mkpath(path, 0755); 139 int fd2 = whitelist_mkpath(path, 0755);
@@ -146,8 +144,7 @@ static void whitelist_file(int dirfd, const char *relpath, const char *path) {
146 if (arg_debug || arg_debug_whitelists) 144 if (arg_debug || arg_debug_whitelists)
147 printf("Debug %d: skip whitelist %s\n", __LINE__, path); 145 printf("Debug %d: skip whitelist %s\n", __LINE__, path);
148 close(fd); 146 close(fd);
149 if (userprivs) 147 EUID_USER();
150 EUID_ROOT();
151 return; 148 return;
152 } 149 }
153 150
@@ -166,8 +163,7 @@ static void whitelist_file(int dirfd, const char *relpath, const char *path) {
166 } 163 }
167 close(fd); 164 close(fd);
168 close(fd2); 165 close(fd2);
169 if (userprivs) 166 EUID_USER();
170 EUID_ROOT();
171 return; 167 return;
172 } 168 }
173 fd3 = openat(fd2, file, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); 169 fd3 = openat(fd2, file, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
@@ -184,19 +180,17 @@ static void whitelist_file(int dirfd, const char *relpath, const char *path) {
184 } 180 }
185 close(fd); 181 close(fd);
186 close(fd2); 182 close(fd2);
187 if (userprivs) 183 EUID_USER();
188 EUID_ROOT();
189 return; 184 return;
190 } 185 }
191
192 close(fd2); 186 close(fd2);
193 if (userprivs)
194 EUID_ROOT();
195 187
196 if (arg_debug || arg_debug_whitelists) 188 if (arg_debug || arg_debug_whitelists)
197 printf("Whitelisting %s\n", path); 189 printf("Whitelisting %s\n", path);
190 EUID_ROOT();
198 if (bind_mount_by_fd(fd, fd3)) 191 if (bind_mount_by_fd(fd, fd3))
199 errExit("mount bind"); 192 errExit("mount bind");
193 EUID_USER();
200 // check the last mount operation 194 // check the last mount operation
201 MountData *mptr = get_last_mount(); // will do exit(1) if the mount cannot be found 195 MountData *mptr = get_last_mount(); // will do exit(1) if the mount cannot be found
202#ifdef TEST_MOUNTINFO 196#ifdef TEST_MOUNTINFO
@@ -219,22 +213,19 @@ static void whitelist_file(int dirfd, const char *relpath, const char *path) {
219} 213}
220 214
221static void whitelist_symlink(const char *link, const char *target) { 215static void whitelist_symlink(const char *link, const char *target) {
216 EUID_ASSERT();
222 assert(link && target); 217 assert(link && target);
223 218
224 // create files as root, except if inside home or run/user/$UID directory 219 // create files as root, except if inside home or run/user/$UID directory
225 int userprivs = 0; 220 if ((strncmp(link, cfg.homedir, homedir_len) != 0 || link[homedir_len] != '/') &&
226 if ((strncmp(link, cfg.homedir, homedir_len) == 0 && link[homedir_len] == '/') || 221 (strncmp(link, runuser, runuser_len) != 0 || link[runuser_len] != '/'))
227 (strncmp(link, runuser, runuser_len) == 0 && link[runuser_len] == '/')) { 222 EUID_ROOT();
228 EUID_USER();
229 userprivs = 1;
230 }
231 223
232 int fd = whitelist_mkpath(link, 0755); 224 int fd = whitelist_mkpath(link, 0755);
233 if (fd == -1) { 225 if (fd == -1) {
234 if (arg_debug || arg_debug_whitelists) 226 if (arg_debug || arg_debug_whitelists)
235 printf("Debug %d: cannot create symbolic link %s\n", __LINE__, link); 227 printf("Debug %d: cannot create symbolic link %s\n", __LINE__, link);
236 if (userprivs) 228 EUID_USER();
237 EUID_ROOT();
238 return; 229 return;
239 } 230 }
240 231
@@ -252,8 +243,7 @@ static void whitelist_symlink(const char *link, const char *target) {
252 printf("Created symbolic link %s -> %s\n", link, target); 243 printf("Created symbolic link %s -> %s\n", link, target);
253 244
254 close(fd); 245 close(fd);
255 if (userprivs) 246 EUID_USER();
256 EUID_ROOT();
257} 247}
258 248
259static void globbing(const char *pattern) { 249static void globbing(const char *pattern) {
@@ -330,10 +320,11 @@ static void tmpfs_topdirs(const TopDir *topdirs) {
330 // init tmpfs 320 // init tmpfs
331 if (strcmp(topdirs[i].path, "/run") == 0) { 321 if (strcmp(topdirs[i].path, "/run") == 0) {
332 // restore /run/firejail directory 322 // restore /run/firejail directory
333 if (mkdir(RUN_FIREJAIL_DIR, 0755) == -1) 323 EUID_ROOT();
334 errExit("mkdir"); 324 mkdir_attr(RUN_FIREJAIL_DIR, 0755, 0, 0);
335 if (bind_mount_fd_to_path(fd, RUN_FIREJAIL_DIR)) 325 if (bind_mount_fd_to_path(fd, RUN_FIREJAIL_DIR))
336 errExit("mount bind"); 326 errExit("mount bind");
327 EUID_USER();
337 close(fd); 328 close(fd);
338 fs_logger2("whitelist", RUN_FIREJAIL_DIR); 329 fs_logger2("whitelist", RUN_FIREJAIL_DIR);
339 330
@@ -351,12 +342,14 @@ static void tmpfs_topdirs(const TopDir *topdirs) {
351 errExit("asprintf"); 342 errExit("asprintf");
352 if (strcmp(env, pamtmpdir) == 0) { 343 if (strcmp(env, pamtmpdir) == 0) {
353 // create empty user-owned /tmp/user/$UID directory 344 // create empty user-owned /tmp/user/$UID directory
345 EUID_ROOT();
354 mkdir_attr("/tmp/user", 0711, 0, 0); 346 mkdir_attr("/tmp/user", 0711, 0, 0);
355 selinux_relabel_path("/tmp/user", "/tmp/user"); 347 selinux_relabel_path("/tmp/user", "/tmp/user");
356 fs_logger("mkdir /tmp/user"); 348 fs_logger("mkdir /tmp/user");
357 mkdir_attr(pamtmpdir, 0700, getuid(), 0); 349 mkdir_attr(pamtmpdir, 0700, getuid(), 0);
358 selinux_relabel_path(pamtmpdir, pamtmpdir); 350 selinux_relabel_path(pamtmpdir, pamtmpdir);
359 fs_logger2("mkdir", pamtmpdir); 351 fs_logger2("mkdir", pamtmpdir);
352 EUID_USER();
360 } 353 }
361 free(pamtmpdir); 354 free(pamtmpdir);
362 } 355 }
@@ -374,11 +367,8 @@ static void tmpfs_topdirs(const TopDir *topdirs) {
374 } 367 }
375 368
376 // user home directory 369 // user home directory
377 if (tmpfs_home) { 370 if (tmpfs_home)
378 EUID_USER();
379 fs_private(); // checks owner if outside /home 371 fs_private(); // checks owner if outside /home
380 EUID_ROOT();
381 }
382 372
383 // /run/user/$UID directory 373 // /run/user/$UID directory
384 if (tmpfs_runuser) { 374 if (tmpfs_runuser) {
@@ -402,6 +392,7 @@ static int reject_topdir(const char *dir) {
402// keep track of whitelist top level directories by adding them to an array 392// keep track of whitelist top level directories by adding them to an array
403// open each directory 393// open each directory
404static TopDir *add_topdir(const char *dir, TopDir *topdirs, const char *path) { 394static TopDir *add_topdir(const char *dir, TopDir *topdirs, const char *path) {
395 EUID_ASSERT();
405 assert(dir && path); 396 assert(dir && path);
406 397
407 // /proc and /sys are not allowed 398 // /proc and /sys are not allowed
@@ -516,6 +507,8 @@ static char *extract_topdir(const char *path) {
516} 507}
517 508
518void fs_whitelist(void) { 509void fs_whitelist(void) {
510 EUID_ASSERT();
511
519 ProfileEntry *entry = cfg.profile; 512 ProfileEntry *entry = cfg.profile;
520 if (!entry) 513 if (!entry)
521 return; 514 return;
@@ -536,7 +529,6 @@ void fs_whitelist(void) {
536 errExit("calloc"); 529 errExit("calloc");
537 530
538 // verify whitelist files, extract symbolic links, etc. 531 // verify whitelist files, extract symbolic links, etc.
539 EUID_USER();
540 while (entry) { 532 while (entry) {
541 int nowhitelist_flag = 0; 533 int nowhitelist_flag = 0;
542 534
@@ -630,7 +622,7 @@ void fs_whitelist(void) {
630 if (!fname) { 622 if (!fname) {
631 if (arg_debug || arg_debug_whitelists) { 623 if (arg_debug || arg_debug_whitelists) {
632 printf("Removed path: %s\n", entry->data); 624 printf("Removed path: %s\n", entry->data);
633 printf("\texpanded: %s\n", new_name); 625 printf("\tnew_name: %s\n", new_name);
634 printf("\trealpath: (null)\n"); 626 printf("\trealpath: (null)\n");
635 printf("\t%s\n", strerror(errno)); 627 printf("\t%s\n", strerror(errno));
636 } 628 }
@@ -712,7 +704,6 @@ void fs_whitelist(void) {
712 free(nowhitelist); 704 free(nowhitelist);
713 705
714 // mount tmpfs on all top level directories 706 // mount tmpfs on all top level directories
715 EUID_ROOT();
716 tmpfs_topdirs(topdirs); 707 tmpfs_topdirs(topdirs);
717 708
718 // go through profile rules again, and interpret whitelist commands 709 // go through profile rules again, and interpret whitelist commands
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c
index 995827fb7..83e50aee2 100644
--- a/src/firejail/sandbox.c
+++ b/src/firejail/sandbox.c
@@ -1004,10 +1004,12 @@ int sandbox(void* sandbox_arg) {
1004 // apply the profile file 1004 // apply the profile file
1005 //**************************** 1005 //****************************
1006 // apply all whitelist commands ... 1006 // apply all whitelist commands ...
1007 EUID_USER();
1007 fs_whitelist(); 1008 fs_whitelist();
1008 1009
1009 // ... followed by blacklist commands 1010 // ... followed by blacklist commands
1010 fs_blacklist(); // mkdir and mkfile are processed all over again 1011 fs_blacklist(); // mkdir and mkfile are processed all over again
1012 EUID_ROOT();
1011 1013
1012 //**************************** 1014 //****************************
1013 // nosound/no3d/notv/novideo and fix for pulseaudio 7.0 1015 // nosound/no3d/notv/novideo and fix for pulseaudio 7.0
diff --git a/src/firejail/selinux.c b/src/firejail/selinux.c
index 6969e7a3d..fa59882ed 100644
--- a/src/firejail/selinux.c
+++ b/src/firejail/selinux.c
@@ -21,6 +21,7 @@
21#include "firejail.h" 21#include "firejail.h"
22#include <sys/types.h> 22#include <sys/types.h>
23#include <sys/stat.h> 23#include <sys/stat.h>
24#include <errno.h>
24 25
25#include <fcntl.h> 26#include <fcntl.h>
26#ifndef O_PATH 27#ifndef O_PATH
@@ -57,7 +58,17 @@ void selinux_relabel_path(const char *path, const char *inside_path)
57 58
58 /* Open the file as O_PATH, to pin it while we determine and adjust the label 59 /* Open the file as O_PATH, to pin it while we determine and adjust the label
59 * Defeat symlink races by not allowing symbolic links */ 60 * Defeat symlink races by not allowing symbolic links */
61 int called_as_root = 0;
62 if (geteuid() == 0)
63 called_as_root = 1;
64 if (called_as_root)
65 EUID_USER();
66
60 fd = safer_openat(-1, path, O_NOFOLLOW|O_CLOEXEC|O_PATH); 67 fd = safer_openat(-1, path, O_NOFOLLOW|O_CLOEXEC|O_PATH);
68
69 if (called_as_root)
70 EUID_ROOT();
71
61 if (fd < 0) 72 if (fd < 0)
62 return; 73 return;
63 if (fstat(fd, &st) < 0) 74 if (fstat(fd, &st) < 0)
@@ -68,8 +79,16 @@ void selinux_relabel_path(const char *path, const char *inside_path)
68 if (arg_debug) 79 if (arg_debug)
69 printf("Relabeling %s as %s (%s)\n", path, inside_path, fcon); 80 printf("Relabeling %s as %s (%s)\n", path, inside_path, fcon);
70 81
71 setfilecon_raw(procfs_path, fcon); 82 if (!called_as_root)
83 EUID_ROOT();
84
85 if (setfilecon_raw(procfs_path, fcon) != 0 && arg_debug)
86 printf("Cannot relabel %s: %s\n", path, strerror(errno));
87
88 if (!called_as_root)
89 EUID_USER();
72 } 90 }
91
73 freecon(fcon); 92 freecon(fcon);
74 close: 93 close:
75 close(fd); 94 close(fd);
diff --git a/src/firejail/util.c b/src/firejail/util.c
index 094a68c60..f0df45eb2 100644
--- a/src/firejail/util.c
+++ b/src/firejail/util.c
@@ -459,31 +459,21 @@ int is_dir(const char *fname) {
459 if (*fname == '\0') 459 if (*fname == '\0')
460 return 0; 460 return 0;
461 461
462 int called_as_root = 0;
463 if (geteuid() == 0)
464 called_as_root = 1;
465
466 if (called_as_root)
467 EUID_USER();
468
469 // if fname doesn't end in '/', add one 462 // if fname doesn't end in '/', add one
470 int rv; 463 int rv;
471 struct stat s; 464 struct stat s;
472 if (fname[strlen(fname) - 1] == '/') 465 if (fname[strlen(fname) - 1] == '/')
473 rv = stat(fname, &s); 466 rv = stat_as_user(fname, &s);
474 else { 467 else {
475 char *tmp; 468 char *tmp;
476 if (asprintf(&tmp, "%s/", fname) == -1) { 469 if (asprintf(&tmp, "%s/", fname) == -1) {
477 fprintf(stderr, "Error: cannot allocate memory, %s:%d\n", __FILE__, __LINE__); 470 fprintf(stderr, "Error: cannot allocate memory, %s:%d\n", __FILE__, __LINE__);
478 errExit("asprintf"); 471 errExit("asprintf");
479 } 472 }
480 rv = stat(tmp, &s); 473 rv = stat_as_user(tmp, &s);
481 free(tmp); 474 free(tmp);
482 } 475 }
483 476
484 if (called_as_root)
485 EUID_ROOT();
486
487 if (rv == -1) 477 if (rv == -1)
488 return 0; 478 return 0;
489 479