aboutsummaryrefslogtreecommitdiffstats
path: root/src/firejail/mountinfo.c
diff options
context:
space:
mode:
authorLibravatar smitsohu <smitsohu@gmail.com>2021-10-18 18:01:46 +0200
committerLibravatar smitsohu <smitsohu@gmail.com>2021-10-18 18:09:38 +0200
commit316a1cd6227e259908287a768953b1171cd9477d (patch)
treeb6aef72d5b6d5b3855fe69b6fd7b567ecd54a0d3 /src/firejail/mountinfo.c
parentreadability (diff)
downloadfirejail-316a1cd6227e259908287a768953b1171cd9477d.tar.gz
firejail-316a1cd6227e259908287a768953b1171cd9477d.tar.zst
firejail-316a1cd6227e259908287a768953b1171cd9477d.zip
mountinfo: improve readability
Removes the inconsistency that some blacklisted paths could be remounted (files specified explicitly) and some could not. Now all blacklisted paths can be mounted nosuid, nodev, noexec if users specify this. Also fixes the bug that mount id can indeed be 0. Other than that no functional or algorithmic changes, only readability improvements.
Diffstat (limited to 'src/firejail/mountinfo.c')
-rw-r--r--src/firejail/mountinfo.c149
1 files changed, 64 insertions, 85 deletions
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
36static int read_oct(const char *path) { 36static 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
52static void unmangle_path(char *path) { 50static 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.
71static void parse_line(char *line, MountData *output) { 67static 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.
222char **build_mount_array(const int mount_id, const char *path) { 214char **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}