aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar startx2017 <vradu.startx@yandex.com>2018-11-06 10:20:49 -0500
committerLibravatar startx2017 <vradu.startx@yandex.com>2018-11-06 10:20:49 -0500
commita314954c05301270dbbb41f3928de7cd2500f88e (patch)
treedad61a8903d4750ae11dc13a6410b5f00730b475
parentmainline merge: mount appimage nodev,nosuid (diff)
downloadfirejail-a314954c05301270dbbb41f3928de7cd2500f88e.tar.gz
firejail-a314954c05301270dbbb41f3928de7cd2500f88e.tar.zst
firejail-a314954c05301270dbbb41f3928de7cd2500f88e.zip
mainline merge: fs_whitelist: minor mountinfo check improvement, cleanup
-rw-r--r--src/firejail/fs_whitelist.c20
1 files changed, 11 insertions, 9 deletions
diff --git a/src/firejail/fs_whitelist.c b/src/firejail/fs_whitelist.c
index 454715a71..a83259224 100644
--- a/src/firejail/fs_whitelist.c
+++ b/src/firejail/fs_whitelist.c
@@ -34,6 +34,7 @@
34 34
35#define EMPTY_STRING ("") 35#define EMPTY_STRING ("")
36#define MAXBUF 4098 36#define MAXBUF 4098
37static size_t homedir_len; // cache length of homedir string
37 38
38 39
39static int mkpath(const char* path, mode_t mode) { 40static int mkpath(const char* path, mode_t mode) {
@@ -42,7 +43,7 @@ static int mkpath(const char* path, mode_t mode) {
42 43
43 // create directories with uid/gid as root or as current user if inside home directory 44 // create directories with uid/gid as root or as current user if inside home directory
44 int userhome = 0; 45 int userhome = 0;
45 if (strncmp(path, cfg.homedir, strlen(cfg.homedir)) == 0) { 46 if (strncmp(path, cfg.homedir, homedir_len) == 0) {
46 EUID_USER(); 47 EUID_USER();
47 userhome = 1; 48 userhome = 1;
48 } 49 }
@@ -123,12 +124,12 @@ static void whitelist_path(ProfileEntry *entry) {
123 char *wfile = NULL; 124 char *wfile = NULL;
124 125
125 if (entry->home_dir) { 126 if (entry->home_dir) {
126 if (strncmp(path, cfg.homedir, strlen(cfg.homedir)) != 0 || path[strlen(cfg.homedir)] != '/') 127 if (strncmp(path, cfg.homedir, homedir_len) != 0 || path[homedir_len] != '/')
127 // either symlink pointing outside home directory 128 // either symlink pointing outside home directory
128 // or entire home directory, skip the mount 129 // or entire home directory, skip the mount
129 return; 130 return;
130 131
131 fname = path + strlen(cfg.homedir) + 1; // strlen("/home/user/") 132 fname = path + homedir_len + 1; // strlen("/home/user/")
132 133
133 if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_HOME_USER_DIR, fname) == -1) 134 if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_HOME_USER_DIR, fname) == -1)
134 errExit("asprintf"); 135 errExit("asprintf");
@@ -302,7 +303,9 @@ static void whitelist_path(ProfileEntry *entry) {
302 303
303 // confirm the file was mounted on the right target 304 // confirm the file was mounted on the right target
304 // strcmp does not work here, because mptr->dir can be a child mount 305 // strcmp does not work here, because mptr->dir can be a child mount
305 if (strncmp(mptr->dir, path, strlen(path)) != 0) 306 size_t path_len = strlen(path);
307 if (strncmp(mptr->dir, path, path_len) != 0 ||
308 (*(mptr->dir + path_len) != '\0' && *(mptr->dir + path_len) != '/'))
306 errLogExit("invalid whitelist mount"); 309 errLogExit("invalid whitelist mount");
307 // No mounts are allowed on top level directories. A destination such as "/etc" is very bad! 310 // No mounts are allowed on top level directories. A destination such as "/etc" is very bad!
308 // - there should be more than one '/' char in dest string 311 // - there should be more than one '/' char in dest string
@@ -325,12 +328,11 @@ static void whitelist_path(ProfileEntry *entry) {
325 328
326 329
327void fs_whitelist(void) { 330void fs_whitelist(void) {
328 char *homedir = cfg.homedir;
329 assert(homedir);
330 ProfileEntry *entry = cfg.profile; 331 ProfileEntry *entry = cfg.profile;
331 if (!entry) 332 if (!entry)
332 return; 333 return;
333 334
335 homedir_len = strlen(cfg.homedir);
334 char *new_name = NULL; 336 char *new_name = NULL;
335 int home_dir = 0; // /home/user directory flag 337 int home_dir = 0; // /home/user directory flag
336 int tmp_dir = 0; // /tmp directory flag 338 int tmp_dir = 0; // /tmp directory flag
@@ -430,7 +432,7 @@ void fs_whitelist(void) {
430 432
431 // if 1 the file was not found; mount an empty directory 433 // if 1 the file was not found; mount an empty directory
432 if (!nowhitelist_flag) { 434 if (!nowhitelist_flag) {
433 if (strncmp(new_name, cfg.homedir, strlen(cfg.homedir)) == 0 && new_name[strlen(cfg.homedir)] == '/') { 435 if (strncmp(new_name, cfg.homedir, homedir_len) == 0 && new_name[homedir_len] == '/') {
434 if(!arg_private) 436 if(!arg_private)
435 home_dir = 1; 437 home_dir = 1;
436 } 438 }
@@ -483,7 +485,7 @@ void fs_whitelist(void) {
483 } 485 }
484 486
485 // check for supported directories 487 // check for supported directories
486 if (strncmp(new_name, cfg.homedir, strlen(cfg.homedir)) == 0 && new_name[strlen(cfg.homedir)] == '/') { 488 if (strncmp(new_name, cfg.homedir, homedir_len) == 0 && new_name[homedir_len] == '/') {
487 // whitelisting home directory is disabled if --private option is present 489 // whitelisting home directory is disabled if --private option is present
488 if (arg_private) { 490 if (arg_private) {
489 if (arg_debug || arg_debug_whitelists) 491 if (arg_debug || arg_debug_whitelists)
@@ -504,7 +506,7 @@ void fs_whitelist(void) {
504 506
505 // both path and absolute path are in user home, 507 // both path and absolute path are in user home,
506 // if not check if the symlink destination is owned by the user 508 // if not check if the symlink destination is owned by the user
507 if (strncmp(fname, cfg.homedir, strlen(cfg.homedir)) != 0 || fname[strlen(cfg.homedir)] != '/') { 509 if (strncmp(fname, cfg.homedir, homedir_len) != 0 || fname[homedir_len] != '/') {
508 if (checkcfg(CFG_FOLLOW_SYMLINK_AS_USER)) { 510 if (checkcfg(CFG_FOLLOW_SYMLINK_AS_USER)) {
509 if (stat(fname, &s) == 0 && s.st_uid != getuid()) { 511 if (stat(fname, &s) == 0 && s.st_uid != getuid()) {
510 free(fname); 512 free(fname);