diff options
author | 2018-04-29 09:21:16 -0400 | |
---|---|---|
committer | 2018-04-29 09:21:16 -0400 | |
commit | f6100167d25ce0e1f53714c94d82da8fdfaf9975 (patch) | |
tree | b28d83c788845bf8abb223584066b758c511e7d5 /src | |
parent | private-lib fixes (diff) | |
download | firejail-f6100167d25ce0e1f53714c94d82da8fdfaf9975.tar.gz firejail-f6100167d25ce0e1f53714c94d82da8fdfaf9975.tar.zst firejail-f6100167d25ce0e1f53714c94d82da8fdfaf9975.zip |
whitelist haderning - based on an idea from smitsohu
Diffstat (limited to 'src')
-rw-r--r-- | src/firejail/firejail.h | 10 | ||||
-rw-r--r-- | src/firejail/fs_whitelist.c | 19 | ||||
-rw-r--r-- | src/firejail/util.c | 36 |
3 files changed, 65 insertions, 0 deletions
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 0df832c09..14f87c36c 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -524,6 +524,16 @@ unsigned extract_timeout(const char *str); | |||
524 | void disable_file_or_dir(const char *fname); | 524 | void disable_file_or_dir(const char *fname); |
525 | void disable_file_path(const char *path, const char *file); | 525 | void disable_file_path(const char *path, const char *file); |
526 | 526 | ||
527 | // Get info regarding the last kernel mount operation. | ||
528 | // The return value points to a static area, and will be overwritten by subsequent calls. | ||
529 | // The function does an exit(1) if anything goes wrong. | ||
530 | typedef struct { | ||
531 | char *fsname; | ||
532 | char *dir; | ||
533 | } MountData; | ||
534 | MountData *get_last_mount(void); | ||
535 | |||
536 | |||
527 | // fs_var.c | 537 | // fs_var.c |
528 | void fs_var_log(void); // mounting /var/log | 538 | void fs_var_log(void); // mounting /var/log |
529 | void fs_var_lib(void); // various other fixes for software in /var directory | 539 | void fs_var_lib(void); // various other fixes for software in /var directory |
diff --git a/src/firejail/fs_whitelist.c b/src/firejail/fs_whitelist.c index 21fa8e624..2b63d949d 100644 --- a/src/firejail/fs_whitelist.c +++ b/src/firejail/fs_whitelist.c | |||
@@ -316,6 +316,16 @@ static void whitelist_path(ProfileEntry *entry) { | |||
316 | if (mount(wfile, path, NULL, MS_BIND|MS_REC, NULL) < 0) | 316 | if (mount(wfile, path, NULL, MS_BIND|MS_REC, NULL) < 0) |
317 | errExit("mount bind"); | 317 | errExit("mount bind"); |
318 | 318 | ||
319 | // check the last mount operation | ||
320 | MountData *mptr = get_last_mount(); // will do exit(1) if the mount cannot be found | ||
321 | |||
322 | // No mounts are allowed on top level directories. A destination such as "/etc" is very bad! | ||
323 | // - there should be more than one '/' char in dest string | ||
324 | if (mptr->dir == strrchr(mptr->dir, '/')) { | ||
325 | fprintf(stderr, "Error: invalid mount on top of %s\n", mptr->dir); | ||
326 | exit(1); | ||
327 | } | ||
328 | |||
319 | free(wfile); | 329 | free(wfile); |
320 | return; | 330 | return; |
321 | 331 | ||
@@ -856,6 +866,15 @@ void fs_whitelist(void) { | |||
856 | fprintf(stderr, "Warning cannot create symbolic link %s\n", entry->link); | 866 | fprintf(stderr, "Warning cannot create symbolic link %s\n", entry->link); |
857 | else if (arg_debug || arg_debug_whitelists) | 867 | else if (arg_debug || arg_debug_whitelists) |
858 | printf("Created symbolic link %s -> %s\n", entry->link, entry->data + 10); | 868 | printf("Created symbolic link %s -> %s\n", entry->link, entry->data + 10); |
869 | |||
870 | // check again for files in /tmp directory | ||
871 | if (strncmp(entry->link, "/tmp/", 5) == 0) { | ||
872 | char *path = realpath(entry->link, NULL); | ||
873 | if (path == NULL || strncmp(path, "/tmp/", 5) != 0) { | ||
874 | fprintf(stderr, "Error: invalid symbolic link %s\n", entry->link); | ||
875 | exit(1); | ||
876 | } | ||
877 | } | ||
859 | } | 878 | } |
860 | } | 879 | } |
861 | } | 880 | } |
diff --git a/src/firejail/util.c b/src/firejail/util.c index a44e52e98..f441f283f 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c | |||
@@ -1029,3 +1029,39 @@ void disable_file_path(const char *path, const char *file) { | |||
1029 | free(fname); | 1029 | free(fname); |
1030 | } | 1030 | } |
1031 | 1031 | ||
1032 | #define MAX_BUF 4096 | ||
1033 | static char mbuf[MAX_BUF]; | ||
1034 | static MountData mdata; | ||
1035 | |||
1036 | // Get info regarding the last kernel mount operation. | ||
1037 | // The return value points to a static area, and will be overwritten by subsequent calls. | ||
1038 | // The function does an exit(1) if anything goes wrong. | ||
1039 | MountData *get_last_mount(void) { | ||
1040 | // open /proc/self/mounts | ||
1041 | FILE *fp = fopen("/proc/self/mounts", "r"); | ||
1042 | if (!fp) | ||
1043 | goto errexit; | ||
1044 | |||
1045 | mbuf[0] = '\0'; | ||
1046 | while (fgets(mbuf, MAX_BUF, fp)); | ||
1047 | fclose(fp); | ||
1048 | if (arg_debug || arg_debug_whitelists) | ||
1049 | printf("%s", mbuf); | ||
1050 | |||
1051 | // there should be no reason to have a new mount on top of a top level directory | ||
1052 | mdata.fsname = mbuf; | ||
1053 | mdata.dir = strstr(mbuf, " "); | ||
1054 | if (!mdata.dir) | ||
1055 | goto errexit; | ||
1056 | mdata.dir++; | ||
1057 | char *end = strstr(mdata.dir, " "); | ||
1058 | if (!end) | ||
1059 | goto errexit; | ||
1060 | *end = '\0'; | ||
1061 | |||
1062 | return &mdata; | ||
1063 | |||
1064 | errexit: | ||
1065 | fprintf(stderr, "Error: cannot read /proc/self/mounts"); | ||
1066 | exit(1); | ||
1067 | } | ||