aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar smitsohu <smitsohu@gmail.com>2018-08-19 14:07:10 +0200
committerLibravatar smitsohu <smitsohu@gmail.com>2018-08-19 14:07:10 +0200
commitb57caa22e5a5d1ce2fbb7cb1bca46c26e1f47540 (patch)
tree93272823ee2ea8e0b5bcb142115db91f45f56511 /src
parenttests: increase some timeouts in which I was running (diff)
downloadfirejail-b57caa22e5a5d1ce2fbb7cb1bca46c26e1f47540.tar.gz
firejail-b57caa22e5a5d1ce2fbb7cb1bca46c26e1f47540.tar.zst
firejail-b57caa22e5a5d1ce2fbb7cb1bca46c26e1f47540.zip
fix issue with join option
Diffstat (limited to 'src')
-rw-r--r--src/firejail/firejail.h3
-rw-r--r--src/firejail/join.c95
-rw-r--r--src/firejail/no_sandbox.c2
-rw-r--r--src/firejail/sandbox.c40
-rw-r--r--src/lib/common.c6
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
407int sandbox(void* sandbox_arg); 408int sandbox(void* sandbox_arg);
408void start_application(int no_sandbox); 409void start_application(int no_sandbox, FILE *fp);
409 410
410// network_main.c 411// network_main.c
411void net_configure_sandbox_ip(Bridge *br); 412void 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
226static 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
256errexit:
257 fprintf(stderr, "Error: no valid sandbox\n");
258 exit(1);
259}
260
261
262
224void join(pid_t pid, int argc, char **argv, int index) { 263void 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
142static 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
142static void sandbox_if_up(Bridge *br) { 154static 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
377void start_application(int no_sandbox) { 389void 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;