aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar smitsohu <smitsohu@gmail.com>2021-06-26 12:35:48 +0200
committerLibravatar smitsohu <smitsohu@gmail.com>2021-06-26 16:18:52 +0200
commit771dccecba69e134cbf425ad036b2d1fa01f1ccc (patch)
tree957db49aee8e29d9658a71da9fdfc7d4424a499a /src
parentcopy_file_as_user function: drop not needed arguments (diff)
downloadfirejail-771dccecba69e134cbf425ad036b2d1fa01f1ccc.tar.gz
firejail-771dccecba69e134cbf425ad036b2d1fa01f1ccc.tar.zst
firejail-771dccecba69e134cbf425ad036b2d1fa01f1ccc.zip
fs_home.c: improve EUID switching, fix selinux relabeling
Diffstat (limited to 'src')
-rw-r--r--src/firejail/fs_home.c76
-rw-r--r--src/firejail/fs_whitelist.c5
-rw-r--r--src/firejail/sandbox.c2
-rw-r--r--src/firejail/util.c1
-rw-r--r--src/firejail/x11.c6
5 files changed, 61 insertions, 29 deletions
diff --git a/src/firejail/fs_home.c b/src/firejail/fs_home.c
index 04f1a0898..1c4f9e07e 100644
--- a/src/firejail/fs_home.c
+++ b/src/firejail/fs_home.c
@@ -35,11 +35,12 @@
35#endif 35#endif
36 36
37static void skel(const char *homedir) { 37static void skel(const char *homedir) {
38 char *fname; 38 EUID_ASSERT();
39 39
40 // zsh 40 // zsh
41 if (!arg_shell_none && (strcmp(cfg.shell,"/usr/bin/zsh") == 0 || strcmp(cfg.shell,"/bin/zsh") == 0)) { 41 if (!arg_shell_none && (strcmp(cfg.shell,"/usr/bin/zsh") == 0 || strcmp(cfg.shell,"/bin/zsh") == 0)) {
42 // copy skel files 42 // copy skel files
43 char *fname;
43 if (asprintf(&fname, "%s/.zshrc", homedir) == -1) 44 if (asprintf(&fname, "%s/.zshrc", homedir) == -1)
44 errExit("asprintf"); 45 errExit("asprintf");
45 // don't copy it if we already have the file 46 // don't copy it if we already have the file
@@ -64,6 +65,7 @@ static void skel(const char *homedir) {
64 // csh 65 // csh
65 else if (!arg_shell_none && strcmp(cfg.shell,"/bin/csh") == 0) { 66 else if (!arg_shell_none && strcmp(cfg.shell,"/bin/csh") == 0) {
66 // copy skel files 67 // copy skel files
68 char *fname;
67 if (asprintf(&fname, "%s/.cshrc", homedir) == -1) 69 if (asprintf(&fname, "%s/.cshrc", homedir) == -1)
68 errExit("asprintf"); 70 errExit("asprintf");
69 // don't copy it if we already have the file 71 // don't copy it if we already have the file
@@ -88,6 +90,7 @@ static void skel(const char *homedir) {
88 // bash etc. 90 // bash etc.
89 else { 91 else {
90 // copy skel files 92 // copy skel files
93 char *fname;
91 if (asprintf(&fname, "%s/.bashrc", homedir) == -1) 94 if (asprintf(&fname, "%s/.bashrc", homedir) == -1)
92 errExit("asprintf"); 95 errExit("asprintf");
93 // don't copy it if we already have the file 96 // don't copy it if we already have the file
@@ -108,6 +111,7 @@ static void skel(const char *homedir) {
108} 111}
109 112
110static int store_xauthority(void) { 113static int store_xauthority(void) {
114 EUID_ASSERT();
111 if (arg_x11_block) 115 if (arg_x11_block)
112 return 0; 116 return 0;
113 117
@@ -118,7 +122,7 @@ static int store_xauthority(void) {
118 errExit("asprintf"); 122 errExit("asprintf");
119 123
120 struct stat s; 124 struct stat s;
121 if (lstat_as_user(src, &s) == 0) { 125 if (lstat(src, &s) == 0) {
122 if (S_ISLNK(s.st_mode)) { 126 if (S_ISLNK(s.st_mode)) {
123 fwarning("invalid .Xauthority file\n"); 127 fwarning("invalid .Xauthority file\n");
124 free(src); 128 free(src);
@@ -126,6 +130,7 @@ static int store_xauthority(void) {
126 } 130 }
127 131
128 // create an empty file as root, and change ownership to user 132 // create an empty file as root, and change ownership to user
133 EUID_ROOT();
129 FILE *fp = fopen(dest, "we"); 134 FILE *fp = fopen(dest, "we");
130 if (fp) { 135 if (fp) {
131 fprintf(fp, "\n"); 136 fprintf(fp, "\n");
@@ -134,10 +139,11 @@ static int store_xauthority(void) {
134 } 139 }
135 else 140 else
136 errExit("fopen"); 141 errExit("fopen");
142 EUID_USER();
137 143
138 copy_file_as_user(src, dest, 0600); // regular user 144 copy_file_as_user(src, dest, 0600); // regular user
139 fs_logger2("clone", dest);
140 selinux_relabel_path(dest, src); 145 selinux_relabel_path(dest, src);
146 fs_logger2("clone", dest);
141 free(src); 147 free(src);
142 return 1; // file copied 148 return 1; // file copied
143 } 149 }
@@ -147,6 +153,7 @@ static int store_xauthority(void) {
147} 153}
148 154
149static int store_asoundrc(void) { 155static int store_asoundrc(void) {
156 EUID_ASSERT();
150 if (arg_nosound) 157 if (arg_nosound)
151 return 0; 158 return 0;
152 159
@@ -157,11 +164,11 @@ static int store_asoundrc(void) {
157 errExit("asprintf"); 164 errExit("asprintf");
158 165
159 struct stat s; 166 struct stat s;
160 if (lstat_as_user(src, &s) == 0) { 167 if (lstat(src, &s) == 0) {
161 if (S_ISLNK(s.st_mode)) { 168 if (S_ISLNK(s.st_mode)) {
162 // make sure the real path of the file is inside the home directory 169 // make sure the real path of the file is inside the home directory
163 /* coverity[toctou] */ 170 /* coverity[toctou] */
164 char *rp = realpath_as_user(src); 171 char *rp = realpath(src, NULL);
165 if (!rp) { 172 if (!rp) {
166 fprintf(stderr, "Error: Cannot access %s\n", src); 173 fprintf(stderr, "Error: Cannot access %s\n", src);
167 exit(1); 174 exit(1);
@@ -174,6 +181,7 @@ static int store_asoundrc(void) {
174 } 181 }
175 182
176 // create an empty file as root, and change ownership to user 183 // create an empty file as root, and change ownership to user
184 EUID_ROOT();
177 FILE *fp = fopen(dest, "we"); 185 FILE *fp = fopen(dest, "we");
178 if (fp) { 186 if (fp) {
179 fprintf(fp, "\n"); 187 fprintf(fp, "\n");
@@ -182,10 +190,11 @@ static int store_asoundrc(void) {
182 } 190 }
183 else 191 else
184 errExit("fopen"); 192 errExit("fopen");
193 EUID_USER();
185 194
186 copy_file_as_user(src, dest, 0644); // regular user 195 copy_file_as_user(src, dest, 0644); // regular user
187 selinux_relabel_path(dest, src);
188 fs_logger2("clone", dest); 196 fs_logger2("clone", dest);
197 selinux_relabel_path(dest, src);
189 free(src); 198 free(src);
190 return 1; // file copied 199 return 1; // file copied
191 } 200 }
@@ -195,6 +204,7 @@ static int store_asoundrc(void) {
195} 204}
196 205
197static void copy_xauthority(void) { 206static void copy_xauthority(void) {
207 EUID_ASSERT();
198 // copy XAUTHORITY_FILE in the new home directory 208 // copy XAUTHORITY_FILE in the new home directory
199 char *src = RUN_XAUTHORITY_FILE ; 209 char *src = RUN_XAUTHORITY_FILE ;
200 char *dest; 210 char *dest;
@@ -208,15 +218,17 @@ static void copy_xauthority(void) {
208 } 218 }
209 219
210 copy_file_as_user(src, dest, S_IRUSR | S_IWUSR); // regular user 220 copy_file_as_user(src, dest, S_IRUSR | S_IWUSR); // regular user
211 selinux_relabel_path(dest, src);
212 fs_logger2("clone", dest); 221 fs_logger2("clone", dest);
222 selinux_relabel_path(dest, dest);
213 free(dest); 223 free(dest);
214 224
215 // delete the temporary file 225 EUID_ROOT();
216 unlink(src); 226 unlink(src); // delete the temporary file
227 EUID_USER();
217} 228}
218 229
219static void copy_asoundrc(void) { 230static void copy_asoundrc(void) {
231 EUID_ASSERT();
220 // copy ASOUNDRC_FILE in the new home directory 232 // copy ASOUNDRC_FILE in the new home directory
221 char *src = RUN_ASOUNDRC_FILE ; 233 char *src = RUN_ASOUNDRC_FILE ;
222 char *dest; 234 char *dest;
@@ -230,12 +242,13 @@ static void copy_asoundrc(void) {
230 } 242 }
231 243
232 copy_file_as_user(src, dest, S_IRUSR | S_IWUSR); // regular user 244 copy_file_as_user(src, dest, S_IRUSR | S_IWUSR); // regular user
233 selinux_relabel_path(dest, src);
234 fs_logger2("clone", dest); 245 fs_logger2("clone", dest);
246 selinux_relabel_path(dest, dest);
235 free(dest); 247 free(dest);
236 248
237 // delete the temporary file 249 EUID_ROOT();
238 unlink(src); 250 unlink(src); // delete the temporary file
251 EUID_USER();
239} 252}
240 253
241// private mode (--private=homedir): 254// private mode (--private=homedir):
@@ -248,18 +261,18 @@ void fs_private_homedir(void) {
248 char *private_homedir = cfg.home_private; 261 char *private_homedir = cfg.home_private;
249 assert(homedir); 262 assert(homedir);
250 assert(private_homedir); 263 assert(private_homedir);
251 264 EUID_ASSERT();
252 int xflag = store_xauthority();
253 int aflag = store_asoundrc();
254 265
255 uid_t u = getuid(); 266 uid_t u = getuid();
256 // gid_t g = getgid(); 267 // gid_t g = getgid();
257 268
269 int xflag = store_xauthority();
270 int aflag = store_asoundrc();
271
258 // mount bind private_homedir on top of homedir 272 // mount bind private_homedir on top of homedir
259 if (arg_debug) 273 if (arg_debug)
260 printf("Mount-bind %s on top of %s\n", private_homedir, homedir); 274 printf("Mount-bind %s on top of %s\n", private_homedir, homedir);
261 // get file descriptors for homedir and private_homedir, fails if there is any symlink 275 // get file descriptors for homedir and private_homedir, fails if there is any symlink
262 EUID_USER();
263 int src = safer_openat(-1, private_homedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); 276 int src = safer_openat(-1, private_homedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
264 if (src == -1) 277 if (src == -1)
265 errExit("opening private directory"); 278 errExit("opening private directory");
@@ -287,6 +300,7 @@ void fs_private_homedir(void) {
287 EUID_ROOT(); 300 EUID_ROOT();
288 if (bind_mount_by_fd(src, dst)) 301 if (bind_mount_by_fd(src, dst))
289 errExit("mount bind"); 302 errExit("mount bind");
303 EUID_USER();
290 304
291 // check /proc/self/mountinfo to confirm the mount is ok 305 // check /proc/self/mountinfo to confirm the mount is ok
292 MountData *mptr = get_last_mount(); 306 MountData *mptr = get_last_mount();
@@ -305,6 +319,7 @@ void fs_private_homedir(void) {
305// if (chmod(homedir, s.st_mode) == -1) 319// if (chmod(homedir, s.st_mode) == -1)
306// errExit("mount-bind chmod"); 320// errExit("mount-bind chmod");
307 321
322 EUID_ROOT();
308 if (u != 0) { 323 if (u != 0) {
309 // mask /root 324 // mask /root
310 if (arg_debug) 325 if (arg_debug)
@@ -323,6 +338,7 @@ void fs_private_homedir(void) {
323 selinux_relabel_path("/home", "/home"); 338 selinux_relabel_path("/home", "/home");
324 fs_logger("tmpfs /home"); 339 fs_logger("tmpfs /home");
325 } 340 }
341 EUID_USER();
326 342
327 skel(homedir); 343 skel(homedir);
328 if (xflag) 344 if (xflag)
@@ -339,6 +355,7 @@ void fs_private_homedir(void) {
339void fs_private(void) { 355void fs_private(void) {
340 char *homedir = cfg.homedir; 356 char *homedir = cfg.homedir;
341 assert(homedir); 357 assert(homedir);
358 EUID_ASSERT();
342 359
343 uid_t u = getuid(); 360 uid_t u = getuid();
344 gid_t g = getgid(); 361 gid_t g = getgid();
@@ -346,6 +363,7 @@ void fs_private(void) {
346 int xflag = store_xauthority(); 363 int xflag = store_xauthority();
347 int aflag = store_asoundrc(); 364 int aflag = store_asoundrc();
348 365
366 EUID_ROOT();
349 // mask /root 367 // mask /root
350 if (arg_debug) 368 if (arg_debug)
351 printf("Mounting a new /root directory\n"); 369 printf("Mounting a new /root directory\n");
@@ -388,6 +406,7 @@ void fs_private(void) {
388 406
389 selinux_relabel_path(homedir, homedir); 407 selinux_relabel_path(homedir, homedir);
390 } 408 }
409 EUID_USER();
391 410
392 skel(homedir); 411 skel(homedir);
393 if (xflag) 412 if (xflag)
@@ -531,26 +550,29 @@ static void duplicate(char *name) {
531// set skel files, 550// set skel files,
532// restore .Xauthority 551// restore .Xauthority
533void fs_private_home_list(void) { 552void fs_private_home_list(void) {
534 timetrace_start();
535
536 char *homedir = cfg.homedir; 553 char *homedir = cfg.homedir;
537 char *private_list = cfg.home_private_keep; 554 char *private_list = cfg.home_private_keep;
538 assert(homedir); 555 assert(homedir);
539 assert(private_list); 556 assert(private_list);
557 EUID_ASSERT();
540 558
541 int xflag = store_xauthority(); 559 timetrace_start();
542 int aflag = store_asoundrc();
543 560
544 uid_t uid = getuid(); 561 uid_t uid = getuid();
545 gid_t gid = getgid(); 562 gid_t gid = getgid();
546 563
564 int xflag = store_xauthority();
565 int aflag = store_asoundrc();
566
547 // create /run/firejail/mnt/home directory 567 // create /run/firejail/mnt/home directory
568 EUID_ROOT();
548 mkdir_attr(RUN_HOME_DIR, 0755, uid, gid); 569 mkdir_attr(RUN_HOME_DIR, 0755, uid, gid);
549 selinux_relabel_path(RUN_HOME_DIR, homedir); 570 selinux_relabel_path(RUN_HOME_DIR, homedir);
571
550 fs_logger_print(); // save the current log 572 fs_logger_print(); // save the current log
573 EUID_USER();
551 574
552 // copy the list of files in the new home directory 575 // copy the list of files in the new home directory
553 EUID_USER();
554 if (arg_debug) 576 if (arg_debug)
555 printf("Copying files in the new home:\n"); 577 printf("Copying files in the new home:\n");
556 char *dlist = strdup(cfg.home_private_keep); 578 char *dlist = strdup(cfg.home_private_keep);
@@ -589,6 +611,7 @@ void fs_private_home_list(void) {
589 if (bind_mount_path_to_fd(RUN_HOME_DIR, fd)) 611 if (bind_mount_path_to_fd(RUN_HOME_DIR, fd))
590 errExit("mount bind"); 612 errExit("mount bind");
591 close(fd); 613 close(fd);
614 EUID_USER();
592 615
593 // check /proc/self/mountinfo to confirm the mount is ok 616 // check /proc/self/mountinfo to confirm the mount is ok
594 MountData *mptr = get_last_mount(); 617 MountData *mptr = get_last_mount();
@@ -596,11 +619,7 @@ void fs_private_home_list(void) {
596 errLogExit("invalid private-home mount"); 619 errLogExit("invalid private-home mount");
597 fs_logger2("tmpfs", homedir); 620 fs_logger2("tmpfs", homedir);
598 621
599 // mask RUN_HOME_DIR, it is writable and not noexec 622 EUID_ROOT();
600 if (mount("tmpfs", RUN_HOME_DIR, "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME, "mode=755,gid=0") < 0)
601 errExit("mounting tmpfs");
602 fs_logger2("tmpfs", RUN_HOME_DIR);
603
604 if (uid != 0) { 623 if (uid != 0) {
605 // mask /root 624 // mask /root
606 if (arg_debug) 625 if (arg_debug)
@@ -620,6 +639,11 @@ void fs_private_home_list(void) {
620 fs_logger("tmpfs /home"); 639 fs_logger("tmpfs /home");
621 } 640 }
622 641
642 // mask RUN_HOME_DIR, it is writable and not noexec
643 if (mount("tmpfs", RUN_HOME_DIR, "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME, "mode=755,gid=0") < 0)
644 errExit("mounting tmpfs");
645 EUID_USER();
646
623 skel(homedir); 647 skel(homedir);
624 if (xflag) 648 if (xflag)
625 copy_xauthority(); 649 copy_xauthority();
diff --git a/src/firejail/fs_whitelist.c b/src/firejail/fs_whitelist.c
index 370035a4d..7588f69b7 100644
--- a/src/firejail/fs_whitelist.c
+++ b/src/firejail/fs_whitelist.c
@@ -374,9 +374,12 @@ static void tmpfs_topdirs(const TopDir *topdirs) {
374 } 374 }
375 375
376 // user home directory 376 // user home directory
377 if (tmpfs_home) 377 if (tmpfs_home) {
378 // checks owner if outside /home 378 // checks owner if outside /home
379 EUID_USER();
379 fs_private(); 380 fs_private();
381 EUID_ROOT();
382 }
380 383
381 // /run/user/$UID directory 384 // /run/user/$UID directory
382 if (tmpfs_runuser) { 385 if (tmpfs_runuser) {
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c
index e06ba3617..95be3335f 100644
--- a/src/firejail/sandbox.c
+++ b/src/firejail/sandbox.c
@@ -840,6 +840,7 @@ int sandbox(void* sandbox_arg) {
840 // private mode 840 // private mode
841 //**************************** 841 //****************************
842 if (arg_private) { 842 if (arg_private) {
843 EUID_USER();
843 if (cfg.home_private) { // --private= 844 if (cfg.home_private) { // --private=
844 if (cfg.chrootdir) 845 if (cfg.chrootdir)
845 fwarning("private=directory feature is disabled in chroot\n"); 846 fwarning("private=directory feature is disabled in chroot\n");
@@ -858,6 +859,7 @@ int sandbox(void* sandbox_arg) {
858 } 859 }
859 else // --private 860 else // --private
860 fs_private(); 861 fs_private();
862 EUID_ROOT();
861 } 863 }
862 864
863 if (arg_private_dev) 865 if (arg_private_dev)
diff --git a/src/firejail/util.c b/src/firejail/util.c
index 0921736f1..8fcaf3f7b 100644
--- a/src/firejail/util.c
+++ b/src/firejail/util.c
@@ -1231,6 +1231,7 @@ unsigned extract_timeout(const char *str) {
1231} 1231}
1232 1232
1233void disable_file_or_dir(const char *fname) { 1233void disable_file_or_dir(const char *fname) {
1234 assert(geteuid() == 0);
1234 assert(fname); 1235 assert(fname);
1235 1236
1236 EUID_USER(); 1237 EUID_USER();
diff --git a/src/firejail/x11.c b/src/firejail/x11.c
index 0619ff380..896aa2fd3 100644
--- a/src/firejail/x11.c
+++ b/src/firejail/x11.c
@@ -1290,9 +1290,11 @@ void x11_xorg(void) {
1290 if (envar) { 1290 if (envar) {
1291 char *rp = realpath(envar, NULL); 1291 char *rp = realpath(envar, NULL);
1292 if (rp) { 1292 if (rp) {
1293 if (strcmp(rp, dest) != 0) 1293 if (strcmp(rp, dest) != 0) {
1294 // disable_file_or_dir returns with EUID 0 1294 EUID_ROOT();
1295 disable_file_or_dir(rp); 1295 disable_file_or_dir(rp);
1296 EUID_USER();
1297 }
1296 free(rp); 1298 free(rp);
1297 } 1299 }
1298 } 1300 }