diff options
-rw-r--r-- | src/firejail/firejail.h | 2 | ||||
-rw-r--r-- | src/firejail/fs.c | 11 | ||||
-rw-r--r-- | src/firejail/mountinfo.c | 149 |
3 files changed, 71 insertions, 91 deletions
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 13b7b9523..a6924b830 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -567,7 +567,7 @@ typedef struct { | |||
567 | // mountinfo.c | 567 | // mountinfo.c |
568 | MountData *get_last_mount(void); | 568 | MountData *get_last_mount(void); |
569 | int get_mount_id(int fd); | 569 | int get_mount_id(int fd); |
570 | char **build_mount_array(const int mount_id, const char *path); | 570 | char **build_mount_array(const int mountid, const char *path); |
571 | 571 | ||
572 | // fs_var.c | 572 | // fs_var.c |
573 | void fs_var_log(void); // mounting /var/log | 573 | void fs_var_log(void); // mounting /var/log |
diff --git a/src/firejail/fs.c b/src/firejail/fs.c index 0b9a38035..9c1b889ed 100644 --- a/src/firejail/fs.c +++ b/src/firejail/fs.c | |||
@@ -654,12 +654,13 @@ static void fs_remount_rec(const char *path, OPERATION op) { | |||
654 | 654 | ||
655 | // build array with all mount points that need to get remounted | 655 | // build array with all mount points that need to get remounted |
656 | char **arr = build_mount_array(mountid, path); | 656 | char **arr = build_mount_array(mountid, path); |
657 | assert(arr); | 657 | if (!arr) |
658 | return; | ||
658 | // remount | 659 | // remount |
659 | char **tmp = arr; | 660 | int i; |
660 | while (*tmp) { | 661 | for (i = 0; arr[i]; i++) { |
661 | fs_remount_simple(*tmp, op); | 662 | fs_remount_simple(arr[i], op); |
662 | free(*tmp++); | 663 | free(arr[i]); |
663 | } | 664 | } |
664 | free(arr); | 665 | free(arr); |
665 | } | 666 | } |
diff --git a/src/firejail/mountinfo.c b/src/firejail/mountinfo.c index 304f80eee..ee437e10b 100644 --- a/src/firejail/mountinfo.c +++ b/src/firejail/mountinfo.c | |||
@@ -33,43 +33,38 @@ static MountData mdata; | |||
33 | 33 | ||
34 | 34 | ||
35 | // Convert octal escape sequence to decimal value | 35 | // Convert octal escape sequence to decimal value |
36 | static int read_oct(const char *path) { | 36 | static unsigned read_oct(char *s) { |
37 | int dec = 0; | 37 | assert(s[0] == '\\'); |
38 | int digit, i; | 38 | s++; |
39 | // there are always exactly three octal digits | 39 | |
40 | for (i = 1; i < 4; i++) { | 40 | int i; |
41 | digit = *(path + i); | 41 | for (i = 0; i < 3; i++) |
42 | if (digit < '0' || digit > '7') { | 42 | assert(s[i] >= '0' && s[i] <= '7'); |
43 | fprintf(stderr, "Error: cannot read /proc/self/mountinfo\n"); | 43 | |
44 | exit(1); | 44 | return ((s[0] - '0') << 6 | |
45 | } | 45 | (s[1] - '0') << 3 | |
46 | dec = (dec << 3) + (digit - '0'); | 46 | (s[2] - '0') << 0); |
47 | } | ||
48 | return dec; | ||
49 | } | 47 | } |
50 | 48 | ||
51 | // Restore empty spaces in pathnames extracted from /proc/self/mountinfo | 49 | // Restore empty spaces in pathnames extracted from /proc/self/mountinfo |
52 | static void unmangle_path(char *path) { | 50 | static void unmangle_path(char *path) { |
53 | char *p = strchr(path, '\\'); | 51 | char *r = strchr(path, '\\'); |
54 | if (p && read_oct(p) == ' ') { | 52 | if (!r) |
55 | *p = ' '; | 53 | return; |
56 | int i = 3; | 54 | |
57 | do { | 55 | char *w = r; |
58 | p++; | 56 | do { |
59 | if (*(p + i) == '\\' && read_oct(p + i) == ' ') { | 57 | while (*r == '\\') { |
60 | *p = ' '; | 58 | *w++ = read_oct(r); |
61 | i += 3; | 59 | r += 4; |
62 | } | 60 | } |
63 | else | 61 | *w++ = *r; |
64 | *p = *(p + i); | 62 | } while (*r++); |
65 | } while (*p); | ||
66 | } | ||
67 | } | 63 | } |
68 | 64 | ||
69 | // Parse a line from /proc/self/mountinfo, | 65 | // Parse a line from /proc/self/mountinfo, |
70 | // the function does an exit(1) if anything goes wrong. | 66 | // the function does an exit(1) if anything goes wrong. |
71 | static void parse_line(char *line, MountData *output) { | 67 | static void parse_line(char *line, MountData *output) { |
72 | assert(line && output); | ||
73 | memset(output, 0, sizeof(*output)); | 68 | memset(output, 0, sizeof(*output)); |
74 | // extract mount id, filesystem name, directory and filesystem types | 69 | // extract mount id, filesystem name, directory and filesystem types |
75 | // examples: | 70 | // examples: |
@@ -87,8 +82,6 @@ static void parse_line(char *line, MountData *output) { | |||
87 | char *ptr = strtok(line, " "); | 82 | char *ptr = strtok(line, " "); |
88 | if (!ptr) | 83 | if (!ptr) |
89 | goto errexit; | 84 | goto errexit; |
90 | if (ptr != line) | ||
91 | goto errexit; | ||
92 | output->mountid = atoi(ptr); | 85 | output->mountid = atoi(ptr); |
93 | int cnt = 1; | 86 | int cnt = 1; |
94 | 87 | ||
@@ -109,10 +102,9 @@ static void parse_line(char *line, MountData *output) { | |||
109 | ptr = strtok(NULL, " "); | 102 | ptr = strtok(NULL, " "); |
110 | if (!ptr) | 103 | if (!ptr) |
111 | goto errexit; | 104 | goto errexit; |
112 | output->fstype = ptr++; | 105 | output->fstype = ptr; |
113 | 106 | ||
114 | 107 | if (output->mountid < 0 || | |
115 | if (output->mountid == 0 || | ||
116 | output->fsname == NULL || | 108 | output->fsname == NULL || |
117 | output->dir == NULL || | 109 | output->dir == NULL || |
118 | output->fstype == NULL) | 110 | output->fstype == NULL) |
@@ -195,9 +187,9 @@ static int get_mount_id_from_fdinfo(int fd) { | |||
195 | char buf[MAX_BUF]; | 187 | char buf[MAX_BUF]; |
196 | while (fgets(buf, MAX_BUF, fp)) { | 188 | while (fgets(buf, MAX_BUF, fp)) { |
197 | if (strncmp(buf, "mnt_id:", 7) == 0) { | 189 | if (strncmp(buf, "mnt_id:", 7) == 0) { |
198 | if (sscanf(buf + 7, "%d", &rv) != 1) | 190 | if (sscanf(buf + 7, "%d", &rv) == 1) |
199 | goto errexit; | 191 | break; |
200 | break; | 192 | goto errexit; |
201 | } | 193 | } |
202 | } | 194 | } |
203 | 195 | ||
@@ -219,62 +211,50 @@ int get_mount_id(int fd) { | |||
219 | 211 | ||
220 | // Check /proc/self/mountinfo if path contains any mounts points. | 212 | // Check /proc/self/mountinfo if path contains any mounts points. |
221 | // Returns an array that can be iterated over for recursive remounting. | 213 | // Returns an array that can be iterated over for recursive remounting. |
222 | char **build_mount_array(const int mount_id, const char *path) { | 214 | char **build_mount_array(const int mountid, const char *path) { |
223 | assert(path); | 215 | assert(path); |
224 | 216 | ||
225 | // open /proc/self/mountinfo | ||
226 | FILE *fp = fopen("/proc/self/mountinfo", "re"); | 217 | FILE *fp = fopen("/proc/self/mountinfo", "re"); |
227 | if (!fp) { | 218 | if (!fp) { |
228 | fprintf(stderr, "Error: cannot read /proc/self/mountinfo\n"); | 219 | fprintf(stderr, "Error: cannot read /proc/self/mountinfo\n"); |
229 | exit(1); | 220 | exit(1); |
230 | } | 221 | } |
231 | 222 | ||
232 | // array to be returned | 223 | // try to find line with mount id |
233 | size_t cnt = 0; | 224 | int found = 0; |
225 | MountData mntp; | ||
226 | char line[MAX_BUF]; | ||
227 | while (fgets(line, MAX_BUF, fp)) { | ||
228 | parse_line(line, &mntp); | ||
229 | if (mntp.mountid == mountid) { | ||
230 | found = 1; | ||
231 | break; | ||
232 | } | ||
233 | } | ||
234 | |||
235 | if (!found) { | ||
236 | fclose(fp); | ||
237 | return NULL; | ||
238 | } | ||
239 | |||
240 | // allocate array | ||
234 | size_t size = 32; | 241 | size_t size = 32; |
235 | char **rv = malloc(size * sizeof(*rv)); | 242 | char **rv = malloc(size * sizeof(*rv)); |
236 | if (!rv) | 243 | if (!rv) |
237 | errExit("malloc"); | 244 | errExit("malloc"); |
238 | 245 | ||
239 | // read /proc/self/mountinfo | 246 | // add directory itself |
240 | size_t pathlen = strlen(path); | 247 | size_t cnt = 0; |
241 | char buf[MAX_BUF]; | 248 | rv[cnt] = strdup(path); |
242 | MountData mntp; | 249 | if (rv[cnt] == NULL) |
243 | int found = 0; | 250 | errExit("strdup"); |
244 | 251 | ||
245 | if (fgets(buf, MAX_BUF, fp) == NULL) { | 252 | // and add all following mountpoints contained in this directory |
246 | fprintf(stderr, "Error: cannot read /proc/self/mountinfo\n"); | 253 | size_t pathlen = strlen(path); |
247 | exit(1); | 254 | while (fgets(line, MAX_BUF, fp)) { |
248 | } | 255 | parse_line(line, &mntp); |
249 | do { | 256 | if (strncmp(mntp.dir, path, pathlen) == 0 && mntp.dir[pathlen] == '/') { |
250 | parse_line(buf, &mntp); | 257 | if (++cnt == size) { |
251 | // find mount point with mount id | ||
252 | if (!found) { | ||
253 | if (mntp.mountid == mount_id) { | ||
254 | // give up if mount id has been reassigned, | ||
255 | // don't remount blacklisted path | ||
256 | if (strncmp(mntp.dir, path, strlen(mntp.dir)) || | ||
257 | strstr(mntp.fsname, "firejail.ro.dir") || | ||
258 | strstr(mntp.fsname, "firejail.ro.file")) | ||
259 | break; | ||
260 | |||
261 | rv[cnt] = strdup(path); | ||
262 | if (rv[cnt] == NULL) | ||
263 | errExit("strdup"); | ||
264 | cnt++; | ||
265 | found = 1; | ||
266 | continue; | ||
267 | } | ||
268 | continue; | ||
269 | } | ||
270 | // from here on add all mount points below path, | ||
271 | // don't remount blacklisted paths | ||
272 | if (strncmp(mntp.dir, path, pathlen) == 0 && | ||
273 | mntp.dir[pathlen] == '/' && | ||
274 | strstr(mntp.fsname, "firejail.ro.dir") == NULL && | ||
275 | strstr(mntp.fsname, "firejail.ro.file") == NULL) { | ||
276 | |||
277 | if (cnt == size) { | ||
278 | size *= 2; | 258 | size *= 2; |
279 | rv = realloc(rv, size * sizeof(*rv)); | 259 | rv = realloc(rv, size * sizeof(*rv)); |
280 | if (!rv) | 260 | if (!rv) |
@@ -283,18 +263,17 @@ char **build_mount_array(const int mount_id, const char *path) { | |||
283 | rv[cnt] = strdup(mntp.dir); | 263 | rv[cnt] = strdup(mntp.dir); |
284 | if (rv[cnt] == NULL) | 264 | if (rv[cnt] == NULL) |
285 | errExit("strdup"); | 265 | errExit("strdup"); |
286 | cnt++; | ||
287 | } | 266 | } |
288 | } while (fgets(buf, MAX_BUF, fp)); | 267 | } |
268 | fclose(fp); | ||
289 | 269 | ||
290 | if (cnt == size) { | 270 | // end of array |
291 | size++; | 271 | if (++cnt == size) { |
272 | ++size; | ||
292 | rv = realloc(rv, size * sizeof(*rv)); | 273 | rv = realloc(rv, size * sizeof(*rv)); |
293 | if (!rv) | 274 | if (!rv) |
294 | errExit("realloc"); | 275 | errExit("realloc"); |
295 | } | 276 | } |
296 | rv[cnt] = NULL; // end of the array | 277 | rv[cnt] = NULL; |
297 | |||
298 | fclose(fp); | ||
299 | return rv; | 278 | return rv; |
300 | } | 279 | } |