diff options
-rw-r--r-- | src/firejail/firejail.h | 2 | ||||
-rw-r--r-- | src/firejail/join.c | 2 | ||||
-rw-r--r-- | src/firejail/list.c | 12 | ||||
-rw-r--r-- | src/firejail/main.c | 35 | ||||
-rw-r--r-- | src/include/euid_common.h | 48 | ||||
-rw-r--r-- | src/lib/common.c | 1 |
6 files changed, 92 insertions, 8 deletions
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 2662cc1d7..577c1a9ae 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -20,6 +20,8 @@ | |||
20 | #ifndef FIREJAIL_H | 20 | #ifndef FIREJAIL_H |
21 | #define FIREJAIL_H | 21 | #define FIREJAIL_H |
22 | #include "../include/common.h" | 22 | #include "../include/common.h" |
23 | #include "../include/euid_common.h" | ||
24 | |||
23 | 25 | ||
24 | // filesystem | 26 | // filesystem |
25 | #define RUN_FIREJAIL_BASEDIR "/run" | 27 | #define RUN_FIREJAIL_BASEDIR "/run" |
diff --git a/src/firejail/join.c b/src/firejail/join.c index b05e25387..e471e4a21 100644 --- a/src/firejail/join.c +++ b/src/firejail/join.c | |||
@@ -183,12 +183,12 @@ void join_name(const char *name, const char *homedir, int argc, char **argv, int | |||
183 | fprintf(stderr, "Error: invalid sandbox name\n"); | 183 | fprintf(stderr, "Error: invalid sandbox name\n"); |
184 | exit(1); | 184 | exit(1); |
185 | } | 185 | } |
186 | |||
186 | pid_t pid; | 187 | pid_t pid; |
187 | if (name2pid(name, &pid)) { | 188 | if (name2pid(name, &pid)) { |
188 | fprintf(stderr, "Error: cannot find sandbox %s\n", name); | 189 | fprintf(stderr, "Error: cannot find sandbox %s\n", name); |
189 | exit(1); | 190 | exit(1); |
190 | } | 191 | } |
191 | |||
192 | join(pid, homedir, argc, argv, index); | 192 | join(pid, homedir, argc, argv, index); |
193 | } | 193 | } |
194 | 194 | ||
diff --git a/src/firejail/list.c b/src/firejail/list.c index 7a3cf0aad..d5ef1ac2c 100644 --- a/src/firejail/list.c +++ b/src/firejail/list.c | |||
@@ -20,7 +20,8 @@ | |||
20 | #include "firejail.h" | 20 | #include "firejail.h" |
21 | 21 | ||
22 | void top(void) { | 22 | void top(void) { |
23 | drop_privs(1); | 23 | if (getuid() != geteuid()) |
24 | drop_privs(1); | ||
24 | 25 | ||
25 | char *arg[4]; | 26 | char *arg[4]; |
26 | arg[0] = "bash"; | 27 | arg[0] = "bash"; |
@@ -31,7 +32,8 @@ void top(void) { | |||
31 | } | 32 | } |
32 | 33 | ||
33 | void netstats(void) { | 34 | void netstats(void) { |
34 | drop_privs(1); | 35 | if (getuid() != geteuid()) |
36 | drop_privs(1); | ||
35 | 37 | ||
36 | char *arg[4]; | 38 | char *arg[4]; |
37 | arg[0] = "bash"; | 39 | arg[0] = "bash"; |
@@ -42,7 +44,8 @@ void netstats(void) { | |||
42 | } | 44 | } |
43 | 45 | ||
44 | void list(void) { | 46 | void list(void) { |
45 | drop_privs(1); | 47 | if (getuid() != geteuid()) |
48 | drop_privs(1); | ||
46 | 49 | ||
47 | char *arg[4]; | 50 | char *arg[4]; |
48 | arg[0] = "bash"; | 51 | arg[0] = "bash"; |
@@ -53,7 +56,8 @@ void list(void) { | |||
53 | } | 56 | } |
54 | 57 | ||
55 | void tree(void) { | 58 | void tree(void) { |
56 | drop_privs(1); | 59 | if (getuid() != geteuid()) |
60 | drop_privs(1); | ||
57 | 61 | ||
58 | char *arg[4]; | 62 | char *arg[4]; |
59 | arg[0] = "bash"; | 63 | arg[0] = "bash"; |
diff --git a/src/firejail/main.c b/src/firejail/main.c index 6fd011868..688653ce2 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c | |||
@@ -45,6 +45,8 @@ printf("time %s:%d %u\n", __FILE__, __LINE__, (uint32_t) systick); | |||
45 | } | 45 | } |
46 | #endif | 46 | #endif |
47 | 47 | ||
48 | uid_t firejail_uid = 0; | ||
49 | |||
48 | #define STACK_SIZE (1024 * 1024) | 50 | #define STACK_SIZE (1024 * 1024) |
49 | static char child_stack[STACK_SIZE]; // space for child's stack | 51 | static char child_stack[STACK_SIZE]; // space for child's stack |
50 | Config cfg; // configuration | 52 | Config cfg; // configuration |
@@ -124,11 +126,13 @@ static void my_handler(int s){ | |||
124 | 126 | ||
125 | static void extract_user_data(void) { | 127 | static void extract_user_data(void) { |
126 | // check suid | 128 | // check suid |
129 | EUID_ROOT(); | ||
127 | if (geteuid()) { | 130 | if (geteuid()) { |
128 | fprintf(stderr, "Error: the sandbox is not setuid root\n"); | 131 | fprintf(stderr, "Error: the sandbox is not setuid root\n"); |
129 | exit(1); | 132 | exit(1); |
130 | } | 133 | } |
131 | 134 | EUID_USER(); | |
135 | |||
132 | struct passwd *pw = getpwuid(getuid()); | 136 | struct passwd *pw = getpwuid(getuid()); |
133 | if (!pw) | 137 | if (!pw) |
134 | errExit("getpwuid"); | 138 | errExit("getpwuid"); |
@@ -315,6 +319,7 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
315 | 319 | ||
316 | // extract pid or sandbox name | 320 | // extract pid or sandbox name |
317 | pid_t pid; | 321 | pid_t pid; |
322 | EUID_ROOT(); | ||
318 | if (read_pid(argv[i] + 12, &pid) == 0) | 323 | if (read_pid(argv[i] + 12, &pid) == 0) |
319 | bandwidth_pid(pid, cmd, dev, down, up); | 324 | bandwidth_pid(pid, cmd, dev, down, up); |
320 | else | 325 | else |
@@ -337,6 +342,7 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
337 | else if (strncmp(argv[i], "--seccomp.print=", 16) == 0) { | 342 | else if (strncmp(argv[i], "--seccomp.print=", 16) == 0) { |
338 | // print seccomp filter for a sandbox specified by pid or by name | 343 | // print seccomp filter for a sandbox specified by pid or by name |
339 | pid_t pid; | 344 | pid_t pid; |
345 | EUID_ROOT(); | ||
340 | if (read_pid(argv[i] + 16, &pid) == 0) | 346 | if (read_pid(argv[i] + 16, &pid) == 0) |
341 | seccomp_print_filter(pid); | 347 | seccomp_print_filter(pid); |
342 | else | 348 | else |
@@ -350,6 +356,7 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
350 | else if (strncmp(argv[i], "--protocol.print=", 17) == 0) { | 356 | else if (strncmp(argv[i], "--protocol.print=", 17) == 0) { |
351 | // print seccomp filter for a sandbox specified by pid or by name | 357 | // print seccomp filter for a sandbox specified by pid or by name |
352 | pid_t pid; | 358 | pid_t pid; |
359 | EUID_ROOT(); | ||
353 | if (read_pid(argv[i] + 17, &pid) == 0) | 360 | if (read_pid(argv[i] + 17, &pid) == 0) |
354 | protocol_print_filter(pid); | 361 | protocol_print_filter(pid); |
355 | else | 362 | else |
@@ -360,6 +367,7 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
360 | else if (strncmp(argv[i], "--caps.print=", 13) == 0) { | 367 | else if (strncmp(argv[i], "--caps.print=", 13) == 0) { |
361 | // join sandbox by pid or by name | 368 | // join sandbox by pid or by name |
362 | pid_t pid; | 369 | pid_t pid; |
370 | EUID_ROOT(); | ||
363 | if (read_pid(argv[i] + 13, &pid) == 0) | 371 | if (read_pid(argv[i] + 13, &pid) == 0) |
364 | caps_print_filter(pid); | 372 | caps_print_filter(pid); |
365 | else | 373 | else |
@@ -369,6 +377,7 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
369 | else if (strncmp(argv[i], "--fs.print=", 11) == 0) { | 377 | else if (strncmp(argv[i], "--fs.print=", 11) == 0) { |
370 | // join sandbox by pid or by name | 378 | // join sandbox by pid or by name |
371 | pid_t pid; | 379 | pid_t pid; |
380 | EUID_ROOT(); | ||
372 | if (read_pid(argv[i] + 11, &pid) == 0) | 381 | if (read_pid(argv[i] + 11, &pid) == 0) |
373 | fs_logger_print_log(pid); | 382 | fs_logger_print_log(pid); |
374 | else | 383 | else |
@@ -378,6 +387,7 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
378 | else if (strncmp(argv[i], "--dns.print=", 12) == 0) { | 387 | else if (strncmp(argv[i], "--dns.print=", 12) == 0) { |
379 | // join sandbox by pid or by name | 388 | // join sandbox by pid or by name |
380 | pid_t pid; | 389 | pid_t pid; |
390 | EUID_ROOT(); | ||
381 | if (read_pid(argv[i] + 12, &pid) == 0) | 391 | if (read_pid(argv[i] + 12, &pid) == 0) |
382 | net_dns_print(pid); | 392 | net_dns_print(pid); |
383 | else | 393 | else |
@@ -411,6 +421,7 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
411 | 421 | ||
412 | // join sandbox by pid or by name | 422 | // join sandbox by pid or by name |
413 | pid_t pid; | 423 | pid_t pid; |
424 | EUID_ROOT(); | ||
414 | if (read_pid(argv[i] + 7, &pid) == 0) | 425 | if (read_pid(argv[i] + 7, &pid) == 0) |
415 | join(pid, cfg.homedir, argc, argv, i + 1); | 426 | join(pid, cfg.homedir, argc, argv, i + 1); |
416 | else | 427 | else |
@@ -456,6 +467,7 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
456 | 467 | ||
457 | // shutdown sandbox by pid or by name | 468 | // shutdown sandbox by pid or by name |
458 | pid_t pid; | 469 | pid_t pid; |
470 | EUID_ROOT(); | ||
459 | if (read_pid(argv[i] + 11, &pid) == 0) | 471 | if (read_pid(argv[i] + 11, &pid) == 0) |
460 | shut(pid); | 472 | shut(pid); |
461 | else | 473 | else |
@@ -480,6 +492,10 @@ int main(int argc, char **argv) { | |||
480 | #ifdef HAVE_SECCOMP | 492 | #ifdef HAVE_SECCOMP |
481 | int highest_errno = errno_highest_nr(); | 493 | int highest_errno = errno_highest_nr(); |
482 | #endif | 494 | #endif |
495 | |||
496 | // drop permissions by default and rise them when required | ||
497 | EUID_INIT(); | ||
498 | EUID_USER(); | ||
483 | 499 | ||
484 | // check argv[0] symlink wrapper if this is not a login shell | 500 | // check argv[0] symlink wrapper if this is not a login shell |
485 | if (*argv[0] != '-') | 501 | if (*argv[0] != '-') |
@@ -517,10 +533,12 @@ int main(int argc, char **argv) { | |||
517 | srand(t ^ sandbox_pid); | 533 | srand(t ^ sandbox_pid); |
518 | 534 | ||
519 | // check firejail directories | 535 | // check firejail directories |
536 | EUID_ROOT(); | ||
520 | fs_build_firejail_dir(); | 537 | fs_build_firejail_dir(); |
521 | shm_create_firejail_dir(); | 538 | shm_create_firejail_dir(); |
522 | bandwidth_shm_del_file(sandbox_pid); | 539 | bandwidth_shm_del_file(sandbox_pid); |
523 | 540 | EUID_USER(); | |
541 | |||
524 | // is this a login shell? | 542 | // is this a login shell? |
525 | if (*argv[0] == '-') { | 543 | if (*argv[0] == '-') { |
526 | fullargc = restricted_shell(cfg.username); | 544 | fullargc = restricted_shell(cfg.username); |
@@ -1449,6 +1467,7 @@ int main(int argc, char **argv) { | |||
1449 | 1467 | ||
1450 | // check and assign an IP address - for macvlan it will be done again in the sandbox! | 1468 | // check and assign an IP address - for macvlan it will be done again in the sandbox! |
1451 | if (any_bridge_configured()) { | 1469 | if (any_bridge_configured()) { |
1470 | EUID_ROOT(); | ||
1452 | lockfd = open(RUN_NETWORK_LOCK_FILE, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); | 1471 | lockfd = open(RUN_NETWORK_LOCK_FILE, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); |
1453 | if (lockfd != -1) { | 1472 | if (lockfd != -1) { |
1454 | int rv = fchown(lockfd, 0, 0); | 1473 | int rv = fchown(lockfd, 0, 0); |
@@ -1463,6 +1482,7 @@ int main(int argc, char **argv) { | |||
1463 | 1482 | ||
1464 | // save network mapping in shared memory | 1483 | // save network mapping in shared memory |
1465 | network_shm_set_file(sandbox_pid); | 1484 | network_shm_set_file(sandbox_pid); |
1485 | EUID_USER(); | ||
1466 | } | 1486 | } |
1467 | 1487 | ||
1468 | // create the parent-child communication pipe | 1488 | // create the parent-child communication pipe |
@@ -1494,12 +1514,14 @@ int main(int argc, char **argv) { | |||
1494 | else if (arg_debug) | 1514 | else if (arg_debug) |
1495 | printf("Using the local network stack\n"); | 1515 | printf("Using the local network stack\n"); |
1496 | 1516 | ||
1517 | EUID_ROOT(); | ||
1497 | child = clone(sandbox, | 1518 | child = clone(sandbox, |
1498 | child_stack + STACK_SIZE, | 1519 | child_stack + STACK_SIZE, |
1499 | flags, | 1520 | flags, |
1500 | NULL); | 1521 | NULL); |
1501 | if (child == -1) | 1522 | if (child == -1) |
1502 | errExit("clone"); | 1523 | errExit("clone"); |
1524 | EUID_USER(); | ||
1503 | 1525 | ||
1504 | if (!arg_command && !arg_quiet) { | 1526 | if (!arg_command && !arg_quiet) { |
1505 | printf("Parent pid %u, child pid %u\n", sandbox_pid, child); | 1527 | printf("Parent pid %u, child pid %u\n", sandbox_pid, child); |
@@ -1508,7 +1530,8 @@ int main(int argc, char **argv) { | |||
1508 | printf("The new log directory is /proc/%d/root/var/log\n", child); | 1530 | printf("The new log directory is /proc/%d/root/var/log\n", child); |
1509 | } | 1531 | } |
1510 | 1532 | ||
1511 | 1533 | ||
1534 | EUID_ROOT(); | ||
1512 | if (!arg_nonetwork) { | 1535 | if (!arg_nonetwork) { |
1513 | // create veth pair or macvlan device | 1536 | // create veth pair or macvlan device |
1514 | if (cfg.bridge0.configured) { | 1537 | if (cfg.bridge0.configured) { |
@@ -1554,6 +1577,7 @@ int main(int argc, char **argv) { | |||
1554 | net_move_interface(cfg.interface3.dev, child); | 1577 | net_move_interface(cfg.interface3.dev, child); |
1555 | } | 1578 | } |
1556 | } | 1579 | } |
1580 | EUID_USER(); | ||
1557 | 1581 | ||
1558 | // close each end of the unused pipes | 1582 | // close each end of the unused pipes |
1559 | close(parent_to_child_fds[0]); | 1583 | close(parent_to_child_fds[0]); |
@@ -1576,7 +1600,9 @@ int main(int argc, char **argv) { | |||
1576 | uid_t uid = getuid(); | 1600 | uid_t uid = getuid(); |
1577 | if (asprintf(&map, "%d %d 1", uid, uid) == -1) | 1601 | if (asprintf(&map, "%d %d 1", uid, uid) == -1) |
1578 | errExit("asprintf"); | 1602 | errExit("asprintf"); |
1603 | EUID_ROOT(); | ||
1579 | update_map(map, map_path); | 1604 | update_map(map, map_path); |
1605 | EUID_USER(); | ||
1580 | free(map); | 1606 | free(map); |
1581 | free(map_path); | 1607 | free(map_path); |
1582 | 1608 | ||
@@ -1586,7 +1612,9 @@ int main(int argc, char **argv) { | |||
1586 | gid_t gid = getgid(); | 1612 | gid_t gid = getgid(); |
1587 | if (asprintf(&map, "%d %d 1", gid, gid) == -1) | 1613 | if (asprintf(&map, "%d %d 1", gid, gid) == -1) |
1588 | errExit("asprintf"); | 1614 | errExit("asprintf"); |
1615 | EUID_ROOT(); | ||
1589 | update_map(map, map_path); | 1616 | update_map(map, map_path); |
1617 | EUID_USER(); | ||
1590 | free(map); | 1618 | free(map); |
1591 | free(map_path); | 1619 | free(map_path); |
1592 | } | 1620 | } |
@@ -1595,6 +1623,7 @@ int main(int argc, char **argv) { | |||
1595 | notify_other(parent_to_child_fds[1]); | 1623 | notify_other(parent_to_child_fds[1]); |
1596 | close(parent_to_child_fds[1]); | 1624 | close(parent_to_child_fds[1]); |
1597 | 1625 | ||
1626 | EUID_ROOT(); | ||
1598 | if (lockfd != -1) | 1627 | if (lockfd != -1) |
1599 | flock(lockfd, LOCK_UN); | 1628 | flock(lockfd, LOCK_UN); |
1600 | 1629 | ||
diff --git a/src/include/euid_common.h b/src/include/euid_common.h new file mode 100644 index 000000000..1cba548ab --- /dev/null +++ b/src/include/euid_common.h | |||
@@ -0,0 +1,48 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014-2016 netblue30 (netblue30@yahoo.com) | ||
3 | * | ||
4 | * This file is part of firejail project | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef EUID_COMMON_H | ||
22 | #define EUID_COMMON_H | ||
23 | #include <stdio.h> | ||
24 | #include <sys/types.h> | ||
25 | #include <unistd.h> | ||
26 | |||
27 | extern uid_t firejail_uid; | ||
28 | extern uid_t firejail_uid_switch; | ||
29 | |||
30 | static inline void EUID_ROOT(void) { | ||
31 | if (seteuid(0) == -1) | ||
32 | fprintf(stderr, "Error: cannot switch euid to root\n"); | ||
33 | } | ||
34 | |||
35 | static inline void EUID_USER(void) { | ||
36 | if (seteuid(firejail_uid) == -1) | ||
37 | fprintf(stderr, "Error: cannot switch euid to user\n"); | ||
38 | } | ||
39 | |||
40 | static inline void EUID_PRINT(void) { | ||
41 | printf("debug: uid %d, euid %d\n", getuid(), geteuid()); | ||
42 | } | ||
43 | |||
44 | static inline void EUID_INIT(void) { | ||
45 | firejail_uid = getuid(); | ||
46 | } | ||
47 | |||
48 | #endif | ||
diff --git a/src/lib/common.c b/src/lib/common.c index d23cd589e..099bb54d3 100644 --- a/src/lib/common.c +++ b/src/lib/common.c | |||
@@ -58,6 +58,7 @@ int join_namespace(pid_t pid, char *type) { | |||
58 | } | 58 | } |
59 | 59 | ||
60 | // return 1 if error | 60 | // return 1 if error |
61 | // this function requires root access - todo: fix it! | ||
61 | int name2pid(const char *name, pid_t *pid) { | 62 | int name2pid(const char *name, pid_t *pid) { |
62 | pid_t parent = getpid(); | 63 | pid_t parent = getpid(); |
63 | 64 | ||