diff options
author | 2018-08-19 14:07:10 +0200 | |
---|---|---|
committer | 2018-08-19 14:07:10 +0200 | |
commit | b57caa22e5a5d1ce2fbb7cb1bca46c26e1f47540 (patch) | |
tree | 93272823ee2ea8e0b5bcb142115db91f45f56511 | |
parent | tests: increase some timeouts in which I was running (diff) | |
download | firejail-b57caa22e5a5d1ce2fbb7cb1bca46c26e1f47540.tar.gz firejail-b57caa22e5a5d1ce2fbb7cb1bca46c26e1f47540.tar.zst firejail-b57caa22e5a5d1ce2fbb7cb1bca46c26e1f47540.zip |
fix issue with join option
-rw-r--r-- | src/firejail/firejail.h | 3 | ||||
-rw-r--r-- | src/firejail/join.c | 95 | ||||
-rw-r--r-- | src/firejail/no_sandbox.c | 2 | ||||
-rw-r--r-- | src/firejail/sandbox.c | 40 | ||||
-rw-r--r-- | src/lib/common.c | 6 |
5 files changed, 131 insertions, 15 deletions
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 5ce380503..348e4f6ab 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -100,6 +100,7 @@ | |||
100 | #define RUN_FSLOGGER_FILE "/run/firejail/mnt/fslogger" | 100 | #define RUN_FSLOGGER_FILE "/run/firejail/mnt/fslogger" |
101 | #define RUN_UMASK_FILE "/run/firejail/mnt/umask" | 101 | #define RUN_UMASK_FILE "/run/firejail/mnt/umask" |
102 | #define RUN_OVERLAY_ROOT "/run/firejail/mnt/oroot" | 102 | #define RUN_OVERLAY_ROOT "/run/firejail/mnt/oroot" |
103 | #define RUN_READY_FOR_JOIN "/run/firejail/mnt/ready-for-join" | ||
103 | 104 | ||
104 | 105 | ||
105 | // profiles | 106 | // profiles |
@@ -405,7 +406,7 @@ char *guess_shell(void); | |||
405 | 406 | ||
406 | // sandbox.c | 407 | // sandbox.c |
407 | int sandbox(void* sandbox_arg); | 408 | int sandbox(void* sandbox_arg); |
408 | void start_application(int no_sandbox); | 409 | void start_application(int no_sandbox, FILE *fp); |
409 | 410 | ||
410 | // network_main.c | 411 | // network_main.c |
411 | void net_configure_sandbox_ip(Bridge *br); | 412 | void net_configure_sandbox_ip(Bridge *br); |
diff --git a/src/firejail/join.c b/src/firejail/join.c index 729c7f797..17191d9a9 100644 --- a/src/firejail/join.c +++ b/src/firejail/join.c | |||
@@ -212,8 +212,10 @@ static void extract_umask(pid_t pid) { | |||
212 | 212 | ||
213 | FILE *fp = fopen(fname, "re"); | 213 | FILE *fp = fopen(fname, "re"); |
214 | free(fname); | 214 | free(fname); |
215 | if (!fp) | 215 | if (!fp) { |
216 | return; | 216 | fprintf(stderr, "Error: cannot open umask file\n"); |
217 | exit(1); | ||
218 | } | ||
217 | if (fscanf(fp, "%3o", &orig_umask) < 1) { | 219 | if (fscanf(fp, "%3o", &orig_umask) < 1) { |
218 | fprintf(stderr, "Error: cannot read umask\n"); | 220 | fprintf(stderr, "Error: cannot read umask\n"); |
219 | exit(1); | 221 | exit(1); |
@@ -221,6 +223,43 @@ static void extract_umask(pid_t pid) { | |||
221 | fclose(fp); | 223 | fclose(fp); |
222 | } | 224 | } |
223 | 225 | ||
226 | static void ready_for_join(pid_t pid) { | ||
227 | char *fname; | ||
228 | if (asprintf(&fname, "/proc/%d/root%s", pid, RUN_READY_FOR_JOIN) == -1) | ||
229 | errExit("asprintf"); | ||
230 | |||
231 | // check if file "ready-for-join" exists | ||
232 | EUID_ROOT(); | ||
233 | FILE *fp = fopen(fname, "re"); | ||
234 | EUID_USER(); | ||
235 | if (!fp) | ||
236 | goto errexit; | ||
237 | int fd = fileno(fp); | ||
238 | if (fd == -1) | ||
239 | errExit("fileno"); | ||
240 | struct stat s; | ||
241 | if (fstat(fd, &s) == -1) | ||
242 | errExit("fstat"); | ||
243 | if (s.st_uid != 0) | ||
244 | goto errexit; | ||
245 | // check if it is non-empty | ||
246 | char buf[BUFLEN]; | ||
247 | if (fgets(buf, BUFLEN, fp) == NULL) | ||
248 | goto errexit; | ||
249 | // confirm "ready" string was written | ||
250 | if (strncmp(buf, "ready\n", 6) != 0) | ||
251 | goto errexit; | ||
252 | fclose(fp); | ||
253 | free(fname); | ||
254 | return; | ||
255 | |||
256 | errexit: | ||
257 | fprintf(stderr, "Error: no valid sandbox\n"); | ||
258 | exit(1); | ||
259 | } | ||
260 | |||
261 | |||
262 | |||
224 | void join(pid_t pid, int argc, char **argv, int index) { | 263 | void join(pid_t pid, int argc, char **argv, int index) { |
225 | EUID_ASSERT(); | 264 | EUID_ASSERT(); |
226 | char *homedir = cfg.homedir; | 265 | char *homedir = cfg.homedir; |
@@ -231,17 +270,53 @@ void join(pid_t pid, int argc, char **argv, int index) { | |||
231 | 270 | ||
232 | // if the pid is that of a firejail process, use the pid of the first child process | 271 | // if the pid is that of a firejail process, use the pid of the first child process |
233 | EUID_ROOT(); | 272 | EUID_ROOT(); |
273 | errno = 0; | ||
234 | char *comm = pid_proc_comm(pid); | 274 | char *comm = pid_proc_comm(pid); |
275 | if (!comm) { | ||
276 | if (errno == ENOENT) { | ||
277 | fprintf(stderr, "Error: cannot find process with id %d\n", pid); | ||
278 | exit(1); | ||
279 | } | ||
280 | else { | ||
281 | fprintf(stderr, "Error: cannot read /proc/%d/comm\n", pid); | ||
282 | exit(1); | ||
283 | } | ||
284 | } | ||
235 | EUID_USER(); | 285 | EUID_USER(); |
236 | if (comm) { | 286 | if (strcmp(comm, "firejail") == 0) { |
237 | if (strcmp(comm, "firejail") == 0) { | 287 | pid_t child; |
238 | pid_t child; | 288 | if (find_child(pid, &child) == 1) { |
239 | if (find_child(pid, &child) == 0) { | 289 | fprintf(stderr, "Error: found firejail process without a child process\n"); |
240 | pid = child; | 290 | exit(1); |
241 | fmessage("Switching to pid %u, the first child process inside the sandbox\n", (unsigned) pid); | 291 | } |
292 | fmessage("Switching to pid %u, the first child process inside the sandbox\n", (unsigned) child); | ||
293 | pid = child; | ||
294 | } | ||
295 | free(comm); | ||
296 | |||
297 | // pid must belong to a valid firejail sandbox | ||
298 | ready_for_join(pid); | ||
299 | |||
300 | // walk down the process tree a few nodes, there should be no firejail leaf | ||
301 | #define MAXNODES 4 | ||
302 | pid_t current = pid, next; | ||
303 | for (int i = 0; i < MAXNODES; i++) { | ||
304 | if (find_child(current, &next) == 1) { | ||
305 | EUID_ROOT(); | ||
306 | comm = pid_proc_comm(current); | ||
307 | EUID_USER(); | ||
308 | if (!comm) { | ||
309 | fprintf(stderr, "Error: cannot read /proc/%d/comm\n", current); | ||
310 | exit(1); | ||
311 | } | ||
312 | if (strcmp(comm, "firejail") == 0) { | ||
313 | fprintf(stderr, "Error: found firejail process without a child process\n"); | ||
314 | exit(1); | ||
242 | } | 315 | } |
316 | free(comm); | ||
317 | break; | ||
243 | } | 318 | } |
244 | free(comm); | 319 | current = next; |
245 | } | 320 | } |
246 | 321 | ||
247 | // check privileges for non-root users | 322 | // check privileges for non-root users |
@@ -406,7 +481,7 @@ void join(pid_t pid, int argc, char **argv, int index) { | |||
406 | } | 481 | } |
407 | 482 | ||
408 | drop_privs(arg_nogroups); | 483 | drop_privs(arg_nogroups); |
409 | start_application(0); | 484 | start_application(0, NULL); |
410 | 485 | ||
411 | // it will never get here!!! | 486 | // it will never get here!!! |
412 | } | 487 | } |
diff --git a/src/firejail/no_sandbox.c b/src/firejail/no_sandbox.c index 5bd3f7e09..7c5cc1df9 100644 --- a/src/firejail/no_sandbox.c +++ b/src/firejail/no_sandbox.c | |||
@@ -233,5 +233,5 @@ void run_no_sandbox(int argc, char **argv) { | |||
233 | 233 | ||
234 | arg_quiet = 1; | 234 | arg_quiet = 1; |
235 | 235 | ||
236 | start_application(1); | 236 | start_application(1, NULL); |
237 | } | 237 | } |
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index 2c28aa24b..5d9526b4c 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c | |||
@@ -139,6 +139,18 @@ void save_umask(void) { | |||
139 | } | 139 | } |
140 | } | 140 | } |
141 | 141 | ||
142 | static FILE *create_ready_for_join_file(void) { | ||
143 | FILE *fp = fopen(RUN_READY_FOR_JOIN, "wxe"); | ||
144 | if (fp) { | ||
145 | ASSERT_PERMS_STREAM(fp, 0, 0, 0644); | ||
146 | return fp; | ||
147 | } | ||
148 | else { | ||
149 | fprintf(stderr, "Error: cannot create %s\n", RUN_READY_FOR_JOIN); | ||
150 | exit(1); | ||
151 | } | ||
152 | } | ||
153 | |||
142 | static void sandbox_if_up(Bridge *br) { | 154 | static void sandbox_if_up(Bridge *br) { |
143 | assert(br); | 155 | assert(br); |
144 | if (!br->configured) | 156 | if (!br->configured) |
@@ -374,7 +386,7 @@ static int ok_to_run(const char *program) { | |||
374 | return 0; | 386 | return 0; |
375 | } | 387 | } |
376 | 388 | ||
377 | void start_application(int no_sandbox) { | 389 | void start_application(int no_sandbox, FILE *fp) { |
378 | // set environment | 390 | // set environment |
379 | if (no_sandbox == 0) { | 391 | if (no_sandbox == 0) { |
380 | env_defaults(); | 392 | env_defaults(); |
@@ -393,6 +405,11 @@ void start_application(int no_sandbox) { | |||
393 | //**************************************** | 405 | //**************************************** |
394 | if (arg_audit) { | 406 | if (arg_audit) { |
395 | assert(arg_audit_prog); | 407 | assert(arg_audit_prog); |
408 | |||
409 | if (fp) { | ||
410 | fprintf(fp, "ready\n"); | ||
411 | fclose(fp); | ||
412 | } | ||
396 | #ifdef HAVE_GCOV | 413 | #ifdef HAVE_GCOV |
397 | __gcov_dump(); | 414 | __gcov_dump(); |
398 | #endif | 415 | #endif |
@@ -423,6 +440,11 @@ void start_application(int no_sandbox) { | |||
423 | print_time(); | 440 | print_time(); |
424 | 441 | ||
425 | int rv = ok_to_run(cfg.original_argv[cfg.original_program_index]); | 442 | int rv = ok_to_run(cfg.original_argv[cfg.original_program_index]); |
443 | |||
444 | if (fp) { | ||
445 | fprintf(fp, "ready\n"); | ||
446 | fclose(fp); | ||
447 | } | ||
426 | #ifdef HAVE_GCOV | 448 | #ifdef HAVE_GCOV |
427 | __gcov_dump(); | 449 | __gcov_dump(); |
428 | #endif | 450 | #endif |
@@ -479,6 +501,11 @@ void start_application(int no_sandbox) { | |||
479 | 501 | ||
480 | if (!arg_command && !arg_quiet) | 502 | if (!arg_command && !arg_quiet) |
481 | print_time(); | 503 | print_time(); |
504 | |||
505 | if (fp) { | ||
506 | fprintf(fp, "ready\n"); | ||
507 | fclose(fp); | ||
508 | } | ||
482 | #ifdef HAVE_GCOV | 509 | #ifdef HAVE_GCOV |
483 | __gcov_dump(); | 510 | __gcov_dump(); |
484 | #endif | 511 | #endif |
@@ -1069,6 +1096,13 @@ int sandbox(void* sandbox_arg) { | |||
1069 | #endif | 1096 | #endif |
1070 | 1097 | ||
1071 | //**************************************** | 1098 | //**************************************** |
1099 | // communicate progress of sandbox set up | ||
1100 | // to --join | ||
1101 | //**************************************** | ||
1102 | |||
1103 | FILE *fp = create_ready_for_join_file(); | ||
1104 | |||
1105 | //**************************************** | ||
1072 | // create a new user namespace | 1106 | // create a new user namespace |
1073 | // - too early to drop privileges | 1107 | // - too early to drop privileges |
1074 | //**************************************** | 1108 | //**************************************** |
@@ -1133,9 +1167,11 @@ int sandbox(void* sandbox_arg) { | |||
1133 | #endif | 1167 | #endif |
1134 | 1168 | ||
1135 | prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // kill the child in case the parent died | 1169 | prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // kill the child in case the parent died |
1136 | start_application(0); // start app | 1170 | start_application(0, fp); // start app |
1137 | } | 1171 | } |
1138 | 1172 | ||
1173 | fclose(fp); | ||
1174 | |||
1139 | int status = monitor_application(app_pid); // monitor application | 1175 | int status = monitor_application(app_pid); // monitor application |
1140 | flush_stdin(); | 1176 | flush_stdin(); |
1141 | 1177 | ||
diff --git a/src/lib/common.c b/src/lib/common.c index fa988446b..d6dd43c4b 100644 --- a/src/lib/common.c +++ b/src/lib/common.c | |||
@@ -129,7 +129,7 @@ char *pid_proc_comm(const pid_t pid) { | |||
129 | // open /proc/pid/cmdline file | 129 | // open /proc/pid/cmdline file |
130 | char *fname; | 130 | char *fname; |
131 | int fd; | 131 | int fd; |
132 | if (asprintf(&fname, "/proc/%d//comm", pid) == -1) | 132 | if (asprintf(&fname, "/proc/%d/comm", pid) == -1) |
133 | return NULL; | 133 | return NULL; |
134 | if ((fd = open(fname, O_RDONLY)) < 0) { | 134 | if ((fd = open(fname, O_RDONLY)) < 0) { |
135 | free(fname); | 135 | free(fname); |
@@ -154,6 +154,8 @@ char *pid_proc_comm(const pid_t pid) { | |||
154 | 154 | ||
155 | // return a malloc copy of the command line | 155 | // return a malloc copy of the command line |
156 | char *rv = strdup(buffer); | 156 | char *rv = strdup(buffer); |
157 | if (!rv) | ||
158 | return NULL; | ||
157 | if (strlen(rv) == 0) { | 159 | if (strlen(rv) == 0) { |
158 | free(rv); | 160 | free(rv); |
159 | return NULL; | 161 | return NULL; |
@@ -192,6 +194,8 @@ char *pid_proc_cmdline(const pid_t pid) { | |||
192 | 194 | ||
193 | // return a malloc copy of the command line | 195 | // return a malloc copy of the command line |
194 | char *rv = strdup((char *) buffer); | 196 | char *rv = strdup((char *) buffer); |
197 | if (!rv) | ||
198 | return NULL; | ||
195 | if (strlen(rv) == 0) { | 199 | if (strlen(rv) == 0) { |
196 | free(rv); | 200 | free(rv); |
197 | return NULL; | 201 | return NULL; |