aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kris7topher@gmail.com>2020-02-23 22:04:13 +0100
committerLibravatar GitHub <noreply@github.com>2020-02-23 22:04:13 +0100
commit683c3973185ed4e5f978517cecf18691f9ccfe53 (patch)
treedc7ac5c91d12672f2ba24cf7e6214c554a02ecbe /src
parentMerge pull request #3239 from kris7t/dhcp-client (diff)
parentRemove redundant permission check from dhcp_start (diff)
downloadfirejail-683c3973185ed4e5f978517cecf18691f9ccfe53.tar.gz
firejail-683c3973185ed4e5f978517cecf18691f9ccfe53.tar.zst
firejail-683c3973185ed4e5f978517cecf18691f9ccfe53.zip
Merge pull request #3241 from kris7t/sbox-harden-exec
Harden sbox_run by using fexecve instead of execvp
Diffstat (limited to 'src')
-rw-r--r--src/firejail/dhcp.c14
-rw-r--r--src/firejail/sbox.c51
2 files changed, 38 insertions, 27 deletions
diff --git a/src/firejail/dhcp.c b/src/firejail/dhcp.c
index 4a7806a7f..37547a985 100644
--- a/src/firejail/dhcp.c
+++ b/src/firejail/dhcp.c
@@ -88,9 +88,6 @@ static void dhcp_run_dhclient(char *dhclient_path, const Dhclient *client) {
88static pid_t dhcp_read_pidfile(const Dhclient *client) { 88static pid_t dhcp_read_pidfile(const Dhclient *client) {
89 // We have to run dhclient as a forking daemon (not pass the -d option), 89 // We have to run dhclient as a forking daemon (not pass the -d option),
90 // because we want to be notified of a successful DHCP lease by the parent process exit. 90 // because we want to be notified of a successful DHCP lease by the parent process exit.
91 // However, try to be extra paranoid with race conditions,
92 // because dhclient only writes the daemon pid into the pidfile
93 // after its parent process has exited.
94 int tries = 0; 91 int tries = 0;
95 pid_t found = 0; 92 pid_t found = 0;
96 while (found == 0 && tries < 10) { 93 while (found == 0 && tries < 10) {
@@ -99,11 +96,8 @@ static pid_t dhcp_read_pidfile(const Dhclient *client) {
99 FILE *pidfile = fopen(client->pid_file, "r"); 96 FILE *pidfile = fopen(client->pid_file, "r");
100 if (pidfile) { 97 if (pidfile) {
101 long pid; 98 long pid;
102 if (fscanf(pidfile, "%ld", &pid) == 1) { 99 if (fscanf(pidfile, "%ld", &pid) == 1)
103 char *pidname = pid_proc_comm((pid_t) pid); 100 found = (pid_t) pid;
104 if (pidname && strcmp(pidname, "dhclient") == 0)
105 found = (pid_t) pid;
106 }
107 fclose(pidfile); 101 fclose(pidfile);
108 } 102 }
109 ++tries; 103 ++tries;
@@ -149,10 +143,6 @@ void dhcp_start(void) {
149 exit(1); 143 exit(1);
150 } 144 }
151 } 145 }
152 if (s.st_uid != 0 && s.st_gid != 0) {
153 fprintf(stderr, "Error: invalid dhclient executable\n");
154 exit(1);
155 }
156 146
157 EUID_ROOT(); 147 EUID_ROOT();
158 if (mkdir(RUN_DHCLIENT_DIR, 0700)) 148 if (mkdir(RUN_DHCLIENT_DIR, 0700))
diff --git a/src/firejail/sbox.c b/src/firejail/sbox.c
index 77ca07a81..c3b68f3a8 100644
--- a/src/firejail/sbox.c
+++ b/src/firejail/sbox.c
@@ -26,6 +26,11 @@
26 #include <sys/wait.h> 26 #include <sys/wait.h>
27#include "../include/seccomp.h" 27#include "../include/seccomp.h"
28 28
29#include <fcntl.h>
30#ifndef O_PATH
31#define O_PATH 010000000
32#endif
33
29static struct sock_filter filter[] = { 34static struct sock_filter filter[] = {
30 VALIDATE_ARCHITECTURE, 35 VALIDATE_ARCHITECTURE,
31 EXAMINE_SYSCALL, 36 EXAMINE_SYSCALL,
@@ -140,24 +145,19 @@ int sbox_run_v(unsigned filtermask, char * const arg[]) {
140 if (child < 0) 145 if (child < 0)
141 errExit("fork"); 146 errExit("fork");
142 if (child == 0) { 147 if (child == 0) {
148 int env_index = 0;
149 char *new_environment[256] = { NULL };
143 // preserve firejail-specific env vars 150 // preserve firejail-specific env vars
144 char *cl = getenv("FIREJAIL_FILE_COPY_LIMIT"); 151 char *cl = getenv("FIREJAIL_FILE_COPY_LIMIT");
145 if (cl) { 152 if (cl) {
146 // duplicate the value, who knows what's going to happen with it in clearenv! 153 if (asprintf(&new_environment[env_index++], "FIREJAIL_FILE_COPY_LIMIT=%s", cl) == -1)
147 cl = strdup(cl); 154 errExit("asprintf");
148 if (!cl)
149 errExit("strdup");
150 } 155 }
151 clearenv(); 156 clearenv();
152 if (cl) {
153 if (setenv("FIREJAIL_FILE_COPY_LIMIT", cl, 1) == -1)
154 errExit("setenv");
155 free(cl);
156 }
157 if (arg_quiet) // --quiet is passed as an environment variable 157 if (arg_quiet) // --quiet is passed as an environment variable
158 setenv("FIREJAIL_QUIET", "yes", 1); 158 new_environment[env_index++] = "FIREJAIL_QUIET=yes";
159 if (arg_debug) // --debug is passed as an environment variable 159 if (arg_debug) // --debug is passed as an environment variable
160 setenv("FIREJAIL_DEBUG", "yes", 1); 160 new_environment[env_index++] = "FIREJAIL_DEBUG=yes";
161 161
162 if (filtermask & SBOX_STDIN_FROM_FILE) { 162 if (filtermask & SBOX_STDIN_FROM_FILE) {
163 int fd; 163 int fd;
@@ -237,11 +237,32 @@ int sbox_run_v(unsigned filtermask, char * const arg[]) {
237 else if (filtermask & SBOX_USER) 237 else if (filtermask & SBOX_USER)
238 drop_privs(1); 238 drop_privs(1);
239 239
240 if (arg[0]) // get rid of scan-build warning 240 if (arg[0]) { // get rid of scan-build warning
241 execvp(arg[0], arg); 241 int fd = open(arg[0], O_PATH | O_CLOEXEC);
242 else 242 if (fd == -1) {
243 if (errno == ENOENT) {
244 fprintf(stderr, "Error: %s does not exist\n", arg[0]);
245 exit(1);
246 } else {
247 errExit("open");
248 }
249 }
250 struct stat s;
251 if (fstat(fd, &s) == -1)
252 errExit("fstat");
253 if (s.st_uid != 0 && s.st_gid != 0) {
254 fprintf(stderr, "Error: %s is not owned by root, refusing to execute\n", arg[0]);
255 exit(1);
256 }
257 if (s.st_mode & 00002) {
258 fprintf(stderr, "Error: %s is world writable, refusing to execute\n", arg[0]);
259 exit(1);
260 }
261 fexecve(fd, arg, new_environment);
262 } else {
243 assert(0); 263 assert(0);
244 perror("execvp"); 264 }
265 perror("fexecve");
245 _exit(1); 266 _exit(1);
246 } 267 }
247 268