aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/firecfg/firecfg.config2
-rw-r--r--src/firejail/appimage.c8
-rw-r--r--src/firejail/checkcfg.c5
-rw-r--r--src/firejail/chroot.c8
-rw-r--r--src/firejail/dbus.c4
-rw-r--r--src/firejail/dhcp.c3
-rw-r--r--src/firejail/firejail.h6
-rw-r--r--src/firejail/fs.c41
-rw-r--r--src/firejail/fs_home.c99
-rw-r--r--src/firejail/fs_mkdir.c9
-rw-r--r--src/firejail/fs_whitelist.c8
-rw-r--r--src/firejail/ls.c16
-rw-r--r--src/firejail/main.c34
-rw-r--r--src/firejail/profile.c22
-rw-r--r--src/firejail/rlimit.c30
-rw-r--r--src/firejail/sandbox.c13
-rw-r--r--src/firejail/seccomp.c5
-rw-r--r--src/firejail/util.c73
-rw-r--r--src/firejail/x11.c6
-rw-r--r--src/firemon/interface.c9
-rw-r--r--src/firemon/netstats.c10
-rw-r--r--src/firemon/procevent.c7
-rw-r--r--src/firemon/top.c10
-rw-r--r--src/include/gcov_wrapper.h46
-rw-r--r--src/lib/syscall.c3
-rw-r--r--src/man/firejail-profile.txt2
-rw-r--r--src/man/firejail.txt60
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
38akonadi_control 38akonadi_control
39akregator 39akregator
40alacarte 40alacarte
41alpine
42alpinef
41amarok 43amarok
42amule 44amule
43amuled 45amuled
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
35static char *devloop = NULL; // device file 32static char *devloop = NULL; // device file
36static long unsigned size = 0; // offset into appimage file 33static 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 = "";
35char *netfilter_default = NULL; 35char *netfilter_default = NULL;
36unsigned long join_timeout = 5000000; // microseconds 36unsigned long join_timeout = 5000000; // microseconds
37char *config_seccomp_error_action_str = "EPERM"; 37char *config_seccomp_error_action_str = "EPERM";
38char *config_seccomp_filter_add = NULL;
38char **whitelist_reject_topdirs = NULL; 39char **whitelist_reject_topdirs = NULL;
39 40
40int checkcfg(int val) { 41int 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
37void fs_check_chroot_dir(void) { 34void 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);
498void errLogExit(char* fmt, ...) __attribute__((noreturn)); 498void errLogExit(char* fmt, ...) __attribute__((noreturn));
499void fwarning(char* fmt, ...); 499void fwarning(char* fmt, ...);
500void fmessage(char* fmt, ...); 500void fmessage(char* fmt, ...);
501long long unsigned parse_arg_size(char *str);
501void drop_privs(int nogroups); 502void drop_privs(int nogroups);
502int mkpath_as_root(const char* path); 503int mkpath_as_root(const char* path);
503void extract_command_name(int index, char **argv); 504void extract_command_name(int index, char **argv);
@@ -507,7 +508,7 @@ void logargs(int argc, char **argv) ;
507void logerr(const char *msg); 508void logerr(const char *msg);
508void set_nice(int inc); 509void set_nice(int inc);
509int copy_file(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode); 510int copy_file(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode);
510void copy_file_as_user(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode); 511void copy_file_as_user(const char *srcname, const char *destname, mode_t mode);
511void copy_file_from_user_to_root(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode); 512void copy_file_from_user_to_root(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode);
512void touch_file_as_user(const char *fname, mode_t mode); 513void touch_file_as_user(const char *fname, mode_t mode);
513int is_dir(const char *fname); 514int is_dir(const char *fname);
@@ -809,6 +810,7 @@ extern char *xvfb_extra_params;
809extern char *netfilter_default; 810extern char *netfilter_default;
810extern unsigned long join_timeout; 811extern unsigned long join_timeout;
811extern char *config_seccomp_error_action_str; 812extern char *config_seccomp_error_action_str;
813extern char *config_seccomp_filter_add;
812extern char **whitelist_reject_topdirs; 814extern char **whitelist_reject_topdirs;
813 815
814int checkcfg(int val); 816int 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
37static void skel(const char *homedir, uid_t u, gid_t g) { 37static 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
110static int store_xauthority(void) { 113static 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
149static int store_asoundrc(void) { 155static 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
197static void copy_xauthority(void) { 206static 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
219static void copy_asoundrc(void) { 230static 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) {
339void fs_private(void) { 355void 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
532void fs_private_home_list(void) { 552void 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
32static void check(const char *fname) { 29static 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
39static uid_t c_uid = 0; 36static uid_t c_uid = 0;
40static char *c_uid_name = NULL; 37static 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
967static int check_postexec(const char *list) { 964static 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
30extern char *xephyr_screen; 27extern 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
28void set_rlimits(void) { 25void 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
56static int force_nonewprivs = 0; 53static int force_nonewprivs = 0;
57 54
58static int monitored_pid = 0; 55static 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
53long 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
54void errLogExit(char* fmt, ...) { 92void 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
332void copy_file_as_user(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode) { 370void 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
1192void disable_file_or_dir(const char *fname) { 1230void 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
41static void net_ifprint(void) { 38static 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
31static unsigned pgs_rss = 0; 28static unsigned pgs_rss = 0;
32static unsigned pgs_shared = 0; 29static unsigned pgs_shared = 0;
33static unsigned clocktick = 0; 30static 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)
35static 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.
420Make directory or file read-write. 420Make directory or file read-write.
421.TP 421.TP
422\fBtmpfs directory 422\fBtmpfs directory
423Mount an empty tmpfs filesystem on top of directory. This option is available only when running the sandbox as root. 423Mount 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
426Blacklist violations logged to syslog. 426Blacklist 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
2131Set the maximum size of the process's virtual memory (address space) in bytes. 2131Set the maximum size of the process's virtual memory (address space) in bytes.
2132Use 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
2144Set the maximum file size that can be created by a process. 2145Set the maximum file size that can be created by a process.
2146Use 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
2147Set the maximum number of files that can be opened by a process. 2149Set 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
2178Enable seccomp filter and blacklist the syscalls in the default list, 2180Enable seccomp filter and blacklist the syscalls in the default list,
2179which is @default-nodebuggers unless allow-debuggers is specified, 2181which is @default-nodebuggers unless \-\-allow-debuggers is specified,
2180then it is @default. 2182then 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.
2189More information about groups can be found in /usr/share/doc/firejail/syscalls.txt 2191More information about groups can be found in /usr/share/doc/firejail/syscalls.txt
2190 2192.br
2191In addition, a system call can be specified by its number instead of
2192name with prefix $, so for example $165 would be equal to mount on i386.
2193Exceptions can be allowed with prefix !.
2194 2193
2195.br 2194.br
2196System architecture is strictly imposed only if flag 2195System 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
2198only if the correct architecture was detected. For the case of I386 2197only if the correct architecture was detected. For the case of I386
2199and AMD64 both 32-bit and 64-bit filters are installed. On a 64 bit 2198and AMD64 both 32-bit and 64-bit filters are installed.
2200architecture, an additional filter for 32 bit system calls can be
2201installed 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
2209Example: 2206Example:
2210.br 2207.br
2211$ firejail \-\-seccomp 2208$ firejail \-\-seccomp
2209.br
2210
2211.br
2212The default list can be customized, see \-\-seccomp= for a description. It can be customized
2213also globally in /etc/firejail/firejail.config file.
2214
2212.TP 2215.TP
2213\fB\-\-seccomp=syscall,@group,!syscall2 2216\fB\-\-seccomp=syscall,@group,!syscall2
2214Enable seccomp filter, whitelist "syscall2", but blacklist the default 2217Enable seccomp filter, blacklist the default list and the syscalls or syscall groups
2215list and the syscalls or syscall groups specified by the 2218specified by the command, but don't blacklist "syscall2". On a 64 bit
2216command. 2219architecture, an additional filter for 32 bit system calls can be
2220installed 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
2234Syscalls can be specified by their number if prefix $ is added,
2235so for example $165 would be equal to mount on i386.
2236.br
2226 2237
2227.br 2238.br
2228Instead of dropping the syscall by returning EPERM, another error 2239Instead 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
2237Example: 2248Example:
2249.br
2238$ firejail \-\-seccomp=unlinkat:ENOENT,utimensat,utimes 2250$ firejail \-\-seccomp=unlinkat:ENOENT,utimensat,utimes
2239.br 2251.br
2240Parent pid 10662, child pid 10663 2252Parent 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
2260testfile
2261.br
2246$ rm testfile 2262$ rm testfile
2247.br 2263.br
2248rm: cannot remove `testfile': Operation not permitted 2264rm: 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
2259Example: 2275Example:
2260.br 2276.br
2261$ firejail \-\-noprofile \-\-shell=none \-\-seccomp=execve bash 2277$ firejail \-\-noprofile \-\-shell=none \-\-seccomp=execve sh
2262.br 2278.br
2263Parent pid 32751, child pid 32752 2279Parent 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
2273Bad system call 2289Operation 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
2335testfile
2336.br
2318$ rm testfile 2337$ rm testfile
2319.br 2338.br
2320rm: cannot remove `testfile': Operation not permitted 2339rm: 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
2329Enable seccomp filter, blacklist all syscall not listed and "syscall2". 2344Enable 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
2569Mount a writable tmpfs filesystem on directory dirname. This option is available only when running the sandbox as root. 2584Mount 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.
2570File globbing is supported, see \fBFILE GLOBBING\fR section for more details.
2571.br 2585.br
2572 2586
2573.br 2587.br
2574Example: 2588Example:
2575.br 2589.br
2576# firejail \-\-tmpfs=/var 2590$ firejail \-\-tmpfs=~/.local/share
2577.TP 2591.TP
2578\fB\-\-top 2592\fB\-\-top
2579Monitor the most CPU-intensive sandboxes, see \fBMONITORING\fR section for more details. 2593Monitor the most CPU-intensive sandboxes, see \fBMONITORING\fR section for more details.