diff options
author | smitsohu <smitsohu@gmail.com> | 2018-07-16 01:49:46 +0200 |
---|---|---|
committer | smitsohu <smitsohu@gmail.com> | 2018-07-16 01:49:46 +0200 |
commit | d22b46bc8df2842470713341e1fa30e65fcd702f (patch) | |
tree | 45753b74fb52f9bf194925b6e46e13247582c2eb /src/firejail/mountinfo.c | |
parent | minor improvements to previous commit 949b924fba58dc05f1c21d6621f05047be5397f0 (diff) | |
download | firejail-d22b46bc8df2842470713341e1fa30e65fcd702f.tar.gz firejail-d22b46bc8df2842470713341e1fa30e65fcd702f.tar.zst firejail-d22b46bc8df2842470713341e1fa30e65fcd702f.zip |
rework fix for empty spaces in mountinfo fields
Diffstat (limited to 'src/firejail/mountinfo.c')
-rw-r--r-- | src/firejail/mountinfo.c | 129 |
1 files changed, 129 insertions, 0 deletions
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 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014-2018 Firejail Authors | ||
3 | * | ||
4 | * This file is part of firejail project | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | */ | ||
20 | |||
21 | #include "firejail.h" | ||
22 | |||
23 | #define MAX_BUF 4096 | ||
24 | static char mbuf[MAX_BUF]; | ||
25 | static MountData mdata; | ||
26 | |||
27 | // Convert octal escape sequence to decimal value | ||
28 | static int read_oct(const char *path) { | ||
29 | int decimal = 0; | ||
30 | int digit, i; | ||
31 | // there are always three octal digits | ||
32 | for (i = 1; i < 4; i++) { | ||
33 | digit = *(path + i); | ||
34 | if (digit < '0' || digit > '7') { | ||
35 | fprintf(stderr, "Error: cannot read /proc/self/mountinfo\n"); | ||
36 | exit(1); | ||
37 | } | ||
38 | decimal = (decimal + digit - '0') * 8; | ||
39 | } | ||
40 | decimal /= 8; | ||
41 | return decimal; | ||
42 | } | ||
43 | |||
44 | // Restore empty spaces in pathnames extracted from /proc/self/mountinfo | ||
45 | static void unmangle_path(char *path) { | ||
46 | char *p = strchr(path, '\\'); | ||
47 | if (p) { | ||
48 | if (read_oct(p) == ' ') { | ||
49 | *p = ' '; | ||
50 | int i = 3; | ||
51 | do { | ||
52 | p++; | ||
53 | if (*(p + i) == '\\' && read_oct(p + i) == ' ') { | ||
54 | *p = ' '; | ||
55 | i += 3; | ||
56 | } | ||
57 | else | ||
58 | *p = *(p + i); | ||
59 | } while (*p); | ||
60 | } | ||
61 | } | ||
62 | } | ||
63 | |||
64 | // Get info regarding the last kernel mount operation. | ||
65 | // The return value points to a static area, and will be overwritten by subsequent calls. | ||
66 | // The function does an exit(1) if anything goes wrong. | ||
67 | MountData *get_last_mount(void) { | ||
68 | // open /proc/self/mountinfo | ||
69 | FILE *fp = fopen("/proc/self/mountinfo", "r"); | ||
70 | if (!fp) | ||
71 | goto errexit; | ||
72 | |||
73 | mbuf[0] = '\0'; | ||
74 | while (fgets(mbuf, MAX_BUF, fp)); | ||
75 | fclose(fp); | ||
76 | if (arg_debug) | ||
77 | printf("%s", mbuf); | ||
78 | |||
79 | // extract filesystem name, directory and filesystem type | ||
80 | // examples: | ||
81 | // 587 543 8:1 /tmp /etc rw,relatime master:1 - ext4 /dev/sda1 rw,errors=remount-ro,data=ordered | ||
82 | // mdata.fsname: /tmp | ||
83 | // mdata.dir: /etc | ||
84 | // mdata.fstype: ext4 | ||
85 | // 585 564 0:76 / /home/netblue/.cache rw,nosuid,nodev - tmpfs tmpfs rw | ||
86 | // mdata.fsname: / | ||
87 | // mdata.dir: /home/netblue/.cache | ||
88 | // mdata.fstype: tmpfs | ||
89 | memset(&mdata, 0, sizeof(mdata)); | ||
90 | char *ptr = strtok(mbuf, " "); | ||
91 | if (!ptr) | ||
92 | goto errexit; | ||
93 | |||
94 | int cnt = 1; | ||
95 | while ((ptr = strtok(NULL, " ")) != NULL) { | ||
96 | cnt++; | ||
97 | if (cnt == 4) | ||
98 | mdata.fsname = ptr; | ||
99 | else if (cnt == 5) { | ||
100 | mdata.dir = ptr; | ||
101 | break; | ||
102 | } | ||
103 | } | ||
104 | |||
105 | ptr = strtok(NULL, "-"); | ||
106 | if (!ptr) | ||
107 | goto errexit; | ||
108 | |||
109 | ptr = strtok(NULL, " "); | ||
110 | if (!ptr) | ||
111 | goto errexit; | ||
112 | mdata.fstype = ptr++; | ||
113 | |||
114 | if (mdata.fsname == NULL || | ||
115 | mdata.dir == NULL || | ||
116 | mdata.fstype == NULL) | ||
117 | goto errexit; | ||
118 | |||
119 | unmangle_path(mdata.fsname); | ||
120 | unmangle_path(mdata.dir); | ||
121 | |||
122 | if (arg_debug) | ||
123 | printf("fsname=%s dir=%s fstype=%s\n", mdata.fsname, mdata.dir, mdata.fstype); | ||
124 | return &mdata; | ||
125 | |||
126 | errexit: | ||
127 | fprintf(stderr, "Error: cannot read /proc/self/mountinfo\n"); | ||
128 | exit(1); | ||
129 | } | ||