aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar smitsohu <smitsohu@gmail.com>2018-08-20 23:34:28 +0200
committerLibravatar smitsohu <smitsohu@gmail.com>2018-08-20 23:34:28 +0200
commitec7f59b8d370c29bd229fa9124640611c0667159 (patch)
tree30b12ce89fd04343aa5cbf5b5254ce63cb8af9fc /src
parentDocument how to access local mail with thunderbird and claws-mail (fixes #1509) (diff)
downloadfirejail-ec7f59b8d370c29bd229fa9124640611c0667159.tar.gz
firejail-ec7f59b8d370c29bd229fa9124640611c0667159.tar.zst
firejail-ec7f59b8d370c29bd229fa9124640611c0667159.zip
refactor, check the sandbox status for all join options
Diffstat (limited to 'src')
-rw-r--r--src/firejail/bandwidth.c5
-rw-r--r--src/firejail/caps.c19
-rw-r--r--src/firejail/cpu.c19
-rw-r--r--src/firejail/firejail.h2
-rw-r--r--src/firejail/fs_logger.c19
-rw-r--r--src/firejail/join.c94
-rw-r--r--src/firejail/ls.c19
-rw-r--r--src/firejail/netfilter.c5
-rw-r--r--src/firejail/network_main.c19
-rw-r--r--src/firejail/protocol.c19
-rw-r--r--src/firejail/seccomp.c19
-rw-r--r--src/firejail/util.c62
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:
401void caps_print_filter(pid_t pid) { 401void 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) {
165void cpu_print_filter(pid_t pid) { 165void 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
480void join(pid_t pid, int argc, char **argv, int index); 480void join(pid_t pid, int argc, char **argv, int index);
481pid_t switch_to_child(pid_t pid);
481 482
482// shutdown.c 483// shutdown.c
483void shut(pid_t pid); 484void shut(pid_t pid);
@@ -538,6 +539,7 @@ unsigned extract_timeout(const char *str);
538void disable_file_or_dir(const char *fname); 539void disable_file_or_dir(const char *fname);
539void disable_file_path(const char *path, const char *file); 540void disable_file_path(const char *path, const char *file);
540int safe_fd(const char *path, int flags); 541int safe_fd(const char *path, int flags);
542int 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) {
120void fs_logger_print_log(pid_t pid) { 120void 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
226static void check_ready_for_join(pid_t pid) { 226pid_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
256errexit:
257 fprintf(stderr, "Error: no valid sandbox\n");
258 exit(1);
259}
260
261
262
263void 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 256void 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) {
295void seccomp_print_filter(pid_t pid) { 295void 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
1097int 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}