diff options
author | smitsohu <smitsohu@gmail.com> | 2019-03-16 19:05:27 +0100 |
---|---|---|
committer | smitsohu <smitsohu@gmail.com> | 2019-03-16 19:05:27 +0100 |
commit | 63b16db2a9555db0e9c4bdc1f9fc0a1d73f42b9d (patch) | |
tree | df985285a5171ef680e882487ea3bc722455d665 | |
parent | Fix assogiate's private-bin (#2603) (diff) | |
download | firejail-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).
-rw-r--r-- | src/firejail/main.c | 11 | ||||
-rw-r--r-- | src/firejail/no_sandbox.c | 25 | ||||
-rw-r--r-- | src/firejail/run_symlink.c | 13 | ||||
-rw-r--r-- | src/firejail/util.c | 13 |
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 | ||
162 | void run_no_sandbox(int argc, char **argv) { | 162 | void 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 |
121 | void drop_privs(int nogroups) { | 121 | void 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 | ||