diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/firecfg/firecfg.config | 2 | ||||
-rw-r--r-- | src/firejail/appimage.c | 8 | ||||
-rw-r--r-- | src/firejail/checkcfg.c | 5 | ||||
-rw-r--r-- | src/firejail/chroot.c | 8 | ||||
-rw-r--r-- | src/firejail/dbus.c | 4 | ||||
-rw-r--r-- | src/firejail/dhcp.c | 3 | ||||
-rw-r--r-- | src/firejail/firejail.h | 6 | ||||
-rw-r--r-- | src/firejail/fs.c | 41 | ||||
-rw-r--r-- | src/firejail/fs_home.c | 99 | ||||
-rw-r--r-- | src/firejail/fs_mkdir.c | 9 | ||||
-rw-r--r-- | src/firejail/fs_whitelist.c | 8 | ||||
-rw-r--r-- | src/firejail/ls.c | 16 | ||||
-rw-r--r-- | src/firejail/main.c | 34 | ||||
-rw-r--r-- | src/firejail/profile.c | 22 | ||||
-rw-r--r-- | src/firejail/rlimit.c | 30 | ||||
-rw-r--r-- | src/firejail/sandbox.c | 13 | ||||
-rw-r--r-- | src/firejail/seccomp.c | 5 | ||||
-rw-r--r-- | src/firejail/util.c | 73 | ||||
-rw-r--r-- | src/firejail/x11.c | 6 | ||||
-rw-r--r-- | src/firemon/interface.c | 9 | ||||
-rw-r--r-- | src/firemon/netstats.c | 10 | ||||
-rw-r--r-- | src/firemon/procevent.c | 7 | ||||
-rw-r--r-- | src/firemon/top.c | 10 | ||||
-rw-r--r-- | src/include/gcov_wrapper.h | 46 | ||||
-rw-r--r-- | src/lib/syscall.c | 3 | ||||
-rw-r--r-- | src/man/firejail-profile.txt | 2 | ||||
-rw-r--r-- | src/man/firejail.txt | 60 |
27 files changed, 326 insertions, 213 deletions
diff --git a/src/firecfg/firecfg.config b/src/firecfg/firecfg.config index f23488e20..e58fe39ec 100644 --- a/src/firecfg/firecfg.config +++ b/src/firecfg/firecfg.config | |||
@@ -38,6 +38,8 @@ abrowser | |||
38 | akonadi_control | 38 | akonadi_control |
39 | akregator | 39 | akregator |
40 | alacarte | 40 | alacarte |
41 | alpine | ||
42 | alpinef | ||
41 | amarok | 43 | amarok |
42 | amule | 44 | amule |
43 | amuled | 45 | amuled |
diff --git a/src/firejail/appimage.c b/src/firejail/appimage.c index a96415985..2266fa499 100644 --- a/src/firejail/appimage.c +++ b/src/firejail/appimage.c | |||
@@ -21,6 +21,7 @@ | |||
21 | // sudo mount -o loop krita-3.0-x86_64.appimage mnt | 21 | // sudo mount -o loop krita-3.0-x86_64.appimage mnt |
22 | 22 | ||
23 | #include "firejail.h" | 23 | #include "firejail.h" |
24 | #include "../include/gcov_wrapper.h" | ||
24 | #include <sys/types.h> | 25 | #include <sys/types.h> |
25 | #include <sys/stat.h> | 26 | #include <sys/stat.h> |
26 | #include <sys/mount.h> | 27 | #include <sys/mount.h> |
@@ -28,10 +29,6 @@ | |||
28 | #include <linux/loop.h> | 29 | #include <linux/loop.h> |
29 | #include <errno.h> | 30 | #include <errno.h> |
30 | 31 | ||
31 | #ifdef HAVE_GCOV | ||
32 | #include <gcov.h> | ||
33 | #endif | ||
34 | |||
35 | static char *devloop = NULL; // device file | 32 | static char *devloop = NULL; // device file |
36 | static long unsigned size = 0; // offset into appimage file | 33 | static long unsigned size = 0; // offset into appimage file |
37 | #define MAXBUF 4096 | 34 | #define MAXBUF 4096 |
@@ -144,9 +141,8 @@ void appimage_set(const char *appimage) { | |||
144 | 141 | ||
145 | if (cfg.cwd) | 142 | if (cfg.cwd) |
146 | env_store_name_val("OWD", cfg.cwd, SETENV); | 143 | env_store_name_val("OWD", cfg.cwd, SETENV); |
147 | #ifdef HAVE_GCOV | 144 | |
148 | __gcov_flush(); | 145 | __gcov_flush(); |
149 | #endif | ||
150 | #else | 146 | #else |
151 | fprintf(stderr, "Error: /dev/loop-control interface is not supported by your kernel\n"); | 147 | fprintf(stderr, "Error: /dev/loop-control interface is not supported by your kernel\n"); |
152 | exit(1); | 148 | exit(1); |
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..37ec22117 100644 --- a/src/firejail/chroot.c +++ b/src/firejail/chroot.c | |||
@@ -20,6 +20,7 @@ | |||
20 | 20 | ||
21 | #ifdef HAVE_CHROOT | 21 | #ifdef HAVE_CHROOT |
22 | #include "firejail.h" | 22 | #include "firejail.h" |
23 | #include "../include/gcov_wrapper.h" | ||
23 | #include <sys/mount.h> | 24 | #include <sys/mount.h> |
24 | #include <sys/sendfile.h> | 25 | #include <sys/sendfile.h> |
25 | #include <errno.h> | 26 | #include <errno.h> |
@@ -29,10 +30,6 @@ | |||
29 | #define O_PATH 010000000 | 30 | #define O_PATH 010000000 |
30 | #endif | 31 | #endif |
31 | 32 | ||
32 | #ifdef HAVE_GCOV | ||
33 | #include <gcov.h> | ||
34 | #endif | ||
35 | |||
36 | // exit if error | 33 | // exit if error |
37 | void fs_check_chroot_dir(void) { | 34 | void fs_check_chroot_dir(void) { |
38 | EUID_ASSERT(); | 35 | EUID_ASSERT(); |
@@ -263,9 +260,8 @@ void fs_chroot(const char *rootdir) { | |||
263 | // update chroot resolv.conf | 260 | // update chroot resolv.conf |
264 | update_file(parentfd, "etc/resolv.conf"); | 261 | update_file(parentfd, "etc/resolv.conf"); |
265 | 262 | ||
266 | #ifdef HAVE_GCOV | ||
267 | __gcov_flush(); | 263 | __gcov_flush(); |
268 | #endif | 264 | |
269 | // create /run/firejail/mnt/oroot | 265 | // create /run/firejail/mnt/oroot |
270 | char *oroot = RUN_OVERLAY_ROOT; | 266 | char *oroot = RUN_OVERLAY_ROOT; |
271 | if (mkdir(oroot, 0755) == -1) | 267 | if (mkdir(oroot, 0755) == -1) |
diff --git a/src/firejail/dbus.c b/src/firejail/dbus.c index bfa28fcba..9a4cb2e6b 100644 --- a/src/firejail/dbus.c +++ b/src/firejail/dbus.c | |||
@@ -470,7 +470,7 @@ void dbus_apply_policy(void) { | |||
470 | create_empty_dir_as_root(RUN_DBUS_DIR, 0755); | 470 | create_empty_dir_as_root(RUN_DBUS_DIR, 0755); |
471 | 471 | ||
472 | if (arg_dbus_user != DBUS_POLICY_ALLOW) { | 472 | if (arg_dbus_user != DBUS_POLICY_ALLOW) { |
473 | create_empty_file_as_root(RUN_DBUS_USER_SOCKET, 0700); | 473 | create_empty_file_as_root(RUN_DBUS_USER_SOCKET, 0600); |
474 | 474 | ||
475 | if (arg_dbus_user == DBUS_POLICY_FILTER) { | 475 | if (arg_dbus_user == DBUS_POLICY_FILTER) { |
476 | assert(dbus_user_proxy_socket != NULL); | 476 | assert(dbus_user_proxy_socket != NULL); |
@@ -509,7 +509,7 @@ void dbus_apply_policy(void) { | |||
509 | } | 509 | } |
510 | 510 | ||
511 | if (arg_dbus_system != DBUS_POLICY_ALLOW) { | 511 | if (arg_dbus_system != DBUS_POLICY_ALLOW) { |
512 | create_empty_file_as_root(RUN_DBUS_SYSTEM_SOCKET, 0700); | 512 | create_empty_file_as_root(RUN_DBUS_SYSTEM_SOCKET, 0600); |
513 | 513 | ||
514 | if (arg_dbus_system == DBUS_POLICY_FILTER) { | 514 | if (arg_dbus_system == DBUS_POLICY_FILTER) { |
515 | assert(dbus_system_proxy_socket != NULL); | 515 | assert(dbus_system_proxy_socket != NULL); |
diff --git a/src/firejail/dhcp.c b/src/firejail/dhcp.c index 47dd39ac0..ec482e2ea 100644 --- a/src/firejail/dhcp.c +++ b/src/firejail/dhcp.c | |||
@@ -160,9 +160,6 @@ void dhcp_start(void) { | |||
160 | exit(1); | 160 | exit(1); |
161 | } | 161 | } |
162 | 162 | ||
163 | sbox_run(SBOX_ROOT| SBOX_SECCOMP, 4, PATH_FCOPY, "--follow-link", dhclient_path, RUN_MNT_DIR); | ||
164 | dhclient_path = RUN_MNT_DIR "/dhclient"; | ||
165 | |||
166 | EUID_ROOT(); | 163 | EUID_ROOT(); |
167 | if (mkdir(RUN_DHCLIENT_DIR, 0700)) | 164 | if (mkdir(RUN_DHCLIENT_DIR, 0700)) |
168 | errExit("mkdir"); | 165 | errExit("mkdir"); |
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 622be4d97..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, |
@@ -498,6 +498,7 @@ int macro_id(const char *name); | |||
498 | void errLogExit(char* fmt, ...) __attribute__((noreturn)); | 498 | void errLogExit(char* fmt, ...) __attribute__((noreturn)); |
499 | void fwarning(char* fmt, ...); | 499 | void fwarning(char* fmt, ...); |
500 | void fmessage(char* fmt, ...); | 500 | void fmessage(char* fmt, ...); |
501 | long long unsigned parse_arg_size(char *str); | ||
501 | void drop_privs(int nogroups); | 502 | void drop_privs(int nogroups); |
502 | int mkpath_as_root(const char* path); | 503 | int mkpath_as_root(const char* path); |
503 | void extract_command_name(int index, char **argv); | 504 | void extract_command_name(int index, char **argv); |
@@ -507,7 +508,7 @@ void logargs(int argc, char **argv) ; | |||
507 | void logerr(const char *msg); | 508 | void logerr(const char *msg); |
508 | void set_nice(int inc); | 509 | void set_nice(int inc); |
509 | 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); |
510 | 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); |
511 | 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); |
512 | void touch_file_as_user(const char *fname, mode_t mode); | 513 | void touch_file_as_user(const char *fname, mode_t mode); |
513 | int is_dir(const char *fname); | 514 | int is_dir(const char *fname); |
@@ -809,6 +810,7 @@ extern char *xvfb_extra_params; | |||
809 | extern char *netfilter_default; | 810 | extern char *netfilter_default; |
810 | extern unsigned long join_timeout; | 811 | extern unsigned long join_timeout; |
811 | extern char *config_seccomp_error_action_str; | 812 | extern char *config_seccomp_error_action_str; |
813 | extern char *config_seccomp_filter_add; | ||
812 | extern char **whitelist_reject_topdirs; | 814 | extern char **whitelist_reject_topdirs; |
813 | 815 | ||
814 | int checkcfg(int val); | 816 | int checkcfg(int val); |
diff --git a/src/firejail/fs.c b/src/firejail/fs.c index 6a49f1465..0e26eb505 100644 --- a/src/firejail/fs.c +++ b/src/firejail/fs.c | |||
@@ -18,6 +18,7 @@ | |||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
19 | */ | 19 | */ |
20 | #include "firejail.h" | 20 | #include "firejail.h" |
21 | #include "../include/gcov_wrapper.h" | ||
21 | #include <sys/mount.h> | 22 | #include <sys/mount.h> |
22 | #include <sys/stat.h> | 23 | #include <sys/stat.h> |
23 | #include <sys/statvfs.h> | 24 | #include <sys/statvfs.h> |
@@ -33,10 +34,6 @@ | |||
33 | #define O_PATH 010000000 | 34 | #define O_PATH 010000000 |
34 | #endif | 35 | #endif |
35 | 36 | ||
36 | #ifdef HAVE_GCOV | ||
37 | #include <gcov.h> | ||
38 | #endif | ||
39 | |||
40 | #define MAX_BUF 4096 | 37 | #define MAX_BUF 4096 |
41 | #define EMPTY_STRING ("") | 38 | #define EMPTY_STRING ("") |
42 | // check noblacklist statements not matched by a proper blacklist in disable-*.inc files | 39 | // check noblacklist statements not matched by a proper blacklist in disable-*.inc files |
@@ -171,21 +168,28 @@ static void disable_file(OPERATION op, const char *filename) { | |||
171 | fs_remount_rec(fname, op); | 168 | fs_remount_rec(fname, op); |
172 | } | 169 | } |
173 | else if (op == MOUNT_TMPFS) { | 170 | else if (op == MOUNT_TMPFS) { |
174 | if (S_ISDIR(s.st_mode)) { | 171 | if (!S_ISDIR(s.st_mode)) { |
175 | if (getuid()) { | 172 | fwarning("%s is not a directory; cannot mount a tmpfs on top of it.\n", fname); |
176 | if (strncmp(cfg.homedir, fname, strlen(cfg.homedir)) != 0 || | 173 | free(fname); |
177 | fname[strlen(cfg.homedir)] != '/') { | 174 | return; |
178 | fprintf(stderr, "Error: tmpfs outside $HOME is only available for root\n"); | 175 | } |
179 | exit(1); | 176 | |
180 | } | 177 | uid_t uid = getuid(); |
178 | if (uid != 0) { | ||
179 | // only user owned directories in user home | ||
180 | if (s.st_uid != uid || | ||
181 | strncmp(cfg.homedir, fname, strlen(cfg.homedir)) != 0 || | ||
182 | fname[strlen(cfg.homedir)] != '/') { | ||
183 | fwarning("you are not allowed to mount a tmpfs on %s\n", fname); | ||
184 | free(fname); | ||
185 | return; | ||
181 | } | 186 | } |
182 | // fs_tmpfs returns with EUID 0 | ||
183 | fs_tmpfs(fname, getuid()); | ||
184 | selinux_relabel_path(fname, fname); | ||
185 | EUID_USER(); | ||
186 | } | 187 | } |
187 | else | 188 | |
188 | fwarning("%s is not a directory; cannot mount a tmpfs on top of it.\n", fname); | 189 | fs_tmpfs(fname, uid); |
190 | EUID_USER(); // fs_tmpfs returns with EUID 0 | ||
191 | |||
192 | selinux_relabel_path(fname, fname); | ||
189 | } | 193 | } |
190 | else | 194 | else |
191 | assert(0); | 195 | assert(0); |
@@ -1206,9 +1210,8 @@ void fs_overlayfs(void) { | |||
1206 | fs_logger("whitelist /tmp"); | 1210 | fs_logger("whitelist /tmp"); |
1207 | 1211 | ||
1208 | // chroot in the new filesystem | 1212 | // chroot in the new filesystem |
1209 | #ifdef HAVE_GCOV | ||
1210 | __gcov_flush(); | 1213 | __gcov_flush(); |
1211 | #endif | 1214 | |
1212 | if (chroot(oroot) == -1) | 1215 | if (chroot(oroot) == -1) |
1213 | errExit("chroot"); | 1216 | errExit("chroot"); |
1214 | 1217 | ||
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..4983db0a0 100644 --- a/src/firejail/fs_mkdir.c +++ b/src/firejail/fs_mkdir.c | |||
@@ -18,6 +18,7 @@ | |||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
19 | */ | 19 | */ |
20 | #include "firejail.h" | 20 | #include "firejail.h" |
21 | #include "../include/gcov_wrapper.h" | ||
21 | #include <sys/types.h> | 22 | #include <sys/types.h> |
22 | #include <sys/stat.h> | 23 | #include <sys/stat.h> |
23 | #include <unistd.h> | 24 | #include <unistd.h> |
@@ -25,10 +26,6 @@ | |||
25 | #include <sys/wait.h> | 26 | #include <sys/wait.h> |
26 | #include <string.h> | 27 | #include <string.h> |
27 | 28 | ||
28 | #ifdef HAVE_GCOV | ||
29 | #include <gcov.h> | ||
30 | #endif | ||
31 | |||
32 | static void check(const char *fname) { | 29 | static void check(const char *fname) { |
33 | // manufacture /run/user directory | 30 | // manufacture /run/user directory |
34 | char *runuser; | 31 | char *runuser; |
@@ -98,9 +95,9 @@ void fs_mkdir(const char *name) { | |||
98 | 95 | ||
99 | // create directory | 96 | // create directory |
100 | mkdir_recursive(expanded); | 97 | mkdir_recursive(expanded); |
101 | #ifdef HAVE_GCOV | 98 | |
102 | __gcov_flush(); | 99 | __gcov_flush(); |
103 | #endif | 100 | |
104 | _exit(0); | 101 | _exit(0); |
105 | } | 102 | } |
106 | // wait for the child to finish | 103 | // wait for the child to finish |
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..70985ba9e 100644 --- a/src/firejail/ls.c +++ b/src/firejail/ls.c | |||
@@ -19,6 +19,7 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include "firejail.h" | 21 | #include "firejail.h" |
22 | #include "../include/gcov_wrapper.h" | ||
22 | #include <sys/types.h> | 23 | #include <sys/types.h> |
23 | #include <sys/stat.h> | 24 | #include <sys/stat.h> |
24 | #include <sys/wait.h> | 25 | #include <sys/wait.h> |
@@ -31,10 +32,6 @@ | |||
31 | //#include <stdio.h> | 32 | //#include <stdio.h> |
32 | //#include <stdlib.h> | 33 | //#include <stdlib.h> |
33 | 34 | ||
34 | #ifdef HAVE_GCOV | ||
35 | #include <gcov.h> | ||
36 | #endif | ||
37 | |||
38 | // uid/gid cache | 35 | // uid/gid cache |
39 | static uid_t c_uid = 0; | 36 | static uid_t c_uid = 0; |
40 | static char *c_uid_name = NULL; | 37 | static char *c_uid_name = NULL; |
@@ -353,9 +350,8 @@ void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) { | |||
353 | ls(fname1); | 350 | ls(fname1); |
354 | else | 351 | else |
355 | cat(fname1); | 352 | cat(fname1); |
356 | #ifdef HAVE_GCOV | 353 | |
357 | __gcov_flush(); | 354 | __gcov_flush(); |
358 | #endif | ||
359 | } | 355 | } |
360 | // get file from host and store it in the sandbox | 356 | // get file from host and store it in the sandbox |
361 | else if (op == SANDBOX_FS_PUT && path2) { | 357 | else if (op == SANDBOX_FS_PUT && path2) { |
@@ -387,9 +383,9 @@ void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) { | |||
387 | // copy the file | 383 | // copy the file |
388 | if (copy_file(src_fname, tmp_fname, getuid(), getgid(), 0600)) // already a regular user | 384 | if (copy_file(src_fname, tmp_fname, getuid(), getgid(), 0600)) // already a regular user |
389 | _exit(1); | 385 | _exit(1); |
390 | #ifdef HAVE_GCOV | 386 | |
391 | __gcov_flush(); | 387 | __gcov_flush(); |
392 | #endif | 388 | |
393 | _exit(0); | 389 | _exit(0); |
394 | } | 390 | } |
395 | 391 | ||
@@ -419,9 +415,9 @@ void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) { | |||
419 | // copy the file | 415 | // copy the file |
420 | if (copy_file(tmp_fname, dest_fname, getuid(), getgid(), 0600)) // already a regular user | 416 | if (copy_file(tmp_fname, dest_fname, getuid(), getgid(), 0600)) // already a regular user |
421 | _exit(1); | 417 | _exit(1); |
422 | #ifdef HAVE_GCOV | 418 | |
423 | __gcov_flush(); | 419 | __gcov_flush(); |
424 | #endif | 420 | |
425 | _exit(0); | 421 | _exit(0); |
426 | } | 422 | } |
427 | 423 | ||
diff --git a/src/firejail/main.c b/src/firejail/main.c index 02366a08c..7a0d52837 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include "firejail.h" | 20 | #include "firejail.h" |
21 | #include "../include/pid.h" | 21 | #include "../include/pid.h" |
22 | #include "../include/firejail_user.h" | 22 | #include "../include/firejail_user.h" |
23 | #include "../include/gcov_wrapper.h" | ||
23 | #include "../include/syscall.h" | 24 | #include "../include/syscall.h" |
24 | #include "../include/seccomp.h" | 25 | #include "../include/seccomp.h" |
25 | #define _GNU_SOURCE | 26 | #define _GNU_SOURCE |
@@ -44,10 +45,6 @@ | |||
44 | #define O_PATH 010000000 | 45 | #define O_PATH 010000000 |
45 | #endif | 46 | #endif |
46 | 47 | ||
47 | #ifdef HAVE_GCOV | ||
48 | #include <gcov.h> | ||
49 | #endif | ||
50 | |||
51 | #ifdef __ia64__ | 48 | #ifdef __ia64__ |
52 | /* clone(2) has a different interface on ia64, as it needs to know | 49 | /* clone(2) has a different interface on ia64, as it needs to know |
53 | the size of the stack */ | 50 | the size of the stack */ |
@@ -967,7 +964,7 @@ void filter_add_blacklist_override(int fd, int syscall, int arg, void *ptrarg, b | |||
967 | static int check_postexec(const char *list) { | 964 | static int check_postexec(const char *list) { |
968 | char *prelist, *postlist; | 965 | char *prelist, *postlist; |
969 | 966 | ||
970 | if (list) { | 967 | if (list && list[0]) { |
971 | syscalls_in_list(list, "@default-keep", -1, &prelist, &postlist, true); | 968 | syscalls_in_list(list, "@default-keep", -1, &prelist, &postlist, true); |
972 | if (postlist) | 969 | if (postlist) |
973 | return 1; | 970 | return 1; |
@@ -1496,8 +1493,11 @@ int main(int argc, char **argv, char **envp) { | |||
1496 | arg_rlimit_nproc = 1; | 1493 | arg_rlimit_nproc = 1; |
1497 | } | 1494 | } |
1498 | else if (strncmp(argv[i], "--rlimit-fsize=", 15) == 0) { | 1495 | else if (strncmp(argv[i], "--rlimit-fsize=", 15) == 0) { |
1499 | check_unsigned(argv[i] + 15, "Error: invalid rlimit"); | 1496 | cfg.rlimit_fsize = parse_arg_size(argv[i] + 15); |
1500 | sscanf(argv[i] + 15, "%llu", &cfg.rlimit_fsize); | 1497 | if (cfg.rlimit_fsize == 0) { |
1498 | perror("Error: invalid rlimit-fsize. Only use positive numbers and k, m or g suffix."); | ||
1499 | exit(1); | ||
1500 | } | ||
1501 | arg_rlimit_fsize = 1; | 1501 | arg_rlimit_fsize = 1; |
1502 | } | 1502 | } |
1503 | else if (strncmp(argv[i], "--rlimit-sigpending=", 20) == 0) { | 1503 | else if (strncmp(argv[i], "--rlimit-sigpending=", 20) == 0) { |
@@ -1506,8 +1506,11 @@ int main(int argc, char **argv, char **envp) { | |||
1506 | arg_rlimit_sigpending = 1; | 1506 | arg_rlimit_sigpending = 1; |
1507 | } | 1507 | } |
1508 | else if (strncmp(argv[i], "--rlimit-as=", 12) == 0) { | 1508 | else if (strncmp(argv[i], "--rlimit-as=", 12) == 0) { |
1509 | check_unsigned(argv[i] + 12, "Error: invalid rlimit"); | 1509 | cfg.rlimit_as = parse_arg_size(argv[i] + 12); |
1510 | sscanf(argv[i] + 12, "%llu", &cfg.rlimit_as); | 1510 | if (cfg.rlimit_as == 0) { |
1511 | perror("Error: invalid rlimit-as. Only use positive numbers and k, m or g suffix."); | ||
1512 | exit(1); | ||
1513 | } | ||
1511 | arg_rlimit_as = 1; | 1514 | arg_rlimit_as = 1; |
1512 | } | 1515 | } |
1513 | else if (strncmp(argv[i], "--ipc-namespace", 15) == 0) | 1516 | else if (strncmp(argv[i], "--ipc-namespace", 15) == 0) |
@@ -2889,6 +2892,15 @@ int main(int argc, char **argv, char **envp) { | |||
2889 | // check network configuration options - it will exit if anything went wrong | 2892 | // check network configuration options - it will exit if anything went wrong |
2890 | net_check_cfg(); | 2893 | net_check_cfg(); |
2891 | 2894 | ||
2895 | // customization of default seccomp filter | ||
2896 | if (config_seccomp_filter_add) { | ||
2897 | if (arg_seccomp && !cfg.seccomp_list_keep && !cfg.seccomp_list_drop) | ||
2898 | profile_list_augment(&cfg.seccomp_list, config_seccomp_filter_add); | ||
2899 | |||
2900 | if (arg_seccomp32 && !cfg.seccomp_list_keep32 && !cfg.seccomp_list_drop32) | ||
2901 | profile_list_augment(&cfg.seccomp_list32, config_seccomp_filter_add); | ||
2902 | } | ||
2903 | |||
2892 | if (arg_seccomp) | 2904 | if (arg_seccomp) |
2893 | arg_seccomp_postexec = check_postexec(cfg.seccomp_list) || check_postexec(cfg.seccomp_list_drop); | 2905 | arg_seccomp_postexec = check_postexec(cfg.seccomp_list) || check_postexec(cfg.seccomp_list_drop); |
2894 | 2906 | ||
@@ -3024,9 +3036,9 @@ int main(int argc, char **argv, char **envp) { | |||
3024 | network_main(child); | 3036 | network_main(child); |
3025 | if (arg_debug) | 3037 | if (arg_debug) |
3026 | printf("Host network configured\n"); | 3038 | printf("Host network configured\n"); |
3027 | #ifdef HAVE_GCOV | 3039 | |
3028 | __gcov_flush(); | 3040 | __gcov_flush(); |
3029 | #endif | 3041 | |
3030 | _exit(0); | 3042 | _exit(0); |
3031 | } | 3043 | } |
3032 | 3044 | ||
diff --git a/src/firejail/profile.c b/src/firejail/profile.c index 807a77bd7..e52bdc6e3 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c | |||
@@ -18,15 +18,12 @@ | |||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
19 | */ | 19 | */ |
20 | #include "firejail.h" | 20 | #include "firejail.h" |
21 | #include "../include/gcov_wrapper.h" | ||
21 | #include "../include/seccomp.h" | 22 | #include "../include/seccomp.h" |
22 | #include "../include/syscall.h" | 23 | #include "../include/syscall.h" |
23 | #include <dirent.h> | 24 | #include <dirent.h> |
24 | #include <sys/stat.h> | 25 | #include <sys/stat.h> |
25 | 26 | ||
26 | #ifdef HAVE_GCOV | ||
27 | #include <gcov.h> | ||
28 | #endif | ||
29 | |||
30 | extern char *xephyr_screen; | 27 | extern char *xephyr_screen; |
31 | 28 | ||
32 | #define MAX_READ 8192 // line buffer for profile files | 29 | #define MAX_READ 8192 // line buffer for profile files |
@@ -1510,8 +1507,11 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
1510 | arg_rlimit_nproc = 1; | 1507 | arg_rlimit_nproc = 1; |
1511 | } | 1508 | } |
1512 | else if (strncmp(ptr, "rlimit-fsize ", 13) == 0) { | 1509 | else if (strncmp(ptr, "rlimit-fsize ", 13) == 0) { |
1513 | check_unsigned(ptr + 13, "Error: invalid rlimit in profile file: "); | 1510 | cfg.rlimit_fsize = parse_arg_size(ptr + 13); |
1514 | sscanf(ptr + 13, "%llu", &cfg.rlimit_fsize); | 1511 | if (cfg.rlimit_fsize == 0) { |
1512 | perror("Error: invalid rlimit-fsize in profile file. Only use positive numbers and k, m or g suffix."); | ||
1513 | exit(1); | ||
1514 | } | ||
1515 | arg_rlimit_fsize = 1; | 1515 | arg_rlimit_fsize = 1; |
1516 | } | 1516 | } |
1517 | else if (strncmp(ptr, "rlimit-sigpending ", 18) == 0) { | 1517 | else if (strncmp(ptr, "rlimit-sigpending ", 18) == 0) { |
@@ -1520,8 +1520,11 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
1520 | arg_rlimit_sigpending = 1; | 1520 | arg_rlimit_sigpending = 1; |
1521 | } | 1521 | } |
1522 | else if (strncmp(ptr, "rlimit-as ", 10) == 0) { | 1522 | else if (strncmp(ptr, "rlimit-as ", 10) == 0) { |
1523 | check_unsigned(ptr + 10, "Error: invalid rlimit in profile file: "); | 1523 | cfg.rlimit_as = parse_arg_size(ptr + 10); |
1524 | sscanf(ptr + 10, "%llu", &cfg.rlimit_as); | 1524 | if (cfg.rlimit_as == 0) { |
1525 | perror("Error: invalid rlimit-as in profile file. Only use positive numbers and k, m or g suffix."); | ||
1526 | exit(1); | ||
1527 | } | ||
1525 | arg_rlimit_as = 1; | 1528 | arg_rlimit_as = 1; |
1526 | } | 1529 | } |
1527 | else { | 1530 | else { |
@@ -1799,9 +1802,8 @@ void profile_read(const char *fname) { | |||
1799 | // else { | 1802 | // else { |
1800 | // free(ptr); | 1803 | // free(ptr); |
1801 | // } | 1804 | // } |
1802 | #ifdef HAVE_GCOV | 1805 | |
1803 | __gcov_flush(); | 1806 | __gcov_flush(); |
1804 | #endif | ||
1805 | } | 1807 | } |
1806 | fclose(fp); | 1808 | fclose(fp); |
1807 | } | 1809 | } |
diff --git a/src/firejail/rlimit.c b/src/firejail/rlimit.c index dd6fec972..f177f4b89 100644 --- a/src/firejail/rlimit.c +++ b/src/firejail/rlimit.c | |||
@@ -18,13 +18,10 @@ | |||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
19 | */ | 19 | */ |
20 | #include "firejail.h" | 20 | #include "firejail.h" |
21 | #include "../include/gcov_wrapper.h" | ||
21 | #include <sys/time.h> | 22 | #include <sys/time.h> |
22 | #include <sys/resource.h> | 23 | #include <sys/resource.h> |
23 | 24 | ||
24 | #ifdef HAVE_GCOV | ||
25 | #include <gcov.h> | ||
26 | #endif | ||
27 | |||
28 | void set_rlimits(void) { | 25 | void set_rlimits(void) { |
29 | EUID_ASSERT(); | 26 | EUID_ASSERT(); |
30 | // resource limits | 27 | // resource limits |
@@ -37,9 +34,9 @@ void set_rlimits(void) { | |||
37 | // set the new limit | 34 | // set the new limit |
38 | rl.rlim_cur = (rlim_t) cfg.rlimit_cpu; | 35 | rl.rlim_cur = (rlim_t) cfg.rlimit_cpu; |
39 | rl.rlim_max = (rlim_t) cfg.rlimit_cpu; | 36 | rl.rlim_max = (rlim_t) cfg.rlimit_cpu; |
40 | #ifdef HAVE_GCOV | 37 | |
41 | __gcov_dump(); | 38 | __gcov_dump(); |
42 | #endif | 39 | |
43 | if (setrlimit(RLIMIT_CPU, &rl) == -1) | 40 | if (setrlimit(RLIMIT_CPU, &rl) == -1) |
44 | errExit("setrlimit"); | 41 | errExit("setrlimit"); |
45 | if (arg_debug) | 42 | if (arg_debug) |
@@ -54,9 +51,10 @@ void set_rlimits(void) { | |||
54 | // set the new limit | 51 | // set the new limit |
55 | rl.rlim_cur = (rlim_t) cfg.rlimit_nofile; | 52 | rl.rlim_cur = (rlim_t) cfg.rlimit_nofile; |
56 | rl.rlim_max = (rlim_t) cfg.rlimit_nofile; | 53 | rl.rlim_max = (rlim_t) cfg.rlimit_nofile; |
57 | #ifdef HAVE_GCOV // gcov-instrumented programs might crash at this point | 54 | |
55 | // gcov-instrumented programs might crash at this point | ||
58 | __gcov_dump(); | 56 | __gcov_dump(); |
59 | #endif | 57 | |
60 | if (setrlimit(RLIMIT_NOFILE, &rl) == -1) | 58 | if (setrlimit(RLIMIT_NOFILE, &rl) == -1) |
61 | errExit("setrlimit"); | 59 | errExit("setrlimit"); |
62 | if (arg_debug) | 60 | if (arg_debug) |
@@ -71,9 +69,9 @@ void set_rlimits(void) { | |||
71 | // set the new limit | 69 | // set the new limit |
72 | rl.rlim_cur = (rlim_t) cfg.rlimit_nproc; | 70 | rl.rlim_cur = (rlim_t) cfg.rlimit_nproc; |
73 | rl.rlim_max = (rlim_t) cfg.rlimit_nproc; | 71 | rl.rlim_max = (rlim_t) cfg.rlimit_nproc; |
74 | #ifdef HAVE_GCOV | 72 | |
75 | __gcov_dump(); | 73 | __gcov_dump(); |
76 | #endif | 74 | |
77 | if (setrlimit(RLIMIT_NPROC, &rl) == -1) | 75 | if (setrlimit(RLIMIT_NPROC, &rl) == -1) |
78 | errExit("setrlimit"); | 76 | errExit("setrlimit"); |
79 | if (arg_debug) | 77 | if (arg_debug) |
@@ -88,9 +86,9 @@ void set_rlimits(void) { | |||
88 | // set the new limit | 86 | // set the new limit |
89 | rl.rlim_cur = (rlim_t) cfg.rlimit_fsize; | 87 | rl.rlim_cur = (rlim_t) cfg.rlimit_fsize; |
90 | rl.rlim_max = (rlim_t) cfg.rlimit_fsize; | 88 | rl.rlim_max = (rlim_t) cfg.rlimit_fsize; |
91 | #ifdef HAVE_GCOV | 89 | |
92 | __gcov_dump(); | 90 | __gcov_dump(); |
93 | #endif | 91 | |
94 | if (setrlimit(RLIMIT_FSIZE, &rl) == -1) | 92 | if (setrlimit(RLIMIT_FSIZE, &rl) == -1) |
95 | errExit("setrlimit"); | 93 | errExit("setrlimit"); |
96 | if (arg_debug) | 94 | if (arg_debug) |
@@ -105,9 +103,9 @@ void set_rlimits(void) { | |||
105 | // set the new limit | 103 | // set the new limit |
106 | rl.rlim_cur = (rlim_t) cfg.rlimit_sigpending; | 104 | rl.rlim_cur = (rlim_t) cfg.rlimit_sigpending; |
107 | rl.rlim_max = (rlim_t) cfg.rlimit_sigpending; | 105 | rl.rlim_max = (rlim_t) cfg.rlimit_sigpending; |
108 | #ifdef HAVE_GCOV | 106 | |
109 | __gcov_dump(); | 107 | __gcov_dump(); |
110 | #endif | 108 | |
111 | if (setrlimit(RLIMIT_SIGPENDING, &rl) == -1) | 109 | if (setrlimit(RLIMIT_SIGPENDING, &rl) == -1) |
112 | errExit("setrlimit"); | 110 | errExit("setrlimit"); |
113 | if (arg_debug) | 111 | if (arg_debug) |
@@ -122,9 +120,9 @@ void set_rlimits(void) { | |||
122 | // set the new limit | 120 | // set the new limit |
123 | rl.rlim_cur = (rlim_t) cfg.rlimit_as; | 121 | rl.rlim_cur = (rlim_t) cfg.rlimit_as; |
124 | rl.rlim_max = (rlim_t) cfg.rlimit_as; | 122 | rl.rlim_max = (rlim_t) cfg.rlimit_as; |
125 | #ifdef HAVE_GCOV | 123 | |
126 | __gcov_dump(); | 124 | __gcov_dump(); |
127 | #endif | 125 | |
128 | if (setrlimit(RLIMIT_AS, &rl) == -1) | 126 | if (setrlimit(RLIMIT_AS, &rl) == -1) |
129 | errExit("setrlimit"); | 127 | errExit("setrlimit"); |
130 | if (arg_debug) | 128 | if (arg_debug) |
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index e06ba3617..fd359c39e 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c | |||
@@ -19,6 +19,7 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include "firejail.h" | 21 | #include "firejail.h" |
22 | #include "../include/gcov_wrapper.h" | ||
22 | #include "../include/seccomp.h" | 23 | #include "../include/seccomp.h" |
23 | #include <sys/mman.h> | 24 | #include <sys/mman.h> |
24 | #include <sys/mount.h> | 25 | #include <sys/mount.h> |
@@ -49,10 +50,6 @@ | |||
49 | #include <sys/apparmor.h> | 50 | #include <sys/apparmor.h> |
50 | #endif | 51 | #endif |
51 | 52 | ||
52 | #ifdef HAVE_GCOV | ||
53 | #include <gcov.h> | ||
54 | #endif | ||
55 | |||
56 | static int force_nonewprivs = 0; | 53 | static int force_nonewprivs = 0; |
57 | 54 | ||
58 | static int monitored_pid = 0; | 55 | static int monitored_pid = 0; |
@@ -507,9 +504,8 @@ void start_application(int no_sandbox, int fd, char *set_sandbox_status) { | |||
507 | exit(1); | 504 | exit(1); |
508 | } | 505 | } |
509 | 506 | ||
510 | #ifdef HAVE_GCOV | ||
511 | __gcov_dump(); | 507 | __gcov_dump(); |
512 | #endif | 508 | |
513 | seccomp_install_filters(); | 509 | seccomp_install_filters(); |
514 | 510 | ||
515 | if (set_sandbox_status) | 511 | if (set_sandbox_status) |
@@ -563,9 +559,8 @@ void start_application(int no_sandbox, int fd, char *set_sandbox_status) { | |||
563 | if (!arg_command && !arg_quiet) | 559 | if (!arg_command && !arg_quiet) |
564 | print_time(); | 560 | print_time(); |
565 | 561 | ||
566 | #ifdef HAVE_GCOV | ||
567 | __gcov_dump(); | 562 | __gcov_dump(); |
568 | #endif | 563 | |
569 | seccomp_install_filters(); | 564 | seccomp_install_filters(); |
570 | 565 | ||
571 | if (set_sandbox_status) | 566 | if (set_sandbox_status) |
@@ -840,6 +835,7 @@ int sandbox(void* sandbox_arg) { | |||
840 | // private mode | 835 | // private mode |
841 | //**************************** | 836 | //**************************** |
842 | if (arg_private) { | 837 | if (arg_private) { |
838 | EUID_USER(); | ||
843 | if (cfg.home_private) { // --private= | 839 | if (cfg.home_private) { // --private= |
844 | if (cfg.chrootdir) | 840 | if (cfg.chrootdir) |
845 | fwarning("private=directory feature is disabled in chroot\n"); | 841 | fwarning("private=directory feature is disabled in chroot\n"); |
@@ -858,6 +854,7 @@ int sandbox(void* sandbox_arg) { | |||
858 | } | 854 | } |
859 | else // --private | 855 | else // --private |
860 | fs_private(); | 856 | fs_private(); |
857 | EUID_ROOT(); | ||
861 | } | 858 | } |
862 | 859 | ||
863 | if (arg_private_dev) | 860 | 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 47c367aad..de31ebdd6 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c | |||
@@ -19,6 +19,7 @@ | |||
19 | */ | 19 | */ |
20 | #define _XOPEN_SOURCE 500 | 20 | #define _XOPEN_SOURCE 500 |
21 | #include "firejail.h" | 21 | #include "firejail.h" |
22 | #include "../include/gcov_wrapper.h" | ||
22 | #include <ftw.h> | 23 | #include <ftw.h> |
23 | #include <sys/stat.h> | 24 | #include <sys/stat.h> |
24 | #include <sys/mount.h> | 25 | #include <sys/mount.h> |
@@ -31,6 +32,9 @@ | |||
31 | #include <sys/wait.h> | 32 | #include <sys/wait.h> |
32 | #include <limits.h> | 33 | #include <limits.h> |
33 | 34 | ||
35 | #include <string.h> | ||
36 | #include <ctype.h> | ||
37 | |||
34 | #include <fcntl.h> | 38 | #include <fcntl.h> |
35 | #ifndef O_PATH | 39 | #ifndef O_PATH |
36 | #define O_PATH 010000000 | 40 | #define O_PATH 010000000 |
@@ -41,15 +45,49 @@ | |||
41 | #include <linux/openat2.h> | 45 | #include <linux/openat2.h> |
42 | #endif | 46 | #endif |
43 | 47 | ||
44 | #ifdef HAVE_GCOV | ||
45 | #include <gcov.h> | ||
46 | #endif | ||
47 | |||
48 | #define MAX_GROUPS 1024 | 48 | #define MAX_GROUPS 1024 |
49 | #define MAXBUF 4098 | 49 | #define MAXBUF 4098 |
50 | #define EMPTY_STRING ("") | 50 | #define EMPTY_STRING ("") |
51 | 51 | ||
52 | 52 | ||
53 | long long unsigned parse_arg_size(char *str) { | ||
54 | long long unsigned result = 0; | ||
55 | int len = strlen(str); | ||
56 | sscanf(str, "%llu", &result); | ||
57 | |||
58 | char suffix = *(str + len - 1); | ||
59 | if (!isdigit(suffix) && (suffix == 'k' || suffix == 'm' || suffix == 'g')) { | ||
60 | len -= 1; | ||
61 | } | ||
62 | |||
63 | /* checks for is value valid positive number */ | ||
64 | for (int i = 0; i < len; i++) { | ||
65 | if (!isdigit(*(str+i))) { | ||
66 | return 0; | ||
67 | } | ||
68 | } | ||
69 | |||
70 | if (isdigit(suffix)) | ||
71 | return result; | ||
72 | |||
73 | switch (suffix) { | ||
74 | case 'k': | ||
75 | result *= 1024; | ||
76 | break; | ||
77 | case 'm': | ||
78 | result *= 1024 * 1024; | ||
79 | break; | ||
80 | case 'g': | ||
81 | result *= 1024 * 1024 * 1024; | ||
82 | break; | ||
83 | default: | ||
84 | result = 0; | ||
85 | break; | ||
86 | } | ||
87 | |||
88 | return result; | ||
89 | } | ||
90 | |||
53 | // send the error to /var/log/auth.log and exit after a small delay | 91 | // send the error to /var/log/auth.log and exit after a small delay |
54 | void errLogExit(char* fmt, ...) { | 92 | void errLogExit(char* fmt, ...) { |
55 | va_list args; | 93 | va_list args; |
@@ -329,7 +367,7 @@ int copy_file(const char *srcname, const char *destname, uid_t uid, gid_t gid, m | |||
329 | } | 367 | } |
330 | 368 | ||
331 | // return -1 if error, 0 if no error | 369 | // return -1 if error, 0 if no error |
332 | void copy_file_as_user(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode) { | 370 | void copy_file_as_user(const char *srcname, const char *destname, mode_t mode) { |
333 | pid_t child = fork(); | 371 | pid_t child = fork(); |
334 | if (child < 0) | 372 | if (child < 0) |
335 | errExit("fork"); | 373 | errExit("fork"); |
@@ -337,13 +375,13 @@ void copy_file_as_user(const char *srcname, const char *destname, uid_t uid, gid | |||
337 | // drop privileges | 375 | // drop privileges |
338 | drop_privs(0); | 376 | drop_privs(0); |
339 | 377 | ||
340 | // copy, set permissions and ownership | 378 | // copy, set permissions |
341 | int rv = copy_file(srcname, destname, uid, gid, mode); // already a regular user | 379 | int rv = copy_file(srcname, destname, -1, -1, mode); // already a regular user |
342 | if (rv) | 380 | if (rv) |
343 | fwarning("cannot copy %s\n", srcname); | 381 | fwarning("cannot copy %s\n", srcname); |
344 | #ifdef HAVE_GCOV | 382 | |
345 | __gcov_flush(); | 383 | __gcov_flush(); |
346 | #endif | 384 | |
347 | _exit(0); | 385 | _exit(0); |
348 | } | 386 | } |
349 | // wait for the child to finish | 387 | // wait for the child to finish |
@@ -375,9 +413,9 @@ void copy_file_from_user_to_root(const char *srcname, const char *destname, uid_ | |||
375 | close(src); | 413 | close(src); |
376 | } | 414 | } |
377 | close(dst); | 415 | close(dst); |
378 | #ifdef HAVE_GCOV | 416 | |
379 | __gcov_flush(); | 417 | __gcov_flush(); |
380 | #endif | 418 | |
381 | _exit(0); | 419 | _exit(0); |
382 | } | 420 | } |
383 | // wait for the child to finish | 421 | // wait for the child to finish |
@@ -406,9 +444,9 @@ void touch_file_as_user(const char *fname, mode_t mode) { | |||
406 | } | 444 | } |
407 | else | 445 | else |
408 | fwarning("cannot create %s\n", fname); | 446 | fwarning("cannot create %s\n", fname); |
409 | #ifdef HAVE_GCOV | 447 | |
410 | __gcov_flush(); | 448 | __gcov_flush(); |
411 | #endif | 449 | |
412 | _exit(0); | 450 | _exit(0); |
413 | } | 451 | } |
414 | // wait for the child to finish | 452 | // wait for the child to finish |
@@ -1015,9 +1053,9 @@ int remove_overlay_directory(void) { | |||
1015 | // remove ~/.firejail | 1053 | // remove ~/.firejail |
1016 | if (rmdir(path) == -1) | 1054 | if (rmdir(path) == -1) |
1017 | errExit("rmdir"); | 1055 | errExit("rmdir"); |
1018 | #ifdef HAVE_GCOV | 1056 | |
1019 | __gcov_flush(); | 1057 | __gcov_flush(); |
1020 | #endif | 1058 | |
1021 | _exit(0); | 1059 | _exit(0); |
1022 | } | 1060 | } |
1023 | // wait for the child to finish | 1061 | // wait for the child to finish |
@@ -1073,9 +1111,9 @@ int create_empty_dir_as_user(const char *dir, mode_t mode) { | |||
1073 | } | 1111 | } |
1074 | else if (arg_debug) | 1112 | else if (arg_debug) |
1075 | printf("Directory %s not created: %s\n", dir, strerror(errno)); | 1113 | printf("Directory %s not created: %s\n", dir, strerror(errno)); |
1076 | #ifdef HAVE_GCOV | 1114 | |
1077 | __gcov_flush(); | 1115 | __gcov_flush(); |
1078 | #endif | 1116 | |
1079 | _exit(0); | 1117 | _exit(0); |
1080 | } | 1118 | } |
1081 | waitpid(child, NULL, 0); | 1119 | waitpid(child, NULL, 0); |
@@ -1190,6 +1228,7 @@ unsigned extract_timeout(const char *str) { | |||
1190 | } | 1228 | } |
1191 | 1229 | ||
1192 | void disable_file_or_dir(const char *fname) { | 1230 | void disable_file_or_dir(const char *fname) { |
1231 | assert(geteuid() == 0); | ||
1193 | assert(fname); | 1232 | assert(fname); |
1194 | 1233 | ||
1195 | EUID_USER(); | 1234 | 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..780e3d706 100644 --- a/src/firemon/interface.c +++ b/src/firemon/interface.c | |||
@@ -18,6 +18,7 @@ | |||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
19 | */ | 19 | */ |
20 | #include "firemon.h" | 20 | #include "firemon.h" |
21 | #include "../include/gcov_wrapper.h" | ||
21 | #include <sys/types.h> | 22 | #include <sys/types.h> |
22 | #include <sys/wait.h> | 23 | #include <sys/wait.h> |
23 | #include <netdb.h> | 24 | #include <netdb.h> |
@@ -33,10 +34,6 @@ | |||
33 | //#include <net/route.h> | 34 | //#include <net/route.h> |
34 | //#include <linux/if_bridge.h> | 35 | //#include <linux/if_bridge.h> |
35 | 36 | ||
36 | #ifdef HAVE_GCOV | ||
37 | #include <gcov.h> | ||
38 | #endif | ||
39 | |||
40 | // print IP addresses for all interfaces | 37 | // print IP addresses for all interfaces |
41 | static void net_ifprint(void) { | 38 | static void net_ifprint(void) { |
42 | uint32_t ip; | 39 | uint32_t ip; |
@@ -149,9 +146,9 @@ static void print_sandbox(pid_t pid) { | |||
149 | if (rv) | 146 | if (rv) |
150 | return; | 147 | return; |
151 | net_ifprint(); | 148 | net_ifprint(); |
152 | #ifdef HAVE_GCOV | 149 | |
153 | __gcov_flush(); | 150 | __gcov_flush(); |
154 | #endif | 151 | |
155 | _exit(0); | 152 | _exit(0); |
156 | } | 153 | } |
157 | 154 | ||
diff --git a/src/firemon/netstats.c b/src/firemon/netstats.c index 23d228e26..9d8e5d7f5 100644 --- a/src/firemon/netstats.c +++ b/src/firemon/netstats.c | |||
@@ -18,16 +18,13 @@ | |||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
19 | */ | 19 | */ |
20 | #include "firemon.h" | 20 | #include "firemon.h" |
21 | #include "../include/gcov_wrapper.h" | ||
21 | #include <termios.h> | 22 | #include <termios.h> |
22 | #include <sys/ioctl.h> | 23 | #include <sys/ioctl.h> |
23 | #include <sys/types.h> | 24 | #include <sys/types.h> |
24 | #include <sys/stat.h> | 25 | #include <sys/stat.h> |
25 | #include <unistd.h> | 26 | #include <unistd.h> |
26 | 27 | ||
27 | #ifdef HAVE_GCOV | ||
28 | #include <gcov.h> | ||
29 | #endif | ||
30 | |||
31 | #define MAXBUF 4096 | 28 | #define MAXBUF 4096 |
32 | 29 | ||
33 | // ip -s link: device stats | 30 | // ip -s link: device stats |
@@ -246,8 +243,7 @@ void netstats(void) { | |||
246 | print_proc(i, itv, col); | 243 | print_proc(i, itv, col); |
247 | } | 244 | } |
248 | } | 245 | } |
249 | #ifdef HAVE_GCOV | 246 | |
250 | __gcov_flush(); | 247 | __gcov_flush(); |
251 | #endif | ||
252 | } | 248 | } |
253 | } | 249 | } |
diff --git a/src/firemon/procevent.c b/src/firemon/procevent.c index 4e809681e..716a9cba4 100644 --- a/src/firemon/procevent.c +++ b/src/firemon/procevent.c | |||
@@ -18,6 +18,7 @@ | |||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
19 | */ | 19 | */ |
20 | #include "firemon.h" | 20 | #include "firemon.h" |
21 | #include "../include/gcov_wrapper.h" | ||
21 | #include <sys/socket.h> | 22 | #include <sys/socket.h> |
22 | #include <linux/connector.h> | 23 | #include <linux/connector.h> |
23 | #include <linux/netlink.h> | 24 | #include <linux/netlink.h> |
@@ -30,10 +31,6 @@ | |||
30 | #include <fcntl.h> | 31 | #include <fcntl.h> |
31 | #include <sys/uio.h> | 32 | #include <sys/uio.h> |
32 | 33 | ||
33 | #ifdef HAVE_GCOV | ||
34 | #include <gcov.h> | ||
35 | #endif | ||
36 | |||
37 | #define PIDS_BUFLEN 4096 | 34 | #define PIDS_BUFLEN 4096 |
38 | #define SERVER_PORT 889 // 889-899 is left unassigned by IANA | 35 | #define SERVER_PORT 889 // 889-899 is left unassigned by IANA |
39 | 36 | ||
@@ -234,9 +231,7 @@ static void __attribute__((noreturn)) procevent_monitor(const int sock, pid_t my | |||
234 | tv.tv_usec = 0; | 231 | tv.tv_usec = 0; |
235 | 232 | ||
236 | while (1) { | 233 | while (1) { |
237 | #ifdef HAVE_GCOV | ||
238 | __gcov_flush(); | 234 | __gcov_flush(); |
239 | #endif | ||
240 | 235 | ||
241 | #define BUFFSIZE 4096 | 236 | #define BUFFSIZE 4096 |
242 | char __attribute__ ((aligned(NLMSG_ALIGNTO)))buf[BUFFSIZE]; | 237 | char __attribute__ ((aligned(NLMSG_ALIGNTO)))buf[BUFFSIZE]; |
diff --git a/src/firemon/top.c b/src/firemon/top.c index 9d6f34991..2217cc7de 100644 --- a/src/firemon/top.c +++ b/src/firemon/top.c | |||
@@ -18,16 +18,13 @@ | |||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
19 | */ | 19 | */ |
20 | #include "firemon.h" | 20 | #include "firemon.h" |
21 | #include "../include/gcov_wrapper.h" | ||
21 | #include <termios.h> | 22 | #include <termios.h> |
22 | #include <sys/ioctl.h> | 23 | #include <sys/ioctl.h> |
23 | #include <sys/types.h> | 24 | #include <sys/types.h> |
24 | #include <sys/stat.h> | 25 | #include <sys/stat.h> |
25 | #include <unistd.h> | 26 | #include <unistd.h> |
26 | 27 | ||
27 | #ifdef HAVE_GCOV | ||
28 | #include <gcov.h> | ||
29 | #endif | ||
30 | |||
31 | static unsigned pgs_rss = 0; | 28 | static unsigned pgs_rss = 0; |
32 | static unsigned pgs_shared = 0; | 29 | static unsigned pgs_shared = 0; |
33 | static unsigned clocktick = 0; | 30 | static unsigned clocktick = 0; |
@@ -330,8 +327,7 @@ void top(void) { | |||
330 | } | 327 | } |
331 | } | 328 | } |
332 | head_print(col, row); | 329 | head_print(col, row); |
333 | #ifdef HAVE_GCOV | 330 | |
334 | __gcov_flush(); | 331 | __gcov_flush(); |
335 | #endif | ||
336 | } | 332 | } |
337 | } | 333 | } |
diff --git a/src/include/gcov_wrapper.h b/src/include/gcov_wrapper.h new file mode 100644 index 000000000..4aafb8e18 --- /dev/null +++ b/src/include/gcov_wrapper.h | |||
@@ -0,0 +1,46 @@ | |||
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 | #ifdef HAS_GCOV | ||
25 | #include <gcov.h> | ||
26 | |||
27 | /* | ||
28 | * __gcov_flush was removed on gcc 11.1.0 (as it's no longer needed), but it | ||
29 | * appears to be the safe/"correct" way to do things on previous versions (as | ||
30 | * it ensured proper locking, which is now done elsewhere). Thus, keep using | ||
31 | * it in the code and ensure that it exists, in order to support gcc <11.1.0 | ||
32 | * and gcc >=11.1.0, respectively. | ||
33 | */ | ||
34 | #if __GNUC__ > 11 || (__GNUC__ == 11 && __GNUC_MINOR__ >= 1) | ||
35 | static void __gcov_flush(void) { | ||
36 | __gcov_dump(); | ||
37 | __gcov_reset(); | ||
38 | } | ||
39 | #endif | ||
40 | #else | ||
41 | #define __gcov_dump() ((void)0) | ||
42 | #define __gcov_reset() ((void)0) | ||
43 | #define __gcov_flush() ((void)0) | ||
44 | #endif /* HAS_GCOV */ | ||
45 | |||
46 | #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-profile.txt b/src/man/firejail-profile.txt index 6f3bef7f2..db58e0910 100644 --- a/src/man/firejail-profile.txt +++ b/src/man/firejail-profile.txt | |||
@@ -420,7 +420,7 @@ Make directory or file read-only. | |||
420 | Make directory or file read-write. | 420 | Make directory or file read-write. |
421 | .TP | 421 | .TP |
422 | \fBtmpfs directory | 422 | \fBtmpfs directory |
423 | Mount an empty tmpfs filesystem on top of directory. This option is available only when running the sandbox as root. | 423 | Mount an empty tmpfs filesystem on top of directory. Directories outside user home or not owned by the user are not allowed. Sandboxes running as root are exempt from these restrictions. |
424 | .TP | 424 | .TP |
425 | \fBtracelog | 425 | \fBtracelog |
426 | Blacklist violations logged to syslog. | 426 | Blacklist violations logged to syslog. |
diff --git a/src/man/firejail.txt b/src/man/firejail.txt index 3212a88e4..0462705c0 100644 --- a/src/man/firejail.txt +++ b/src/man/firejail.txt | |||
@@ -2129,6 +2129,7 @@ $ firejail --read-only=~/test --read-write=~/test/a | |||
2129 | .TP | 2129 | .TP |
2130 | \fB\-\-rlimit-as=number | 2130 | \fB\-\-rlimit-as=number |
2131 | Set the maximum size of the process's virtual memory (address space) in bytes. | 2131 | Set the maximum size of the process's virtual memory (address space) in bytes. |
2132 | Use k(ilobyte), m(egabyte) or g(igabyte) for size suffix (base 1024). | ||
2132 | 2133 | ||
2133 | .TP | 2134 | .TP |
2134 | \fB\-\-rlimit-cpu=number | 2135 | \fB\-\-rlimit-cpu=number |
@@ -2142,6 +2143,7 @@ track of CPU seconds for each process independently. | |||
2142 | .TP | 2143 | .TP |
2143 | \fB\-\-rlimit-fsize=number | 2144 | \fB\-\-rlimit-fsize=number |
2144 | Set the maximum file size that can be created by a process. | 2145 | Set the maximum file size that can be created by a process. |
2146 | Use k(ilobyte), m(egabyte) or g(igabyte) for size suffix (base 1024). | ||
2145 | .TP | 2147 | .TP |
2146 | \fB\-\-rlimit-nofile=number | 2148 | \fB\-\-rlimit-nofile=number |
2147 | Set the maximum number of files that can be opened by a process. | 2149 | Set the maximum number of files that can be opened by a process. |
@@ -2176,7 +2178,7 @@ $ firejail \-\-net=eth0 \-\-scan | |||
2176 | .TP | 2178 | .TP |
2177 | \fB\-\-seccomp | 2179 | \fB\-\-seccomp |
2178 | Enable seccomp filter and blacklist the syscalls in the default list, | 2180 | Enable seccomp filter and blacklist the syscalls in the default list, |
2179 | which is @default-nodebuggers unless allow-debuggers is specified, | 2181 | which is @default-nodebuggers unless \-\-allow-debuggers is specified, |
2180 | then it is @default. | 2182 | then it is @default. |
2181 | 2183 | ||
2182 | .br | 2184 | .br |
@@ -2187,18 +2189,13 @@ system call groups are defined: @aio, @basic-io, @chown, @clock, | |||
2187 | @network-io, @obsolete, @privileged, @process, @raw-io, @reboot, | 2189 | @network-io, @obsolete, @privileged, @process, @raw-io, @reboot, |
2188 | @resources, @setuid, @swap, @sync, @system-service and @timer. | 2190 | @resources, @setuid, @swap, @sync, @system-service and @timer. |
2189 | 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 |
2190 | 2192 | .br | |
2191 | In addition, a system call can be specified by its number instead of | ||
2192 | name with prefix $, so for example $165 would be equal to mount on i386. | ||
2193 | Exceptions can be allowed with prefix !. | ||
2194 | 2193 | ||
2195 | .br | 2194 | .br |
2196 | System architecture is strictly imposed only if flag | 2195 | System architecture is strictly imposed only if flag |
2197 | \-\-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 |
2198 | 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 |
2199 | 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. |
2200 | architecture, an additional filter for 32 bit system calls can be | ||
2201 | installed with \-\-seccomp.32. | ||
2202 | .br | 2199 | .br |
2203 | 2200 | ||
2204 | .br | 2201 | .br |
@@ -2209,11 +2206,18 @@ Firejail will print seccomp violations to the audit log if the kernel was compil | |||
2209 | Example: | 2206 | Example: |
2210 | .br | 2207 | .br |
2211 | $ 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 | |||
2212 | .TP | 2215 | .TP |
2213 | \fB\-\-seccomp=syscall,@group,!syscall2 | 2216 | \fB\-\-seccomp=syscall,@group,!syscall2 |
2214 | Enable seccomp filter, whitelist "syscall2", but blacklist the default | 2217 | Enable seccomp filter, blacklist the default list and the syscalls or syscall groups |
2215 | list and the syscalls or syscall groups specified by the | 2218 | specified by the command, but don't blacklist "syscall2". On a 64 bit |
2216 | command. | 2219 | architecture, an additional filter for 32 bit system calls can be |
2220 | installed with \-\-seccomp.32. | ||
2217 | .br | 2221 | .br |
2218 | 2222 | ||
2219 | .br | 2223 | .br |
@@ -2223,6 +2227,13 @@ $ firejail \-\-seccomp=utime,utimensat,utimes firefox | |||
2223 | .br | 2227 | .br |
2224 | $ firejail \-\-seccomp=@clock,mkdir,unlinkat transmission-gtk | 2228 | $ firejail \-\-seccomp=@clock,mkdir,unlinkat transmission-gtk |
2225 | .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 | ||
2226 | 2237 | ||
2227 | .br | 2238 | .br |
2228 | Instead of dropping the syscall by returning EPERM, another error | 2239 | Instead of dropping the syscall by returning EPERM, another error |
@@ -2235,6 +2246,7 @@ by using \fBsyscall:kill\fR syntax, or the attempt may be logged with | |||
2235 | 2246 | ||
2236 | .br | 2247 | .br |
2237 | Example: | 2248 | Example: |
2249 | .br | ||
2238 | $ firejail \-\-seccomp=unlinkat:ENOENT,utimensat,utimes | 2250 | $ firejail \-\-seccomp=unlinkat:ENOENT,utimensat,utimes |
2239 | .br | 2251 | .br |
2240 | Parent pid 10662, child pid 10663 | 2252 | Parent pid 10662, child pid 10663 |
@@ -2243,9 +2255,13 @@ Child process initialized | |||
2243 | .br | 2255 | .br |
2244 | $ touch testfile | 2256 | $ touch testfile |
2245 | .br | 2257 | .br |
2258 | $ ls testfile | ||
2259 | .br | ||
2260 | testfile | ||
2261 | .br | ||
2246 | $ rm testfile | 2262 | $ rm testfile |
2247 | .br | 2263 | .br |
2248 | rm: cannot remove `testfile': Operation not permitted | 2264 | rm: cannot remove `testfile': No such file or directory |
2249 | .br | 2265 | .br |
2250 | 2266 | ||
2251 | .br | 2267 | .br |
@@ -2258,7 +2274,7 @@ filters. | |||
2258 | .br | 2274 | .br |
2259 | Example: | 2275 | Example: |
2260 | .br | 2276 | .br |
2261 | $ firejail \-\-noprofile \-\-shell=none \-\-seccomp=execve bash | 2277 | $ firejail \-\-noprofile \-\-shell=none \-\-seccomp=execve sh |
2262 | .br | 2278 | .br |
2263 | Parent pid 32751, child pid 32752 | 2279 | Parent pid 32751, child pid 32752 |
2264 | .br | 2280 | .br |
@@ -2270,8 +2286,7 @@ Child process initialized in 46.44 ms | |||
2270 | .br | 2286 | .br |
2271 | $ ls | 2287 | $ ls |
2272 | .br | 2288 | .br |
2273 | Bad system call | 2289 | Operation not permitted |
2274 | .br | ||
2275 | 2290 | ||
2276 | .TP | 2291 | .TP |
2277 | \fB\-\-seccomp.block-secondary | 2292 | \fB\-\-seccomp.block-secondary |
@@ -2315,15 +2330,15 @@ Child process initialized | |||
2315 | .br | 2330 | .br |
2316 | $ touch testfile | 2331 | $ touch testfile |
2317 | .br | 2332 | .br |
2333 | $ ls testfile | ||
2334 | .br | ||
2335 | testfile | ||
2336 | .br | ||
2318 | $ rm testfile | 2337 | $ rm testfile |
2319 | .br | 2338 | .br |
2320 | rm: cannot remove `testfile': Operation not permitted | 2339 | rm: cannot remove `testfile': No such file or directory |
2321 | .br | 2340 | .br |
2322 | 2341 | ||
2323 | |||
2324 | |||
2325 | |||
2326 | |||
2327 | .TP | 2342 | .TP |
2328 | \fB\-\-seccomp.keep=syscall,@group,!syscall2 | 2343 | \fB\-\-seccomp.keep=syscall,@group,!syscall2 |
2329 | Enable seccomp filter, blacklist all syscall not listed and "syscall2". | 2344 | Enable seccomp filter, blacklist all syscall not listed and "syscall2". |
@@ -2566,14 +2581,13 @@ Kill the sandbox automatically after the time has elapsed. The time is specified | |||
2566 | $ firejail \-\-timeout=01:30:00 firefox | 2581 | $ firejail \-\-timeout=01:30:00 firefox |
2567 | .TP | 2582 | .TP |
2568 | \fB\-\-tmpfs=dirname | 2583 | \fB\-\-tmpfs=dirname |
2569 | Mount a writable tmpfs filesystem on directory dirname. This option is available only when running the sandbox as root. | 2584 | Mount a writable tmpfs filesystem on directory dirname. Directories outside user home or not owned by the user are not allowed. Sandboxes running as root are exempt from these restrictions. File globbing is supported, see \fBFILE GLOBBING\fR section for more details. |
2570 | File globbing is supported, see \fBFILE GLOBBING\fR section for more details. | ||
2571 | .br | 2585 | .br |
2572 | 2586 | ||
2573 | .br | 2587 | .br |
2574 | Example: | 2588 | Example: |
2575 | .br | 2589 | .br |
2576 | # firejail \-\-tmpfs=/var | 2590 | $ firejail \-\-tmpfs=~/.local/share |
2577 | .TP | 2591 | .TP |
2578 | \fB\-\-top | 2592 | \fB\-\-top |
2579 | Monitor the most CPU-intensive sandboxes, see \fBMONITORING\fR section for more details. | 2593 | Monitor the most CPU-intensive sandboxes, see \fBMONITORING\fR section for more details. |