aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar netblue30 <netblue30@yahoo.com>2015-11-09 06:49:12 -0500
committerLibravatar netblue30 <netblue30@yahoo.com>2015-11-09 06:49:12 -0500
commitb2671e94086fb123698a556e96c2a7ec1ceb6f36 (patch)
tree0f8d85e6888163daadf4605d720ddabe49cc3f78 /src
parentmove firejail directory form /tmp to /run (diff)
downloadfirejail-b2671e94086fb123698a556e96c2a7ec1ceb6f36.tar.gz
firejail-b2671e94086fb123698a556e96c2a7ec1ceb6f36.tar.zst
firejail-b2671e94086fb123698a556e96c2a7ec1ceb6f36.zip
fix for broken --tmpfs=/tmp
Diffstat (limited to 'src')
-rw-r--r--src/firejail/fs.c99
1 files changed, 47 insertions, 52 deletions
diff --git a/src/firejail/fs.c b/src/firejail/fs.c
index ca44a2d5d..56aab8871 100644
--- a/src/firejail/fs.c
+++ b/src/firejail/fs.c
@@ -27,6 +27,35 @@
27#include <fcntl.h> 27#include <fcntl.h>
28#include <errno.h> 28#include <errno.h>
29 29
30static void create_empty_dir(void) {
31 struct stat s;
32
33 if (stat(RO_DIR, &s)) {
34 /* coverity[toctou] */
35 int rv = mkdir(RO_DIR, S_IRUSR | S_IXUSR);
36 if (rv == -1)
37 errExit("mkdir");
38 if (chown(RO_DIR, 0, 0) < 0)
39 errExit("chown");
40 }
41}
42
43static void create_empty_file(void) {
44 struct stat s;
45
46 if (stat(RO_FILE, &s)) {
47 /* coverity[toctou] */
48 FILE *fp = fopen(RO_FILE, "w");
49 if (!fp)
50 errExit("fopen");
51 fclose(fp);
52 if (chown(RO_FILE, 0, 0) < 0)
53 errExit("chown");
54 if (chmod(RO_FILE, S_IRUSR) < 0)
55 errExit("chown");
56 }
57}
58
30// build /tmp/firejail directory 59// build /tmp/firejail directory
31void fs_build_firejail_dir(void) { 60void fs_build_firejail_dir(void) {
32 struct stat s; 61 struct stat s;
@@ -49,6 +78,9 @@ void fs_build_firejail_dir(void) {
49 exit(1); 78 exit(1);
50 } 79 }
51 } 80 }
81
82 create_empty_dir();
83 create_empty_file();
52} 84}
53 85
54 86
@@ -126,47 +158,16 @@ typedef enum {
126} OPERATION; 158} OPERATION;
127 159
128 160
129static char *create_empty_dir(void) {
130 struct stat s;
131 fs_build_firejail_dir();
132
133 if (stat(RO_DIR, &s)) {
134 /* coverity[toctou] */
135 int rv = mkdir(RO_DIR, S_IRUSR | S_IXUSR);
136 if (rv == -1)
137 errExit("mkdir");
138 if (chown(RO_DIR, 0, 0) < 0)
139 errExit("chown");
140 }
141
142 return RO_DIR;
143}
144 161
145static char *create_empty_file(void) {
146 struct stat s;
147 fs_build_firejail_dir();
148
149 if (stat(RO_FILE, &s)) {
150 /* coverity[toctou] */
151 FILE *fp = fopen(RO_FILE, "w");
152 if (!fp)
153 errExit("fopen");
154 fclose(fp);
155 if (chown(RO_FILE, 0, 0) < 0)
156 errExit("chown");
157 if (chmod(RO_FILE, S_IRUSR) < 0)
158 errExit("chown");
159 }
160
161 return RO_FILE;
162}
163 162
164static void disable_file(OPERATION op, const char *filename, const char *emptydir, const char *emptyfile) { 163static void disable_file(OPERATION op, const char *filename) {
165 assert(filename); 164 assert(filename);
166 assert(emptydir);
167 assert(emptyfile);
168 assert(op <OPERATION_MAX); 165 assert(op <OPERATION_MAX);
169 166
167
168 // rebuild /run/firejail directory in case tmpfs was mounted on top of /run
169 fs_build_firejail_dir();
170
170 // Resolve all symlinks 171 // Resolve all symlinks
171 char* fname = realpath(filename, NULL); 172 char* fname = realpath(filename, NULL);
172 if (fname == NULL) { 173 if (fname == NULL) {
@@ -196,11 +197,11 @@ static void disable_file(OPERATION op, const char *filename, const char *emptydi
196 if (arg_debug) 197 if (arg_debug)
197 printf("Disable %s\n", fname); 198 printf("Disable %s\n", fname);
198 if (S_ISDIR(s.st_mode)) { 199 if (S_ISDIR(s.st_mode)) {
199 if (mount(emptydir, fname, "none", MS_BIND, "mode=400,gid=0") < 0) 200 if (mount(RO_DIR, fname, "none", MS_BIND, "mode=400,gid=0") < 0)
200 errExit("disable file"); 201 errExit("disable file");
201 } 202 }
202 else { 203 else {
203 if (mount(emptyfile, fname, "none", MS_BIND, "mode=400,gid=0") < 0) 204 if (mount(RO_FILE, fname, "none", MS_BIND, "mode=400,gid=0") < 0)
204 errExit("disable file"); 205 errExit("disable file");
205 } 206 }
206 } 207 }
@@ -231,10 +232,8 @@ static void disable_file(OPERATION op, const char *filename, const char *emptydi
231} 232}
232 233
233// Treat pattern as a shell glob pattern and blacklist matching files 234// Treat pattern as a shell glob pattern and blacklist matching files
234static void globbing(OPERATION op, const char *pattern, const char *noblacklist[], size_t noblacklist_len, const char *emptydir, const char *emptyfile) { 235static void globbing(OPERATION op, const char *pattern, const char *noblacklist[], size_t noblacklist_len) {
235 assert(pattern); 236 assert(pattern);
236 assert(emptydir);
237 assert(emptyfile);
238 237
239 glob_t globbuf; 238 glob_t globbuf;
240 // Profiles contain blacklists for files that might not exist on a user's machine. 239 // Profiles contain blacklists for files that might not exist on a user's machine.
@@ -269,7 +268,7 @@ static void globbing(OPERATION op, const char *pattern, const char *noblacklist[
269 } 268 }
270 } 269 }
271 if (okay_to_blacklist) 270 if (okay_to_blacklist)
272 disable_file(op, path, emptydir, emptyfile); 271 disable_file(op, path);
273 } 272 }
274 globfree(&globbuf); 273 globfree(&globbuf);
275} 274}
@@ -283,9 +282,6 @@ void fs_blacklist(void) {
283 if (!entry) 282 if (!entry)
284 return; 283 return;
285 284
286 char *emptydir = create_empty_dir();
287 char *emptyfile = create_empty_file();
288
289 // a statically allocated buffer works for all current needs 285 // a statically allocated buffer works for all current needs
290 // TODO: if dynamic allocation is ever needed, we should probably add 286 // TODO: if dynamic allocation is ever needed, we should probably add
291 // libraries that make it easy to do without introducing security bugs 287 // libraries that make it easy to do without introducing security bugs
@@ -385,11 +381,11 @@ void fs_blacklist(void) {
385 for (path = &paths[0]; *path; path++) { 381 for (path = &paths[0]; *path; path++) {
386 char newname[strlen(*path) + fname_len + 1]; 382 char newname[strlen(*path) + fname_len + 1];
387 sprintf(newname, "%s%s", *path, fname); 383 sprintf(newname, "%s%s", *path, fname);
388 globbing(op, newname, (const char**)noblacklist, noblacklist_c, emptydir, emptyfile); 384 globbing(op, newname, (const char**)noblacklist, noblacklist_c);
389 } 385 }
390 } 386 }
391 else 387 else
392 globbing(op, ptr, (const char**)noblacklist, noblacklist_c, emptydir, emptyfile); 388 globbing(op, ptr, (const char**)noblacklist, noblacklist_c);
393 } 389 }
394 390
395 if (new_name) 391 if (new_name)
@@ -516,10 +512,10 @@ void fs_proc_sys_dev_boot(void) {
516 fs_rdonly_noexit("/proc/bus"); 512 fs_rdonly_noexit("/proc/bus");
517 513
518 // disable /proc/kcore 514 // disable /proc/kcore
519 disable_file(BLACKLIST_FILE, "/proc/kcore", "not used", "/dev/null"); 515 disable_file(BLACKLIST_FILE, "/proc/kcore");
520 516
521 // disable /proc/kallsyms 517 // disable /proc/kallsyms
522 disable_file(BLACKLIST_FILE, "/proc/kallsyms", "not used", "/dev/null"); 518 disable_file(BLACKLIST_FILE, "/proc/kallsyms");
523 519
524 // disable /boot 520 // disable /boot
525 if (stat("/boot", &s) == 0) { 521 if (stat("/boot", &s) == 0) {
@@ -531,7 +527,7 @@ void fs_proc_sys_dev_boot(void) {
531 527
532 // disable /dev/port 528 // disable /dev/port
533 if (stat("/dev/port", &s) == 0) { 529 if (stat("/dev/port", &s) == 0) {
534 disable_file(BLACKLIST_FILE, "/dev/port", "not used", "/dev/null"); 530 disable_file(BLACKLIST_FILE, "/dev/port");
535 } 531 }
536} 532}
537 533
@@ -542,7 +538,6 @@ static void sanitize_home(void) {
542 if (d == NULL) 538 if (d == NULL)
543 return; 539 return;
544 540
545 char *emptydir = create_empty_dir();
546 while ((dir = readdir(d))) { 541 while ((dir = readdir(d))) {
547 if(strcmp(dir->d_name, "." ) == 0 || strcmp(dir->d_name, ".." ) == 0) 542 if(strcmp(dir->d_name, "." ) == 0 || strcmp(dir->d_name, ".." ) == 0)
548 continue; 543 continue;
@@ -570,7 +565,7 @@ static void sanitize_home(void) {
570// name); 565// name);
571 566
572 // disable directory 567 // disable directory
573 disable_file(BLACKLIST_FILE, name, emptydir, "not used"); 568 disable_file(BLACKLIST_FILE, name);
574 free(name); 569 free(name);
575 } 570 }
576 } 571 }