diff options
-rw-r--r-- | src/firejail/sandbox.c | 10 | ||||
-rw-r--r-- | src/firejail/util.c | 85 |
2 files changed, 62 insertions, 33 deletions
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index 1e60b6477..709ce96b6 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c | |||
@@ -1022,19 +1022,17 @@ int sandbox(void* sandbox_arg) { | |||
1022 | #endif | 1022 | #endif |
1023 | 1023 | ||
1024 | //**************************************** | 1024 | //**************************************** |
1025 | // drop privileges or create a new user namespace | 1025 | // create a new user namespace |
1026 | // - too early to drop privileges | ||
1026 | //**************************************** | 1027 | //**************************************** |
1027 | save_nogroups(); | 1028 | save_nogroups(); |
1028 | if (arg_noroot) { | 1029 | if (arg_noroot) { |
1029 | int rv = unshare(CLONE_NEWUSER); | 1030 | int rv = unshare(CLONE_NEWUSER); |
1030 | if (rv == -1) { | 1031 | if (rv == -1) { |
1031 | fwarning("cannot create a new user namespace, going forward without it...\n"); | 1032 | fwarning("cannot create a new user namespace, going forward without it...\n"); |
1032 | drop_privs(arg_nogroups); | ||
1033 | arg_noroot = 0; | 1033 | arg_noroot = 0; |
1034 | } | 1034 | } |
1035 | } | 1035 | } |
1036 | else | ||
1037 | drop_privs(arg_nogroups); | ||
1038 | 1036 | ||
1039 | // notify parent that new user namespace has been created so a proper | 1037 | // notify parent that new user namespace has been created so a proper |
1040 | // UID/GID map can be setup | 1038 | // UID/GID map can be setup |
@@ -1066,8 +1064,9 @@ int sandbox(void* sandbox_arg) { | |||
1066 | } | 1064 | } |
1067 | 1065 | ||
1068 | //**************************************** | 1066 | //**************************************** |
1069 | // fork the application and monitor it | 1067 | // drop privileges, fork the application and monitor it |
1070 | //**************************************** | 1068 | //**************************************** |
1069 | drop_privs(arg_nogroups); | ||
1071 | pid_t app_pid = fork(); | 1070 | pid_t app_pid = fork(); |
1072 | if (app_pid == -1) | 1071 | if (app_pid == -1) |
1073 | errExit("fork"); | 1072 | errExit("fork"); |
@@ -1085,6 +1084,7 @@ int sandbox(void* sandbox_arg) { | |||
1085 | printf("AppArmor enabled\n"); | 1084 | printf("AppArmor enabled\n"); |
1086 | } | 1085 | } |
1087 | #endif | 1086 | #endif |
1087 | |||
1088 | prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // kill the child in case the parent died | 1088 | prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // kill the child in case the parent died |
1089 | start_application(0); // start app | 1089 | start_application(0); // start app |
1090 | } | 1090 | } |
diff --git a/src/firejail/util.c b/src/firejail/util.c index c644f83a8..14e9f6440 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c | |||
@@ -32,6 +32,61 @@ | |||
32 | #include <sys/wait.h> | 32 | #include <sys/wait.h> |
33 | 33 | ||
34 | #define MAX_GROUPS 1024 | 34 | #define MAX_GROUPS 1024 |
35 | |||
36 | static void clean_supplementary_groups(gid_t gid) { | ||
37 | assert(cfg.username); | ||
38 | gid_t groups[MAX_GROUPS]; | ||
39 | int ngroups = MAX_GROUPS; | ||
40 | |||
41 | int rv = getgrouplist(cfg.username, gid, groups, &ngroups); | ||
42 | if (rv == -1) | ||
43 | goto clean_all; | ||
44 | |||
45 | // clean supplementary group list | ||
46 | // allow only tty, audio, video, games | ||
47 | gid_t new_groups[MAX_GROUPS]; | ||
48 | int new_ngroups = 0; | ||
49 | char *allowed[] = { | ||
50 | "tty", | ||
51 | "audio", | ||
52 | "video", | ||
53 | "games", | ||
54 | NULL | ||
55 | }; | ||
56 | |||
57 | int i = 0; | ||
58 | while (allowed[i]) { | ||
59 | gid_t g = get_group_id(allowed[i]); | ||
60 | if (g) { | ||
61 | int j; | ||
62 | for (j = 0; j < ngroups; j++) { | ||
63 | if (g == groups[j]) { | ||
64 | new_groups[new_ngroups] = g; | ||
65 | new_ngroups++; | ||
66 | break; | ||
67 | } | ||
68 | } | ||
69 | } | ||
70 | i++; | ||
71 | } | ||
72 | |||
73 | if (new_ngroups) { | ||
74 | rv = setgroups(new_ngroups, new_groups); | ||
75 | if (rv) | ||
76 | goto clean_all; | ||
77 | } | ||
78 | else | ||
79 | goto clean_all; | ||
80 | |||
81 | return; | ||
82 | |||
83 | clean_all: | ||
84 | fwarning("cleaning all supplementary groups\n"); | ||
85 | if (setgroups(0, NULL) < 0) | ||
86 | errExit("setgroups"); | ||
87 | } | ||
88 | |||
89 | |||
35 | // drop privileges | 90 | // drop privileges |
36 | // - for root group or if nogroups is set, supplementary groups are not configured | 91 | // - for root group or if nogroups is set, supplementary groups are not configured |
37 | void drop_privs(int nogroups) { | 92 | void drop_privs(int nogroups) { |
@@ -45,34 +100,8 @@ void drop_privs(int nogroups) { | |||
45 | if (arg_debug) | 100 | if (arg_debug) |
46 | printf("Username %s, no supplementary groups\n", cfg.username); | 101 | printf("Username %s, no supplementary groups\n", cfg.username); |
47 | } | 102 | } |
48 | else { | 103 | else if (arg_noroot) |
49 | assert(cfg.username); | 104 | clean_supplementary_groups(gid); |
50 | gid_t groups[MAX_GROUPS]; | ||
51 | int ngroups = MAX_GROUPS; | ||
52 | int rv = getgrouplist(cfg.username, gid, groups, &ngroups); | ||
53 | |||
54 | if (arg_debug && rv) { | ||
55 | printf("Username %s, groups ", cfg.username); | ||
56 | int i; | ||
57 | for (i = 0; i < ngroups; i++) | ||
58 | printf("%u, ", groups[i]); | ||
59 | printf("\n"); | ||
60 | } | ||
61 | |||
62 | if (rv == -1) { | ||
63 | fwarning("cannot extract supplementary group list, dropping them\n"); | ||
64 | if (setgroups(0, NULL) < 0) | ||
65 | errExit("setgroups"); | ||
66 | } | ||
67 | else { | ||
68 | rv = setgroups(ngroups, groups); | ||
69 | if (rv) { | ||
70 | fwarning("cannot set supplementary group list, dropping them\n"); | ||
71 | if (setgroups(0, NULL) < 0) | ||
72 | errExit("setgroups"); | ||
73 | } | ||
74 | } | ||
75 | } | ||
76 | 105 | ||
77 | // set uid/gid | 106 | // set uid/gid |
78 | if (setgid(getgid()) < 0) | 107 | if (setgid(getgid()) < 0) |