aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/firecfg/firecfg.config2
-rw-r--r--src/firejail/firejail.h1
-rw-r--r--src/firejail/fs.c57
-rw-r--r--src/firejail/main.c8
-rw-r--r--src/firejail/pulseaudio.c8
-rw-r--r--src/firejail/sbox.c7
-rw-r--r--src/firejail/x11.c9
-rw-r--r--src/firemon/procevent.c44
8 files changed, 97 insertions, 39 deletions
diff --git a/src/firecfg/firecfg.config b/src/firecfg/firecfg.config
index da8937717..1bfc9e66e 100644
--- a/src/firecfg/firecfg.config
+++ b/src/firecfg/firecfg.config
@@ -316,6 +316,7 @@ psi-plus
316qbittorrent 316qbittorrent
317qemu-launcher 317qemu-launcher
318qlipper 318qlipper
319qmmp
319qpdfview 320qpdfview
320qtox 321qtox
321quassel 322quassel
@@ -333,6 +334,7 @@ ristretto
333rocketchat 334rocketchat
334rtorrent 335rtorrent
335runenpass.sh 336runenpass.sh
337sayonara
336scallion 338scallion
337scribus 339scribus
338sdat2img 340sdat2img
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h
index efc0dfd8d..d873a36f5 100644
--- a/src/firejail/firejail.h
+++ b/src/firejail/firejail.h
@@ -794,6 +794,7 @@ void build_appimage_cmdline(char **command_line, char **window_title, int argc,
794#define SBOX_CAPS_NETWORK (1 << 4) // caps filter for programs running network programs 794#define SBOX_CAPS_NETWORK (1 << 4) // caps filter for programs running network programs
795#define SBOX_ALLOW_STDIN (1 << 5) // don't close stdin 795#define SBOX_ALLOW_STDIN (1 << 5) // don't close stdin
796#define SBOX_STDIN_FROM_FILE (1 << 6) // open file and redirect it to stdin 796#define SBOX_STDIN_FROM_FILE (1 << 6) // open file and redirect it to stdin
797#define SBOX_CAPS_HIDEPID (1 << 7) // hidepid caps filter for running firemon
797 798
798// run sbox 799// run sbox
799int sbox_run(unsigned filter, int num, ...); 800int sbox_run(unsigned filter, int num, ...);
diff --git a/src/firejail/fs.c b/src/firejail/fs.c
index ea0631da5..0562c7424 100644
--- a/src/firejail/fs.c
+++ b/src/firejail/fs.c
@@ -484,29 +484,44 @@ void fs_rdonly(const char *dir) {
484 484
485static void fs_rdwr(const char *dir) { 485static void fs_rdwr(const char *dir) {
486 assert(dir); 486 assert(dir);
487 // check directory exists 487 // check directory exists and ensure we have a resolved path
488 // the resolved path allows to run a sanity check after the mount
489 char *path = realpath(dir, NULL);
490 if (path == NULL)
491 return;
492 // allow only user owned directories, except the user is root
493 uid_t u = getuid();
488 struct stat s; 494 struct stat s;
489 int rv = stat(dir, &s); 495 int rv = stat(path, &s);
490 if (rv == 0) { 496 if (rv) {
491 // if the file is outside /home directory, allow only root user 497 free(path);
492 uid_t u = getuid(); 498 return;
493 if (u != 0 && s.st_uid != u) { 499 }
494 fwarning("you are not allowed to change %s to read-write\n", dir); 500 if (u != 0 && s.st_uid != u) {
495 return; 501 fwarning("you are not allowed to change %s to read-write\n", path);
496 } 502 free(path);
497 503 return;
498 // mount --bind /bin /bin 504 }
499 // mount --bind -o remount,rw /bin 505 // mount --bind /bin /bin
500 unsigned long flags = 0; 506 // mount --bind -o remount,rw /bin
501 get_mount_flags(dir, &flags); 507 unsigned long flags = 0;
502 if ((flags & MS_RDONLY) == 0) 508 get_mount_flags(path, &flags);
503 return; 509 if ((flags & MS_RDONLY) == 0) {
504 flags &= ~MS_RDONLY; 510 free(path);
505 if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0 || 511 return;
506 mount(NULL, dir, NULL, flags|MS_BIND|MS_REMOUNT|MS_REC, NULL) < 0)
507 errExit("mount read-write");
508 fs_logger2("read-write", dir);
509 } 512 }
513 flags &= ~MS_RDONLY;
514 if (mount(path, path, NULL, MS_BIND|MS_REC, NULL) < 0 ||
515 mount(NULL, path, NULL, flags|MS_BIND|MS_REMOUNT|MS_REC, NULL) < 0)
516 errExit("mount read-write");
517 fs_logger2("read-write", path);
518
519 // run a check on /proc/self/mountinfo to validate the mount
520 MountData *mptr = get_last_mount();
521 if (strncmp(mptr->dir, path, strlen(path)) != 0)
522 errLogExit("invalid read-write mount");
523
524 free(path);
510} 525}
511 526
512void fs_noexec(const char *dir) { 527void fs_noexec(const char *dir) {
diff --git a/src/firejail/main.c b/src/firejail/main.c
index 2e47dd938..9d28f3352 100644
--- a/src/firejail/main.c
+++ b/src/firejail/main.c
@@ -551,21 +551,21 @@ static void run_cmd_and_exit(int i, int argc, char **argv) {
551 } 551 }
552 else if (strcmp(argv[i], "--list") == 0) { 552 else if (strcmp(argv[i], "--list") == 0) {
553 if (pid_hidepid()) 553 if (pid_hidepid())
554 sbox_run(SBOX_ROOT| SBOX_CAPS_NONE | SBOX_SECCOMP, 2, PATH_FIREMON, "--list"); 554 sbox_run(SBOX_ROOT| SBOX_CAPS_HIDEPID | SBOX_SECCOMP, 2, PATH_FIREMON, "--list");
555 else 555 else
556 sbox_run(SBOX_USER| SBOX_CAPS_NONE | SBOX_SECCOMP, 2, PATH_FIREMON, "--list"); 556 sbox_run(SBOX_USER| SBOX_CAPS_NONE | SBOX_SECCOMP, 2, PATH_FIREMON, "--list");
557 exit(0); 557 exit(0);
558 } 558 }
559 else if (strcmp(argv[i], "--tree") == 0) { 559 else if (strcmp(argv[i], "--tree") == 0) {
560 if (pid_hidepid()) 560 if (pid_hidepid())
561 sbox_run(SBOX_ROOT | SBOX_CAPS_NONE | SBOX_SECCOMP, 2, PATH_FIREMON, "--tree"); 561 sbox_run(SBOX_ROOT | SBOX_CAPS_HIDEPID | SBOX_SECCOMP, 2, PATH_FIREMON, "--tree");
562 else 562 else
563 sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 2, PATH_FIREMON, "--tree"); 563 sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 2, PATH_FIREMON, "--tree");
564 exit(0); 564 exit(0);
565 } 565 }
566 else if (strcmp(argv[i], "--top") == 0) { 566 else if (strcmp(argv[i], "--top") == 0) {
567 if (pid_hidepid()) 567 if (pid_hidepid())
568 sbox_run(SBOX_ROOT | SBOX_CAPS_NONE | SBOX_SECCOMP | SBOX_ALLOW_STDIN, 568 sbox_run(SBOX_ROOT | SBOX_CAPS_HIDEPID | SBOX_SECCOMP | SBOX_ALLOW_STDIN,
569 2, PATH_FIREMON, "--top"); 569 2, PATH_FIREMON, "--top");
570 else 570 else
571 sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP | SBOX_ALLOW_STDIN, 571 sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP | SBOX_ALLOW_STDIN,
@@ -577,7 +577,7 @@ static void run_cmd_and_exit(int i, int argc, char **argv) {
577 if (checkcfg(CFG_NETWORK)) { 577 if (checkcfg(CFG_NETWORK)) {
578 struct stat s; 578 struct stat s;
579 if (stat("/proc/sys/kernel/grsecurity", &s) == 0 || pid_hidepid()) 579 if (stat("/proc/sys/kernel/grsecurity", &s) == 0 || pid_hidepid())
580 sbox_run(SBOX_ROOT | SBOX_CAPS_NONE | SBOX_SECCOMP | SBOX_ALLOW_STDIN, 580 sbox_run(SBOX_ROOT | SBOX_CAPS_HIDEPID | SBOX_SECCOMP | SBOX_ALLOW_STDIN,
581 2, PATH_FIREMON, "--netstats"); 581 2, PATH_FIREMON, "--netstats");
582 else 582 else
583 sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP | SBOX_ALLOW_STDIN, 583 sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP | SBOX_ALLOW_STDIN,
diff --git a/src/firejail/pulseaudio.c b/src/firejail/pulseaudio.c
index eaaba86c0..15d44e4cc 100644
--- a/src/firejail/pulseaudio.c
+++ b/src/firejail/pulseaudio.c
@@ -178,10 +178,10 @@ void pulseaudio_init(void) {
178 178
179 // check /proc/self/mountinfo to confirm the mount is ok 179 // check /proc/self/mountinfo to confirm the mount is ok
180 MountData *mptr = get_last_mount(); 180 MountData *mptr = get_last_mount();
181 if (strncmp(mptr->dir, homeusercfg, strlen(homeusercfg)) != 0) 181 if (strcmp(mptr->dir, homeusercfg) != 0)
182 errLogExit("invalid mount on top of %s (should be %s)\n", mptr->dir, homeusercfg); 182 errLogExit("invalid pulseaudio mount");
183 if (strncmp(mptr->fstype, "tmpfs", 5) != 0) 183 if (strcmp(mptr->fstype, "tmpfs") != 0)
184 errLogExit("invalid mount on top of %s (filesystem type is %s)\n", mptr->dir, mptr->fstype); 184 errLogExit("invalid pulseaudio mount");
185 185
186 char *p; 186 char *p;
187 if (asprintf(&p, "%s/client.conf", homeusercfg) == -1) 187 if (asprintf(&p, "%s/client.conf", homeusercfg) == -1)
diff --git a/src/firejail/sbox.c b/src/firejail/sbox.c
index 53df20a54..c11daad58 100644
--- a/src/firejail/sbox.c
+++ b/src/firejail/sbox.c
@@ -166,6 +166,13 @@ int sbox_run(unsigned filter, int num, ...) {
166 caps_set(set); 166 caps_set(set);
167#endif 167#endif
168 } 168 }
169 else if (filter & SBOX_CAPS_HIDEPID) {
170#ifndef HAVE_GCOV // the following filter will prevent GCOV from saving info in .gcda files
171 uint64_t set = ((uint64_t) 1) << CAP_SYS_PTRACE;
172 set |= ((uint64_t) 1) << CAP_SYS_PACCT;
173 caps_set(set);
174#endif
175 }
169 176
170 if (filter & SBOX_SECCOMP) { 177 if (filter & SBOX_SECCOMP) {
171 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { 178 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
diff --git a/src/firejail/x11.c b/src/firejail/x11.c
index 0eace3215..ec8775370 100644
--- a/src/firejail/x11.c
+++ b/src/firejail/x11.c
@@ -1196,10 +1196,11 @@ void x11_xorg(void) {
1196 1196
1197 // check /proc/self/mountinfo to confirm the mount is ok 1197 // check /proc/self/mountinfo to confirm the mount is ok
1198 MountData *mptr = get_last_mount(); 1198 MountData *mptr = get_last_mount();
1199 if (strncmp(mptr->dir, dest, strlen(dest)) != 0) 1199 if (strcmp(mptr->dir, dest) != 0)
1200 errLogExit("invalid mount on top of %s (should be %s)\n", mptr->dir, dest); 1200 errLogExit("invalid .Xauthority mount");
1201 if (strncmp(mptr->fstype, "tmpfs", 5) != 0) 1201 if (strcmp(mptr->fstype, "tmpfs") != 0)
1202 errLogExit("invalid mount on top of %s (filesystem type is %s)\n", mptr->dir, mptr->fstype); 1202 errLogExit("invalid .Xauthority mount");
1203
1203 free(dest); 1204 free(dest);
1204#endif 1205#endif
1205} 1206}
diff --git a/src/firemon/procevent.c b/src/firemon/procevent.c
index 301e5397b..5b16191be 100644
--- a/src/firemon/procevent.c
+++ b/src/firemon/procevent.c
@@ -94,10 +94,21 @@ static int pid_is_firejail(pid_t pid) {
94 // list of firejail arguments that don't trigger sandbox creation 94 // list of firejail arguments that don't trigger sandbox creation
95 // the initial -- is not included 95 // the initial -- is not included
96 char *exclude_args[] = { 96 char *exclude_args[] = {
97 "ls", "list", "tree", "x11", "help", "version", "top", "netstats", "debug-syscalls", 97 // all print options
98 "debug-errnos", "debug-protocols", "protocol.print", "debug.caps", 98 "apparmor.print", "caps.print", "cpu.print", "dns.print", "fs.print", "netfilter.print",
99 "shutdown", "bandwidth", "caps.print", "cpu.print", "debug-caps", 99 "netfilter6.print", "profile.print", "protocol.print", "seccomp.print",
100 "fs.print", "get", "overlay-clean", NULL 100 // debug
101 "debug-caps", "debug-errnos", "debug-protocols", "debug-syscalls",
102 // file transfer
103 "ls", "get", "put",
104 // stats
105 "tree", "list", "top",
106 // network
107 "netstats", "bandwidth",
108 // etc
109 "help", "version", "overlay-clean",
110
111 NULL // end of list marker
101 }; 112 };
102 113
103 int i; 114 int i;
@@ -291,6 +302,7 @@ static int procevent_monitor(const int sock, pid_t mypid) {
291 child %= max_pids; 302 child %= max_pids;
292 pids[child].level = pids[pid].level + 1; 303 pids[child].level = pids[pid].level + 1;
293 pids[child].uid = pid_get_uid(child); 304 pids[child].uid = pid_get_uid(child);
305 pids[child].parent = pid;
294 } 306 }
295 sprintf(lineptr, " fork"); 307 sprintf(lineptr, " fork");
296 break; 308 break;
@@ -318,12 +330,22 @@ static int procevent_monitor(const int sock, pid_t mypid) {
318 sprintf(lineptr, " exit"); 330 sprintf(lineptr, " exit");
319 break; 331 break;
320 332
333
334
321 case PROC_EVENT_UID: 335 case PROC_EVENT_UID:
322 pid = proc_ev->event_data.id.process_tgid; 336 pid = proc_ev->event_data.id.process_tgid;
323#ifdef DEBUG_PRCTL 337#ifdef DEBUG_PRCTL
324 printf("%s: %d, event uid, pid %d\n", __FUNCTION__, __LINE__, pid); 338 printf("%s: %d, event uid, pid %d\n", __FUNCTION__, __LINE__, pid);
325#endif 339#endif
326 sprintf(lineptr, " uid "); 340 if (pids[pid].level == 1 ||
341 pids[pids[pid].parent].level == 1) {
342 sprintf(lineptr, "\n");
343 continue;
344 }
345 else
346 sprintf(lineptr, " uid (%d:%d)",
347 proc_ev->event_data.id.r.ruid,
348 proc_ev->event_data.id.e.euid);
327 break; 349 break;
328 350
329 case PROC_EVENT_GID: 351 case PROC_EVENT_GID:
@@ -331,9 +353,19 @@ static int procevent_monitor(const int sock, pid_t mypid) {
331#ifdef DEBUG_PRCTL 353#ifdef DEBUG_PRCTL
332 printf("%s: %d, event gid, pid %d\n", __FUNCTION__, __LINE__, pid); 354 printf("%s: %d, event gid, pid %d\n", __FUNCTION__, __LINE__, pid);
333#endif 355#endif
334 sprintf(lineptr, " gid "); 356 if (pids[pid].level == 1 ||
357 pids[pids[pid].parent].level == 1) {
358 sprintf(lineptr, "\n");
359 continue;
360 }
361 else
362 sprintf(lineptr, " gid (%d:%d)",
363 proc_ev->event_data.id.r.rgid,
364 proc_ev->event_data.id.e.egid);
335 break; 365 break;
336 366
367
368
337 case PROC_EVENT_SID: 369 case PROC_EVENT_SID:
338 pid = proc_ev->event_data.sid.process_tgid; 370 pid = proc_ev->event_data.sid.process_tgid;
339#ifdef DEBUG_PRCTL 371#ifdef DEBUG_PRCTL