aboutsummaryrefslogtreecommitdiffstats
path: root/src/firejail/join.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/firejail/join.c')
-rw-r--r--src/firejail/join.c59
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
304bool is_ready_for_join(const pid_t pid) { 304bool 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
366void check_join_permission(pid_t pid) { 333void 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;