diff options
30 files changed, 202 insertions, 91 deletions
@@ -1,6 +1,11 @@ | |||
1 | firejail (0.9.65) baseline; urgency=low | 1 | firejail (0.9.65) baseline; urgency=low |
2 | * deprecated --audit options, relpaced by jailcheck utility | 2 | * deprecated --audit options, relpaced by jailcheck utility |
3 | * deprecated follow-symlink-as-user from firejail.config | 3 | * deprecated follow-symlink-as-user from firejail.config |
4 | * new firejail.config settings: private-bin, private-etc | ||
5 | * new firejail.config settings: private-opt, private-srv | ||
6 | * new firejail.config settings: whitelist-disable-topdir | ||
7 | * new firejail.config settings: seccomp-filter-add | ||
8 | * removed kcmp syscall from seccomp default filter | ||
4 | * rename --noautopulse to keep-config-pulse | 9 | * rename --noautopulse to keep-config-pulse |
5 | * filtering environment variables | 10 | * filtering environment variables |
6 | * zsh completion | 11 | * zsh completion |
diff --git a/etc/firejail.config b/etc/firejail.config index f5b3d5efa..43db49422 100644 --- a/etc/firejail.config +++ b/etc/firejail.config | |||
@@ -113,6 +113,10 @@ | |||
113 | # Enable or disable seccomp support, default enabled. | 113 | # Enable or disable seccomp support, default enabled. |
114 | # seccomp yes | 114 | # seccomp yes |
115 | 115 | ||
116 | # Add rules to the default seccomp filter. Same syntax as for --seccomp= | ||
117 | # None by default; this is an example. | ||
118 | # seccomp-filter-add !chroot,kcmp,mincore | ||
119 | |||
116 | # Seccomp error action, kill, log or errno (EPERM, ENOSYS etc) | 120 | # Seccomp error action, kill, log or errno (EPERM, ENOSYS etc) |
117 | # seccomp-error-action EPERM | 121 | # seccomp-error-action EPERM |
118 | 122 | ||
diff --git a/etc/profile-a-l/cargo.profile b/etc/profile-a-l/cargo.profile index 043fd6718..7cf04c550 100644 --- a/etc/profile-a-l/cargo.profile +++ b/etc/profile-a-l/cargo.profile | |||
@@ -34,6 +34,7 @@ include disable-xdg.inc | |||
34 | #whitelist ${HOME}/.cargo | 34 | #whitelist ${HOME}/.cargo |
35 | #whitelist ${HOME}/.rustup | 35 | #whitelist ${HOME}/.rustup |
36 | #include whitelist-common.inc | 36 | #include whitelist-common.inc |
37 | whitelist /usr/share/pkgconfig | ||
37 | include whitelist-runuser-common.inc | 38 | include whitelist-runuser-common.inc |
38 | include whitelist-usr-share-common.inc | 39 | include whitelist-usr-share-common.inc |
39 | include whitelist-var-common.inc | 40 | include whitelist-var-common.inc |
diff --git a/etc/profile-a-l/chromium-common.profile b/etc/profile-a-l/chromium-common.profile index f7493aa82..b0e0254d4 100644 --- a/etc/profile-a-l/chromium-common.profile +++ b/etc/profile-a-l/chromium-common.profile | |||
@@ -37,8 +37,9 @@ include whitelist-var-common.inc | |||
37 | # Add the next line to your chromium-common.local if your kernel allows unprivileged userns clone. | 37 | # Add the next line to your chromium-common.local if your kernel allows unprivileged userns clone. |
38 | #include chromium-common-hardened.inc.profile | 38 | #include chromium-common-hardened.inc.profile |
39 | 39 | ||
40 | # Add the next line to your chromium-common.local to allow screen sharing under wayland. | 40 | # Add the next two lines to your chromium-common.local to allow screen sharing under wayland. |
41 | #whitelist ${RUNUSER}/pipewire-0 | 41 | #whitelist ${RUNUSER}/pipewire-0 |
42 | #whitelist /usr/share/pipewire/client.conf | ||
42 | 43 | ||
43 | apparmor | 44 | apparmor |
44 | caps.keep sys_admin,sys_chroot | 45 | caps.keep sys_admin,sys_chroot |
diff --git a/etc/profile-a-l/firefox.profile b/etc/profile-a-l/firefox.profile index 7874c882f..3ad67734d 100644 --- a/etc/profile-a-l/firefox.profile +++ b/etc/profile-a-l/firefox.profile | |||
@@ -56,8 +56,9 @@ dbus-user.own org.mpris.MediaPlayer2.firefox.* | |||
56 | #dbus-user.own org.mpris.MediaPlayer2.plasma-browser-integration | 56 | #dbus-user.own org.mpris.MediaPlayer2.plasma-browser-integration |
57 | #dbus-user.talk org.kde.JobViewServer | 57 | #dbus-user.talk org.kde.JobViewServer |
58 | #dbus-user.talk org.kde.kuiserver | 58 | #dbus-user.talk org.kde.kuiserver |
59 | # Add the next two lines to your firefox.local to allow screen sharing under wayland. | 59 | # Add the next three lines to your firefox.local to allow screen sharing under wayland. |
60 | #whitelist ${RUNUSER}/pipewire-0 | 60 | #whitelist ${RUNUSER}/pipewire-0 |
61 | #whitelist /usr/share/pipewire/client.conf | ||
61 | #dbus-user.talk org.freedesktop.portal.* | 62 | #dbus-user.talk org.freedesktop.portal.* |
62 | # Add the next line to your firefox.local if screen sharing sharing still does not work | 63 | # Add the next line to your firefox.local if screen sharing sharing still does not work |
63 | # with the above lines (might depend on the portal implementation). | 64 | # with the above lines (might depend on the portal implementation). |
diff --git a/etc/profile-a-l/librewolf.profile b/etc/profile-a-l/librewolf.profile index 8e3e58f19..da047357a 100644 --- a/etc/profile-a-l/librewolf.profile +++ b/etc/profile-a-l/librewolf.profile | |||
@@ -44,8 +44,9 @@ dbus-user filter | |||
44 | #dbus-user.own org.mpris.MediaPlayer2.plasma-browser-integration | 44 | #dbus-user.own org.mpris.MediaPlayer2.plasma-browser-integration |
45 | #dbus-user.talk org.kde.JobViewServer | 45 | #dbus-user.talk org.kde.JobViewServer |
46 | #dbus-user.talk org.kde.kuiserver | 46 | #dbus-user.talk org.kde.kuiserver |
47 | # Add the next lines to your librewolf.local to allow screensharing under Wayland. | 47 | # Add the next three lines to your librewolf.local to allow screensharing under Wayland. |
48 | #whitelist ${RUNUSER}/pipewire-0 | 48 | #whitelist ${RUNUSER}/pipewire-0 |
49 | #whitelist /usr/share/pipewire/client.conf | ||
49 | #dbus-user.talk org.freedesktop.portal.* | 50 | #dbus-user.talk org.freedesktop.portal.* |
50 | # Also add the next line to your librewolf.local if screensharing does not work with | 51 | # Also add the next line to your librewolf.local if screensharing does not work with |
51 | # the above lines (depends on the portal implementation). | 52 | # the above lines (depends on the portal implementation). |
diff --git a/etc/templates/syscalls.txt b/etc/templates/syscalls.txt index 0775f60ff..3992c984a 100644 --- a/etc/templates/syscalls.txt +++ b/etc/templates/syscalls.txt | |||
@@ -33,7 +33,7 @@ Definition of groups | |||
33 | @clock=adjtimex,clock_adjtime,clock_settime,settimeofday,stime | 33 | @clock=adjtimex,clock_adjtime,clock_settime,settimeofday,stime |
34 | @cpu-emulation=modify_ldt,subpage_prot,switch_endian,vm86,vm86old | 34 | @cpu-emulation=modify_ldt,subpage_prot,switch_endian,vm86,vm86old |
35 | @debug=lookup_dcookie,perf_event_open,process_vm_writev,rtas,s390_runtime_instr,sys_debug_setcontext | 35 | @debug=lookup_dcookie,perf_event_open,process_vm_writev,rtas,s390_runtime_instr,sys_debug_setcontext |
36 | @default=@clock,@cpu-emulation,@debug,@module,@mount,@obsolete,@raw-io,@reboot,@swap,open_by_handle_at,name_to_handle_at,ioprio_set,ni_syscall,syslog,fanotify_init,kcmp,add_key,request_key,mbind,migrate_pages,move_pages,keyctl,io_setup,io_destroy,io_getevents,io_submit,io_cancel,remap_file_pages,set_mempolicyvmsplice,userfaultfd,acct,bpf,nfsservctl,setdomainname,sethostname,vhangup | 36 | @default=@clock,@cpu-emulation,@debug,@module,@mount,@obsolete,@raw-io,@reboot,@swap,open_by_handle_at,name_to_handle_at,ioprio_set,ni_syscall,syslog,fanotify_init,add_key,request_key,mbind,migrate_pages,move_pages,keyctl,io_setup,io_destroy,io_getevents,io_submit,io_cancel,remap_file_pages,set_mempolicyvmsplice,userfaultfd,acct,bpf,nfsservctl,setdomainname,sethostname,vhangup |
37 | @default-nodebuggers=@default,ptrace,personality,process_vm_readv | 37 | @default-nodebuggers=@default,ptrace,personality,process_vm_readv |
38 | @default-keep=execveat,execve,prctl | 38 | @default-keep=execveat,execve,prctl |
39 | @file-system=access,chdir,chmod,close,creat,faccessat,faccessat2,fallocate,fchdir,fchmod,fchmodat,fcntl,fcntl64,fgetxattr,flistxattr,fremovexattr,fsetxattr,fstat,fstat64,fstatat64,fstatfs,fstatfs64,ftruncate,ftruncate64,futimesat,getcwd,getdents,getdents64,getxattr,inotify_add_watch,inotify_init,inotify_init1,inotify_rm_watch,lgetxattr,link,linkat,listxattr,llistxattr,lremovexattr,lsetxattr,lstat,lstat64,mkdir,mkdirat,mknod,mknodat,mmap,mmap2,munmap,newfstatat,oldfstat,oldlstat,oldstat,open,openat,readlink,readlinkat,removexattr,rename,renameat,renameat2,rmdir,setxattr,stat,stat64,statfs,statfs64,statx,symlink,symlinkat,truncate,truncate64,unlink,unlinkat,utime,utimensat,utimes | 39 | @file-system=access,chdir,chmod,close,creat,faccessat,faccessat2,fallocate,fchdir,fchmod,fchmodat,fcntl,fcntl64,fgetxattr,flistxattr,fremovexattr,fsetxattr,fstat,fstat64,fstatat64,fstatfs,fstatfs64,ftruncate,ftruncate64,futimesat,getcwd,getdents,getdents64,getxattr,inotify_add_watch,inotify_init,inotify_init1,inotify_rm_watch,lgetxattr,link,linkat,listxattr,llistxattr,lremovexattr,lsetxattr,lstat,lstat64,mkdir,mkdirat,mknod,mknodat,mmap,mmap2,munmap,newfstatat,oldfstat,oldlstat,oldstat,open,openat,readlink,readlinkat,removexattr,rename,renameat,renameat2,rmdir,setxattr,stat,stat64,statfs,statfs64,statx,symlink,symlinkat,truncate,truncate64,unlink,unlinkat,utime,utimensat,utimes |
diff --git a/src/firejail/appimage.c b/src/firejail/appimage.c index a96415985..056640eec 100644 --- a/src/firejail/appimage.c +++ b/src/firejail/appimage.c | |||
@@ -29,7 +29,7 @@ | |||
29 | #include <errno.h> | 29 | #include <errno.h> |
30 | 30 | ||
31 | #ifdef HAVE_GCOV | 31 | #ifdef HAVE_GCOV |
32 | #include <gcov.h> | 32 | #include "../include/gcov_wrapper.h" |
33 | #endif | 33 | #endif |
34 | 34 | ||
35 | static char *devloop = NULL; // device file | 35 | static char *devloop = NULL; // device file |
diff --git a/src/firejail/checkcfg.c b/src/firejail/checkcfg.c index f3ab0a6d8..1e9f4b641 100644 --- a/src/firejail/checkcfg.c +++ b/src/firejail/checkcfg.c | |||
@@ -35,6 +35,7 @@ char *xvfb_extra_params = ""; | |||
35 | char *netfilter_default = NULL; | 35 | char *netfilter_default = NULL; |
36 | unsigned long join_timeout = 5000000; // microseconds | 36 | unsigned long join_timeout = 5000000; // microseconds |
37 | char *config_seccomp_error_action_str = "EPERM"; | 37 | char *config_seccomp_error_action_str = "EPERM"; |
38 | char *config_seccomp_filter_add = NULL; | ||
38 | char **whitelist_reject_topdirs = NULL; | 39 | char **whitelist_reject_topdirs = NULL; |
39 | 40 | ||
40 | int checkcfg(int val) { | 41 | int checkcfg(int val) { |
@@ -225,6 +226,10 @@ int checkcfg(int val) { | |||
225 | else if (strncmp(ptr, "join-timeout ", 13) == 0) | 226 | else if (strncmp(ptr, "join-timeout ", 13) == 0) |
226 | join_timeout = strtoul(ptr + 13, NULL, 10) * 1000000; // seconds to microseconds | 227 | join_timeout = strtoul(ptr + 13, NULL, 10) * 1000000; // seconds to microseconds |
227 | 228 | ||
229 | // add rules to default seccomp filter | ||
230 | else if (strncmp(ptr, "seccomp-filter-add ", 19) == 0) | ||
231 | config_seccomp_filter_add = seccomp_check_list(ptr + 19); | ||
232 | |||
228 | // seccomp error action | 233 | // seccomp error action |
229 | else if (strncmp(ptr, "seccomp-error-action ", 21) == 0) { | 234 | else if (strncmp(ptr, "seccomp-error-action ", 21) == 0) { |
230 | if (strcmp(ptr + 21, "kill") == 0) | 235 | if (strcmp(ptr + 21, "kill") == 0) |
diff --git a/src/firejail/chroot.c b/src/firejail/chroot.c index edc31cdea..0d4baa618 100644 --- a/src/firejail/chroot.c +++ b/src/firejail/chroot.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #endif | 30 | #endif |
31 | 31 | ||
32 | #ifdef HAVE_GCOV | 32 | #ifdef HAVE_GCOV |
33 | #include <gcov.h> | 33 | #include "../include/gcov_wrapper.h" |
34 | #endif | 34 | #endif |
35 | 35 | ||
36 | // exit if error | 36 | // exit if error |
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index c84965074..9971d30b6 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -5,7 +5,7 @@ | |||
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
8 | * the Free Software Foundation; eithe r version 2 of the License, or | 8 | * the Free Software Foundation; either version 2 of the License, or |
9 | * (at your option) any later version. | 9 | * (at your option) any later version. |
10 | * | 10 | * |
11 | * This program is distributed in the hope that it will be useful, | 11 | * This program is distributed in the hope that it will be useful, |
@@ -508,7 +508,7 @@ void logargs(int argc, char **argv) ; | |||
508 | void logerr(const char *msg); | 508 | void logerr(const char *msg); |
509 | void set_nice(int inc); | 509 | void set_nice(int inc); |
510 | int copy_file(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode); | 510 | int copy_file(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode); |
511 | void copy_file_as_user(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode); | 511 | void copy_file_as_user(const char *srcname, const char *destname, mode_t mode); |
512 | void copy_file_from_user_to_root(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode); | 512 | void copy_file_from_user_to_root(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode); |
513 | void touch_file_as_user(const char *fname, mode_t mode); | 513 | void touch_file_as_user(const char *fname, mode_t mode); |
514 | int is_dir(const char *fname); | 514 | int is_dir(const char *fname); |
@@ -810,6 +810,7 @@ extern char *xvfb_extra_params; | |||
810 | extern char *netfilter_default; | 810 | extern char *netfilter_default; |
811 | extern unsigned long join_timeout; | 811 | extern unsigned long join_timeout; |
812 | extern char *config_seccomp_error_action_str; | 812 | extern char *config_seccomp_error_action_str; |
813 | extern char *config_seccomp_filter_add; | ||
813 | extern char **whitelist_reject_topdirs; | 814 | extern char **whitelist_reject_topdirs; |
814 | 815 | ||
815 | int checkcfg(int val); | 816 | int checkcfg(int val); |
diff --git a/src/firejail/fs.c b/src/firejail/fs.c index 4ae7dbfa4..806fa9249 100644 --- a/src/firejail/fs.c +++ b/src/firejail/fs.c | |||
@@ -34,7 +34,7 @@ | |||
34 | #endif | 34 | #endif |
35 | 35 | ||
36 | #ifdef HAVE_GCOV | 36 | #ifdef HAVE_GCOV |
37 | #include <gcov.h> | 37 | #include "../include/gcov_wrapper.h" |
38 | #endif | 38 | #endif |
39 | 39 | ||
40 | #define MAX_BUF 4096 | 40 | #define MAX_BUF 4096 |
diff --git a/src/firejail/fs_home.c b/src/firejail/fs_home.c index eab952eb8..0ed476063 100644 --- a/src/firejail/fs_home.c +++ b/src/firejail/fs_home.c | |||
@@ -34,12 +34,13 @@ | |||
34 | #define O_PATH 010000000 | 34 | #define O_PATH 010000000 |
35 | #endif | 35 | #endif |
36 | 36 | ||
37 | static void skel(const char *homedir, uid_t u, gid_t g) { | 37 | static void skel(const char *homedir) { |
38 | char *fname; | 38 | EUID_ASSERT(); |
39 | 39 | ||
40 | // zsh | 40 | // zsh |
41 | if (!arg_shell_none && (strcmp(cfg.shell,"/usr/bin/zsh") == 0 || strcmp(cfg.shell,"/bin/zsh") == 0)) { | 41 | if (!arg_shell_none && (strcmp(cfg.shell,"/usr/bin/zsh") == 0 || strcmp(cfg.shell,"/bin/zsh") == 0)) { |
42 | // copy skel files | 42 | // copy skel files |
43 | char *fname; | ||
43 | if (asprintf(&fname, "%s/.zshrc", homedir) == -1) | 44 | if (asprintf(&fname, "%s/.zshrc", homedir) == -1) |
44 | errExit("asprintf"); | 45 | errExit("asprintf"); |
45 | // don't copy it if we already have the file | 46 | // don't copy it if we already have the file |
@@ -50,7 +51,7 @@ static void skel(const char *homedir, uid_t u, gid_t g) { | |||
50 | exit(1); | 51 | exit(1); |
51 | } | 52 | } |
52 | if (access("/etc/skel/.zshrc", R_OK) == 0) { | 53 | if (access("/etc/skel/.zshrc", R_OK) == 0) { |
53 | copy_file_as_user("/etc/skel/.zshrc", fname, u, g, 0644); // regular user | 54 | copy_file_as_user("/etc/skel/.zshrc", fname, 0644); // regular user |
54 | fs_logger("clone /etc/skel/.zshrc"); | 55 | fs_logger("clone /etc/skel/.zshrc"); |
55 | fs_logger2("clone", fname); | 56 | fs_logger2("clone", fname); |
56 | } | 57 | } |
@@ -64,6 +65,7 @@ static void skel(const char *homedir, uid_t u, gid_t g) { | |||
64 | // csh | 65 | // csh |
65 | else if (!arg_shell_none && strcmp(cfg.shell,"/bin/csh") == 0) { | 66 | else if (!arg_shell_none && strcmp(cfg.shell,"/bin/csh") == 0) { |
66 | // copy skel files | 67 | // copy skel files |
68 | char *fname; | ||
67 | if (asprintf(&fname, "%s/.cshrc", homedir) == -1) | 69 | if (asprintf(&fname, "%s/.cshrc", homedir) == -1) |
68 | errExit("asprintf"); | 70 | errExit("asprintf"); |
69 | // don't copy it if we already have the file | 71 | // don't copy it if we already have the file |
@@ -74,7 +76,7 @@ static void skel(const char *homedir, uid_t u, gid_t g) { | |||
74 | exit(1); | 76 | exit(1); |
75 | } | 77 | } |
76 | if (access("/etc/skel/.cshrc", R_OK) == 0) { | 78 | if (access("/etc/skel/.cshrc", R_OK) == 0) { |
77 | copy_file_as_user("/etc/skel/.cshrc", fname, u, g, 0644); // regular user | 79 | copy_file_as_user("/etc/skel/.cshrc", fname, 0644); // regular user |
78 | fs_logger("clone /etc/skel/.cshrc"); | 80 | fs_logger("clone /etc/skel/.cshrc"); |
79 | fs_logger2("clone", fname); | 81 | fs_logger2("clone", fname); |
80 | } | 82 | } |
@@ -88,6 +90,7 @@ static void skel(const char *homedir, uid_t u, gid_t g) { | |||
88 | // bash etc. | 90 | // bash etc. |
89 | else { | 91 | else { |
90 | // copy skel files | 92 | // copy skel files |
93 | char *fname; | ||
91 | if (asprintf(&fname, "%s/.bashrc", homedir) == -1) | 94 | if (asprintf(&fname, "%s/.bashrc", homedir) == -1) |
92 | errExit("asprintf"); | 95 | errExit("asprintf"); |
93 | // don't copy it if we already have the file | 96 | // don't copy it if we already have the file |
@@ -98,7 +101,7 @@ static void skel(const char *homedir, uid_t u, gid_t g) { | |||
98 | exit(1); | 101 | exit(1); |
99 | } | 102 | } |
100 | if (access("/etc/skel/.bashrc", R_OK) == 0) { | 103 | if (access("/etc/skel/.bashrc", R_OK) == 0) { |
101 | copy_file_as_user("/etc/skel/.bashrc", fname, u, g, 0644); // regular user | 104 | copy_file_as_user("/etc/skel/.bashrc", fname, 0644); // regular user |
102 | fs_logger("clone /etc/skel/.bashrc"); | 105 | fs_logger("clone /etc/skel/.bashrc"); |
103 | fs_logger2("clone", fname); | 106 | fs_logger2("clone", fname); |
104 | } | 107 | } |
@@ -108,6 +111,7 @@ static void skel(const char *homedir, uid_t u, gid_t g) { | |||
108 | } | 111 | } |
109 | 112 | ||
110 | static int store_xauthority(void) { | 113 | static int store_xauthority(void) { |
114 | EUID_ASSERT(); | ||
111 | if (arg_x11_block) | 115 | if (arg_x11_block) |
112 | return 0; | 116 | return 0; |
113 | 117 | ||
@@ -118,7 +122,7 @@ static int store_xauthority(void) { | |||
118 | errExit("asprintf"); | 122 | errExit("asprintf"); |
119 | 123 | ||
120 | struct stat s; | 124 | struct stat s; |
121 | if (lstat_as_user(src, &s) == 0) { | 125 | if (lstat(src, &s) == 0) { |
122 | if (S_ISLNK(s.st_mode)) { | 126 | if (S_ISLNK(s.st_mode)) { |
123 | fwarning("invalid .Xauthority file\n"); | 127 | fwarning("invalid .Xauthority file\n"); |
124 | free(src); | 128 | free(src); |
@@ -126,6 +130,7 @@ static int store_xauthority(void) { | |||
126 | } | 130 | } |
127 | 131 | ||
128 | // create an empty file as root, and change ownership to user | 132 | // create an empty file as root, and change ownership to user |
133 | EUID_ROOT(); | ||
129 | FILE *fp = fopen(dest, "we"); | 134 | FILE *fp = fopen(dest, "we"); |
130 | if (fp) { | 135 | if (fp) { |
131 | fprintf(fp, "\n"); | 136 | fprintf(fp, "\n"); |
@@ -134,10 +139,11 @@ static int store_xauthority(void) { | |||
134 | } | 139 | } |
135 | else | 140 | else |
136 | errExit("fopen"); | 141 | errExit("fopen"); |
142 | EUID_USER(); | ||
137 | 143 | ||
138 | copy_file_as_user(src, dest, getuid(), getgid(), 0600); // regular user | 144 | copy_file_as_user(src, dest, 0600); // regular user |
139 | fs_logger2("clone", dest); | ||
140 | selinux_relabel_path(dest, src); | 145 | selinux_relabel_path(dest, src); |
146 | fs_logger2("clone", dest); | ||
141 | free(src); | 147 | free(src); |
142 | return 1; // file copied | 148 | return 1; // file copied |
143 | } | 149 | } |
@@ -147,6 +153,7 @@ static int store_xauthority(void) { | |||
147 | } | 153 | } |
148 | 154 | ||
149 | static int store_asoundrc(void) { | 155 | static int store_asoundrc(void) { |
156 | EUID_ASSERT(); | ||
150 | if (arg_nosound) | 157 | if (arg_nosound) |
151 | return 0; | 158 | return 0; |
152 | 159 | ||
@@ -157,11 +164,11 @@ static int store_asoundrc(void) { | |||
157 | errExit("asprintf"); | 164 | errExit("asprintf"); |
158 | 165 | ||
159 | struct stat s; | 166 | struct stat s; |
160 | if (lstat_as_user(src, &s) == 0) { | 167 | if (lstat(src, &s) == 0) { |
161 | if (S_ISLNK(s.st_mode)) { | 168 | if (S_ISLNK(s.st_mode)) { |
162 | // make sure the real path of the file is inside the home directory | 169 | // make sure the real path of the file is inside the home directory |
163 | /* coverity[toctou] */ | 170 | /* coverity[toctou] */ |
164 | char *rp = realpath_as_user(src); | 171 | char *rp = realpath(src, NULL); |
165 | if (!rp) { | 172 | if (!rp) { |
166 | fprintf(stderr, "Error: Cannot access %s\n", src); | 173 | fprintf(stderr, "Error: Cannot access %s\n", src); |
167 | exit(1); | 174 | exit(1); |
@@ -174,6 +181,7 @@ static int store_asoundrc(void) { | |||
174 | } | 181 | } |
175 | 182 | ||
176 | // create an empty file as root, and change ownership to user | 183 | // create an empty file as root, and change ownership to user |
184 | EUID_ROOT(); | ||
177 | FILE *fp = fopen(dest, "we"); | 185 | FILE *fp = fopen(dest, "we"); |
178 | if (fp) { | 186 | if (fp) { |
179 | fprintf(fp, "\n"); | 187 | fprintf(fp, "\n"); |
@@ -182,10 +190,11 @@ static int store_asoundrc(void) { | |||
182 | } | 190 | } |
183 | else | 191 | else |
184 | errExit("fopen"); | 192 | errExit("fopen"); |
193 | EUID_USER(); | ||
185 | 194 | ||
186 | copy_file_as_user(src, dest, getuid(), getgid(), 0644); // regular user | 195 | copy_file_as_user(src, dest, 0644); // regular user |
187 | selinux_relabel_path(dest, src); | ||
188 | fs_logger2("clone", dest); | 196 | fs_logger2("clone", dest); |
197 | selinux_relabel_path(dest, src); | ||
189 | free(src); | 198 | free(src); |
190 | return 1; // file copied | 199 | return 1; // file copied |
191 | } | 200 | } |
@@ -195,6 +204,7 @@ static int store_asoundrc(void) { | |||
195 | } | 204 | } |
196 | 205 | ||
197 | static void copy_xauthority(void) { | 206 | static void copy_xauthority(void) { |
207 | EUID_ASSERT(); | ||
198 | // copy XAUTHORITY_FILE in the new home directory | 208 | // copy XAUTHORITY_FILE in the new home directory |
199 | char *src = RUN_XAUTHORITY_FILE ; | 209 | char *src = RUN_XAUTHORITY_FILE ; |
200 | char *dest; | 210 | char *dest; |
@@ -207,16 +217,18 @@ static void copy_xauthority(void) { | |||
207 | exit(1); | 217 | exit(1); |
208 | } | 218 | } |
209 | 219 | ||
210 | copy_file_as_user(src, dest, getuid(), getgid(), S_IRUSR | S_IWUSR); // regular user | 220 | copy_file_as_user(src, dest, S_IRUSR | S_IWUSR); // regular user |
211 | selinux_relabel_path(dest, src); | ||
212 | fs_logger2("clone", dest); | 221 | fs_logger2("clone", dest); |
222 | selinux_relabel_path(dest, dest); | ||
213 | free(dest); | 223 | free(dest); |
214 | 224 | ||
215 | // delete the temporary file | 225 | EUID_ROOT(); |
216 | unlink(src); | 226 | unlink(src); // delete the temporary file |
227 | EUID_USER(); | ||
217 | } | 228 | } |
218 | 229 | ||
219 | static void copy_asoundrc(void) { | 230 | static void copy_asoundrc(void) { |
231 | EUID_ASSERT(); | ||
220 | // copy ASOUNDRC_FILE in the new home directory | 232 | // copy ASOUNDRC_FILE in the new home directory |
221 | char *src = RUN_ASOUNDRC_FILE ; | 233 | char *src = RUN_ASOUNDRC_FILE ; |
222 | char *dest; | 234 | char *dest; |
@@ -229,13 +241,14 @@ static void copy_asoundrc(void) { | |||
229 | exit(1); | 241 | exit(1); |
230 | } | 242 | } |
231 | 243 | ||
232 | copy_file_as_user(src, dest, getuid(), getgid(), S_IRUSR | S_IWUSR); // regular user | 244 | copy_file_as_user(src, dest, S_IRUSR | S_IWUSR); // regular user |
233 | selinux_relabel_path(dest, src); | ||
234 | fs_logger2("clone", dest); | 245 | fs_logger2("clone", dest); |
246 | selinux_relabel_path(dest, dest); | ||
235 | free(dest); | 247 | free(dest); |
236 | 248 | ||
237 | // delete the temporary file | 249 | EUID_ROOT(); |
238 | unlink(src); | 250 | unlink(src); // delete the temporary file |
251 | EUID_USER(); | ||
239 | } | 252 | } |
240 | 253 | ||
241 | // private mode (--private=homedir): | 254 | // private mode (--private=homedir): |
@@ -248,18 +261,18 @@ void fs_private_homedir(void) { | |||
248 | char *private_homedir = cfg.home_private; | 261 | char *private_homedir = cfg.home_private; |
249 | assert(homedir); | 262 | assert(homedir); |
250 | assert(private_homedir); | 263 | assert(private_homedir); |
264 | EUID_ASSERT(); | ||
265 | |||
266 | uid_t u = getuid(); | ||
267 | // gid_t g = getgid(); | ||
251 | 268 | ||
252 | int xflag = store_xauthority(); | 269 | int xflag = store_xauthority(); |
253 | int aflag = store_asoundrc(); | 270 | int aflag = store_asoundrc(); |
254 | 271 | ||
255 | uid_t u = getuid(); | ||
256 | gid_t g = getgid(); | ||
257 | |||
258 | // mount bind private_homedir on top of homedir | 272 | // mount bind private_homedir on top of homedir |
259 | if (arg_debug) | 273 | if (arg_debug) |
260 | printf("Mount-bind %s on top of %s\n", private_homedir, homedir); | 274 | printf("Mount-bind %s on top of %s\n", private_homedir, homedir); |
261 | // get file descriptors for homedir and private_homedir, fails if there is any symlink | 275 | // get file descriptors for homedir and private_homedir, fails if there is any symlink |
262 | EUID_USER(); | ||
263 | int src = safer_openat(-1, private_homedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); | 276 | int src = safer_openat(-1, private_homedir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); |
264 | if (src == -1) | 277 | if (src == -1) |
265 | errExit("opening private directory"); | 278 | errExit("opening private directory"); |
@@ -287,6 +300,7 @@ void fs_private_homedir(void) { | |||
287 | EUID_ROOT(); | 300 | EUID_ROOT(); |
288 | if (bind_mount_by_fd(src, dst)) | 301 | if (bind_mount_by_fd(src, dst)) |
289 | errExit("mount bind"); | 302 | errExit("mount bind"); |
303 | EUID_USER(); | ||
290 | 304 | ||
291 | // check /proc/self/mountinfo to confirm the mount is ok | 305 | // check /proc/self/mountinfo to confirm the mount is ok |
292 | MountData *mptr = get_last_mount(); | 306 | MountData *mptr = get_last_mount(); |
@@ -305,6 +319,7 @@ void fs_private_homedir(void) { | |||
305 | // if (chmod(homedir, s.st_mode) == -1) | 319 | // if (chmod(homedir, s.st_mode) == -1) |
306 | // errExit("mount-bind chmod"); | 320 | // errExit("mount-bind chmod"); |
307 | 321 | ||
322 | EUID_ROOT(); | ||
308 | if (u != 0) { | 323 | if (u != 0) { |
309 | // mask /root | 324 | // mask /root |
310 | if (arg_debug) | 325 | if (arg_debug) |
@@ -323,8 +338,9 @@ void fs_private_homedir(void) { | |||
323 | selinux_relabel_path("/home", "/home"); | 338 | selinux_relabel_path("/home", "/home"); |
324 | fs_logger("tmpfs /home"); | 339 | fs_logger("tmpfs /home"); |
325 | } | 340 | } |
341 | EUID_USER(); | ||
326 | 342 | ||
327 | skel(homedir, u, g); | 343 | skel(homedir); |
328 | if (xflag) | 344 | if (xflag) |
329 | copy_xauthority(); | 345 | copy_xauthority(); |
330 | if (aflag) | 346 | if (aflag) |
@@ -339,12 +355,15 @@ void fs_private_homedir(void) { | |||
339 | void fs_private(void) { | 355 | void fs_private(void) { |
340 | char *homedir = cfg.homedir; | 356 | char *homedir = cfg.homedir; |
341 | assert(homedir); | 357 | assert(homedir); |
358 | EUID_ASSERT(); | ||
359 | |||
342 | uid_t u = getuid(); | 360 | uid_t u = getuid(); |
343 | gid_t g = getgid(); | 361 | gid_t g = getgid(); |
344 | 362 | ||
345 | int xflag = store_xauthority(); | 363 | int xflag = store_xauthority(); |
346 | int aflag = store_asoundrc(); | 364 | int aflag = store_asoundrc(); |
347 | 365 | ||
366 | EUID_ROOT(); | ||
348 | // mask /root | 367 | // mask /root |
349 | if (arg_debug) | 368 | if (arg_debug) |
350 | printf("Mounting a new /root directory\n"); | 369 | printf("Mounting a new /root directory\n"); |
@@ -387,8 +406,9 @@ void fs_private(void) { | |||
387 | 406 | ||
388 | selinux_relabel_path(homedir, homedir); | 407 | selinux_relabel_path(homedir, homedir); |
389 | } | 408 | } |
409 | EUID_USER(); | ||
390 | 410 | ||
391 | skel(homedir, u, g); | 411 | skel(homedir); |
392 | if (xflag) | 412 | if (xflag) |
393 | copy_xauthority(); | 413 | copy_xauthority(); |
394 | if (aflag) | 414 | if (aflag) |
@@ -530,26 +550,29 @@ static void duplicate(char *name) { | |||
530 | // set skel files, | 550 | // set skel files, |
531 | // restore .Xauthority | 551 | // restore .Xauthority |
532 | void fs_private_home_list(void) { | 552 | void fs_private_home_list(void) { |
533 | timetrace_start(); | ||
534 | |||
535 | char *homedir = cfg.homedir; | 553 | char *homedir = cfg.homedir; |
536 | char *private_list = cfg.home_private_keep; | 554 | char *private_list = cfg.home_private_keep; |
537 | assert(homedir); | 555 | assert(homedir); |
538 | assert(private_list); | 556 | assert(private_list); |
557 | EUID_ASSERT(); | ||
539 | 558 | ||
540 | int xflag = store_xauthority(); | 559 | timetrace_start(); |
541 | int aflag = store_asoundrc(); | ||
542 | 560 | ||
543 | uid_t uid = getuid(); | 561 | uid_t uid = getuid(); |
544 | gid_t gid = getgid(); | 562 | gid_t gid = getgid(); |
545 | 563 | ||
564 | int xflag = store_xauthority(); | ||
565 | int aflag = store_asoundrc(); | ||
566 | |||
546 | // create /run/firejail/mnt/home directory | 567 | // create /run/firejail/mnt/home directory |
568 | EUID_ROOT(); | ||
547 | mkdir_attr(RUN_HOME_DIR, 0755, uid, gid); | 569 | mkdir_attr(RUN_HOME_DIR, 0755, uid, gid); |
548 | selinux_relabel_path(RUN_HOME_DIR, homedir); | 570 | selinux_relabel_path(RUN_HOME_DIR, homedir); |
571 | |||
549 | fs_logger_print(); // save the current log | 572 | fs_logger_print(); // save the current log |
573 | EUID_USER(); | ||
550 | 574 | ||
551 | // copy the list of files in the new home directory | 575 | // copy the list of files in the new home directory |
552 | EUID_USER(); | ||
553 | if (arg_debug) | 576 | if (arg_debug) |
554 | printf("Copying files in the new home:\n"); | 577 | printf("Copying files in the new home:\n"); |
555 | char *dlist = strdup(cfg.home_private_keep); | 578 | char *dlist = strdup(cfg.home_private_keep); |
@@ -587,6 +610,7 @@ void fs_private_home_list(void) { | |||
587 | EUID_ROOT(); | 610 | EUID_ROOT(); |
588 | if (bind_mount_path_to_fd(RUN_HOME_DIR, fd)) | 611 | if (bind_mount_path_to_fd(RUN_HOME_DIR, fd)) |
589 | errExit("mount bind"); | 612 | errExit("mount bind"); |
613 | EUID_USER(); | ||
590 | close(fd); | 614 | close(fd); |
591 | 615 | ||
592 | // check /proc/self/mountinfo to confirm the mount is ok | 616 | // check /proc/self/mountinfo to confirm the mount is ok |
@@ -595,11 +619,7 @@ void fs_private_home_list(void) { | |||
595 | errLogExit("invalid private-home mount"); | 619 | errLogExit("invalid private-home mount"); |
596 | fs_logger2("tmpfs", homedir); | 620 | fs_logger2("tmpfs", homedir); |
597 | 621 | ||
598 | // mask RUN_HOME_DIR, it is writable and not noexec | 622 | EUID_ROOT(); |
599 | if (mount("tmpfs", RUN_HOME_DIR, "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME, "mode=755,gid=0") < 0) | ||
600 | errExit("mounting tmpfs"); | ||
601 | fs_logger2("tmpfs", RUN_HOME_DIR); | ||
602 | |||
603 | if (uid != 0) { | 623 | if (uid != 0) { |
604 | // mask /root | 624 | // mask /root |
605 | if (arg_debug) | 625 | if (arg_debug) |
@@ -619,7 +639,12 @@ void fs_private_home_list(void) { | |||
619 | fs_logger("tmpfs /home"); | 639 | fs_logger("tmpfs /home"); |
620 | } | 640 | } |
621 | 641 | ||
622 | skel(homedir, uid, gid); | 642 | // mask RUN_HOME_DIR, it is writable and not noexec |
643 | if (mount("tmpfs", RUN_HOME_DIR, "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME, "mode=755,gid=0") < 0) | ||
644 | errExit("mounting tmpfs"); | ||
645 | EUID_USER(); | ||
646 | |||
647 | skel(homedir); | ||
623 | if (xflag) | 648 | if (xflag) |
624 | copy_xauthority(); | 649 | copy_xauthority(); |
625 | if (aflag) | 650 | if (aflag) |
diff --git a/src/firejail/fs_mkdir.c b/src/firejail/fs_mkdir.c index bbc2aa938..0195435f9 100644 --- a/src/firejail/fs_mkdir.c +++ b/src/firejail/fs_mkdir.c | |||
@@ -26,7 +26,7 @@ | |||
26 | #include <string.h> | 26 | #include <string.h> |
27 | 27 | ||
28 | #ifdef HAVE_GCOV | 28 | #ifdef HAVE_GCOV |
29 | #include <gcov.h> | 29 | #include "../include/gcov_wrapper.h" |
30 | #endif | 30 | #endif |
31 | 31 | ||
32 | static void check(const char *fname) { | 32 | static void check(const char *fname) { |
diff --git a/src/firejail/fs_whitelist.c b/src/firejail/fs_whitelist.c index 370035a4d..943f275de 100644 --- a/src/firejail/fs_whitelist.c +++ b/src/firejail/fs_whitelist.c | |||
@@ -374,9 +374,11 @@ static void tmpfs_topdirs(const TopDir *topdirs) { | |||
374 | } | 374 | } |
375 | 375 | ||
376 | // user home directory | 376 | // user home directory |
377 | if (tmpfs_home) | 377 | if (tmpfs_home) { |
378 | // checks owner if outside /home | 378 | EUID_USER(); |
379 | fs_private(); | 379 | fs_private(); // checks owner if outside /home |
380 | EUID_ROOT(); | ||
381 | } | ||
380 | 382 | ||
381 | // /run/user/$UID directory | 383 | // /run/user/$UID directory |
382 | if (tmpfs_runuser) { | 384 | if (tmpfs_runuser) { |
diff --git a/src/firejail/ls.c b/src/firejail/ls.c index 6ee557648..ae7e89741 100644 --- a/src/firejail/ls.c +++ b/src/firejail/ls.c | |||
@@ -32,7 +32,7 @@ | |||
32 | //#include <stdlib.h> | 32 | //#include <stdlib.h> |
33 | 33 | ||
34 | #ifdef HAVE_GCOV | 34 | #ifdef HAVE_GCOV |
35 | #include <gcov.h> | 35 | #include "../include/gcov_wrapper.h" |
36 | #endif | 36 | #endif |
37 | 37 | ||
38 | // uid/gid cache | 38 | // uid/gid cache |
diff --git a/src/firejail/main.c b/src/firejail/main.c index b376095f1..7b32f6f07 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c | |||
@@ -45,7 +45,7 @@ | |||
45 | #endif | 45 | #endif |
46 | 46 | ||
47 | #ifdef HAVE_GCOV | 47 | #ifdef HAVE_GCOV |
48 | #include <gcov.h> | 48 | #include "../include/gcov_wrapper.h" |
49 | #endif | 49 | #endif |
50 | 50 | ||
51 | #ifdef __ia64__ | 51 | #ifdef __ia64__ |
@@ -967,7 +967,7 @@ void filter_add_blacklist_override(int fd, int syscall, int arg, void *ptrarg, b | |||
967 | static int check_postexec(const char *list) { | 967 | static int check_postexec(const char *list) { |
968 | char *prelist, *postlist; | 968 | char *prelist, *postlist; |
969 | 969 | ||
970 | if (list) { | 970 | if (list && list[0]) { |
971 | syscalls_in_list(list, "@default-keep", -1, &prelist, &postlist, true); | 971 | syscalls_in_list(list, "@default-keep", -1, &prelist, &postlist, true); |
972 | if (postlist) | 972 | if (postlist) |
973 | return 1; | 973 | return 1; |
@@ -2895,6 +2895,15 @@ int main(int argc, char **argv, char **envp) { | |||
2895 | // check network configuration options - it will exit if anything went wrong | 2895 | // check network configuration options - it will exit if anything went wrong |
2896 | net_check_cfg(); | 2896 | net_check_cfg(); |
2897 | 2897 | ||
2898 | // customization of default seccomp filter | ||
2899 | if (config_seccomp_filter_add) { | ||
2900 | if (arg_seccomp && !cfg.seccomp_list_keep && !cfg.seccomp_list_drop) | ||
2901 | profile_list_augment(&cfg.seccomp_list, config_seccomp_filter_add); | ||
2902 | |||
2903 | if (arg_seccomp32 && !cfg.seccomp_list_keep32 && !cfg.seccomp_list_drop32) | ||
2904 | profile_list_augment(&cfg.seccomp_list32, config_seccomp_filter_add); | ||
2905 | } | ||
2906 | |||
2898 | if (arg_seccomp) | 2907 | if (arg_seccomp) |
2899 | arg_seccomp_postexec = check_postexec(cfg.seccomp_list) || check_postexec(cfg.seccomp_list_drop); | 2908 | arg_seccomp_postexec = check_postexec(cfg.seccomp_list) || check_postexec(cfg.seccomp_list_drop); |
2900 | 2909 | ||
diff --git a/src/firejail/profile.c b/src/firejail/profile.c index 5b1478918..7b21eb387 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c | |||
@@ -24,7 +24,7 @@ | |||
24 | #include <sys/stat.h> | 24 | #include <sys/stat.h> |
25 | 25 | ||
26 | #ifdef HAVE_GCOV | 26 | #ifdef HAVE_GCOV |
27 | #include <gcov.h> | 27 | #include "../include/gcov_wrapper.h" |
28 | #endif | 28 | #endif |
29 | 29 | ||
30 | extern char *xephyr_screen; | 30 | extern char *xephyr_screen; |
diff --git a/src/firejail/rlimit.c b/src/firejail/rlimit.c index dd6fec972..2666486fa 100644 --- a/src/firejail/rlimit.c +++ b/src/firejail/rlimit.c | |||
@@ -22,7 +22,7 @@ | |||
22 | #include <sys/resource.h> | 22 | #include <sys/resource.h> |
23 | 23 | ||
24 | #ifdef HAVE_GCOV | 24 | #ifdef HAVE_GCOV |
25 | #include <gcov.h> | 25 | #include "../include/gcov_wrapper.h" |
26 | #endif | 26 | #endif |
27 | 27 | ||
28 | void set_rlimits(void) { | 28 | void set_rlimits(void) { |
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index e06ba3617..99abce57f 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c | |||
@@ -50,7 +50,7 @@ | |||
50 | #endif | 50 | #endif |
51 | 51 | ||
52 | #ifdef HAVE_GCOV | 52 | #ifdef HAVE_GCOV |
53 | #include <gcov.h> | 53 | #include "../include/gcov_wrapper.h" |
54 | #endif | 54 | #endif |
55 | 55 | ||
56 | static int force_nonewprivs = 0; | 56 | static int force_nonewprivs = 0; |
@@ -840,6 +840,7 @@ int sandbox(void* sandbox_arg) { | |||
840 | // private mode | 840 | // private mode |
841 | //**************************** | 841 | //**************************** |
842 | if (arg_private) { | 842 | if (arg_private) { |
843 | EUID_USER(); | ||
843 | if (cfg.home_private) { // --private= | 844 | if (cfg.home_private) { // --private= |
844 | if (cfg.chrootdir) | 845 | if (cfg.chrootdir) |
845 | fwarning("private=directory feature is disabled in chroot\n"); | 846 | fwarning("private=directory feature is disabled in chroot\n"); |
@@ -858,6 +859,7 @@ int sandbox(void* sandbox_arg) { | |||
858 | } | 859 | } |
859 | else // --private | 860 | else // --private |
860 | fs_private(); | 861 | fs_private(); |
862 | EUID_ROOT(); | ||
861 | } | 863 | } |
862 | 864 | ||
863 | if (arg_private_dev) | 865 | if (arg_private_dev) |
diff --git a/src/firejail/seccomp.c b/src/firejail/seccomp.c index 9670fe816..3d9bf9082 100644 --- a/src/firejail/seccomp.c +++ b/src/firejail/seccomp.c | |||
@@ -208,7 +208,8 @@ int seccomp_filter_drop(bool native) { | |||
208 | // - seccomp | 208 | // - seccomp |
209 | if (cfg.seccomp_list_drop == NULL) { | 209 | if (cfg.seccomp_list_drop == NULL) { |
210 | // default seccomp if error action is not changed | 210 | // default seccomp if error action is not changed |
211 | if (cfg.seccomp_list == NULL && arg_seccomp_error_action == DEFAULT_SECCOMP_ERROR_ACTION) { | 211 | if ((cfg.seccomp_list == NULL || cfg.seccomp_list[0] == '\0') |
212 | && arg_seccomp_error_action == DEFAULT_SECCOMP_ERROR_ACTION) { | ||
212 | if (arg_seccomp_block_secondary) | 213 | if (arg_seccomp_block_secondary) |
213 | seccomp_filter_block_secondary(); | 214 | seccomp_filter_block_secondary(); |
214 | else { | 215 | else { |
@@ -261,7 +262,7 @@ int seccomp_filter_drop(bool native) { | |||
261 | } | 262 | } |
262 | 263 | ||
263 | // build the seccomp filter as a regular user | 264 | // build the seccomp filter as a regular user |
264 | if (list) | 265 | if (list && list[0]) |
265 | if (arg_allow_debuggers) | 266 | if (arg_allow_debuggers) |
266 | rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 7, | 267 | rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 7, |
267 | PATH_FSECCOMP, command, "drop", filter, postexec_filter, list, "allow-debuggers"); | 268 | PATH_FSECCOMP, command, "drop", filter, postexec_filter, list, "allow-debuggers"); |
diff --git a/src/firejail/util.c b/src/firejail/util.c index 68b76b8e8..55998e6c3 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c | |||
@@ -45,7 +45,7 @@ | |||
45 | #endif | 45 | #endif |
46 | 46 | ||
47 | #ifdef HAVE_GCOV | 47 | #ifdef HAVE_GCOV |
48 | #include <gcov.h> | 48 | #include "../include/gcov_wrapper.h" |
49 | #endif | 49 | #endif |
50 | 50 | ||
51 | #define MAX_GROUPS 1024 | 51 | #define MAX_GROUPS 1024 |
@@ -370,7 +370,7 @@ int copy_file(const char *srcname, const char *destname, uid_t uid, gid_t gid, m | |||
370 | } | 370 | } |
371 | 371 | ||
372 | // return -1 if error, 0 if no error | 372 | // return -1 if error, 0 if no error |
373 | void copy_file_as_user(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode) { | 373 | void copy_file_as_user(const char *srcname, const char *destname, mode_t mode) { |
374 | pid_t child = fork(); | 374 | pid_t child = fork(); |
375 | if (child < 0) | 375 | if (child < 0) |
376 | errExit("fork"); | 376 | errExit("fork"); |
@@ -378,8 +378,8 @@ void copy_file_as_user(const char *srcname, const char *destname, uid_t uid, gid | |||
378 | // drop privileges | 378 | // drop privileges |
379 | drop_privs(0); | 379 | drop_privs(0); |
380 | 380 | ||
381 | // copy, set permissions and ownership | 381 | // copy, set permissions |
382 | int rv = copy_file(srcname, destname, uid, gid, mode); // already a regular user | 382 | int rv = copy_file(srcname, destname, -1, -1, mode); // already a regular user |
383 | if (rv) | 383 | if (rv) |
384 | fwarning("cannot copy %s\n", srcname); | 384 | fwarning("cannot copy %s\n", srcname); |
385 | #ifdef HAVE_GCOV | 385 | #ifdef HAVE_GCOV |
@@ -1231,6 +1231,7 @@ unsigned extract_timeout(const char *str) { | |||
1231 | } | 1231 | } |
1232 | 1232 | ||
1233 | void disable_file_or_dir(const char *fname) { | 1233 | void disable_file_or_dir(const char *fname) { |
1234 | assert(geteuid() == 0); | ||
1234 | assert(fname); | 1235 | assert(fname); |
1235 | 1236 | ||
1236 | EUID_USER(); | 1237 | EUID_USER(); |
diff --git a/src/firejail/x11.c b/src/firejail/x11.c index 0619ff380..896aa2fd3 100644 --- a/src/firejail/x11.c +++ b/src/firejail/x11.c | |||
@@ -1290,9 +1290,11 @@ void x11_xorg(void) { | |||
1290 | if (envar) { | 1290 | if (envar) { |
1291 | char *rp = realpath(envar, NULL); | 1291 | char *rp = realpath(envar, NULL); |
1292 | if (rp) { | 1292 | if (rp) { |
1293 | if (strcmp(rp, dest) != 0) | 1293 | if (strcmp(rp, dest) != 0) { |
1294 | // disable_file_or_dir returns with EUID 0 | 1294 | EUID_ROOT(); |
1295 | disable_file_or_dir(rp); | 1295 | disable_file_or_dir(rp); |
1296 | EUID_USER(); | ||
1297 | } | ||
1296 | free(rp); | 1298 | free(rp); |
1297 | } | 1299 | } |
1298 | } | 1300 | } |
diff --git a/src/firemon/interface.c b/src/firemon/interface.c index b93d4a5a2..372cdee41 100644 --- a/src/firemon/interface.c +++ b/src/firemon/interface.c | |||
@@ -34,7 +34,7 @@ | |||
34 | //#include <linux/if_bridge.h> | 34 | //#include <linux/if_bridge.h> |
35 | 35 | ||
36 | #ifdef HAVE_GCOV | 36 | #ifdef HAVE_GCOV |
37 | #include <gcov.h> | 37 | #include "../include/gcov_wrapper.h" |
38 | #endif | 38 | #endif |
39 | 39 | ||
40 | // print IP addresses for all interfaces | 40 | // print IP addresses for all interfaces |
diff --git a/src/firemon/netstats.c b/src/firemon/netstats.c index 23d228e26..bc951aa26 100644 --- a/src/firemon/netstats.c +++ b/src/firemon/netstats.c | |||
@@ -25,7 +25,7 @@ | |||
25 | #include <unistd.h> | 25 | #include <unistd.h> |
26 | 26 | ||
27 | #ifdef HAVE_GCOV | 27 | #ifdef HAVE_GCOV |
28 | #include <gcov.h> | 28 | #include "../include/gcov_wrapper.h" |
29 | #endif | 29 | #endif |
30 | 30 | ||
31 | #define MAXBUF 4096 | 31 | #define MAXBUF 4096 |
diff --git a/src/firemon/procevent.c b/src/firemon/procevent.c index 4e809681e..79f487582 100644 --- a/src/firemon/procevent.c +++ b/src/firemon/procevent.c | |||
@@ -31,7 +31,7 @@ | |||
31 | #include <sys/uio.h> | 31 | #include <sys/uio.h> |
32 | 32 | ||
33 | #ifdef HAVE_GCOV | 33 | #ifdef HAVE_GCOV |
34 | #include <gcov.h> | 34 | #include "../include/gcov_wrapper.h" |
35 | #endif | 35 | #endif |
36 | 36 | ||
37 | #define PIDS_BUFLEN 4096 | 37 | #define PIDS_BUFLEN 4096 |
diff --git a/src/firemon/top.c b/src/firemon/top.c index 9d6f34991..d0f911e60 100644 --- a/src/firemon/top.c +++ b/src/firemon/top.c | |||
@@ -25,7 +25,7 @@ | |||
25 | #include <unistd.h> | 25 | #include <unistd.h> |
26 | 26 | ||
27 | #ifdef HAVE_GCOV | 27 | #ifdef HAVE_GCOV |
28 | #include <gcov.h> | 28 | #include "../include/gcov_wrapper.h" |
29 | #endif | 29 | #endif |
30 | 30 | ||
31 | static unsigned pgs_rss = 0; | 31 | static unsigned pgs_rss = 0; |
diff --git a/src/include/gcov_wrapper.h b/src/include/gcov_wrapper.h new file mode 100644 index 000000000..2f409309d --- /dev/null +++ b/src/include/gcov_wrapper.h | |||
@@ -0,0 +1,40 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2021 Firejail Authors | ||
3 | * | ||
4 | * This file is part of firejail project | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef GCOV_WRAPPER_H | ||
22 | #define GCOV_WRAPPER_H | ||
23 | |||
24 | #include <gcov.h> | ||
25 | |||
26 | /* | ||
27 | * __gcov_flush was removed on gcc 11.1.0 (as it's no longer needed), but it | ||
28 | * appears to be the safe/"correct" way to do things on previous versions (as | ||
29 | * it ensured proper locking, which is now done elsewhere). Thus, keep using | ||
30 | * it in the code and ensure that it exists, in order to support gcc <11.1.0 | ||
31 | * and gcc >=11.1.0, respectively. | ||
32 | */ | ||
33 | #if __GNUC__ > 11 || (__GNUC__ == 11 && __GNUC_MINOR__ >= 1) | ||
34 | static void __gcov_flush(void) { | ||
35 | __gcov_dump(); | ||
36 | __gcov_reset(); | ||
37 | } | ||
38 | #endif | ||
39 | |||
40 | #endif /* GCOV_WRAPPER_H */ | ||
diff --git a/src/lib/syscall.c b/src/lib/syscall.c index b3131ac17..d0d9ff5aa 100644 --- a/src/lib/syscall.c +++ b/src/lib/syscall.c | |||
@@ -253,9 +253,6 @@ static const SyscallGroupList sysgroups[] = { | |||
253 | #ifdef SYS_fanotify_init | 253 | #ifdef SYS_fanotify_init |
254 | "fanotify_init," | 254 | "fanotify_init," |
255 | #endif | 255 | #endif |
256 | #ifdef SYS_kcmp | ||
257 | "kcmp," | ||
258 | #endif | ||
259 | #ifdef SYS_add_key | 256 | #ifdef SYS_add_key |
260 | "add_key," | 257 | "add_key," |
261 | #endif | 258 | #endif |
diff --git a/src/man/firejail.txt b/src/man/firejail.txt index d18811316..0462705c0 100644 --- a/src/man/firejail.txt +++ b/src/man/firejail.txt | |||
@@ -2178,7 +2178,7 @@ $ firejail \-\-net=eth0 \-\-scan | |||
2178 | .TP | 2178 | .TP |
2179 | \fB\-\-seccomp | 2179 | \fB\-\-seccomp |
2180 | Enable seccomp filter and blacklist the syscalls in the default list, | 2180 | Enable seccomp filter and blacklist the syscalls in the default list, |
2181 | which is @default-nodebuggers unless allow-debuggers is specified, | 2181 | which is @default-nodebuggers unless \-\-allow-debuggers is specified, |
2182 | then it is @default. | 2182 | then it is @default. |
2183 | 2183 | ||
2184 | .br | 2184 | .br |
@@ -2189,18 +2189,13 @@ system call groups are defined: @aio, @basic-io, @chown, @clock, | |||
2189 | @network-io, @obsolete, @privileged, @process, @raw-io, @reboot, | 2189 | @network-io, @obsolete, @privileged, @process, @raw-io, @reboot, |
2190 | @resources, @setuid, @swap, @sync, @system-service and @timer. | 2190 | @resources, @setuid, @swap, @sync, @system-service and @timer. |
2191 | More information about groups can be found in /usr/share/doc/firejail/syscalls.txt | 2191 | More information about groups can be found in /usr/share/doc/firejail/syscalls.txt |
2192 | 2192 | .br | |
2193 | In addition, a system call can be specified by its number instead of | ||
2194 | name with prefix $, so for example $165 would be equal to mount on i386. | ||
2195 | Exceptions can be allowed with prefix !. | ||
2196 | 2193 | ||
2197 | .br | 2194 | .br |
2198 | System architecture is strictly imposed only if flag | 2195 | System architecture is strictly imposed only if flag |
2199 | \-\-seccomp.block-secondary is used. The filter is applied at run time | 2196 | \-\-seccomp.block-secondary is used. The filter is applied at run time |
2200 | only if the correct architecture was detected. For the case of I386 | 2197 | only if the correct architecture was detected. For the case of I386 |
2201 | and AMD64 both 32-bit and 64-bit filters are installed. On a 64 bit | 2198 | and AMD64 both 32-bit and 64-bit filters are installed. |
2202 | architecture, an additional filter for 32 bit system calls can be | ||
2203 | installed with \-\-seccomp.32. | ||
2204 | .br | 2199 | .br |
2205 | 2200 | ||
2206 | .br | 2201 | .br |
@@ -2211,11 +2206,18 @@ Firejail will print seccomp violations to the audit log if the kernel was compil | |||
2211 | Example: | 2206 | Example: |
2212 | .br | 2207 | .br |
2213 | $ firejail \-\-seccomp | 2208 | $ firejail \-\-seccomp |
2209 | .br | ||
2210 | |||
2211 | .br | ||
2212 | The default list can be customized, see \-\-seccomp= for a description. It can be customized | ||
2213 | also globally in /etc/firejail/firejail.config file. | ||
2214 | |||
2214 | .TP | 2215 | .TP |
2215 | \fB\-\-seccomp=syscall,@group,!syscall2 | 2216 | \fB\-\-seccomp=syscall,@group,!syscall2 |
2216 | Enable seccomp filter, whitelist "syscall2", but blacklist the default | 2217 | Enable seccomp filter, blacklist the default list and the syscalls or syscall groups |
2217 | list and the syscalls or syscall groups specified by the | 2218 | specified by the command, but don't blacklist "syscall2". On a 64 bit |
2218 | command. | 2219 | architecture, an additional filter for 32 bit system calls can be |
2220 | installed with \-\-seccomp.32. | ||
2219 | .br | 2221 | .br |
2220 | 2222 | ||
2221 | .br | 2223 | .br |
@@ -2225,6 +2227,13 @@ $ firejail \-\-seccomp=utime,utimensat,utimes firefox | |||
2225 | .br | 2227 | .br |
2226 | $ firejail \-\-seccomp=@clock,mkdir,unlinkat transmission-gtk | 2228 | $ firejail \-\-seccomp=@clock,mkdir,unlinkat transmission-gtk |
2227 | .br | 2229 | .br |
2230 | $ firejail '\-\-seccomp=@ipc,!pipe,!pipe2' audacious | ||
2231 | .br | ||
2232 | |||
2233 | .br | ||
2234 | Syscalls can be specified by their number if prefix $ is added, | ||
2235 | so for example $165 would be equal to mount on i386. | ||
2236 | .br | ||
2228 | 2237 | ||
2229 | .br | 2238 | .br |
2230 | Instead of dropping the syscall by returning EPERM, another error | 2239 | Instead of dropping the syscall by returning EPERM, another error |
@@ -2237,6 +2246,7 @@ by using \fBsyscall:kill\fR syntax, or the attempt may be logged with | |||
2237 | 2246 | ||
2238 | .br | 2247 | .br |
2239 | Example: | 2248 | Example: |
2249 | .br | ||
2240 | $ firejail \-\-seccomp=unlinkat:ENOENT,utimensat,utimes | 2250 | $ firejail \-\-seccomp=unlinkat:ENOENT,utimensat,utimes |
2241 | .br | 2251 | .br |
2242 | Parent pid 10662, child pid 10663 | 2252 | Parent pid 10662, child pid 10663 |
@@ -2245,9 +2255,13 @@ Child process initialized | |||
2245 | .br | 2255 | .br |
2246 | $ touch testfile | 2256 | $ touch testfile |
2247 | .br | 2257 | .br |
2258 | $ ls testfile | ||
2259 | .br | ||
2260 | testfile | ||
2261 | .br | ||
2248 | $ rm testfile | 2262 | $ rm testfile |
2249 | .br | 2263 | .br |
2250 | rm: cannot remove `testfile': Operation not permitted | 2264 | rm: cannot remove `testfile': No such file or directory |
2251 | .br | 2265 | .br |
2252 | 2266 | ||
2253 | .br | 2267 | .br |
@@ -2260,7 +2274,7 @@ filters. | |||
2260 | .br | 2274 | .br |
2261 | Example: | 2275 | Example: |
2262 | .br | 2276 | .br |
2263 | $ firejail \-\-noprofile \-\-shell=none \-\-seccomp=execve bash | 2277 | $ firejail \-\-noprofile \-\-shell=none \-\-seccomp=execve sh |
2264 | .br | 2278 | .br |
2265 | Parent pid 32751, child pid 32752 | 2279 | Parent pid 32751, child pid 32752 |
2266 | .br | 2280 | .br |
@@ -2272,8 +2286,7 @@ Child process initialized in 46.44 ms | |||
2272 | .br | 2286 | .br |
2273 | $ ls | 2287 | $ ls |
2274 | .br | 2288 | .br |
2275 | Bad system call | 2289 | Operation not permitted |
2276 | .br | ||
2277 | 2290 | ||
2278 | .TP | 2291 | .TP |
2279 | \fB\-\-seccomp.block-secondary | 2292 | \fB\-\-seccomp.block-secondary |
@@ -2317,15 +2330,15 @@ Child process initialized | |||
2317 | .br | 2330 | .br |
2318 | $ touch testfile | 2331 | $ touch testfile |
2319 | .br | 2332 | .br |
2333 | $ ls testfile | ||
2334 | .br | ||
2335 | testfile | ||
2336 | .br | ||
2320 | $ rm testfile | 2337 | $ rm testfile |
2321 | .br | 2338 | .br |
2322 | rm: cannot remove `testfile': Operation not permitted | 2339 | rm: cannot remove `testfile': No such file or directory |
2323 | .br | 2340 | .br |
2324 | 2341 | ||
2325 | |||
2326 | |||
2327 | |||
2328 | |||
2329 | .TP | 2342 | .TP |
2330 | \fB\-\-seccomp.keep=syscall,@group,!syscall2 | 2343 | \fB\-\-seccomp.keep=syscall,@group,!syscall2 |
2331 | Enable seccomp filter, blacklist all syscall not listed and "syscall2". | 2344 | Enable seccomp filter, blacklist all syscall not listed and "syscall2". |