diff options
Diffstat (limited to 'src/firejail/join.c')
-rw-r--r-- | src/firejail/join.c | 59 |
1 files changed, 13 insertions, 46 deletions
diff --git a/src/firejail/join.c b/src/firejail/join.c index 14eea4612..c7619ef3b 100644 --- a/src/firejail/join.c +++ b/src/firejail/join.c | |||
@@ -292,7 +292,7 @@ static void extract_umask(pid_t pid) { | |||
292 | fprintf(stderr, "Error: cannot open umask file\n"); | 292 | fprintf(stderr, "Error: cannot open umask file\n"); |
293 | exit(1); | 293 | exit(1); |
294 | } | 294 | } |
295 | if (fscanf(fp, "%3o", &orig_umask) < 1) { | 295 | if (fscanf(fp, "%o", &orig_umask) != 1) { |
296 | fprintf(stderr, "Error: cannot read umask\n"); | 296 | fprintf(stderr, "Error: cannot read umask\n"); |
297 | exit(1); | 297 | exit(1); |
298 | } | 298 | } |
@@ -303,66 +303,33 @@ static void extract_umask(pid_t pid) { | |||
303 | // it is no firejail sandbox at all, return true if the sandbox is complete | 303 | // it is no firejail sandbox at all, return true if the sandbox is complete |
304 | bool is_ready_for_join(const pid_t pid) { | 304 | bool is_ready_for_join(const pid_t pid) { |
305 | EUID_ASSERT(); | 305 | EUID_ASSERT(); |
306 | // check if a file "ready-for-join" exists | 306 | // check if a file /run/firejail/mnt/join exists |
307 | char *fname; | 307 | char *fname; |
308 | if (asprintf(&fname, "/proc/%d/root%s", pid, RUN_READY_FOR_JOIN) == -1) | 308 | if (asprintf(&fname, "/proc/%d/root%s", pid, RUN_JOIN_FILE) == -1) |
309 | errExit("asprintf"); | 309 | errExit("asprintf"); |
310 | EUID_ROOT(); | 310 | EUID_ROOT(); |
311 | FILE *fp = fopen(fname, "re"); | 311 | int fd = open(fname, O_RDONLY|O_CLOEXEC); |
312 | EUID_USER(); | 312 | EUID_USER(); |
313 | free(fname); | 313 | free(fname); |
314 | if (!fp) | ||
315 | return false; | ||
316 | // regular file owned by root | ||
317 | int fd = fileno(fp); | ||
318 | if (fd == -1) | 314 | if (fd == -1) |
319 | errExit("fileno"); | 315 | return false; |
320 | struct stat s; | 316 | struct stat s; |
321 | if (fstat(fd, &s) == -1) | 317 | if (fstat(fd, &s) == -1) |
322 | errExit("fstat"); | 318 | errExit("fstat"); |
323 | if (!S_ISREG(s.st_mode) || s.st_uid != 0) { | 319 | if (!S_ISREG(s.st_mode) || s.st_uid != 0) { |
324 | fclose(fp); | 320 | close(fd); |
325 | return false; | 321 | return false; |
326 | } | 322 | } |
327 | // check if it is non-empty | 323 | char status; |
328 | char buf[BUFLEN]; | 324 | if (read(fd, &status, 1) == 1 && status == SANDBOX_DONE) { |
329 | if (fgets(buf, BUFLEN, fp) == NULL) { | 325 | close(fd); |
330 | fclose(fp); | 326 | return true; |
331 | return false; | ||
332 | } | 327 | } |
333 | fclose(fp); | 328 | close(fd); |
334 | // confirm "ready" string was written | 329 | return false; |
335 | if (strcmp(buf, "ready\n") != 0) | ||
336 | return false; | ||
337 | |||
338 | // walk down the process tree a few nodes, there should be no firejail leaf | ||
339 | #define MAXNODES 5 | ||
340 | pid_t current = pid, next; | ||
341 | int i; | ||
342 | for (i = 0; i < MAXNODES; i++) { | ||
343 | if (find_child(current, &next) == 1) { | ||
344 | // found a leaf | ||
345 | EUID_ROOT(); | ||
346 | char *comm = pid_proc_comm(current); | ||
347 | EUID_USER(); | ||
348 | if (!comm) { | ||
349 | fprintf(stderr, "Error: cannot read /proc file\n"); | ||
350 | exit(1); | ||
351 | } | ||
352 | if (strcmp(comm, "firejail") == 0) { | ||
353 | free(comm); | ||
354 | return false; | ||
355 | } | ||
356 | free(comm); | ||
357 | break; | ||
358 | } | ||
359 | current = next; | ||
360 | } | ||
361 | |||
362 | return true; | ||
363 | } | 330 | } |
364 | 331 | ||
365 | #define SNOOZE 100000 // sleep interval in microseconds | 332 | #define SNOOZE 10000 // sleep interval in microseconds |
366 | void check_join_permission(pid_t pid) { | 333 | void check_join_permission(pid_t pid) { |
367 | // check if pid belongs to a fully set up firejail sandbox | 334 | // check if pid belongs to a fully set up firejail sandbox |
368 | unsigned long i; | 335 | unsigned long i; |