aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar smitsohu <smitsohu@gmail.com>2021-11-20 15:06:27 +0100
committerLibravatar GitHub <noreply@github.com>2021-11-20 15:06:27 +0100
commit6acd0d3d9f8b9b0baf9a3b289db70363abf65d9e (patch)
treec9a9f344e15e1448ed68d0b92133ec31d64b76c1
parenttesting (diff)
parentConsider nosound and novideo when keeping groups (diff)
downloadfirejail-6acd0d3d9f8b9b0baf9a3b289db70363abf65d9e.tar.gz
firejail-6acd0d3d9f8b9b0baf9a3b289db70363abf65d9e.tar.zst
firejail-6acd0d3d9f8b9b0baf9a3b289db70363abf65d9e.zip
Merge pull request #4632 from kmk3/consider-nosound-novideo-groups
Consider nosound and novideo when keeping groups & misc refactors
-rw-r--r--src/firejail/main.c160
-rw-r--r--src/firejail/util.c56
2 files changed, 124 insertions, 92 deletions
diff --git a/src/firejail/main.c b/src/firejail/main.c
index 32c25c8d9..b4117bb70 100644
--- a/src/firejail/main.c
+++ b/src/firejail/main.c
@@ -3094,94 +3094,98 @@ int main(int argc, char **argv, char **envp) {
3094 } 3094 }
3095 EUID_ASSERT(); 3095 EUID_ASSERT();
3096 3096
3097 // close each end of the unused pipes 3097 // close each end of the unused pipes
3098 close(parent_to_child_fds[0]); 3098 close(parent_to_child_fds[0]);
3099 close(child_to_parent_fds[1]); 3099 close(child_to_parent_fds[1]);
3100 3100
3101 // notify child that base setup is complete 3101 // notify child that base setup is complete
3102 notify_other(parent_to_child_fds[1]); 3102 notify_other(parent_to_child_fds[1]);
3103 3103
3104 // wait for child to create new user namespace with CLONE_NEWUSER 3104 // wait for child to create new user namespace with CLONE_NEWUSER
3105 wait_for_other(child_to_parent_fds[0]); 3105 wait_for_other(child_to_parent_fds[0]);
3106 close(child_to_parent_fds[0]); 3106 close(child_to_parent_fds[0]);
3107 3107
3108 if (arg_noroot) { 3108 if (arg_noroot) {
3109 // update the UID and GID maps in the new child user namespace 3109 // update the UID and GID maps in the new child user namespace
3110 // uid 3110 // uid
3111 char *map_path; 3111 char *map_path;
3112 if (asprintf(&map_path, "/proc/%d/uid_map", child) == -1) 3112 if (asprintf(&map_path, "/proc/%d/uid_map", child) == -1)
3113 errExit("asprintf"); 3113 errExit("asprintf");
3114 3114
3115 char *map; 3115 char *map;
3116 uid_t uid = getuid(); 3116 uid_t uid = getuid();
3117 if (asprintf(&map, "%d %d 1", uid, uid) == -1) 3117 if (asprintf(&map, "%d %d 1", uid, uid) == -1)
3118 errExit("asprintf"); 3118 errExit("asprintf");
3119 EUID_ROOT(); 3119 EUID_ROOT();
3120 update_map(map, map_path); 3120 update_map(map, map_path);
3121 EUID_USER(); 3121 EUID_USER();
3122 free(map); 3122 free(map);
3123 free(map_path); 3123 free(map_path);
3124 3124
3125 // gid file 3125 // gid file
3126 if (asprintf(&map_path, "/proc/%d/gid_map", child) == -1) 3126 if (asprintf(&map_path, "/proc/%d/gid_map", child) == -1)
3127 errExit("asprintf"); 3127 errExit("asprintf");
3128 char gidmap[1024]; 3128 char gidmap[1024];
3129 char *ptr = gidmap; 3129 char *ptr = gidmap;
3130 *ptr = '\0'; 3130 *ptr = '\0';
3131 3131
3132 // add user group 3132 // add user group
3133 gid_t gid = getgid(); 3133 gid_t gid = getgid();
3134 sprintf(ptr, "%d %d 1\n", gid, gid); 3134 sprintf(ptr, "%d %d 1\n", gid, gid);
3135 ptr += strlen(ptr); 3135 ptr += strlen(ptr);
3136 3136
3137 if (!arg_nogroups) { 3137 if (!arg_nogroups) {
3138 // add firejail group 3138 // add firejail group
3139 gid_t g = get_group_id("firejail"); 3139 gid_t g = get_group_id("firejail");
3140 if (g) { 3140 if (g) {
3141 sprintf(ptr, "%d %d 1\n", g, g); 3141 sprintf(ptr, "%d %d 1\n", g, g);
3142 ptr += strlen(ptr); 3142 ptr += strlen(ptr);
3143 } 3143 }
3144 3144
3145 // add tty group 3145 // add tty group
3146 g = get_group_id("tty"); 3146 g = get_group_id("tty");
3147 if (g) { 3147 if (g) {
3148 sprintf(ptr, "%d %d 1\n", g, g); 3148 sprintf(ptr, "%d %d 1\n", g, g);
3149 ptr += strlen(ptr); 3149 ptr += strlen(ptr);
3150 } 3150 }
3151 3151
3152 // add audio group 3152 // add audio group
3153 g = get_group_id("audio"); 3153 if (!arg_nosound) {
3154 if (g) { 3154 g = get_group_id("audio");
3155 sprintf(ptr, "%d %d 1\n", g, g); 3155 if (g) {
3156 ptr += strlen(ptr); 3156 sprintf(ptr, "%d %d 1\n", g, g);
3157 } 3157 ptr += strlen(ptr);
3158 3158 }
3159 // add video group 3159 }
3160 g = get_group_id("video"); 3160
3161 if (g) { 3161 // add video group
3162 sprintf(ptr, "%d %d 1\n", g, g); 3162 if (!arg_novideo) {
3163 ptr += strlen(ptr); 3163 g = get_group_id("video");
3164 } 3164 if (g) {
3165 3165 sprintf(ptr, "%d %d 1\n", g, g);
3166 // add games group 3166 ptr += strlen(ptr);
3167 g = get_group_id("games"); 3167 }
3168 if (g) { 3168 }
3169 sprintf(ptr, "%d %d 1\n", g, g); 3169
3170 } 3170 // add games group
3171 } 3171 g = get_group_id("games");
3172 3172 if (g) {
3173 EUID_ROOT(); 3173 sprintf(ptr, "%d %d 1\n", g, g);
3174 update_map(gidmap, map_path); 3174 }
3175 EUID_USER(); 3175 }
3176 free(map_path); 3176
3177 } 3177 EUID_ROOT();
3178 update_map(gidmap, map_path);
3179 EUID_USER();
3180 free(map_path);
3181 }
3178 EUID_ASSERT(); 3182 EUID_ASSERT();
3179 3183
3180 // notify child that UID/GID mapping is complete 3184 // notify child that UID/GID mapping is complete
3181 notify_other(parent_to_child_fds[1]); 3185 notify_other(parent_to_child_fds[1]);
3182 close(parent_to_child_fds[1]); 3186 close(parent_to_child_fds[1]);
3183 3187
3184 EUID_ROOT(); 3188 EUID_ROOT();
3185 if (lockfd_network != -1) { 3189 if (lockfd_network != -1) {
3186 flock(lockfd_network, LOCK_UN); 3190 flock(lockfd_network, LOCK_UN);
3187 close(lockfd_network); 3191 close(lockfd_network);
diff --git a/src/firejail/util.c b/src/firejail/util.c
index 86977cecf..3bfb4435e 100644
--- a/src/firejail/util.c
+++ b/src/firejail/util.c
@@ -103,6 +103,36 @@ void errLogExit(char* fmt, ...) {
103 exit(1); 103 exit(1);
104} 104}
105 105
106static int find_group(gid_t group, const gid_t *groups, int ngroups) {
107 int i;
108 for (i = 0; i < ngroups; i++) {
109 if (group == groups[i])
110 return i;
111 }
112
113 return -1;
114}
115
116// Gets group from "groupname" and adds it to "new_groups" if it exists on
117// "groups". Always returns the current value of new_ngroups.
118static int copy_group_ifcont(const char *groupname,
119 const gid_t *groups, int ngroups,
120 gid_t *new_groups, int *new_ngroups, int new_sz) {
121 if (*new_ngroups >= new_sz) {
122 errno = ERANGE;
123 goto out;
124 }
125
126 gid_t g = get_group_id(groupname);
127 if (g && find_group(g, groups, ngroups) >= 0) {
128 new_groups[*new_ngroups] = g;
129 (*new_ngroups)++;
130 }
131
132out:
133 return *new_ngroups;
134}
135
106static void clean_supplementary_groups(gid_t gid) { 136static void clean_supplementary_groups(gid_t gid) {
107 assert(cfg.username); 137 assert(cfg.username);
108 gid_t groups[MAX_GROUPS]; 138 gid_t groups[MAX_GROUPS];
@@ -112,34 +142,32 @@ static void clean_supplementary_groups(gid_t gid) {
112 goto clean_all; 142 goto clean_all;
113 143
114 // clean supplementary group list 144 // clean supplementary group list
115 // allow only firejail, tty, audio, video, games
116 gid_t new_groups[MAX_GROUPS]; 145 gid_t new_groups[MAX_GROUPS];
117 int new_ngroups = 0; 146 int new_ngroups = 0;
118 char *allowed[] = { 147 char *allowed[] = {
119 "firejail", 148 "firejail",
120 "tty", 149 "tty",
121 "audio",
122 "video",
123 "games", 150 "games",
124 NULL 151 NULL
125 }; 152 };
126 153
127 int i = 0; 154 int i = 0;
128 while (allowed[i]) { 155 while (allowed[i]) {
129 gid_t g = get_group_id(allowed[i]); 156 copy_group_ifcont(allowed[i], groups, ngroups,
130 if (g) { 157 new_groups, &new_ngroups, MAX_GROUPS);
131 int j;
132 for (j = 0; j < ngroups; j++) {
133 if (g == groups[j]) {
134 new_groups[new_ngroups] = g;
135 new_ngroups++;
136 break;
137 }
138 }
139 }
140 i++; 158 i++;
141 } 159 }
142 160
161 if (!arg_nosound) {
162 copy_group_ifcont("audio", groups, ngroups,
163 new_groups, &new_ngroups, MAX_GROUPS);
164 }
165
166 if (!arg_novideo) {
167 copy_group_ifcont("video", groups, ngroups,
168 new_groups, &new_ngroups, MAX_GROUPS);
169 }
170
143 if (new_ngroups) { 171 if (new_ngroups) {
144 rv = setgroups(new_ngroups, new_groups); 172 rv = setgroups(new_ngroups, new_groups);
145 if (rv) 173 if (rv)