aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar netblue30 <netblue30@protonmail.com>2021-12-08 17:21:45 +0000
committerLibravatar GitHub <noreply@github.com>2021-12-08 17:21:45 +0000
commit1afa38f31ce468f18915f14e5218cea240c9b0b7 (patch)
treedb7ec8361f5ea153e949254a675803a41a4b1b33
parentMerge pull request #4744 from crocket/master (diff)
parentFix keeping certain groups with nogroups (diff)
downloadfirejail-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
-rw-r--r--src/firejail/firejail.h3
-rw-r--r--src/firejail/main.c96
-rw-r--r--src/firejail/profile.c2
-rw-r--r--src/firejail/sandbox.c2
-rw-r--r--src/firejail/util.c49
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));
506void fwarning(char* fmt, ...); 506void fwarning(char* fmt, ...);
507void fmessage(char* fmt, ...); 507void fmessage(char* fmt, ...);
508long long unsigned parse_arg_size(char *str); 508long long unsigned parse_arg_size(char *str);
509void drop_privs(int nogroups); 509int check_can_drop_all_groups();
510void drop_privs(int force_nogroups);
510int mkpath_as_root(const char* path); 511int mkpath_as_root(const char* path);
511void extract_command_name(int index, char **argv); 512void extract_command_name(int index, char **argv);
512void logsignal(int s); 513void 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
107int 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
137out:
138 return can_drop_all_groups;
139}
140
106static int find_group(gid_t group, const gid_t *groups, int ngroups) { 141static 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
219void drop_privs(int nogroups) { 257void 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