diff options
author | smitsohu <smitsohu@gmail.com> | 2018-08-20 23:34:28 +0200 |
---|---|---|
committer | smitsohu <smitsohu@gmail.com> | 2018-08-20 23:34:28 +0200 |
commit | ec7f59b8d370c29bd229fa9124640611c0667159 (patch) | |
tree | 30b12ce89fd04343aa5cbf5b5254ce63cb8af9fc /src/firejail | |
parent | Document how to access local mail with thunderbird and claws-mail (fixes #1509) (diff) | |
download | firejail-ec7f59b8d370c29bd229fa9124640611c0667159.tar.gz firejail-ec7f59b8d370c29bd229fa9124640611c0667159.tar.zst firejail-ec7f59b8d370c29bd229fa9124640611c0667159.zip |
refactor, check the sandbox status for all join options
Diffstat (limited to 'src/firejail')
-rw-r--r-- | src/firejail/bandwidth.c | 5 | ||||
-rw-r--r-- | src/firejail/caps.c | 19 | ||||
-rw-r--r-- | src/firejail/cpu.c | 19 | ||||
-rw-r--r-- | src/firejail/firejail.h | 2 | ||||
-rw-r--r-- | src/firejail/fs_logger.c | 19 | ||||
-rw-r--r-- | src/firejail/join.c | 94 | ||||
-rw-r--r-- | src/firejail/ls.c | 19 | ||||
-rw-r--r-- | src/firejail/netfilter.c | 5 | ||||
-rw-r--r-- | src/firejail/network_main.c | 19 | ||||
-rw-r--r-- | src/firejail/protocol.c | 19 | ||||
-rw-r--r-- | src/firejail/seccomp.c | 19 | ||||
-rw-r--r-- | src/firejail/util.c | 62 |
12 files changed, 145 insertions, 156 deletions
diff --git a/src/firejail/bandwidth.c b/src/firejail/bandwidth.c index 49a94186c..d7764682a 100644 --- a/src/firejail/bandwidth.c +++ b/src/firejail/bandwidth.c | |||
@@ -333,6 +333,11 @@ void bandwidth_pid(pid_t pid, const char *command, const char *dev, int down, in | |||
333 | exit(1); | 333 | exit(1); |
334 | } | 334 | } |
335 | 335 | ||
336 | if (invalid_sandbox(child)) { | ||
337 | fprintf(stderr, "Error: cannot join the network namespace\n"); | ||
338 | exit(1); | ||
339 | } | ||
340 | |||
336 | EUID_ROOT(); | 341 | EUID_ROOT(); |
337 | if (join_namespace(child, "net")) { | 342 | if (join_namespace(child, "net")) { |
338 | fprintf(stderr, "Error: cannot join the network namespace\n"); | 343 | fprintf(stderr, "Error: cannot join the network namespace\n"); |
diff --git a/src/firejail/caps.c b/src/firejail/caps.c index dae45d9df..bd3b5e229 100644 --- a/src/firejail/caps.c +++ b/src/firejail/caps.c | |||
@@ -401,18 +401,13 @@ errexit: | |||
401 | void caps_print_filter(pid_t pid) { | 401 | void caps_print_filter(pid_t pid) { |
402 | EUID_ASSERT(); | 402 | EUID_ASSERT(); |
403 | 403 | ||
404 | // if the pid is that of a firejail process, use the pid of the first child process | 404 | // in case the pid is that of a firejail process, use the pid of the first child process |
405 | EUID_ROOT(); // grsecurity | 405 | pid = switch_to_child(pid); |
406 | char *comm = pid_proc_comm(pid); | 406 | |
407 | EUID_USER(); // grsecurity | 407 | // now check if the pid belongs to a firejail sandbox |
408 | if (comm) { | 408 | if (invalid_sandbox(pid)) { |
409 | if (strcmp(comm, "firejail") == 0) { | 409 | fprintf(stderr, "Error: no valid sandbox\n"); |
410 | pid_t child; | 410 | exit(1); |
411 | if (find_child(pid, &child) == 0) { | ||
412 | pid = child; | ||
413 | } | ||
414 | } | ||
415 | free(comm); | ||
416 | } | 411 | } |
417 | 412 | ||
418 | // check privileges for non-root users | 413 | // check privileges for non-root users |
diff --git a/src/firejail/cpu.c b/src/firejail/cpu.c index 8f72fb69e..a92562e67 100644 --- a/src/firejail/cpu.c +++ b/src/firejail/cpu.c | |||
@@ -165,18 +165,13 @@ static void print_cpu(int pid) { | |||
165 | void cpu_print_filter(pid_t pid) { | 165 | void cpu_print_filter(pid_t pid) { |
166 | EUID_ASSERT(); | 166 | EUID_ASSERT(); |
167 | 167 | ||
168 | // if the pid is that of a firejail process, use the pid of the first child process | 168 | // in case the pid is that of a firejail process, use the pid of the first child process |
169 | EUID_ROOT(); // grsecurity | 169 | pid = switch_to_child(pid); |
170 | char *comm = pid_proc_comm(pid); | 170 | |
171 | EUID_USER(); // grsecurity | 171 | // now check if the pid belongs to a firejail sandbox |
172 | if (comm) { | 172 | if (invalid_sandbox(pid)) { |
173 | if (strcmp(comm, "firejail") == 0) { | 173 | fprintf(stderr, "Error: no valid sandbox\n"); |
174 | pid_t child; | 174 | exit(1); |
175 | if (find_child(pid, &child) == 0) { | ||
176 | pid = child; | ||
177 | } | ||
178 | } | ||
179 | free(comm); | ||
180 | } | 175 | } |
181 | 176 | ||
182 | // check privileges for non-root users | 177 | // check privileges for non-root users |
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 348e4f6ab..906ec6307 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -478,6 +478,7 @@ void usage(void); | |||
478 | 478 | ||
479 | // join.c | 479 | // join.c |
480 | void join(pid_t pid, int argc, char **argv, int index); | 480 | void join(pid_t pid, int argc, char **argv, int index); |
481 | pid_t switch_to_child(pid_t pid); | ||
481 | 482 | ||
482 | // shutdown.c | 483 | // shutdown.c |
483 | void shut(pid_t pid); | 484 | void shut(pid_t pid); |
@@ -538,6 +539,7 @@ unsigned extract_timeout(const char *str); | |||
538 | void disable_file_or_dir(const char *fname); | 539 | void disable_file_or_dir(const char *fname); |
539 | void disable_file_path(const char *path, const char *file); | 540 | void disable_file_path(const char *path, const char *file); |
540 | int safe_fd(const char *path, int flags); | 541 | int safe_fd(const char *path, int flags); |
542 | int invalid_sandbox(const pid_t pid); | ||
541 | 543 | ||
542 | // Get info regarding the last kernel mount operation from /proc/self/mountinfo | 544 | // Get info regarding the last kernel mount operation from /proc/self/mountinfo |
543 | // The return value points to a static area, and will be overwritten by subsequent calls. | 545 | // The return value points to a static area, and will be overwritten by subsequent calls. |
diff --git a/src/firejail/fs_logger.c b/src/firejail/fs_logger.c index 93f28a26b..bf3ac26be 100644 --- a/src/firejail/fs_logger.c +++ b/src/firejail/fs_logger.c | |||
@@ -120,18 +120,13 @@ void fs_logger_change_owner(void) { | |||
120 | void fs_logger_print_log(pid_t pid) { | 120 | void fs_logger_print_log(pid_t pid) { |
121 | EUID_ASSERT(); | 121 | EUID_ASSERT(); |
122 | 122 | ||
123 | // if the pid is that of a firejail process, use the pid of the first child process | 123 | // in case the pid is that of a firejail process, use the pid of the first child process |
124 | EUID_ROOT(); | 124 | pid = switch_to_child(pid); |
125 | char *comm = pid_proc_comm(pid); | 125 | |
126 | EUID_USER(); | 126 | // now check if the pid belongs to a firejail sandbox |
127 | if (comm) { | 127 | if (invalid_sandbox(pid)) { |
128 | if (strcmp(comm, "firejail") == 0) { | 128 | fprintf(stderr, "Error: no valid sandbox\n"); |
129 | pid_t child; | 129 | exit(1); |
130 | if (find_child(pid, &child) == 0) { | ||
131 | pid = child; | ||
132 | } | ||
133 | } | ||
134 | free(comm); | ||
135 | } | 130 | } |
136 | 131 | ||
137 | // check privileges for non-root users | 132 | // check privileges for non-root users |
diff --git a/src/firejail/join.c b/src/firejail/join.c index 910e97d07..cdd95b6a8 100644 --- a/src/firejail/join.c +++ b/src/firejail/join.c | |||
@@ -223,52 +223,7 @@ static void extract_umask(pid_t pid) { | |||
223 | fclose(fp); | 223 | fclose(fp); |
224 | } | 224 | } |
225 | 225 | ||
226 | static void check_ready_for_join(pid_t pid) { | 226 | pid_t switch_to_child(pid_t pid) { |
227 | char *fname; | ||
228 | if (asprintf(&fname, "/proc/%d/root%s", pid, RUN_READY_FOR_JOIN) == -1) | ||
229 | errExit("asprintf"); | ||
230 | |||
231 | // check if file "ready-for-join" exists | ||
232 | EUID_ROOT(); | ||
233 | FILE *fp = fopen(fname, "re"); | ||
234 | EUID_USER(); | ||
235 | if (!fp) | ||
236 | goto errexit; | ||
237 | int fd = fileno(fp); | ||
238 | if (fd == -1) | ||
239 | errExit("fileno"); | ||
240 | struct stat s; | ||
241 | if (fstat(fd, &s) == -1) | ||
242 | errExit("fstat"); | ||
243 | if (!S_ISREG(s.st_mode) || s.st_uid != 0) | ||
244 | goto errexit; | ||
245 | // check if it is non-empty | ||
246 | char buf[BUFLEN]; | ||
247 | if (fgets(buf, BUFLEN, fp) == NULL) | ||
248 | goto errexit; | ||
249 | // confirm "ready" string was written | ||
250 | if (strncmp(buf, "ready\n", 6) != 0) | ||
251 | goto errexit; | ||
252 | fclose(fp); | ||
253 | free(fname); | ||
254 | return; | ||
255 | |||
256 | errexit: | ||
257 | fprintf(stderr, "Error: no valid sandbox\n"); | ||
258 | exit(1); | ||
259 | } | ||
260 | |||
261 | |||
262 | |||
263 | void join(pid_t pid, int argc, char **argv, int index) { | ||
264 | EUID_ASSERT(); | ||
265 | char *homedir = cfg.homedir; | ||
266 | pid_t parent = pid; | ||
267 | |||
268 | extract_command(argc, argv, index); | ||
269 | signal (SIGTERM, signal_handler); | ||
270 | |||
271 | // if the pid is that of a firejail process, use the pid of the first child process | ||
272 | EUID_ROOT(); | 227 | EUID_ROOT(); |
273 | errno = 0; | 228 | errno = 0; |
274 | char *comm = pid_proc_comm(pid); | 229 | char *comm = pid_proc_comm(pid); |
@@ -278,7 +233,7 @@ void join(pid_t pid, int argc, char **argv, int index) { | |||
278 | exit(1); | 233 | exit(1); |
279 | } | 234 | } |
280 | else { | 235 | else { |
281 | fprintf(stderr, "Error: cannot read /proc/%d/comm\n", pid); | 236 | fprintf(stderr, "Error: cannot read /proc file\n"); |
282 | exit(1); | 237 | exit(1); |
283 | } | 238 | } |
284 | } | 239 | } |
@@ -286,38 +241,33 @@ void join(pid_t pid, int argc, char **argv, int index) { | |||
286 | if (strcmp(comm, "firejail") == 0) { | 241 | if (strcmp(comm, "firejail") == 0) { |
287 | pid_t child; | 242 | pid_t child; |
288 | if (find_child(pid, &child) == 1) { | 243 | if (find_child(pid, &child) == 1) { |
289 | fprintf(stderr, "Error: found firejail process without a child process\n"); | 244 | fprintf(stderr, "Error: no valid sandbox\n"); |
290 | exit(1); | 245 | exit(1); |
291 | } | 246 | } |
292 | fmessage("Switching to pid %u, the first child process inside the sandbox\n", (unsigned) child); | 247 | fmessage("Switching to pid %u, the first child process inside the sandbox\n", (unsigned) child); |
293 | pid = child; | 248 | pid = child; |
294 | } | 249 | } |
295 | free(comm); | 250 | free(comm); |
251 | return pid; | ||
252 | } | ||
296 | 253 | ||
297 | // pid must belong to a valid firejail sandbox | 254 | |
298 | check_ready_for_join(pid); | 255 | |
299 | 256 | void join(pid_t pid, int argc, char **argv, int index) { | |
300 | // walk down the process tree a few nodes, there should be no firejail leaf | 257 | EUID_ASSERT(); |
301 | #define MAXNODES 4 | 258 | char *homedir = cfg.homedir; |
302 | pid_t current = pid, next; | 259 | pid_t parent = pid; |
303 | int i; | 260 | |
304 | for (i = 0; i < MAXNODES; i++) { | 261 | extract_command(argc, argv, index); |
305 | if (find_child(current, &next) == 1) { | 262 | signal (SIGTERM, signal_handler); |
306 | EUID_ROOT(); | 263 | |
307 | comm = pid_proc_comm(current); | 264 | // in case the pid is that of a firejail process, use the pid of the first child process |
308 | EUID_USER(); | 265 | pid = switch_to_child(pid); |
309 | if (!comm) { | 266 | |
310 | fprintf(stderr, "Error: cannot read /proc/%d/comm\n", current); | 267 | // now check if the pid belongs to a firejail sandbox |
311 | exit(1); | 268 | if (invalid_sandbox(pid)) { |
312 | } | 269 | fprintf(stderr, "Error: no valid sandbox\n"); |
313 | if (strcmp(comm, "firejail") == 0) { | 270 | exit(1); |
314 | fprintf(stderr, "Error: found firejail process without a child process\n"); | ||
315 | exit(1); | ||
316 | } | ||
317 | free(comm); | ||
318 | break; | ||
319 | } | ||
320 | current = next; | ||
321 | } | 271 | } |
322 | 272 | ||
323 | // check privileges for non-root users | 273 | // check privileges for non-root users |
diff --git a/src/firejail/ls.c b/src/firejail/ls.c index 601cab4f8..51370da60 100644 --- a/src/firejail/ls.c +++ b/src/firejail/ls.c | |||
@@ -212,18 +212,13 @@ void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) { | |||
212 | EUID_ASSERT(); | 212 | EUID_ASSERT(); |
213 | assert(path1); | 213 | assert(path1); |
214 | 214 | ||
215 | // if the pid is that of a firejail process, use the pid of the first child process | 215 | // in case the pid is that of a firejail process, use the pid of the first child process |
216 | EUID_ROOT(); | 216 | pid = switch_to_child(pid); |
217 | char *comm = pid_proc_comm(pid); | 217 | |
218 | EUID_USER(); | 218 | // now check if the pid belongs to a firejail sandbox |
219 | if (comm) { | 219 | if (invalid_sandbox(pid)) { |
220 | if (strcmp(comm, "firejail") == 0) { | 220 | fprintf(stderr, "Error: no valid sandbox\n"); |
221 | pid_t child; | 221 | exit(1); |
222 | if (find_child(pid, &child) == 0) { | ||
223 | pid = child; | ||
224 | } | ||
225 | } | ||
226 | free(comm); | ||
227 | } | 222 | } |
228 | 223 | ||
229 | // check privileges for non-root users | 224 | // check privileges for non-root users |
diff --git a/src/firejail/netfilter.c b/src/firejail/netfilter.c index 11c7e9669..8fbd11bba 100644 --- a/src/firejail/netfilter.c +++ b/src/firejail/netfilter.c | |||
@@ -175,6 +175,11 @@ void netfilter_print(pid_t pid, int ipv6) { | |||
175 | exit(1); | 175 | exit(1); |
176 | } | 176 | } |
177 | 177 | ||
178 | if (invalid_sandbox(child)) { | ||
179 | fprintf(stderr, "Error: cannot join the network namespace\n"); | ||
180 | exit(1); | ||
181 | } | ||
182 | |||
178 | EUID_ROOT(); | 183 | EUID_ROOT(); |
179 | if (join_namespace(child, "net")) { | 184 | if (join_namespace(child, "net")) { |
180 | fprintf(stderr, "Error: cannot join the network namespace\n"); | 185 | fprintf(stderr, "Error: cannot join the network namespace\n"); |
diff --git a/src/firejail/network_main.c b/src/firejail/network_main.c index 1a40e8a0f..e3c750767 100644 --- a/src/firejail/network_main.c +++ b/src/firejail/network_main.c | |||
@@ -269,18 +269,13 @@ void net_dns_print(pid_t pid) { | |||
269 | EUID_ASSERT(); | 269 | EUID_ASSERT(); |
270 | // drop privileges - will not be able to read /etc/resolv.conf for --noroot option | 270 | // drop privileges - will not be able to read /etc/resolv.conf for --noroot option |
271 | 271 | ||
272 | // if the pid is that of a firejail process, use the pid of the first child process | 272 | // in case the pid is that of a firejail process, use the pid of the first child process |
273 | EUID_ROOT(); | 273 | pid = switch_to_child(pid); |
274 | char *comm = pid_proc_comm(pid); | 274 | |
275 | EUID_USER(); | 275 | // now check if the pid belongs to a firejail sandbox |
276 | if (comm) { | 276 | if (invalid_sandbox(pid)) { |
277 | if (strcmp(comm, "firejail") == 0) { | 277 | fprintf(stderr, "Error: no valid sandbox\n"); |
278 | pid_t child; | 278 | exit(1); |
279 | if (find_child(pid, &child) == 0) { | ||
280 | pid = child; | ||
281 | } | ||
282 | } | ||
283 | free(comm); | ||
284 | } | 279 | } |
285 | 280 | ||
286 | // check privileges for non-root users | 281 | // check privileges for non-root users |
diff --git a/src/firejail/protocol.c b/src/firejail/protocol.c index eb3763253..9989ddb68 100644 --- a/src/firejail/protocol.c +++ b/src/firejail/protocol.c | |||
@@ -64,18 +64,13 @@ void protocol_print_filter(pid_t pid) { | |||
64 | 64 | ||
65 | (void) pid; | 65 | (void) pid; |
66 | #ifdef SYS_socket | 66 | #ifdef SYS_socket |
67 | // if the pid is that of a firejail process, use the pid of the first child process | 67 | // in case the pid is that of a firejail process, use the pid of the first child process |
68 | EUID_ROOT(); | 68 | pid = switch_to_child(pid); |
69 | char *comm = pid_proc_comm(pid); | 69 | |
70 | EUID_USER(); | 70 | // now check if the pid belongs to a firejail sandbox |
71 | if (comm) { | 71 | if (invalid_sandbox(pid)) { |
72 | if (strcmp(comm, "firejail") == 0) { | 72 | fprintf(stderr, "Error: no valid sandbox\n"); |
73 | pid_t child; | 73 | exit(1); |
74 | if (find_child(pid, &child) == 0) { | ||
75 | pid = child; | ||
76 | } | ||
77 | } | ||
78 | free(comm); | ||
79 | } | 74 | } |
80 | 75 | ||
81 | // check privileges for non-root users | 76 | // check privileges for non-root users |
diff --git a/src/firejail/seccomp.c b/src/firejail/seccomp.c index 3da0206e1..7be7b3950 100644 --- a/src/firejail/seccomp.c +++ b/src/firejail/seccomp.c | |||
@@ -295,18 +295,13 @@ int seccomp_filter_keep(void) { | |||
295 | void seccomp_print_filter(pid_t pid) { | 295 | void seccomp_print_filter(pid_t pid) { |
296 | EUID_ASSERT(); | 296 | EUID_ASSERT(); |
297 | 297 | ||
298 | // if the pid is that of a firejail process, use the pid of the first child process | 298 | // in case the pid is that of a firejail process, use the pid of the first child process |
299 | EUID_ROOT(); | 299 | pid = switch_to_child(pid); |
300 | char *comm = pid_proc_comm(pid); | 300 | |
301 | EUID_USER(); | 301 | // now check if the pid belongs to a firejail sandbox |
302 | if (comm) { | 302 | if (invalid_sandbox(pid)) { |
303 | if (strcmp(comm, "firejail") == 0) { | 303 | fprintf(stderr, "Error: no valid sandbox\n"); |
304 | pid_t child; | 304 | exit(1); |
305 | if (find_child(pid, &child) == 0) { | ||
306 | pid = child; | ||
307 | } | ||
308 | } | ||
309 | free(comm); | ||
310 | } | 305 | } |
311 | 306 | ||
312 | // check privileges for non-root users | 307 | // check privileges for non-root users |
diff --git a/src/firejail/util.c b/src/firejail/util.c index 5738e7cf8..c15e3b691 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c | |||
@@ -1090,3 +1090,65 @@ errexit: | |||
1090 | fprintf(stderr, "Error: cannot open \"%s\", invalid filename\n", path); | 1090 | fprintf(stderr, "Error: cannot open \"%s\", invalid filename\n", path); |
1091 | exit(1); | 1091 | exit(1); |
1092 | } | 1092 | } |
1093 | |||
1094 | |||
1095 | // return 1 if the sandbox identified by pid is not fully set up yet or if | ||
1096 | // it is no firejail sandbox at all, return 0 if the sandbox is complete | ||
1097 | int invalid_sandbox(const pid_t pid) { | ||
1098 | // check if a file "ready-for-join" exists | ||
1099 | char *fname; | ||
1100 | if (asprintf(&fname, "/proc/%d/root%s", pid, RUN_READY_FOR_JOIN) == -1) | ||
1101 | errExit("asprintf"); | ||
1102 | EUID_ROOT(); | ||
1103 | FILE *fp = fopen(fname, "re"); | ||
1104 | EUID_USER(); | ||
1105 | free(fname); | ||
1106 | if (!fp) | ||
1107 | return 1; | ||
1108 | // regular file owned by root | ||
1109 | int fd = fileno(fp); | ||
1110 | if (fd == -1) | ||
1111 | errExit("fileno"); | ||
1112 | struct stat s; | ||
1113 | if (fstat(fd, &s) == -1) | ||
1114 | errExit("fstat"); | ||
1115 | if (!S_ISREG(s.st_mode) || s.st_uid != 0) { | ||
1116 | fclose(fp); | ||
1117 | return 1; | ||
1118 | } | ||
1119 | // check if it is non-empty | ||
1120 | char buf[BUFLEN]; | ||
1121 | if (fgets(buf, BUFLEN, fp) == NULL) { | ||
1122 | fclose(fp); | ||
1123 | return 1; | ||
1124 | } | ||
1125 | fclose(fp); | ||
1126 | // confirm "ready" string was written | ||
1127 | if (strncmp(buf, "ready\n", 6) != 0) | ||
1128 | return 1; | ||
1129 | |||
1130 | // walk down the process tree a few nodes, there should be no firejail leaf | ||
1131 | #define MAXNODES 5 | ||
1132 | pid_t current = pid, next; | ||
1133 | int i; | ||
1134 | for (i = 0; i < MAXNODES; i++) { | ||
1135 | if (find_child(current, &next) == 1) { | ||
1136 | EUID_ROOT(); | ||
1137 | char *comm = pid_proc_comm(current); | ||
1138 | EUID_USER(); | ||
1139 | if (!comm) { | ||
1140 | fprintf(stderr, "Error: cannot read /proc file\n"); | ||
1141 | exit(1); | ||
1142 | } | ||
1143 | if (strcmp(comm, "firejail") == 0) { | ||
1144 | free(comm); | ||
1145 | return 1; | ||
1146 | } | ||
1147 | free(comm); | ||
1148 | break; | ||
1149 | } | ||
1150 | current = next; | ||
1151 | } | ||
1152 | |||
1153 | return 0; | ||
1154 | } | ||