diff options
-rw-r--r-- | src/firejail/dhcp.c | 10 | ||||
-rw-r--r-- | src/firejail/sbox.c | 51 |
2 files changed, 38 insertions, 23 deletions
diff --git a/src/firejail/dhcp.c b/src/firejail/dhcp.c index 4a7806a7f..bc5d68a5e 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) { | |||
88 | static pid_t dhcp_read_pidfile(const Dhclient *client) { | 88 | static 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; |
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 | |||
29 | static struct sock_filter filter[] = { | 34 | static 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 | ||