summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar smitsohu <smitsohu@gmail.com>2019-03-16 19:05:27 +0100
committerLibravatar smitsohu <smitsohu@gmail.com>2019-03-16 19:05:27 +0100
commit63b16db2a9555db0e9c4bdc1f9fc0a1d73f42b9d (patch)
treedf985285a5171ef680e882487ea3bc722455d665 /src
parentFix assogiate's private-bin (#2603) (diff)
downloadfirejail-63b16db2a9555db0e9c4bdc1f9fc0a1d73f42b9d.tar.gz
firejail-63b16db2a9555db0e9c4bdc1f9fc0a1d73f42b9d.tar.zst
firejail-63b16db2a9555db0e9c4bdc1f9fc0a1d73f42b9d.zip
hardening: replace setuid/setgid calls with setresuid/setresgid
when nesting containers and sandboxes, it is possible setuid() fails silently to reset the saved uid, which is then cleared only by the next execve. This is solved by replacing setuid() with more robust setresuid() function calls. Also add code to drop privileges when entering the run_no_sandbox() function (along with some minor tidy up).
Diffstat (limited to 'src')
-rw-r--r--src/firejail/main.c11
-rw-r--r--src/firejail/no_sandbox.c25
-rw-r--r--src/firejail/run_symlink.c13
-rw-r--r--src/firejail/util.c13
4 files changed, 32 insertions, 30 deletions
diff --git a/src/firejail/main.c b/src/firejail/main.c
index e02554c5e..a9af46b6f 100644
--- a/src/firejail/main.c
+++ b/src/firejail/main.c
@@ -866,11 +866,12 @@ static void run_builder(int argc, char **argv) {
866 (void) argc; 866 (void) argc;
867 867
868 // drop privileges 868 // drop privileges
869 EUID_ROOT(); 869 gid_t gid = getgid();
870 if (setgid(getgid()) < 0) 870 uid_t uid = getuid();
871 errExit("setgid/getgid"); 871 if (setresgid(gid, gid, gid) != 0)
872 if (setuid(getuid()) < 0) 872 errExit("setresgid");
873 errExit("setuid/getuid"); 873 if (setresuid(uid, uid, uid) != 0)
874 errExit("setresuid");
874 875
875 assert(getenv("LD_PRELOAD") == NULL); 876 assert(getenv("LD_PRELOAD") == NULL);
876 umask(orig_umask); 877 umask(orig_umask);
diff --git a/src/firejail/no_sandbox.c b/src/firejail/no_sandbox.c
index 9ad4e8ba1..096f34cc5 100644
--- a/src/firejail/no_sandbox.c
+++ b/src/firejail/no_sandbox.c
@@ -161,32 +161,31 @@ int check_kernel_procs(void) {
161 161
162void run_no_sandbox(int argc, char **argv) { 162void run_no_sandbox(int argc, char **argv) {
163 EUID_ASSERT(); 163 EUID_ASSERT();
164 // drop privileges
165 gid_t gid = getgid();
166 uid_t uid = getuid();
167 if (setresgid(gid, gid, gid) != 0)
168 errExit("setresgid");
169 if (setresuid(uid, uid, uid) != 0)
170 errExit("setresuid");
164 171
165 // process limited subset of options 172 // process limited subset of options
166 int i; 173 int i;
167 for (i = 0; i < argc; i++) { 174 for (i = 0; i < argc; i++) {
168 if (strcmp(argv[i], "--debug") == 0) 175 if (strcmp(argv[i], "--debug") == 0)
169 arg_debug = 1; 176 arg_debug = 1;
170 else if (strcmp(argv[i], "--shell=none") == 0 || 177 else if (strncmp(argv[i], "--shell=", 8) == 0)
171 strncmp(argv[i], "--shell=", 8) == 0)
172 fwarning("shell-related command line options are disregarded - using SHELL environment variable\n"); 178 fwarning("shell-related command line options are disregarded - using SHELL environment variable\n");
173 } 179 }
174 180
175 // use $SHELL to get shell used in sandbox 181 // use $SHELL to get shell used in sandbox, guess shell otherwise
176 char *shell = getenv("SHELL"); 182 cfg.shell = guess_shell();
177 if (shell && access(shell, R_OK) == 0)
178 cfg.shell = shell;
179
180 // guess shell otherwise
181 if (!cfg.shell) {
182 cfg.shell = guess_shell();
183 if (arg_debug)
184 printf("Autoselecting %s as shell\n", cfg.shell);
185 }
186 if (!cfg.shell) { 183 if (!cfg.shell) {
187 fprintf(stderr, "Error: unable to guess your shell, please set SHELL environment variable\n"); 184 fprintf(stderr, "Error: unable to guess your shell, please set SHELL environment variable\n");
188 exit(1); 185 exit(1);
189 } 186 }
187 else if (arg_debug)
188 printf("Selecting %s as shell\n", cfg.shell);
190 189
191 int prog_index = 0; 190 int prog_index = 0;
192 // find first non option arg: 191 // find first non option arg:
diff --git a/src/firejail/run_symlink.c b/src/firejail/run_symlink.c
index ee62bba32..e10f90850 100644
--- a/src/firejail/run_symlink.c
+++ b/src/firejail/run_symlink.c
@@ -34,11 +34,12 @@ void run_symlink(int argc, char **argv, int run_as_is) {
34 return; 34 return;
35 35
36 // drop privileges 36 // drop privileges
37 EUID_ROOT(); 37 gid_t gid = getgid();
38 if (setgid(getgid()) < 0) 38 uid_t uid = getuid();
39 errExit("setgid/getgid"); 39 if (setresgid(gid, gid, gid) != 0)
40 if (setuid(getuid()) < 0) 40 errExit("setresgid");
41 errExit("setuid/getuid"); 41 if (setresuid(uid, uid, uid) != 0)
42 errExit("setresuid");
42 43
43 // find the real program by looking in PATH 44 // find the real program by looking in PATH
44 char *p = getenv("PATH"); 45 char *p = getenv("PATH");
@@ -94,7 +95,7 @@ void run_symlink(int argc, char **argv, int run_as_is) {
94 umask(orig_umask); 95 umask(orig_umask);
95 96
96 // desktop integration is not supported for root user; instead, the original program is started 97 // desktop integration is not supported for root user; instead, the original program is started
97 if (getuid() == 0 || run_as_is) { 98 if (uid == 0 || run_as_is) {
98 argv[0] = program; 99 argv[0] = program;
99 execv(program, argv); 100 execv(program, argv);
100 exit(1); 101 exit(1);
diff --git a/src/firejail/util.c b/src/firejail/util.c
index dd298a31a..52f0f89c5 100644
--- a/src/firejail/util.c
+++ b/src/firejail/util.c
@@ -119,12 +119,13 @@ clean_all:
119// drop privileges 119// drop privileges
120// - for root group or if nogroups is set, supplementary groups are not configured 120// - for root group or if nogroups is set, supplementary groups are not configured
121void drop_privs(int nogroups) { 121void drop_privs(int nogroups) {
122 EUID_ROOT();
123 gid_t gid = getgid(); 122 gid_t gid = getgid();
123 uid_t uid = getuid();
124 if (arg_debug) 124 if (arg_debug)
125 printf("Drop privileges: pid %d, uid %d, gid %d, nogroups %d\n", getpid(), getuid(), gid, nogroups); 125 printf("Drop privileges: pid %d, uid %d, gid %d, nogroups %d\n", getpid(), uid, gid, nogroups);
126 126
127 // configure supplementary groups 127 // configure supplementary groups
128 EUID_ROOT();
128 if (gid == 0 || nogroups) { 129 if (gid == 0 || nogroups) {
129 if (setgroups(0, NULL) < 0) 130 if (setgroups(0, NULL) < 0)
130 errExit("setgroups"); 131 errExit("setgroups");
@@ -135,10 +136,10 @@ void drop_privs(int nogroups) {
135 clean_supplementary_groups(gid); 136 clean_supplementary_groups(gid);
136 137
137 // set uid/gid 138 // set uid/gid
138 if (setgid(getgid()) < 0) 139 if (setresgid(gid, gid, gid) != 0)
139 errExit("setgid/getgid"); 140 errExit("setresgid");
140 if (setuid(getuid()) < 0) 141 if (setresuid(uid, uid, uid) != 0)
141 errExit("setuid/getuid"); 142 errExit("setresuid");
142} 143}
143 144
144 145