diff options
-rw-r--r-- | etc/firejail.config | 5 | ||||
-rw-r--r-- | src/firejail/caps.c | 17 | ||||
-rw-r--r-- | src/firejail/checkcfg.c | 6 | ||||
-rw-r--r-- | src/firejail/cpu.c | 4 | ||||
-rw-r--r-- | src/firejail/firejail.h | 4 | ||||
-rw-r--r-- | src/firejail/join.c | 121 | ||||
-rw-r--r-- | src/firejail/ls.c | 17 | ||||
-rw-r--r-- | src/firejail/network_main.c | 17 | ||||
-rw-r--r-- | src/firejail/protocol.c | 17 | ||||
-rw-r--r-- | src/firejail/seccomp.c | 17 | ||||
-rw-r--r-- | src/firejail/util.c | 80 |
11 files changed, 122 insertions, 183 deletions
diff --git a/etc/firejail.config b/etc/firejail.config index 565796d5a..3bff2f7ed 100644 --- a/etc/firejail.config +++ b/etc/firejail.config | |||
@@ -62,6 +62,11 @@ | |||
62 | # root user can always join sandboxes. | 62 | # root user can always join sandboxes. |
63 | # join yes | 63 | # join yes |
64 | 64 | ||
65 | # Timeout when joining a sandbox, default five seconds. Wait up to | ||
66 | # the specified period of time to allow sandbox setup to finish. | ||
67 | # It is not possible to join a sandbox while it is still starting up. | ||
68 | # join-timeout 5 | ||
69 | |||
65 | # Enable or disable sandbox name change, default enabled. | 70 | # Enable or disable sandbox name change, default enabled. |
66 | # name-change yes | 71 | # name-change yes |
67 | 72 | ||
diff --git a/src/firejail/caps.c b/src/firejail/caps.c index 71dd9430b..738675766 100644 --- a/src/firejail/caps.c +++ b/src/firejail/caps.c | |||
@@ -404,21 +404,8 @@ void caps_print_filter(pid_t pid) { | |||
404 | // in case the pid is that of a firejail process, use the pid of the first child process | 404 | // in case the pid is that of a firejail process, use the pid of the first child process |
405 | pid = switch_to_child(pid); | 405 | pid = switch_to_child(pid); |
406 | 406 | ||
407 | // now check if the pid belongs to a firejail sandbox | 407 | // exit if no permission to join the sandbox |
408 | if (invalid_sandbox(pid)) { | 408 | check_join_permission(pid); |
409 | fprintf(stderr, "Error: no valid sandbox\n"); | ||
410 | exit(1); | ||
411 | } | ||
412 | |||
413 | // check privileges for non-root users | ||
414 | uid_t uid = getuid(); | ||
415 | if (uid != 0) { | ||
416 | uid_t sandbox_uid = pid_get_uid(pid); | ||
417 | if (uid != sandbox_uid) { | ||
418 | fprintf(stderr, "Error: permission denied.\n"); | ||
419 | exit(1); | ||
420 | } | ||
421 | } | ||
422 | 409 | ||
423 | uint64_t caps = extract_caps(pid); | 410 | uint64_t caps = extract_caps(pid); |
424 | int i; | 411 | int i; |
diff --git a/src/firejail/checkcfg.c b/src/firejail/checkcfg.c index f94b95d60..d6b591133 100644 --- a/src/firejail/checkcfg.c +++ b/src/firejail/checkcfg.c | |||
@@ -31,6 +31,7 @@ char *xpra_extra_params = ""; | |||
31 | char *xvfb_screen = "800x600x24"; | 31 | char *xvfb_screen = "800x600x24"; |
32 | char *xvfb_extra_params = ""; | 32 | char *xvfb_extra_params = ""; |
33 | char *netfilter_default = NULL; | 33 | char *netfilter_default = NULL; |
34 | unsigned long join_timeout = 5000000; // microseconds | ||
34 | 35 | ||
35 | int checkcfg(int val) { | 36 | int checkcfg(int val) { |
36 | assert(val < CFG_MAX); | 37 | assert(val < CFG_MAX); |
@@ -213,6 +214,11 @@ int checkcfg(int val) { | |||
213 | if (setenv("FIREJAIL_FILE_COPY_LIMIT", ptr + 16, 1) == -1) | 214 | if (setenv("FIREJAIL_FILE_COPY_LIMIT", ptr + 16, 1) == -1) |
214 | errExit("setenv"); | 215 | errExit("setenv"); |
215 | } | 216 | } |
217 | |||
218 | // timeout for join option | ||
219 | else if (strncmp(ptr, "join-timeout ", 13) == 0) | ||
220 | join_timeout = strtoul(ptr + 13, NULL, 10) * 1000000; // seconds to microseconds | ||
221 | |||
216 | else | 222 | else |
217 | goto errout; | 223 | goto errout; |
218 | 224 | ||
diff --git a/src/firejail/cpu.c b/src/firejail/cpu.c index 7a0807257..702186eaf 100644 --- a/src/firejail/cpu.c +++ b/src/firejail/cpu.c | |||
@@ -170,13 +170,11 @@ void cpu_print_filter(pid_t pid) { | |||
170 | pid = switch_to_child(pid); | 170 | pid = switch_to_child(pid); |
171 | 171 | ||
172 | // now check if the pid belongs to a firejail sandbox | 172 | // now check if the pid belongs to a firejail sandbox |
173 | if (invalid_sandbox(pid)) { | 173 | if (is_ready_for_join(pid) == false) { |
174 | fprintf(stderr, "Error: no valid sandbox\n"); | 174 | fprintf(stderr, "Error: no valid sandbox\n"); |
175 | exit(1); | 175 | exit(1); |
176 | } | 176 | } |
177 | 177 | ||
178 | |||
179 | |||
180 | print_cpu(pid); | 178 | print_cpu(pid); |
181 | exit(0); | 179 | exit(0); |
182 | } | 180 | } |
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index fdbeb4691..03bcbda46 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -426,6 +426,8 @@ void usage(void); | |||
426 | 426 | ||
427 | // join.c | 427 | // join.c |
428 | void join(pid_t pid, int argc, char **argv, int index); | 428 | void join(pid_t pid, int argc, char **argv, int index); |
429 | bool is_ready_for_join(const pid_t pid); | ||
430 | void check_join_permission(pid_t pid); | ||
429 | pid_t switch_to_child(pid_t pid); | 431 | pid_t switch_to_child(pid_t pid); |
430 | 432 | ||
431 | // shutdown.c | 433 | // shutdown.c |
@@ -491,7 +493,6 @@ unsigned extract_timeout(const char *str); | |||
491 | void disable_file_or_dir(const char *fname); | 493 | void disable_file_or_dir(const char *fname); |
492 | void disable_file_path(const char *path, const char *file); | 494 | void disable_file_path(const char *path, const char *file); |
493 | int safe_fd(const char *path, int flags); | 495 | int safe_fd(const char *path, int flags); |
494 | int invalid_sandbox(const pid_t pid); | ||
495 | int has_handler(pid_t pid, int signal); | 496 | int has_handler(pid_t pid, int signal); |
496 | void enter_network_namespace(pid_t pid); | 497 | void enter_network_namespace(pid_t pid); |
497 | 498 | ||
@@ -737,6 +738,7 @@ extern char *xpra_extra_params; | |||
737 | extern char *xvfb_screen; | 738 | extern char *xvfb_screen; |
738 | extern char *xvfb_extra_params; | 739 | extern char *xvfb_extra_params; |
739 | extern char *netfilter_default; | 740 | extern char *netfilter_default; |
741 | extern unsigned long join_timeout; | ||
740 | int checkcfg(int val); | 742 | int checkcfg(int val); |
741 | void print_compiletime_support(void); | 743 | void print_compiletime_support(void); |
742 | 744 | ||
diff --git a/src/firejail/join.c b/src/firejail/join.c index 46dae0271..1494c782f 100644 --- a/src/firejail/join.c +++ b/src/firejail/join.c | |||
@@ -255,32 +255,114 @@ static void extract_umask(pid_t pid) { | |||
255 | fclose(fp); | 255 | fclose(fp); |
256 | } | 256 | } |
257 | 257 | ||
258 | // return false if the sandbox identified by pid is not fully set up yet or if | ||
259 | // it is no firejail sandbox at all, return true if the sandbox is complete | ||
260 | bool is_ready_for_join(const pid_t pid) { | ||
261 | EUID_ASSERT(); | ||
262 | // check if a file "ready-for-join" exists | ||
263 | char *fname; | ||
264 | if (asprintf(&fname, "/proc/%d/root%s", pid, RUN_READY_FOR_JOIN) == -1) | ||
265 | errExit("asprintf"); | ||
266 | EUID_ROOT(); | ||
267 | FILE *fp = fopen(fname, "re"); | ||
268 | EUID_USER(); | ||
269 | free(fname); | ||
270 | if (!fp) | ||
271 | return false; | ||
272 | // regular file owned by root | ||
273 | int fd = fileno(fp); | ||
274 | if (fd == -1) | ||
275 | errExit("fileno"); | ||
276 | struct stat s; | ||
277 | if (fstat(fd, &s) == -1) | ||
278 | errExit("fstat"); | ||
279 | if (!S_ISREG(s.st_mode) || s.st_uid != 0) { | ||
280 | fclose(fp); | ||
281 | return false; | ||
282 | } | ||
283 | // check if it is non-empty | ||
284 | char buf[BUFLEN]; | ||
285 | if (fgets(buf, BUFLEN, fp) == NULL) { | ||
286 | fclose(fp); | ||
287 | return false; | ||
288 | } | ||
289 | fclose(fp); | ||
290 | // confirm "ready" string was written | ||
291 | if (strcmp(buf, "ready\n") != 0) | ||
292 | return false; | ||
293 | |||
294 | // walk down the process tree a few nodes, there should be no firejail leaf | ||
295 | #define MAXNODES 5 | ||
296 | pid_t current = pid, next; | ||
297 | int i; | ||
298 | for (i = 0; i < MAXNODES; i++) { | ||
299 | if (find_child(current, &next) == 1) { | ||
300 | // found a leaf | ||
301 | EUID_ROOT(); | ||
302 | char *comm = pid_proc_comm(current); | ||
303 | EUID_USER(); | ||
304 | if (!comm) { | ||
305 | fprintf(stderr, "Error: cannot read /proc file\n"); | ||
306 | exit(1); | ||
307 | } | ||
308 | if (strcmp(comm, "firejail") == 0) { | ||
309 | free(comm); | ||
310 | return false; | ||
311 | } | ||
312 | free(comm); | ||
313 | break; | ||
314 | } | ||
315 | current = next; | ||
316 | } | ||
317 | |||
318 | return true; | ||
319 | } | ||
320 | |||
321 | #define SNOOZE 100000 // sleep interval in microseconds | ||
322 | void check_join_permission(pid_t pid) { | ||
323 | // check if pid belongs to a fully set up firejail sandbox | ||
324 | unsigned long i; | ||
325 | for (i = 0; is_ready_for_join(pid) == false; i += SNOOZE) { // give sandbox some time to start up | ||
326 | if (i >= join_timeout) { | ||
327 | fprintf(stderr, "Error: no valid sandbox\n"); | ||
328 | exit(1); | ||
329 | } | ||
330 | usleep(SNOOZE); | ||
331 | } | ||
332 | // check privileges for non-root users | ||
333 | uid_t uid = getuid(); | ||
334 | if (uid != 0) { | ||
335 | uid_t sandbox_uid = pid_get_uid(pid); | ||
336 | if (uid != sandbox_uid) { | ||
337 | fprintf(stderr, "Error: permission is denied to join a sandbox created by a different user.\n"); | ||
338 | exit(1); | ||
339 | } | ||
340 | } | ||
341 | } | ||
342 | |||
258 | pid_t switch_to_child(pid_t pid) { | 343 | pid_t switch_to_child(pid_t pid) { |
344 | EUID_ASSERT(); | ||
259 | EUID_ROOT(); | 345 | EUID_ROOT(); |
346 | pid_t rv = pid; | ||
260 | errno = 0; | 347 | errno = 0; |
261 | char *comm = pid_proc_comm(pid); | 348 | char *comm = pid_proc_comm(pid); |
262 | if (!comm) { | 349 | if (!comm) { |
263 | if (errno == ENOENT) { | 350 | if (errno == ENOENT) |
264 | fprintf(stderr, "Error: cannot find process with pid %d\n", pid); | 351 | fprintf(stderr, "Error: cannot find process with pid %d\n", pid); |
265 | exit(1); | 352 | else |
266 | } | ||
267 | else { | ||
268 | fprintf(stderr, "Error: cannot read /proc file\n"); | 353 | fprintf(stderr, "Error: cannot read /proc file\n"); |
269 | exit(1); | 354 | exit(1); |
270 | } | ||
271 | } | 355 | } |
272 | EUID_USER(); | 356 | EUID_USER(); |
273 | if (strcmp(comm, "firejail") == 0) { | 357 | if (strcmp(comm, "firejail") == 0) { |
274 | pid_t child; | 358 | if (find_child(pid, &rv) == 1) { |
275 | if (find_child(pid, &child) == 1) { | ||
276 | fprintf(stderr, "Error: no valid sandbox\n"); | 359 | fprintf(stderr, "Error: no valid sandbox\n"); |
277 | exit(1); | 360 | exit(1); |
278 | } | 361 | } |
279 | fmessage("Switching to pid %u, the first child process inside the sandbox\n", (unsigned) child); | 362 | fmessage("Switching to pid %u, the first child process inside the sandbox\n", (unsigned) rv); |
280 | pid = child; | ||
281 | } | 363 | } |
282 | free(comm); | 364 | free(comm); |
283 | return pid; | 365 | return rv; |
284 | } | 366 | } |
285 | 367 | ||
286 | 368 | ||
@@ -292,21 +374,8 @@ void join(pid_t pid, int argc, char **argv, int index) { | |||
292 | // in case the pid is that of a firejail process, use the pid of the first child process | 374 | // in case the pid is that of a firejail process, use the pid of the first child process |
293 | pid = switch_to_child(pid); | 375 | pid = switch_to_child(pid); |
294 | 376 | ||
295 | // now check if the pid belongs to a firejail sandbox | 377 | // exit if no permission to join the sandbox |
296 | if (invalid_sandbox(pid)) { | 378 | check_join_permission(pid); |
297 | fprintf(stderr, "Error: no valid sandbox\n"); | ||
298 | exit(1); | ||
299 | } | ||
300 | |||
301 | // check privileges for non-root users | ||
302 | uid_t uid = getuid(); | ||
303 | if (uid != 0) { | ||
304 | uid_t sandbox_uid = pid_get_uid(pid); | ||
305 | if (uid != sandbox_uid) { | ||
306 | fprintf(stderr, "Error: permission is denied to join a sandbox created by a different user.\n"); | ||
307 | exit(1); | ||
308 | } | ||
309 | } | ||
310 | 379 | ||
311 | extract_x11_display(parent); | 380 | extract_x11_display(parent); |
312 | 381 | ||
diff --git a/src/firejail/ls.c b/src/firejail/ls.c index 08cf5f16a..75333fdc2 100644 --- a/src/firejail/ls.c +++ b/src/firejail/ls.c | |||
@@ -215,21 +215,8 @@ void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) { | |||
215 | // in case the pid is that of a firejail process, use the pid of the first child process | 215 | // in case the pid is that of a firejail process, use the pid of the first child process |
216 | pid = switch_to_child(pid); | 216 | pid = switch_to_child(pid); |
217 | 217 | ||
218 | // now check if the pid belongs to a firejail sandbox | 218 | // exit if no permission to join the sandbox |
219 | if (invalid_sandbox(pid)) { | 219 | check_join_permission(pid); |
220 | fprintf(stderr, "Error: no valid sandbox\n"); | ||
221 | exit(1); | ||
222 | } | ||
223 | |||
224 | // check privileges for non-root users | ||
225 | uid_t uid = getuid(); | ||
226 | if (uid != 0) { | ||
227 | uid_t sandbox_uid = pid_get_uid(pid); | ||
228 | if (uid != sandbox_uid) { | ||
229 | fprintf(stderr, "Error: permission denied.\n"); | ||
230 | exit(1); | ||
231 | } | ||
232 | } | ||
233 | 220 | ||
234 | // expand paths | 221 | // expand paths |
235 | char *fname1 = expand_path(path1);; | 222 | char *fname1 = expand_path(path1);; |
diff --git a/src/firejail/network_main.c b/src/firejail/network_main.c index 6a199469a..6800bde8d 100644 --- a/src/firejail/network_main.c +++ b/src/firejail/network_main.c | |||
@@ -272,21 +272,8 @@ void net_dns_print(pid_t pid) { | |||
272 | // in case the pid is that of a firejail process, use the pid of the first child process | 272 | // in case the pid is that of a firejail process, use the pid of the first child process |
273 | pid = switch_to_child(pid); | 273 | pid = switch_to_child(pid); |
274 | 274 | ||
275 | // now check if the pid belongs to a firejail sandbox | 275 | // exit if no permission to join the sandbox |
276 | if (invalid_sandbox(pid)) { | 276 | check_join_permission(pid); |
277 | fprintf(stderr, "Error: no valid sandbox\n"); | ||
278 | exit(1); | ||
279 | } | ||
280 | |||
281 | // check privileges for non-root users | ||
282 | uid_t uid = getuid(); | ||
283 | if (uid != 0) { | ||
284 | uid_t sandbox_uid = pid_get_uid(pid); | ||
285 | if (uid != sandbox_uid) { | ||
286 | fprintf(stderr, "Error: permission denied.\n"); | ||
287 | exit(1); | ||
288 | } | ||
289 | } | ||
290 | 277 | ||
291 | EUID_ROOT(); | 278 | EUID_ROOT(); |
292 | if (join_namespace(pid, "mnt")) | 279 | if (join_namespace(pid, "mnt")) |
diff --git a/src/firejail/protocol.c b/src/firejail/protocol.c index 72d29c671..d3a9e0153 100644 --- a/src/firejail/protocol.c +++ b/src/firejail/protocol.c | |||
@@ -67,21 +67,8 @@ void protocol_print_filter(pid_t pid) { | |||
67 | // in case the pid is that of a firejail process, use the pid of the first child process | 67 | // in case the pid is that of a firejail process, use the pid of the first child process |
68 | pid = switch_to_child(pid); | 68 | pid = switch_to_child(pid); |
69 | 69 | ||
70 | // now check if the pid belongs to a firejail sandbox | 70 | // exit if no permission to join the sandbox |
71 | if (invalid_sandbox(pid)) { | 71 | check_join_permission(pid); |
72 | fprintf(stderr, "Error: no valid sandbox\n"); | ||
73 | exit(1); | ||
74 | } | ||
75 | |||
76 | // check privileges for non-root users | ||
77 | uid_t uid = getuid(); | ||
78 | if (uid != 0) { | ||
79 | uid_t sandbox_uid = pid_get_uid(pid); | ||
80 | if (uid != sandbox_uid) { | ||
81 | fprintf(stderr, "Error: permission denied.\n"); | ||
82 | exit(1); | ||
83 | } | ||
84 | } | ||
85 | 72 | ||
86 | // find the seccomp filter | 73 | // find the seccomp filter |
87 | EUID_ROOT(); | 74 | EUID_ROOT(); |
diff --git a/src/firejail/seccomp.c b/src/firejail/seccomp.c index 609ebb7be..648ce1612 100644 --- a/src/firejail/seccomp.c +++ b/src/firejail/seccomp.c | |||
@@ -332,21 +332,8 @@ void seccomp_print_filter(pid_t pid) { | |||
332 | // in case the pid is that of a firejail process, use the pid of the first child process | 332 | // in case the pid is that of a firejail process, use the pid of the first child process |
333 | pid = switch_to_child(pid); | 333 | pid = switch_to_child(pid); |
334 | 334 | ||
335 | // now check if the pid belongs to a firejail sandbox | 335 | // exit if no permission to join the sandbox |
336 | if (invalid_sandbox(pid)) { | 336 | check_join_permission(pid); |
337 | fprintf(stderr, "Error: no valid sandbox\n"); | ||
338 | exit(1); | ||
339 | } | ||
340 | |||
341 | // check privileges for non-root users | ||
342 | uid_t uid = getuid(); | ||
343 | if (uid != 0) { | ||
344 | uid_t sandbox_uid = pid_get_uid(pid); | ||
345 | if (uid != sandbox_uid) { | ||
346 | fprintf(stderr, "Error: permission denied.\n"); | ||
347 | exit(1); | ||
348 | } | ||
349 | } | ||
350 | 337 | ||
351 | // find the seccomp list file | 338 | // find the seccomp list file |
352 | EUID_ROOT(); | 339 | EUID_ROOT(); |
diff --git a/src/firejail/util.c b/src/firejail/util.c index dd70d68a9..18d121ca9 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c | |||
@@ -1200,69 +1200,6 @@ errexit: | |||
1200 | exit(1); | 1200 | exit(1); |
1201 | } | 1201 | } |
1202 | 1202 | ||
1203 | |||
1204 | // return 1 if the sandbox identified by pid is not fully set up yet or if | ||
1205 | // it is no firejail sandbox at all, return 0 if the sandbox is complete | ||
1206 | int invalid_sandbox(const pid_t pid) { | ||
1207 | // check if a file "ready-for-join" exists | ||
1208 | char *fname; | ||
1209 | if (asprintf(&fname, "/proc/%d/root%s", pid, RUN_READY_FOR_JOIN) == -1) | ||
1210 | errExit("asprintf"); | ||
1211 | EUID_ROOT(); | ||
1212 | FILE *fp = fopen(fname, "re"); | ||
1213 | EUID_USER(); | ||
1214 | free(fname); | ||
1215 | if (!fp) | ||
1216 | return 1; | ||
1217 | // regular file owned by root | ||
1218 | int fd = fileno(fp); | ||
1219 | if (fd == -1) | ||
1220 | errExit("fileno"); | ||
1221 | struct stat s; | ||
1222 | if (fstat(fd, &s) == -1) | ||
1223 | errExit("fstat"); | ||
1224 | if (!S_ISREG(s.st_mode) || s.st_uid != 0) { | ||
1225 | fclose(fp); | ||
1226 | return 1; | ||
1227 | } | ||
1228 | // check if it is non-empty | ||
1229 | char buf[BUFLEN]; | ||
1230 | if (fgets(buf, BUFLEN, fp) == NULL) { | ||
1231 | fclose(fp); | ||
1232 | return 1; | ||
1233 | } | ||
1234 | fclose(fp); | ||
1235 | // confirm "ready" string was written | ||
1236 | if (strncmp(buf, "ready\n", 6) != 0) | ||
1237 | return 1; | ||
1238 | |||
1239 | // walk down the process tree a few nodes, there should be no firejail leaf | ||
1240 | #define MAXNODES 5 | ||
1241 | pid_t current = pid, next; | ||
1242 | int i; | ||
1243 | for (i = 0; i < MAXNODES; i++) { | ||
1244 | if (find_child(current, &next) == 1) { | ||
1245 | // found a leaf | ||
1246 | EUID_ROOT(); | ||
1247 | char *comm = pid_proc_comm(current); | ||
1248 | EUID_USER(); | ||
1249 | if (!comm) { | ||
1250 | fprintf(stderr, "Error: cannot read /proc file\n"); | ||
1251 | exit(1); | ||
1252 | } | ||
1253 | if (strcmp(comm, "firejail") == 0) { | ||
1254 | free(comm); | ||
1255 | return 1; | ||
1256 | } | ||
1257 | free(comm); | ||
1258 | break; | ||
1259 | } | ||
1260 | current = next; | ||
1261 | } | ||
1262 | |||
1263 | return 0; | ||
1264 | } | ||
1265 | |||
1266 | int has_handler(pid_t pid, int signal) { | 1203 | int has_handler(pid_t pid, int signal) { |
1267 | if (signal > 0 && signal <= SIGRTMAX) { | 1204 | if (signal > 0 && signal <= SIGRTMAX) { |
1268 | char *fname; | 1205 | char *fname; |
@@ -1297,21 +1234,8 @@ void enter_network_namespace(pid_t pid) { | |||
1297 | // in case the pid is that of a firejail process, use the pid of the first child process | 1234 | // in case the pid is that of a firejail process, use the pid of the first child process |
1298 | pid_t child = switch_to_child(pid); | 1235 | pid_t child = switch_to_child(pid); |
1299 | 1236 | ||
1300 | // now check if the pid belongs to a firejail sandbox | 1237 | // exit if no permission to join the sandbox |
1301 | if (invalid_sandbox(child)) { | 1238 | check_join_permission(child); |
1302 | fprintf(stderr, "Error: no valid sandbox\n"); | ||
1303 | exit(1); | ||
1304 | } | ||
1305 | |||
1306 | // check privileges for non-root users | ||
1307 | uid_t uid = getuid(); | ||
1308 | if (uid != 0) { | ||
1309 | uid_t sandbox_uid = pid_get_uid(pid); | ||
1310 | if (uid != sandbox_uid) { | ||
1311 | fprintf(stderr, "Error: permission is denied to join a sandbox created by a different user.\n"); | ||
1312 | exit(1); | ||
1313 | } | ||
1314 | } | ||
1315 | 1239 | ||
1316 | // check network namespace | 1240 | // check network namespace |
1317 | char *name; | 1241 | char *name; |