diff options
author | netblue30 <netblue30@protonmail.com> | 2021-12-08 17:21:45 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-08 17:21:45 +0000 |
commit | 1afa38f31ce468f18915f14e5218cea240c9b0b7 (patch) | |
tree | db7ec8361f5ea153e949254a675803a41a4b1b33 /src | |
parent | Merge pull request #4744 from crocket/master (diff) | |
parent | Fix keeping certain groups with nogroups (diff) | |
download | firejail-1afa38f31ce468f18915f14e5218cea240c9b0b7.tar.gz firejail-1afa38f31ce468f18915f14e5218cea240c9b0b7.tar.zst firejail-1afa38f31ce468f18915f14e5218cea240c9b0b7.zip |
Merge pull request #4732 from kmk3/fix-groups-misc3
Fix keeping certain groups with nogroups
Diffstat (limited to 'src')
-rw-r--r-- | src/firejail/firejail.h | 3 | ||||
-rw-r--r-- | src/firejail/main.c | 96 | ||||
-rw-r--r-- | src/firejail/profile.c | 2 | ||||
-rw-r--r-- | src/firejail/sandbox.c | 2 | ||||
-rw-r--r-- | src/firejail/util.c | 49 |
5 files changed, 97 insertions, 55 deletions
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index a7673ae20..c04a644f4 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -506,7 +506,8 @@ void errLogExit(char* fmt, ...) __attribute__((noreturn)); | |||
506 | void fwarning(char* fmt, ...); | 506 | void fwarning(char* fmt, ...); |
507 | void fmessage(char* fmt, ...); | 507 | void fmessage(char* fmt, ...); |
508 | long long unsigned parse_arg_size(char *str); | 508 | long long unsigned parse_arg_size(char *str); |
509 | void drop_privs(int nogroups); | 509 | int check_can_drop_all_groups(); |
510 | void drop_privs(int force_nogroups); | ||
510 | int mkpath_as_root(const char* path); | 511 | int mkpath_as_root(const char* path); |
511 | void extract_command_name(int index, char **argv); | 512 | void extract_command_name(int index, char **argv); |
512 | void logsignal(int s); | 513 | void logsignal(int s); |
diff --git a/src/firejail/main.c b/src/firejail/main.c index 59e88bdc6..0262db608 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c | |||
@@ -2642,7 +2642,7 @@ int main(int argc, char **argv, char **envp) { | |||
2642 | else if (cfg.dns4 == NULL) | 2642 | else if (cfg.dns4 == NULL) |
2643 | cfg.dns4 = dns; | 2643 | cfg.dns4 = dns; |
2644 | else { | 2644 | else { |
2645 | fwarning("Warning: up to 4 DNS servers can be specified, %s ignored\n", dns); | 2645 | fwarning("up to 4 DNS servers can be specified, %s ignored\n", dns); |
2646 | free(dns); | 2646 | free(dns); |
2647 | } | 2647 | } |
2648 | } | 2648 | } |
@@ -3155,62 +3155,64 @@ int main(int argc, char **argv, char **envp) { | |||
3155 | ptr += strlen(ptr); | 3155 | ptr += strlen(ptr); |
3156 | 3156 | ||
3157 | gid_t g; | 3157 | gid_t g; |
3158 | // add audio group | 3158 | if (!arg_nogroups || !check_can_drop_all_groups()) { |
3159 | if (!arg_nosound) { | 3159 | // add audio group |
3160 | g = get_group_id("audio"); | 3160 | if (!arg_nosound) { |
3161 | if (g) { | 3161 | g = get_group_id("audio"); |
3162 | sprintf(ptr, "%d %d 1\n", g, g); | 3162 | if (g) { |
3163 | ptr += strlen(ptr); | 3163 | sprintf(ptr, "%d %d 1\n", g, g); |
3164 | ptr += strlen(ptr); | ||
3165 | } | ||
3164 | } | 3166 | } |
3165 | } | ||
3166 | 3167 | ||
3167 | // add video group | 3168 | // add video group |
3168 | if (!arg_novideo) { | 3169 | if (!arg_novideo) { |
3169 | g = get_group_id("video"); | 3170 | g = get_group_id("video"); |
3170 | if (g) { | 3171 | if (g) { |
3171 | sprintf(ptr, "%d %d 1\n", g, g); | 3172 | sprintf(ptr, "%d %d 1\n", g, g); |
3172 | ptr += strlen(ptr); | 3173 | ptr += strlen(ptr); |
3174 | } | ||
3173 | } | 3175 | } |
3174 | } | ||
3175 | 3176 | ||
3176 | // add render group | 3177 | // add render group |
3177 | if (!arg_no3d) { | 3178 | if (!arg_no3d) { |
3178 | g = get_group_id("render"); | 3179 | g = get_group_id("render"); |
3179 | if (g) { | 3180 | if (g) { |
3180 | sprintf(ptr, "%d %d 1\n", g, g); | 3181 | sprintf(ptr, "%d %d 1\n", g, g); |
3181 | ptr += strlen(ptr); | 3182 | ptr += strlen(ptr); |
3183 | } | ||
3182 | } | 3184 | } |
3183 | } | ||
3184 | 3185 | ||
3185 | // add lp group | 3186 | // add lp group |
3186 | if (!arg_noprinters) { | 3187 | if (!arg_noprinters) { |
3187 | g = get_group_id("lp"); | 3188 | g = get_group_id("lp"); |
3188 | if (g) { | 3189 | if (g) { |
3189 | sprintf(ptr, "%d %d 1\n", g, g); | 3190 | sprintf(ptr, "%d %d 1\n", g, g); |
3190 | ptr += strlen(ptr); | 3191 | ptr += strlen(ptr); |
3192 | } | ||
3191 | } | 3193 | } |
3192 | } | ||
3193 | 3194 | ||
3194 | // add cdrom/optical groups | 3195 | // add cdrom/optical groups |
3195 | if (!arg_nodvd) { | 3196 | if (!arg_nodvd) { |
3196 | g = get_group_id("cdrom"); | 3197 | g = get_group_id("cdrom"); |
3197 | if (g) { | 3198 | if (g) { |
3198 | sprintf(ptr, "%d %d 1\n", g, g); | 3199 | sprintf(ptr, "%d %d 1\n", g, g); |
3199 | ptr += strlen(ptr); | 3200 | ptr += strlen(ptr); |
3200 | } | 3201 | } |
3201 | g = get_group_id("optical"); | 3202 | g = get_group_id("optical"); |
3202 | if (g) { | 3203 | if (g) { |
3203 | sprintf(ptr, "%d %d 1\n", g, g); | 3204 | sprintf(ptr, "%d %d 1\n", g, g); |
3204 | ptr += strlen(ptr); | 3205 | ptr += strlen(ptr); |
3206 | } | ||
3205 | } | 3207 | } |
3206 | } | ||
3207 | 3208 | ||
3208 | // add input group | 3209 | // add input group |
3209 | if (!arg_noinput) { | 3210 | if (!arg_noinput) { |
3210 | g = get_group_id("input"); | 3211 | g = get_group_id("input"); |
3211 | if (g) { | 3212 | if (g) { |
3212 | sprintf(ptr, "%d %d 1\n", g, g); | 3213 | sprintf(ptr, "%d %d 1\n", g, g); |
3213 | ptr += strlen(ptr); | 3214 | ptr += strlen(ptr); |
3215 | } | ||
3214 | } | 3216 | } |
3215 | } | 3217 | } |
3216 | 3218 | ||
diff --git a/src/firejail/profile.c b/src/firejail/profile.c index 756b370aa..5e24591fa 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c | |||
@@ -1106,7 +1106,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
1106 | else if (cfg.dns4 == NULL) | 1106 | else if (cfg.dns4 == NULL) |
1107 | cfg.dns4 = dns; | 1107 | cfg.dns4 = dns; |
1108 | else { | 1108 | else { |
1109 | fwarning("Warning: up to 4 DNS servers can be specified, %s ignored\n", dns); | 1109 | fwarning("up to 4 DNS servers can be specified, %s ignored\n", dns); |
1110 | free(dns); | 1110 | free(dns); |
1111 | } | 1111 | } |
1112 | return 0; | 1112 | return 0; |
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index 3887b5701..96fa4c81a 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c | |||
@@ -1225,7 +1225,7 @@ int sandbox(void* sandbox_arg) { | |||
1225 | //**************************************** | 1225 | //**************************************** |
1226 | // drop privileges | 1226 | // drop privileges |
1227 | //**************************************** | 1227 | //**************************************** |
1228 | drop_privs(arg_nogroups); | 1228 | drop_privs(0); |
1229 | 1229 | ||
1230 | // kill the sandbox in case the parent died | 1230 | // kill the sandbox in case the parent died |
1231 | prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); | 1231 | prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); |
diff --git a/src/firejail/util.c b/src/firejail/util.c index 97afe9649..c1c31b43c 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c | |||
@@ -103,6 +103,41 @@ void errLogExit(char* fmt, ...) { | |||
103 | exit(1); | 103 | exit(1); |
104 | } | 104 | } |
105 | 105 | ||
106 | // Returns whether all supplementary groups can be safely dropped | ||
107 | int check_can_drop_all_groups() { | ||
108 | static int can_drop_all_groups = -1; | ||
109 | |||
110 | // Avoid needlessly checking (and printing) things twice | ||
111 | if (can_drop_all_groups != -1) | ||
112 | goto out; | ||
113 | |||
114 | // nvidia cards require video group; ignore nogroups | ||
115 | if (access("/dev/nvidiactl", R_OK) == 0 && arg_no3d == 0) { | ||
116 | fwarning("NVIDIA card detected, nogroups command ignored\n"); | ||
117 | can_drop_all_groups = 0; | ||
118 | goto out; | ||
119 | } | ||
120 | |||
121 | /* When we are not sure that the system has working seat-based ACLs | ||
122 | * (e.g.: probably yes on (e)udev + (e)logind, probably not on eudev + | ||
123 | * seatd), supplementary groups (e.g.: audio and input) might be needed | ||
124 | * to avoid breakage (e.g.: audio or gamepads not working). See #4600 | ||
125 | * and #4603. | ||
126 | */ | ||
127 | if (access("/run/systemd/seats/", F_OK) != 0) { | ||
128 | fwarning("logind not detected, nogroups command ignored\n"); | ||
129 | can_drop_all_groups = 0; | ||
130 | goto out; | ||
131 | } | ||
132 | |||
133 | if (arg_debug) | ||
134 | fprintf(stderr, "nogroups command not ignored\n"); | ||
135 | can_drop_all_groups = 1; | ||
136 | |||
137 | out: | ||
138 | return can_drop_all_groups; | ||
139 | } | ||
140 | |||
106 | static int find_group(gid_t group, const gid_t *groups, int ngroups) { | 141 | static int find_group(gid_t group, const gid_t *groups, int ngroups) { |
107 | int i; | 142 | int i; |
108 | for (i = 0; i < ngroups; i++) { | 143 | for (i = 0; i < ngroups; i++) { |
@@ -141,6 +176,9 @@ static void clean_supplementary_groups(gid_t gid) { | |||
141 | if (rv == -1) | 176 | if (rv == -1) |
142 | goto clean_all; | 177 | goto clean_all; |
143 | 178 | ||
179 | if (arg_nogroups && check_can_drop_all_groups()) | ||
180 | goto clean_all; | ||
181 | |||
144 | // clean supplementary group list | 182 | // clean supplementary group list |
145 | gid_t new_groups[MAX_GROUPS]; | 183 | gid_t new_groups[MAX_GROUPS]; |
146 | int new_ngroups = 0; | 184 | int new_ngroups = 0; |
@@ -215,21 +253,22 @@ clean_all: | |||
215 | 253 | ||
216 | 254 | ||
217 | // drop privileges | 255 | // drop privileges |
218 | // - for root group or if nogroups is set, supplementary groups are not configured | 256 | // - for root group or if force_nogroups is set, supplementary groups are not configured |
219 | void drop_privs(int nogroups) { | 257 | void drop_privs(int force_nogroups) { |
220 | gid_t gid = getgid(); | 258 | gid_t gid = getgid(); |
221 | if (arg_debug) | 259 | if (arg_debug) |
222 | printf("Drop privileges: pid %d, uid %d, gid %d, nogroups %d\n", getpid(), getuid(), gid, nogroups); | 260 | printf("Drop privileges: pid %d, uid %d, gid %d, force_nogroups %d\n", |
261 | getpid(), getuid(), gid, force_nogroups); | ||
223 | 262 | ||
224 | // configure supplementary groups | 263 | // configure supplementary groups |
225 | EUID_ROOT(); | 264 | EUID_ROOT(); |
226 | if (gid == 0 || nogroups) { | 265 | if (gid == 0 || force_nogroups) { |
227 | if (setgroups(0, NULL) < 0) | 266 | if (setgroups(0, NULL) < 0) |
228 | errExit("setgroups"); | 267 | errExit("setgroups"); |
229 | if (arg_debug) | 268 | if (arg_debug) |
230 | printf("No supplementary groups\n"); | 269 | printf("No supplementary groups\n"); |
231 | } | 270 | } |
232 | else if (arg_noroot) | 271 | else if (arg_noroot || arg_nogroups) |
233 | clean_supplementary_groups(gid); | 272 | clean_supplementary_groups(gid); |
234 | 273 | ||
235 | // set uid/gid | 274 | // set uid/gid |