aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar smitsohu <smitsohu@gmail.com>2018-06-26 01:57:42 +0200
committerLibravatar smitsohu <smitsohu@gmail.com>2018-06-26 01:57:42 +0200
commit9f27bf2ed081072c5c93dbec0d3eec3025619acb (patch)
tree8f1af453e3f9114d13b2933052dac6b416d9227b /src
parentdon't include globals.local twice (take two) (#2010) (diff)
downloadfirejail-9f27bf2ed081072c5c93dbec0d3eec3025619acb.tar.gz
firejail-9f27bf2ed081072c5c93dbec0d3eec3025619acb.tar.zst
firejail-9f27bf2ed081072c5c93dbec0d3eec3025619acb.zip
whitelist symlink handling, allow /var/tmp symlinks - issue #2011
Diffstat (limited to 'src')
-rw-r--r--src/firejail/fs_whitelist.c62
1 files changed, 41 insertions, 21 deletions
diff --git a/src/firejail/fs_whitelist.c b/src/firejail/fs_whitelist.c
index af1993457..d67087616 100644
--- a/src/firejail/fs_whitelist.c
+++ b/src/firejail/fs_whitelist.c
@@ -196,7 +196,6 @@ static void whitelist_path(ProfileEntry *entry) {
196 const char *fname; 196 const char *fname;
197 char *wfile = NULL; 197 char *wfile = NULL;
198 198
199 EUID_USER();
200 if (entry->home_dir) { 199 if (entry->home_dir) {
201 if (strncmp(path, cfg.homedir, strlen(cfg.homedir)) == 0) { 200 if (strncmp(path, cfg.homedir, strlen(cfg.homedir)) == 0) {
202 fname = path + strlen(cfg.homedir); 201 fname = path + strlen(cfg.homedir);
@@ -204,7 +203,8 @@ static void whitelist_path(ProfileEntry *entry) {
204 goto errexit; 203 goto errexit;
205 } 204 }
206 else 205 else
207 fname = path; 206 // symlink pointing outside /home, skip the mount
207 return;
208 208
209 if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_HOME_USER_DIR, fname) == -1) 209 if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_HOME_USER_DIR, fname) == -1)
210 errExit("asprintf"); 210 errExit("asprintf");
@@ -236,17 +236,27 @@ static void whitelist_path(ProfileEntry *entry) {
236 errExit("asprintf"); 236 errExit("asprintf");
237 } 237 }
238 else if (entry->var_dir) { 238 else if (entry->var_dir) {
239 fname = path + 5; // strlen("/var/") 239 if (strncmp(path, "/var/", 5) == 0) {
240 if (*fname == '\0') 240 fname = path + 5; // strlen("/var/")
241 goto errexit; 241 if (*fname == '\0')
242 goto errexit;
243 }
244 else
245 // symlink pointing outside /var, skip the mount
246 return;
242 247
243 if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_VAR_DIR, fname) == -1) 248 if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_VAR_DIR, fname) == -1)
244 errExit("asprintf"); 249 errExit("asprintf");
245 } 250 }
246 else if (entry->dev_dir) { 251 else if (entry->dev_dir) {
247 fname = path + 5; // strlen("/dev/") 252 if (strncmp(path, "/dev/", 5) == 0) {
248 if (*fname == '\0') 253 fname = path + 5; // strlen("/dev/")
249 goto errexit; 254 if (*fname == '\0')
255 goto errexit;
256 }
257 else
258 // symlink pointing outside /dev, skip the mount
259 return;
250 260
251 if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_DEV_DIR, fname) == -1) 261 if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_DEV_DIR, fname) == -1)
252 errExit("asprintf"); 262 errExit("asprintf");
@@ -268,9 +278,14 @@ static void whitelist_path(ProfileEntry *entry) {
268 errExit("asprintf"); 278 errExit("asprintf");
269 } 279 }
270 else if (entry->etc_dir) { 280 else if (entry->etc_dir) {
271 fname = path + 5; // strlen("/etc/") 281 if (strncmp(path, "/etc/", 5) == 0) {
272 if (*fname == '\0') 282 fname = path + 5; // strlen("/etc/")
273 goto errexit; 283 if (*fname == '\0')
284 goto errexit;
285 }
286 else
287 // symlink pointing outside /etc, skip the mount
288 return;
274 289
275 if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_ETC_DIR, fname) == -1) 290 if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_ETC_DIR, fname) == -1)
276 errExit("asprintf"); 291 errExit("asprintf");
@@ -293,6 +308,7 @@ static void whitelist_path(ProfileEntry *entry) {
293 } 308 }
294 309
295 // check if the file exists 310 // check if the file exists
311 EUID_USER();
296 assert(wfile); 312 assert(wfile);
297 struct stat s; 313 struct stat s;
298 if (stat(wfile, &s) == 0) { 314 if (stat(wfile, &s) == 0) {
@@ -300,11 +316,12 @@ static void whitelist_path(ProfileEntry *entry) {
300 printf("Whitelisting %s\n", path); 316 printf("Whitelisting %s\n", path);
301 } 317 }
302 else { 318 else {
319 free(wfile);
303 EUID_ROOT(); 320 EUID_ROOT();
304 return; 321 return;
305 } 322 }
306
307 EUID_ROOT(); 323 EUID_ROOT();
324
308 // create the path if necessary 325 // create the path if necessary
309 mkpath(path, s.st_mode); 326 mkpath(path, s.st_mode);
310 fs_logger2("whitelist", path); 327 fs_logger2("whitelist", path);
@@ -329,8 +346,10 @@ static void whitelist_path(ProfileEntry *entry) {
329 SET_PERMS_STREAM(fp, s.st_uid, s.st_gid, s.st_mode); 346 SET_PERMS_STREAM(fp, s.st_uid, s.st_gid, s.st_mode);
330 fclose(fp); 347 fclose(fp);
331 } 348 }
332 else 349 else {
350 free(wfile);
333 return; // the file is already present 351 return; // the file is already present
352 }
334 } 353 }
335 354
336 // mount 355 // mount
@@ -565,19 +584,20 @@ void fs_whitelist(void) {
565 entry->var_dir = 1; 584 entry->var_dir = 1;
566 var_dir = 1; 585 var_dir = 1;
567 // both path and absolute path are under /var 586 // both path and absolute path are under /var
568 // exceptions: /var/run and /var/lock 587 // exceptions: /var/tmp, /var/run and /var/lock
569 if (strcmp(new_name, "/var/run")== 0) 588 if (strcmp(new_name, "/var/run")== 0 && strcmp(fname, "/run") == 0);
570 ; 589 else if (strcmp(new_name, "/var/lock")== 0 && strcmp(fname, "/run/lock") == 0);
571 else if (strcmp(new_name, "/var/lock")== 0) 590 else if (strcmp(new_name, "/var/tmp")== 0 && strcmp(fname, "/tmp") == 0);
572 ; 591 else {
573 else if (strncmp(fname, "/var/", 5) != 0) { 592 // both path and absolute path are under /var
574 goto errexit; 593 if (strncmp(fname, "/var/", 5) != 0) {
594 goto errexit;
595 }
575 } 596 }
576 } 597 }
577 else if (strncmp(new_name, "/dev/", 5) == 0) { 598 else if (strncmp(new_name, "/dev/", 5) == 0) {
578 entry->dev_dir = 1; 599 entry->dev_dir = 1;
579 dev_dir = 1; 600 dev_dir = 1;
580
581 // special handling for /dev/shm 601 // special handling for /dev/shm
582 // on some platforms (Debian wheezy, Ubuntu 14.04), it is a symlink to /run/shm 602 // on some platforms (Debian wheezy, Ubuntu 14.04), it is a symlink to /run/shm
583 if (strcmp(new_name, "/dev/shm") == 0 && strcmp(fname, "/run/shm") == 0); 603 if (strcmp(new_name, "/dev/shm") == 0 && strcmp(fname, "/run/shm") == 0);