From d22b46bc8df2842470713341e1fa30e65fcd702f Mon Sep 17 00:00:00 2001 From: smitsohu Date: Mon, 16 Jul 2018 01:49:46 +0200 Subject: rework fix for empty spaces in mountinfo fields cf. 949b924fba58dc05f1c21d6621f05047be5397f0 and 5c69440cc943f530830b8534d99d2061bdcfaf40 --- src/firejail/mountinfo.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++ src/firejail/util.c | 104 -------------------------------------- 2 files changed, 129 insertions(+), 104 deletions(-) create mode 100644 src/firejail/mountinfo.c diff --git a/src/firejail/mountinfo.c b/src/firejail/mountinfo.c new file mode 100644 index 000000000..4a7816901 --- /dev/null +++ b/src/firejail/mountinfo.c @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2014-2018 Firejail Authors + * + * This file is part of firejail project + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "firejail.h" + +#define MAX_BUF 4096 +static char mbuf[MAX_BUF]; +static MountData mdata; + +// Convert octal escape sequence to decimal value +static int read_oct(const char *path) { + int decimal = 0; + int digit, i; + // there are always three octal digits + for (i = 1; i < 4; i++) { + digit = *(path + i); + if (digit < '0' || digit > '7') { + fprintf(stderr, "Error: cannot read /proc/self/mountinfo\n"); + exit(1); + } + decimal = (decimal + digit - '0') * 8; + } + decimal /= 8; + return decimal; +} + +// Restore empty spaces in pathnames extracted from /proc/self/mountinfo +static void unmangle_path(char *path) { + char *p = strchr(path, '\\'); + if (p) { + if (read_oct(p) == ' ') { + *p = ' '; + int i = 3; + do { + p++; + if (*(p + i) == '\\' && read_oct(p + i) == ' ') { + *p = ' '; + i += 3; + } + else + *p = *(p + i); + } while (*p); + } + } +} + +// Get info regarding the last kernel mount operation. +// 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/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) + printf("%s", mbuf); + + // 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; + + 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; + mdata.fstype = ptr++; + + if (mdata.fsname == NULL || + mdata.dir == NULL || + mdata.fstype == NULL) + goto errexit; + + unmangle_path(mdata.fsname); + unmangle_path(mdata.dir); + + 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/mountinfo\n"); + exit(1); +} diff --git a/src/firejail/util.c b/src/firejail/util.c index 52db987b7..f634ff700 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c @@ -1045,110 +1045,6 @@ void disable_file_path(const char *path, const char *file) { free(fname); } -// Restore empty spaces in pathnames extracted from /proc/self/mountinfo -static void unmangle_path(char *path) { - int i, decimal; - char *worker; - - char *p = strchr(path, '\\'); - while (p) { - // convert octal to decimal - decimal = 0; - for (i = 1; i < 4; i++) { - worker = p + i; - // there are always three octal digits - if (*worker < '0' || *worker > '7') { - fprintf(stderr, "Error: cannot read /proc/self/mountinfo\n"); - exit(1); - } - decimal = (*worker - '0' + decimal) * 8; - } - decimal /= 8; - // do the replacement - if (decimal == ' ') { - *p = ' '; - worker = p; - do { - worker++; - *worker = *(worker + 3); - } while (*worker); - } - - p = strchr(p + 1, '\\'); - } -} - -#define MAX_BUF 4096 -static char mbuf[MAX_BUF]; -static MountData mdata; - -// Get info regarding the last kernel mount operation. -// 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/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) - printf("%s", mbuf); - - // 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; - - 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; - mdata.fstype = ptr++; - - if (mdata.fsname == NULL || - mdata.dir == NULL || - mdata.fstype == NULL) - goto errexit; - - unmangle_path(mdata.fsname); - unmangle_path(mdata.dir); - - 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/mountinfo\n"); - exit(1); -} - // The returned file descriptor should be suitable for privileged operations on // user controlled paths. Passed flags are ignored if path is a top level directory. int safe_fd(const char *path, int flags) { -- cgit v1.2.3-54-g00ecf