From c875f1007508c166a66fd0cbf5132068982e8700 Mon Sep 17 00:00:00 2001 From: netblue30 Date: Thu, 3 May 2018 11:25:59 -0400 Subject: moving get_mount_info from /proc/self/mounts to /proc/slef/mountinfo --- README | 1 + src/firejail/firejail.h | 7 +++--- src/firejail/fs_whitelist.c | 11 +++++++++ src/firejail/util.c | 55 ++++++++++++++++++++++++++++++++++----------- 4 files changed, 58 insertions(+), 16 deletions(-) diff --git a/README b/README index fa15353c6..7384a8c99 100644 --- a/README +++ b/README @@ -40,6 +40,7 @@ Committers - startx2017 (https://github.com/startx2017) - 0.9.38-LTS and *bugfixes branches maintainer) - Topi Miettinen (https://github.com/topimiettinen) - Vincent43 (https://github.com/Vincent43) +- chiraag-nataraj (https://github.com/chiraag-nataraj) - netblue30 (netblue30@yahoo.com) diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 84f535575..7544b642a 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h @@ -525,12 +525,13 @@ unsigned extract_timeout(const char *str); void disable_file_or_dir(const char *fname); void disable_file_path(const char *path, const char *file); -// Get info regarding the last kernel mount operation. +// Get info regarding the last kernel mount operation from /proc/self/mountinfo // The return value points to a static area, and will be overwritten by subsequent calls. // The function does an exit(1) if anything goes wrong. typedef struct { - char *fsname; - char *dir; + char *fsname; // the pathname of the directory in the filesystem which forms the root of this mount + char *dir; // mount destination + char *fstype; // filesystem type } MountData; MountData *get_last_mount(void); diff --git a/src/firejail/fs_whitelist.c b/src/firejail/fs_whitelist.c index 60bb0f6ed..754714943 100644 --- a/src/firejail/fs_whitelist.c +++ b/src/firejail/fs_whitelist.c @@ -27,6 +27,12 @@ #include #include +// mountinfo functionality test; +// 1. enable TEST_MOUNTINFO definition +// 2. set a symlink in /tmp: ln -s /etc /tmp/etc +// 3. run firejail --debug --whitelist=/tmp/etc +//#define TEST_MOUNTINFO + static char *dentry[] = { "Downloads", "Загрузки", @@ -204,8 +210,10 @@ static void whitelist_path(ProfileEntry *entry) { } else if (entry->tmp_dir) { fname = path + 5; // strlen("/tmp/") +#ifndef TEST_MOUNTINFO if (*fname == '\0') goto errexit; +#endif if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_TMP_DIR, fname) == -1) errExit("asprintf"); @@ -516,10 +524,13 @@ void fs_whitelist(void) { else if (strncmp(new_name, "/tmp/", 5) == 0) { entry->tmp_dir = 1; tmp_dir = 1; + +#ifndef TEST_MOUNTINFO // both path and absolute path are under /tmp if (strncmp(fname, "/tmp/", 5) != 0) { goto errexit; } +#endif } else if (strncmp(new_name, "/media/", 7) == 0) { entry->media_dir = 1; diff --git a/src/firejail/util.c b/src/firejail/util.c index 28ad6b990..d6835569d 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c @@ -1037,32 +1037,61 @@ static MountData mdata; // The return value points to a static area, and will be overwritten by subsequent calls. // The function does an exit(1) if anything goes wrong. MountData *get_last_mount(void) { - // open /proc/self/mounts - FILE *fp = fopen("/proc/self/mounts", "r"); + // open /proc/self/mountinfo + FILE *fp = fopen("/proc/self/mountinfo", "r"); if (!fp) goto errexit; mbuf[0] = '\0'; while (fgets(mbuf, MAX_BUF, fp)); fclose(fp); - if (arg_debug || arg_debug_whitelists) + if (arg_debug) printf("%s", mbuf); - // extract filesystem name and directory - mdata.fsname = mbuf; - mdata.dir = strstr(mbuf, " "); - if (!mdata.dir) + // extract filesystem name, directory and filesystem type + // examples: + // 587 543 8:1 /tmp /etc rw,relatime master:1 - ext4 /dev/sda1 rw,errors=remount-ro,data=ordered + // mdata.fsname: /tmp + // mdata.dir: /etc + // mdata.fstype: ext4 + // 585 564 0:76 / /home/netblue/.cache rw,nosuid,nodev - tmpfs tmpfs rw + // mdata.fsname: / + // mdata.dir: /home/netblue/.cache + // mdata.fstype: tmpfs + memset(&mdata, 0, sizeof(mdata)); + char *ptr = strtok(mbuf, " "); + if (!ptr) goto errexit; - *mdata.dir = '\0'; - mdata.dir++; - char *end = strstr(mdata.dir, " "); - if (!end) + + int cnt = 1; + while ((ptr = strtok(NULL, " ")) != NULL) { + cnt++; + if (cnt == 4) + mdata.fsname = ptr; + else if (cnt == 5) { + mdata.dir = ptr; + break; + } + } + + ptr = strtok(NULL, "-"); + if (!ptr) + goto errexit; + + ptr = strtok(NULL, " "); + if (!ptr) goto errexit; - *end = '\0'; + mdata.fstype = ptr++; + if (mdata.fsname == NULL || + mdata.dir == NULL || + mdata.fstype == NULL) + goto errexit; + if (arg_debug) + printf("fsname=%s dir=%s fstype=%s\n", mdata.fsname, mdata.dir, mdata.fstype); return &mdata; errexit: - fprintf(stderr, "Error: cannot read /proc/self/mounts"); + fprintf(stderr, "Error: cannot read /proc/self/mountinfo\n"); exit(1); } -- cgit v1.2.3-54-g00ecf