summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/firejail/Makefile.in2
-rw-r--r--src/firejail/caps.c6
-rw-r--r--src/firejail/cgroup.c2
-rw-r--r--src/firejail/env.c1
-rw-r--r--src/firejail/errno.c6
-rw-r--r--src/firejail/fs.c1
-rw-r--r--src/firejail/fs_bin.c1
-rw-r--r--src/firejail/fs_home.c1
-rw-r--r--src/firejail/fs_logger.c5
-rw-r--r--src/firejail/fs_mkdir.c30
-rw-r--r--src/firejail/join.c5
-rw-r--r--src/firejail/list.c12
-rw-r--r--src/firejail/main.c101
-rw-r--r--src/firejail/netfilter.c1
-rw-r--r--src/firejail/network_main.c5
-rw-r--r--src/firejail/no_sandbox.c13
-rw-r--r--src/firejail/output.c4
-rw-r--r--src/firejail/profile.c6
-rw-r--r--src/firejail/protocol.c8
-rw-r--r--src/firejail/restricted_shell.c1
-rw-r--r--src/firejail/run_symlink.c2
-rw-r--r--src/firejail/seccomp.c4
-rw-r--r--src/firejail/shutdown.c4
-rw-r--r--src/firejail/syscall.c2
-rw-r--r--src/firejail/user.c1
-rw-r--r--src/firejail/util.c3
-rw-r--r--src/include/euid_common.h9
27 files changed, 133 insertions, 103 deletions
diff --git a/src/firejail/Makefile.in b/src/firejail/Makefile.in
index 83a2b0592..cf57d96d5 100644
--- a/src/firejail/Makefile.in
+++ b/src/firejail/Makefile.in
@@ -23,7 +23,7 @@ BINOBJS = $(foreach file, $(OBJS), $file)
23CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)/firejail"' -DLIBDIR='"$(libdir)"' $(HAVE_SECCOMP) $(HAVE_SECCOMP_H) $(HAVE_CHROOT) $(HAVE_NETWORK) $(HAVE_USERNS) $(HAVE_BIND) -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -pie -Wformat -Wformat-security 23CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)/firejail"' -DLIBDIR='"$(libdir)"' $(HAVE_SECCOMP) $(HAVE_SECCOMP_H) $(HAVE_CHROOT) $(HAVE_NETWORK) $(HAVE_USERNS) $(HAVE_BIND) -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -pie -Wformat -Wformat-security
24LDFLAGS += -pie -Wl,-z,relro -Wl,-z,now -lpthread 24LDFLAGS += -pie -Wl,-z,relro -Wl,-z,now -lpthread
25 25
26%.o : %.c $(H_FILE_LIST) 26%.o : %.c $(H_FILE_LIST) ../include/common.h ../include/euid_common.h ../include/libnetlink.h ../include/pid.h
27 $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@ 27 $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@
28 28
29firejail: $(OBJS) ../lib/libnetlink.o ../lib/common.o 29firejail: $(OBJS) ../lib/libnetlink.o ../lib/common.o
diff --git a/src/firejail/caps.c b/src/firejail/caps.c
index 1c4ac8d37..838934aee 100644
--- a/src/firejail/caps.c
+++ b/src/firejail/caps.c
@@ -193,6 +193,7 @@ static int caps_find_name(const char *name) {
193 193
194// return 1 if error, 0 if OK 194// return 1 if error, 0 if OK
195int caps_check_list(const char *clist, void (*callback)(int)) { 195int caps_check_list(const char *clist, void (*callback)(int)) {
196
196 // don't allow empty lists 197 // don't allow empty lists
197 if (clist == NULL || *clist == '\0') { 198 if (clist == NULL || *clist == '\0') {
198 fprintf(stderr, "Error: empty capabilities lists are not allowed\n"); 199 fprintf(stderr, "Error: empty capabilities lists are not allowed\n");
@@ -240,6 +241,7 @@ int caps_check_list(const char *clist, void (*callback)(int)) {
240} 241}
241 242
242void caps_print(void) { 243void caps_print(void) {
244 EUID_ASSERT();
243 int i; 245 int i;
244 int elems = sizeof(capslist) / sizeof(capslist[0]); 246 int elems = sizeof(capslist) / sizeof(capslist[0]);
245 247
@@ -364,6 +366,8 @@ void caps_keep_list(const char *clist) {
364 366
365#define MAXBUF 4098 367#define MAXBUF 4098
366static uint64_t extract_caps(int pid) { 368static uint64_t extract_caps(int pid) {
369 EUID_ASSERT();
370
367 char *file; 371 char *file;
368 if (asprintf(&file, "/proc/%d/status", pid) == -1) { 372 if (asprintf(&file, "/proc/%d/status", pid) == -1) {
369 errExit("asprintf"); 373 errExit("asprintf");
@@ -410,6 +414,8 @@ void caps_print_filter_name(const char *name) {
410} 414}
411 415
412void caps_print_filter(pid_t pid) { 416void caps_print_filter(pid_t pid) {
417 EUID_ASSERT();
418
413 // if the pid is that of a firejail process, use the pid of the first child process 419 // if the pid is that of a firejail process, use the pid of the first child process
414 char *comm = pid_proc_comm(pid); 420 char *comm = pid_proc_comm(pid);
415 if (comm) { 421 if (comm) {
diff --git a/src/firejail/cgroup.c b/src/firejail/cgroup.c
index 040a1f934..ebd87f0d2 100644
--- a/src/firejail/cgroup.c
+++ b/src/firejail/cgroup.c
@@ -71,6 +71,8 @@ errout:
71 71
72 72
73void set_cgroup(const char *path) { 73void set_cgroup(const char *path) {
74 EUID_ASSERT();
75
74 invalid_filename(path); 76 invalid_filename(path);
75 77
76 // path starts with /sys/fs/cgroup 78 // path starts with /sys/fs/cgroup
diff --git a/src/firejail/env.c b/src/firejail/env.c
index cccab966d..7fbf7aac5 100644
--- a/src/firejail/env.c
+++ b/src/firejail/env.c
@@ -125,6 +125,7 @@ void env_defaults(void) {
125 125
126// parse and store the environment setting 126// parse and store the environment setting
127void env_store(const char *str) { 127void env_store(const char *str) {
128 EUID_ASSERT();
128 assert(str); 129 assert(str);
129 130
130 // some basic checking 131 // some basic checking
diff --git a/src/firejail/errno.c b/src/firejail/errno.c
index 6c8bd3876..c493dfa09 100644
--- a/src/firejail/errno.c
+++ b/src/firejail/errno.c
@@ -172,7 +172,7 @@ static ErrnoEntry errnolist[] = {
172}; 172};
173 173
174int errno_highest_nr(void) { 174int errno_highest_nr(void) {
175 int i, max = 0; 175 int i, max = 0;
176 int elems = sizeof(errnolist) / sizeof(errnolist[0]); 176 int elems = sizeof(errnolist) / sizeof(errnolist[0]);
177 for (i = 0; i < elems; i++) { 177 for (i = 0; i < elems; i++) {
178 if (errnolist[i].nr > max) 178 if (errnolist[i].nr > max)
@@ -183,6 +183,8 @@ int errno_highest_nr(void) {
183} 183}
184 184
185int errno_find_name(const char *name) { 185int errno_find_name(const char *name) {
186 EUID_ASSERT();
187
186 int i; 188 int i;
187 int elems = sizeof(errnolist) / sizeof(errnolist[0]); 189 int elems = sizeof(errnolist) / sizeof(errnolist[0]);
188 for (i = 0; i < elems; i++) { 190 for (i = 0; i < elems; i++) {
@@ -205,6 +207,8 @@ char *errno_find_nr(int nr) {
205} 207}
206 208
207void errno_print(void) { 209void errno_print(void) {
210 EUID_ASSERT();
211
208 int i; 212 int i;
209 int elems = sizeof(errnolist) / sizeof(errnolist[0]); 213 int elems = sizeof(errnolist) / sizeof(errnolist[0]);
210 for (i = 0; i < elems; i++) { 214 for (i = 0; i < elems; i++) {
diff --git a/src/firejail/fs.c b/src/firejail/fs.c
index 616b87562..3b1a87310 100644
--- a/src/firejail/fs.c
+++ b/src/firejail/fs.c
@@ -874,6 +874,7 @@ void fs_overlayfs(void) {
874#ifdef HAVE_CHROOT 874#ifdef HAVE_CHROOT
875// return 1 if error 875// return 1 if error
876int fs_check_chroot_dir(const char *rootdir) { 876int fs_check_chroot_dir(const char *rootdir) {
877 EUID_ASSERT();
877 assert(rootdir); 878 assert(rootdir);
878 struct stat s; 879 struct stat s;
879 char *name; 880 char *name;
diff --git a/src/firejail/fs_bin.c b/src/firejail/fs_bin.c
index af67ac290..447ef7f8f 100644
--- a/src/firejail/fs_bin.c
+++ b/src/firejail/fs_bin.c
@@ -64,6 +64,7 @@ static char *check_dir_or_file(const char *name) {
64} 64}
65 65
66void fs_check_bin_list(void) { 66void fs_check_bin_list(void) {
67 EUID_ASSERT();
67 if (strstr(cfg.bin_private_keep, "..")) { 68 if (strstr(cfg.bin_private_keep, "..")) {
68 fprintf(stderr, "Error: invalid private bin list\n"); 69 fprintf(stderr, "Error: invalid private bin list\n");
69 exit(1); 70 exit(1);
diff --git a/src/firejail/fs_home.c b/src/firejail/fs_home.c
index 2bfabbe89..2b6142c6c 100644
--- a/src/firejail/fs_home.c
+++ b/src/firejail/fs_home.c
@@ -338,6 +338,7 @@ void fs_private(void) {
338 338
339// check new private home directory (--private= option) - exit if it fails 339// check new private home directory (--private= option) - exit if it fails
340void fs_check_private_dir(void) { 340void fs_check_private_dir(void) {
341 EUID_ASSERT();
341 invalid_filename(cfg.home_private); 342 invalid_filename(cfg.home_private);
342 343
343 // Expand the home directory 344 // Expand the home directory
diff --git a/src/firejail/fs_logger.c b/src/firejail/fs_logger.c
index 0829ad7ac..f803982d7 100644
--- a/src/firejail/fs_logger.c
+++ b/src/firejail/fs_logger.c
@@ -122,6 +122,8 @@ void fs_logger_change_owner(void) {
122} 122}
123 123
124void fs_logger_print_log_name(const char *name) { 124void fs_logger_print_log_name(const char *name) {
125 EUID_ASSERT();
126
125 if (!name || strlen(name) == 0) { 127 if (!name || strlen(name) == 0) {
126 fprintf(stderr, "Error: invalid sandbox name\n"); 128 fprintf(stderr, "Error: invalid sandbox name\n");
127 exit(1); 129 exit(1);
@@ -136,6 +138,8 @@ void fs_logger_print_log_name(const char *name) {
136} 138}
137 139
138void fs_logger_print_log(pid_t pid) { 140void fs_logger_print_log(pid_t pid) {
141 EUID_ASSERT();
142
139 // if the pid is that of a firejail process, use the pid of the first child process 143 // if the pid is that of a firejail process, use the pid of the first child process
140 char *comm = pid_proc_comm(pid); 144 char *comm = pid_proc_comm(pid);
141 if (comm) { 145 if (comm) {
@@ -163,6 +167,7 @@ void fs_logger_print_log(pid_t pid) {
163 } 167 }
164 168
165 // print RUN_FSLOGGER_FILE 169 // print RUN_FSLOGGER_FILE
170 EUID_ROOT();
166 char *fname; 171 char *fname;
167 if (asprintf(&fname, "/proc/%d/root%s", pid, RUN_FSLOGGER_FILE) == -1) 172 if (asprintf(&fname, "/proc/%d/root%s", pid, RUN_FSLOGGER_FILE) == -1)
168 errExit("asprintf"); 173 errExit("asprintf");
diff --git a/src/firejail/fs_mkdir.c b/src/firejail/fs_mkdir.c
index 69bf2fae7..398c534bf 100644
--- a/src/firejail/fs_mkdir.c
+++ b/src/firejail/fs_mkdir.c
@@ -25,6 +25,8 @@
25 #include <sys/wait.h> 25 #include <sys/wait.h>
26 26
27void fs_mkdir(const char *name) { 27void fs_mkdir(const char *name) {
28 EUID_ASSERT();
29
28 // check directory name 30 // check directory name
29 invalid_filename(name); 31 invalid_filename(name);
30 char *expanded = expand_home(name, cfg.homedir); 32 char *expanded = expand_home(name, cfg.homedir);
@@ -39,31 +41,9 @@ void fs_mkdir(const char *name) {
39 goto doexit; 41 goto doexit;
40 } 42 }
41 43
42 // fork a process, drop privileges, and create the directory 44 // create directory
43 // no error recovery will be attempted 45 if (mkdir(expanded, 0700) == -1)
44 pid_t child = fork(); 46 fprintf(stderr, "Warning: cannot create %s directory\n", expanded);
45 if (child < 0)
46 errExit("fork");
47 if (child == 0) {
48 if (arg_debug)
49 printf("Create %s directory\n", expanded);
50
51 // drop privileges
52 if (setgroups(0, NULL) < 0)
53 errExit("setgroups");
54 if (setgid(getgid()) < 0)
55 errExit("setgid/getgid");
56 if (setuid(getuid()) < 0)
57 errExit("setuid/getuid");
58
59 // create directory
60 if (mkdir(expanded, 0700) == -1)
61 fprintf(stderr, "Warning: cannot create %s directory\n", expanded);
62 exit(0);
63 }
64
65 // wait for the child to finish
66 waitpid(child, NULL, 0);
67 47
68doexit: 48doexit:
69 free(expanded); 49 free(expanded);
diff --git a/src/firejail/join.c b/src/firejail/join.c
index e471e4a21..4cd315d90 100644
--- a/src/firejail/join.c
+++ b/src/firejail/join.c
@@ -30,6 +30,7 @@ static int apply_seccomp = 0;
30#define BUFLEN 4096 30#define BUFLEN 4096
31 31
32static void extract_command(int argc, char **argv, int index) { 32static void extract_command(int argc, char **argv, int index) {
33 EUID_ASSERT();
33 if (index >= argc) 34 if (index >= argc)
34 return; 35 return;
35 36
@@ -179,6 +180,7 @@ static void extract_user_namespace(pid_t pid) {
179} 180}
180 181
181void join_name(const char *name, const char *homedir, int argc, char **argv, int index) { 182void join_name(const char *name, const char *homedir, int argc, char **argv, int index) {
183 EUID_ASSERT();
182 if (!name || strlen(name) == 0) { 184 if (!name || strlen(name) == 0) {
183 fprintf(stderr, "Error: invalid sandbox name\n"); 185 fprintf(stderr, "Error: invalid sandbox name\n");
184 exit(1); 186 exit(1);
@@ -193,6 +195,8 @@ void join_name(const char *name, const char *homedir, int argc, char **argv, int
193} 195}
194 196
195void join(pid_t pid, const char *homedir, int argc, char **argv, int index) { 197void join(pid_t pid, const char *homedir, int argc, char **argv, int index) {
198 EUID_ASSERT();
199
196 extract_command(argc, argv, index); 200 extract_command(argc, argv, index);
197 201
198 // if the pid is that of a firejail process, use the pid of the first child process 202 // if the pid is that of a firejail process, use the pid of the first child process
@@ -222,6 +226,7 @@ void join(pid_t pid, const char *homedir, int argc, char **argv, int index) {
222 } 226 }
223 } 227 }
224 228
229 EUID_ROOT();
225 // in user mode set caps seccomp, cpu, cgroup, etc 230 // in user mode set caps seccomp, cpu, cgroup, etc
226 if (getuid() != 0) { 231 if (getuid() != 0) {
227 extract_caps_seccomp(pid); 232 extract_caps_seccomp(pid);
diff --git a/src/firejail/list.c b/src/firejail/list.c
index d5ef1ac2c..676df6a14 100644
--- a/src/firejail/list.c
+++ b/src/firejail/list.c
@@ -20,8 +20,7 @@
20#include "firejail.h" 20#include "firejail.h"
21 21
22void top(void) { 22void top(void) {
23 if (getuid() != geteuid()) 23 EUID_ASSERT();
24 drop_privs(1);
25 24
26 char *arg[4]; 25 char *arg[4];
27 arg[0] = "bash"; 26 arg[0] = "bash";
@@ -32,8 +31,7 @@ void top(void) {
32} 31}
33 32
34void netstats(void) { 33void netstats(void) {
35 if (getuid() != geteuid()) 34 EUID_ASSERT();
36 drop_privs(1);
37 35
38 char *arg[4]; 36 char *arg[4];
39 arg[0] = "bash"; 37 arg[0] = "bash";
@@ -44,8 +42,7 @@ void netstats(void) {
44} 42}
45 43
46void list(void) { 44void list(void) {
47 if (getuid() != geteuid()) 45 EUID_ASSERT();
48 drop_privs(1);
49 46
50 char *arg[4]; 47 char *arg[4];
51 arg[0] = "bash"; 48 arg[0] = "bash";
@@ -56,8 +53,7 @@ void list(void) {
56} 53}
57 54
58void tree(void) { 55void tree(void) {
59 if (getuid() != geteuid()) 56 EUID_ASSERT();
60 drop_privs(1);
61 57
62 char *arg[4]; 58 char *arg[4];
63 arg[0] = "bash"; 59 arg[0] = "bash";
diff --git a/src/firejail/main.c b/src/firejail/main.c
index 3c714f385..fe4027a55 100644
--- a/src/firejail/main.c
+++ b/src/firejail/main.c
@@ -128,40 +128,6 @@ static void my_handler(int s){
128 myexit(1); 128 myexit(1);
129} 129}
130 130
131static void extract_user_data(void) {
132 // check suid
133 EUID_ROOT();
134 if (geteuid()) {
135 fprintf(stderr, "Error: the sandbox is not setuid root\n");
136 exit(1);
137 }
138 EUID_USER();
139
140 struct passwd *pw = getpwuid(getuid());
141 if (!pw)
142 errExit("getpwuid");
143 cfg.username = strdup(pw->pw_name);
144 if (!cfg.username)
145 errExit("strdup");
146
147 // build home directory name
148 cfg.homedir = NULL;
149 if (pw->pw_dir != NULL) {
150 cfg.homedir = strdup(pw->pw_dir);
151 if (!cfg.homedir)
152 errExit("strdup");
153 }
154 else {
155 fprintf(stderr, "Error: user %s doesn't have a user directory assigned\n", cfg.username);
156 exit(1);
157 }
158
159 cfg.cwd = getcwd(NULL, 0);
160}
161
162
163
164
165static inline Bridge *last_bridge_configured(void) { 131static inline Bridge *last_bridge_configured(void) {
166 if (cfg.bridge3.configured) 132 if (cfg.bridge3.configured)
167 return &cfg.bridge3; 133 return &cfg.bridge3;
@@ -175,8 +141,6 @@ static inline Bridge *last_bridge_configured(void) {
175 return NULL; 141 return NULL;
176} 142}
177 143
178
179
180// return 1 if error, 0 if a valid pid was found 144// return 1 if error, 0 if a valid pid was found
181static int read_pid(char *str, pid_t *pid) { 145static int read_pid(char *str, pid_t *pid) {
182 char *endptr; 146 char *endptr;
@@ -193,15 +157,43 @@ static int read_pid(char *str, pid_t *pid) {
193 return 0; 157 return 0;
194} 158}
195 159
196static void init_cfg(void) { 160// init configuration
161static void init_cfg(int argc, char **argv) {
162 EUID_ASSERT();
197 memset(&cfg, 0, sizeof(cfg)); 163 memset(&cfg, 0, sizeof(cfg));
198 164
165 cfg.original_argv = argv;
166 cfg.original_argc = argc;
199 cfg.bridge0.devsandbox = "eth0"; 167 cfg.bridge0.devsandbox = "eth0";
200 cfg.bridge1.devsandbox = "eth1"; 168 cfg.bridge1.devsandbox = "eth1";
201 cfg.bridge2.devsandbox = "eth2"; 169 cfg.bridge2.devsandbox = "eth2";
202 cfg.bridge3.devsandbox = "eth3"; 170 cfg.bridge3.devsandbox = "eth3";
203 171
204 extract_user_data(); 172 // extract user data
173 struct passwd *pw = getpwuid(getuid());
174 if (!pw)
175 errExit("getpwuid");
176 cfg.username = strdup(pw->pw_name);
177 if (!cfg.username)
178 errExit("strdup");
179
180 // build home directory name
181 cfg.homedir = NULL;
182 if (pw->pw_dir != NULL) {
183 cfg.homedir = strdup(pw->pw_dir);
184 if (!cfg.homedir)
185 errExit("strdup");
186 }
187 else {
188 fprintf(stderr, "Error: user %s doesn't have a user directory assigned\n", cfg.username);
189 exit(1);
190 }
191 cfg.cwd = getcwd(NULL, 0);
192
193 // initialize random number generator
194 sandbox_pid = getpid();
195 time_t t = time(NULL);
196 srand(t ^ sandbox_pid);
205} 197}
206 198
207static void check_network(Bridge *br) { 199static void check_network(Bridge *br) {
@@ -219,6 +211,7 @@ static void check_network(Bridge *br) {
219 211
220#ifdef HAVE_USERNS 212#ifdef HAVE_USERNS
221void check_user_namespace(void) { 213void check_user_namespace(void) {
214 EUID_ASSERT();
222 if (getuid() == 0) { 215 if (getuid() == 0) {
223 fprintf(stderr, "Error: --noroot option cannot be used when starting the sandbox as root.\n"); 216 fprintf(stderr, "Error: --noroot option cannot be used when starting the sandbox as root.\n");
224 exit(1); 217 exit(1);
@@ -241,6 +234,8 @@ void check_user_namespace(void) {
241 234
242// exit commands 235// exit commands
243static void run_cmd_and_exit(int i, int argc, char **argv) { 236static void run_cmd_and_exit(int i, int argc, char **argv) {
237 EUID_ASSERT();
238
244 //************************************* 239 //*************************************
245 // basic arguments 240 // basic arguments
246 //************************************* 241 //*************************************
@@ -346,7 +341,6 @@ static void run_cmd_and_exit(int i, int argc, char **argv) {
346 else if (strncmp(argv[i], "--seccomp.print=", 16) == 0) { 341 else if (strncmp(argv[i], "--seccomp.print=", 16) == 0) {
347 // print seccomp filter for a sandbox specified by pid or by name 342 // print seccomp filter for a sandbox specified by pid or by name
348 pid_t pid; 343 pid_t pid;
349 EUID_ROOT();
350 if (read_pid(argv[i] + 16, &pid) == 0) 344 if (read_pid(argv[i] + 16, &pid) == 0)
351 seccomp_print_filter(pid); 345 seccomp_print_filter(pid);
352 else 346 else
@@ -360,7 +354,6 @@ static void run_cmd_and_exit(int i, int argc, char **argv) {
360 else if (strncmp(argv[i], "--protocol.print=", 17) == 0) { 354 else if (strncmp(argv[i], "--protocol.print=", 17) == 0) {
361 // print seccomp filter for a sandbox specified by pid or by name 355 // print seccomp filter for a sandbox specified by pid or by name
362 pid_t pid; 356 pid_t pid;
363 EUID_ROOT();
364 if (read_pid(argv[i] + 17, &pid) == 0) 357 if (read_pid(argv[i] + 17, &pid) == 0)
365 protocol_print_filter(pid); 358 protocol_print_filter(pid);
366 else 359 else
@@ -371,7 +364,6 @@ static void run_cmd_and_exit(int i, int argc, char **argv) {
371 else if (strncmp(argv[i], "--caps.print=", 13) == 0) { 364 else if (strncmp(argv[i], "--caps.print=", 13) == 0) {
372 // join sandbox by pid or by name 365 // join sandbox by pid or by name
373 pid_t pid; 366 pid_t pid;
374 EUID_ROOT();
375 if (read_pid(argv[i] + 13, &pid) == 0) 367 if (read_pid(argv[i] + 13, &pid) == 0)
376 caps_print_filter(pid); 368 caps_print_filter(pid);
377 else 369 else
@@ -381,7 +373,6 @@ static void run_cmd_and_exit(int i, int argc, char **argv) {
381 else if (strncmp(argv[i], "--fs.print=", 11) == 0) { 373 else if (strncmp(argv[i], "--fs.print=", 11) == 0) {
382 // join sandbox by pid or by name 374 // join sandbox by pid or by name
383 pid_t pid; 375 pid_t pid;
384 EUID_ROOT();
385 if (read_pid(argv[i] + 11, &pid) == 0) 376 if (read_pid(argv[i] + 11, &pid) == 0)
386 fs_logger_print_log(pid); 377 fs_logger_print_log(pid);
387 else 378 else
@@ -391,7 +382,6 @@ static void run_cmd_and_exit(int i, int argc, char **argv) {
391 else if (strncmp(argv[i], "--dns.print=", 12) == 0) { 382 else if (strncmp(argv[i], "--dns.print=", 12) == 0) {
392 // join sandbox by pid or by name 383 // join sandbox by pid or by name
393 pid_t pid; 384 pid_t pid;
394 EUID_ROOT();
395 if (read_pid(argv[i] + 12, &pid) == 0) 385 if (read_pid(argv[i] + 12, &pid) == 0)
396 net_dns_print(pid); 386 net_dns_print(pid);
397 else 387 else
@@ -425,7 +415,6 @@ static void run_cmd_and_exit(int i, int argc, char **argv) {
425 415
426 // join sandbox by pid or by name 416 // join sandbox by pid or by name
427 pid_t pid; 417 pid_t pid;
428 EUID_ROOT();
429 if (read_pid(argv[i] + 7, &pid) == 0) 418 if (read_pid(argv[i] + 7, &pid) == 0)
430 join(pid, cfg.homedir, argc, argv, i + 1); 419 join(pid, cfg.homedir, argc, argv, i + 1);
431 else 420 else
@@ -471,7 +460,6 @@ static void run_cmd_and_exit(int i, int argc, char **argv) {
471 460
472 // shutdown sandbox by pid or by name 461 // shutdown sandbox by pid or by name
473 pid_t pid; 462 pid_t pid;
474 EUID_ROOT();
475 if (read_pid(argv[i] + 11, &pid) == 0) 463 if (read_pid(argv[i] + 11, &pid) == 0)
476 shut(pid); 464 shut(pid);
477 else 465 else
@@ -526,7 +514,8 @@ int main(int argc, char **argv) {
526#ifdef HAVE_SECCOMP 514#ifdef HAVE_SECCOMP
527 int highest_errno = errno_highest_nr(); 515 int highest_errno = errno_highest_nr();
528#endif 516#endif
529 517
518
530 // drop permissions by default and rise them when required 519 // drop permissions by default and rise them when required
531 EUID_INIT(); 520 EUID_INIT();
532 EUID_USER(); 521 EUID_USER();
@@ -535,7 +524,6 @@ int main(int argc, char **argv) {
535 if (*argv[0] != '-') 524 if (*argv[0] != '-')
536 run_symlink(argc, argv); 525 run_symlink(argc, argv);
537 526
538
539 // check if we already have a sandbox running 527 // check if we already have a sandbox running
540 int rv = check_kernel_procs(); 528 int rv = check_kernel_procs();
541 if (rv == 0) { 529 if (rv == 0) {
@@ -556,19 +544,22 @@ int main(int argc, char **argv) {
556 } 544 }
557 } 545 }
558 546
547 // check root/suid
548 EUID_ROOT();
549 if (geteuid()) {
550 fprintf(stderr, "Error: the sandbox is not setuid root\n");
551 exit(1);
552 }
553 EUID_USER();
554
559 // initialize globals 555 // initialize globals
560 init_cfg(); 556 init_cfg(argc, argv);
561 cfg.original_argv = argv;
562 cfg.original_argc = argc;
563 557
564 // initialize random number generator
565 sandbox_pid = getpid();
566 time_t t = time(NULL);
567 srand(t ^ sandbox_pid);
568 558
569 // check firejail directories 559 // check firejail directories
570 EUID_ROOT(); 560 EUID_ROOT();
571 fs_build_firejail_dir(); 561 fs_build_firejail_dir();
562 // todo: deprecate shm functions
572 shm_create_firejail_dir(); 563 shm_create_firejail_dir();
573 bandwidth_shm_del_file(sandbox_pid); 564 bandwidth_shm_del_file(sandbox_pid);
574 EUID_USER(); 565 EUID_USER();
diff --git a/src/firejail/netfilter.c b/src/firejail/netfilter.c
index 2ed09434a..4a5499699 100644
--- a/src/firejail/netfilter.c
+++ b/src/firejail/netfilter.c
@@ -44,6 +44,7 @@ static char *client_filter =
44"COMMIT\n"; 44"COMMIT\n";
45 45
46void check_netfilter_file(const char *fname) { 46void check_netfilter_file(const char *fname) {
47 EUID_ASSERT();
47 invalid_filename(fname); 48 invalid_filename(fname);
48 49
49 if (is_dir(fname) || is_link(fname) || strstr(fname, "..")) { 50 if (is_dir(fname) || is_link(fname) || strstr(fname, "..")) {
diff --git a/src/firejail/network_main.c b/src/firejail/network_main.c
index bd104343a..9ddd56dcd 100644
--- a/src/firejail/network_main.c
+++ b/src/firejail/network_main.c
@@ -165,6 +165,7 @@ void check_default_gw(uint32_t defaultgw) {
165} 165}
166 166
167void net_check_cfg(void) { 167void net_check_cfg(void) {
168 EUID_ASSERT();
168 int net_configured = 0; 169 int net_configured = 0;
169 if (cfg.bridge0.configured) 170 if (cfg.bridge0.configured)
170 net_configured++; 171 net_configured++;
@@ -223,6 +224,7 @@ void net_check_cfg(void) {
223 224
224 225
225void net_dns_print_name(const char *name) { 226void net_dns_print_name(const char *name) {
227 EUID_ASSERT();
226 if (!name || strlen(name) == 0) { 228 if (!name || strlen(name) == 0) {
227 fprintf(stderr, "Error: invalid sandbox name\n"); 229 fprintf(stderr, "Error: invalid sandbox name\n");
228 exit(1); 230 exit(1);
@@ -238,8 +240,8 @@ void net_dns_print_name(const char *name) {
238 240
239#define MAXBUF 4096 241#define MAXBUF 4096
240void net_dns_print(pid_t pid) { 242void net_dns_print(pid_t pid) {
243 EUID_ASSERT();
241 // drop privileges - will not be able to read /etc/resolv.conf for --noroot option 244 // drop privileges - will not be able to read /etc/resolv.conf for --noroot option
242// drop_privs(1);
243 245
244 // if the pid is that of a firejail process, use the pid of the first child process 246 // if the pid is that of a firejail process, use the pid of the first child process
245 char *comm = pid_proc_comm(pid); 247 char *comm = pid_proc_comm(pid);
@@ -258,6 +260,7 @@ void net_dns_print(pid_t pid) {
258 } 260 }
259 261
260 char *fname; 262 char *fname;
263 EUID_ROOT();
261 if (asprintf(&fname, "/proc/%d/root/etc/resolv.conf", pid) == -1) 264 if (asprintf(&fname, "/proc/%d/root/etc/resolv.conf", pid) == -1)
262 errExit("asprintf"); 265 errExit("asprintf");
263 266
diff --git a/src/firejail/no_sandbox.c b/src/firejail/no_sandbox.c
index 15d61362a..9f9ace527 100644
--- a/src/firejail/no_sandbox.c
+++ b/src/firejail/no_sandbox.c
@@ -26,6 +26,8 @@
26// check process space for kernel processes 26// check process space for kernel processes
27// return 1 if found, 0 if not found 27// return 1 if found, 0 if not found
28int check_kernel_procs(void) { 28int check_kernel_procs(void) {
29 EUID_ASSERT();
30
29 char *kern_proc[] = { 31 char *kern_proc[] = {
30 "kthreadd", 32 "kthreadd",
31 "ksoftirqd", 33 "ksoftirqd",
@@ -97,14 +99,7 @@ int check_kernel_procs(void) {
97} 99}
98 100
99void run_no_sandbox(int argc, char **argv) { 101void run_no_sandbox(int argc, char **argv) {
100 // drop privileges 102 EUID_ASSERT();
101 int rv = setgroups(0, NULL); // this could fail
102 (void) rv;
103 if (setgid(getgid()) < 0)
104 errExit("setgid/getgid");
105 if (setuid(getuid()) < 0)
106 errExit("setuid/getuid");
107
108 103
109 // build command 104 // build command
110 char *command = NULL; 105 char *command = NULL;
@@ -141,7 +136,7 @@ void run_no_sandbox(int argc, char **argv) {
141 // start the program in /bin/sh 136 // start the program in /bin/sh
142 fprintf(stderr, "Warning: an existing sandbox was detected. " 137 fprintf(stderr, "Warning: an existing sandbox was detected. "
143 "%s will run without any additional sandboxing features in a /bin/sh shell\n", command); 138 "%s will run without any additional sandboxing features in a /bin/sh shell\n", command);
144 rv = system(command); 139 int rv = system(command);
145 (void) rv; 140 (void) rv;
146 if (allocated) 141 if (allocated)
147 free(command); 142 free(command);
diff --git a/src/firejail/output.c b/src/firejail/output.c
index d553e283f..a554b76aa 100644
--- a/src/firejail/output.c
+++ b/src/firejail/output.c
@@ -23,6 +23,8 @@
23#include <unistd.h> 23#include <unistd.h>
24 24
25void check_output(int argc, char **argv) { 25void check_output(int argc, char **argv) {
26 EUID_ASSERT();
27
26 int i; 28 int i;
27 char *outfile = NULL; 29 char *outfile = NULL;
28// drop_privs(0); 30// drop_privs(0);
@@ -55,8 +57,6 @@ void check_output(int argc, char **argv) {
55 } 57 }
56 } 58 }
57 59
58 // drop privileges and try to open the file for writing
59 drop_privs(0);
60 /* coverity[toctou] */ 60 /* coverity[toctou] */
61 FILE *fp = fopen(outfile, "a"); 61 FILE *fp = fopen(outfile, "a");
62 if (!fp) { 62 if (!fp) {
diff --git a/src/firejail/profile.c b/src/firejail/profile.c
index 0c28eefd8..518fdf194 100644
--- a/src/firejail/profile.c
+++ b/src/firejail/profile.c
@@ -66,6 +66,8 @@ int profile_find(const char *name, const char *dir) {
66// return 1 if the command is to be added to the linked list of profile commands 66// return 1 if the command is to be added to the linked list of profile commands
67// return 0 if the command was already executed inside the function 67// return 0 if the command was already executed inside the function
68int profile_check_line(char *ptr, int lineno, const char *fname) { 68int profile_check_line(char *ptr, int lineno, const char *fname) {
69 EUID_ASSERT();
70
69 // check ignore list 71 // check ignore list
70 int i; 72 int i;
71 for (i = 0; i < MAX_PROFILE_IGNORE; i++) { 73 for (i = 0; i < MAX_PROFILE_IGNORE; i++) {
@@ -458,6 +460,8 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
458 460
459// add a profile entry in cfg.profile list; use str to populate the list 461// add a profile entry in cfg.profile list; use str to populate the list
460void profile_add(char *str) { 462void profile_add(char *str) {
463 EUID_ASSERT();
464
461 ProfileEntry *prf = malloc(sizeof(ProfileEntry)); 465 ProfileEntry *prf = malloc(sizeof(ProfileEntry));
462 if (!prf) 466 if (!prf)
463 errExit("malloc"); 467 errExit("malloc");
@@ -479,6 +483,8 @@ void profile_add(char *str) {
479// read a profile file 483// read a profile file
480static int include_level = 0; 484static int include_level = 0;
481void profile_read(const char *fname) { 485void profile_read(const char *fname) {
486 EUID_ASSERT();
487
482 // exit program if maximum include level was reached 488 // exit program if maximum include level was reached
483 if (include_level > MAX_INCLUDE_LEVEL) { 489 if (include_level > MAX_INCLUDE_LEVEL) {
484 fprintf(stderr, "Error: maximum profile include level was reached\n"); 490 fprintf(stderr, "Error: maximum profile include level was reached\n");
diff --git a/src/firejail/protocol.c b/src/firejail/protocol.c
index 407f8c62d..24fbfc024 100644
--- a/src/firejail/protocol.c
+++ b/src/firejail/protocol.c
@@ -101,6 +101,8 @@ static struct sock_filter *find_protocol_domain(const char *p) {
101 101
102// --debug-protocols 102// --debug-protocols
103void protocol_list(void) { 103void protocol_list(void) {
104 EUID_ASSERT();
105
104#ifndef SYS_socket 106#ifndef SYS_socket
105 fprintf(stderr, "Warning: --protocol not supported on this platform\n"); 107 fprintf(stderr, "Warning: --protocol not supported on this platform\n");
106 return; 108 return;
@@ -117,6 +119,7 @@ void protocol_list(void) {
117 119
118// check protocol list and store it in cfg structure 120// check protocol list and store it in cfg structure
119void protocol_store(const char *prlist) { 121void protocol_store(const char *prlist) {
122 EUID_ASSERT();
120 assert(prlist); 123 assert(prlist);
121 124
122 if (cfg.protocol) { 125 if (cfg.protocol) {
@@ -308,6 +311,8 @@ void protocol_filter_load(const char *fname) {
308 311
309// --protocol.print 312// --protocol.print
310void protocol_print_filter_name(const char *name) { 313void protocol_print_filter_name(const char *name) {
314 EUID_ASSERT();
315
311 (void) name; 316 (void) name;
312#ifdef SYS_socket 317#ifdef SYS_socket
313 if (!name || strlen(name) == 0) { 318 if (!name || strlen(name) == 0) {
@@ -329,6 +334,8 @@ void protocol_print_filter_name(const char *name) {
329 334
330// --protocol.print 335// --protocol.print
331void protocol_print_filter(pid_t pid) { 336void protocol_print_filter(pid_t pid) {
337 EUID_ASSERT();
338
332 (void) pid; 339 (void) pid;
333#ifdef SYS_socket 340#ifdef SYS_socket
334 // if the pid is that of a firejail process, use the pid of the first child process 341 // if the pid is that of a firejail process, use the pid of the first child process
@@ -358,6 +365,7 @@ void protocol_print_filter(pid_t pid) {
358 } 365 }
359 366
360 // find the seccomp filter 367 // find the seccomp filter
368 EUID_ROOT();
361 char *fname; 369 char *fname;
362 if (asprintf(&fname, "/proc/%d/root%s", pid, RUN_PROTOCOL_CFG) == -1) 370 if (asprintf(&fname, "/proc/%d/root%s", pid, RUN_PROTOCOL_CFG) == -1)
363 errExit("asprintf"); 371 errExit("asprintf");
diff --git a/src/firejail/restricted_shell.c b/src/firejail/restricted_shell.c
index 95e543031..da4e9d332 100644
--- a/src/firejail/restricted_shell.c
+++ b/src/firejail/restricted_shell.c
@@ -24,6 +24,7 @@ char *restricted_user = NULL;
24 24
25 25
26int restricted_shell(const char *user) { 26int restricted_shell(const char *user) {
27 EUID_ASSERT();
27 assert(user); 28 assert(user);
28 29
29 // open profile file: 30 // open profile file:
diff --git a/src/firejail/run_symlink.c b/src/firejail/run_symlink.c
index bc1bb3011..d57816e12 100644
--- a/src/firejail/run_symlink.c
+++ b/src/firejail/run_symlink.c
@@ -23,6 +23,8 @@
23#include <unistd.h> 23#include <unistd.h>
24 24
25void run_symlink(int argc, char **argv) { 25void run_symlink(int argc, char **argv) {
26 EUID_ASSERT();
27
26 char *program = strrchr(argv[0], '/'); 28 char *program = strrchr(argv[0], '/');
27 if (program) 29 if (program)
28 program += 1; 30 program += 1;
diff --git a/src/firejail/seccomp.c b/src/firejail/seccomp.c
index 57f483b1c..f9a9df211 100644
--- a/src/firejail/seccomp.c
+++ b/src/firejail/seccomp.c
@@ -800,6 +800,7 @@ void seccomp_set(void) {
800} 800}
801 801
802void seccomp_print_filter_name(const char *name) { 802void seccomp_print_filter_name(const char *name) {
803 EUID_ASSERT();
803 if (!name || strlen(name) == 0) { 804 if (!name || strlen(name) == 0) {
804 fprintf(stderr, "Error: invalid sandbox name\n"); 805 fprintf(stderr, "Error: invalid sandbox name\n");
805 exit(1); 806 exit(1);
@@ -814,6 +815,8 @@ void seccomp_print_filter_name(const char *name) {
814} 815}
815 816
816void seccomp_print_filter(pid_t pid) { 817void seccomp_print_filter(pid_t pid) {
818 EUID_ASSERT();
819
817 // if the pid is that of a firejail process, use the pid of the first child process 820 // if the pid is that of a firejail process, use the pid of the first child process
818 char *comm = pid_proc_comm(pid); 821 char *comm = pid_proc_comm(pid);
819 if (comm) { 822 if (comm) {
@@ -842,6 +845,7 @@ void seccomp_print_filter(pid_t pid) {
842 845
843 846
844 // find the seccomp filter 847 // find the seccomp filter
848 EUID_ROOT();
845 char *fname; 849 char *fname;
846 if (asprintf(&fname, "/proc/%d/root%s", pid, RUN_SECCOMP_CFG) == -1) 850 if (asprintf(&fname, "/proc/%d/root%s", pid, RUN_SECCOMP_CFG) == -1)
847 errExit("asprintf"); 851 errExit("asprintf");
diff --git a/src/firejail/shutdown.c b/src/firejail/shutdown.c
index edaac7eb9..c88683aaa 100644
--- a/src/firejail/shutdown.c
+++ b/src/firejail/shutdown.c
@@ -24,6 +24,7 @@
24#include <sys/prctl.h> 24#include <sys/prctl.h>
25 25
26void shut_name(const char *name) { 26void shut_name(const char *name) {
27 EUID_ASSERT();
27 if (!name || strlen(name) == 0) { 28 if (!name || strlen(name) == 0) {
28 fprintf(stderr, "Error: invalid sandbox name\n"); 29 fprintf(stderr, "Error: invalid sandbox name\n");
29 exit(1); 30 exit(1);
@@ -39,6 +40,8 @@ void shut_name(const char *name) {
39} 40}
40 41
41void shut(pid_t pid) { 42void shut(pid_t pid) {
43 EUID_ASSERT();
44
42 pid_t parent = pid; 45 pid_t parent = pid;
43 // if the pid is that of a firejail process, use the pid of a child process inside the sandbox 46 // if the pid is that of a firejail process, use the pid of a child process inside the sandbox
44 char *comm = pid_proc_comm(pid); 47 char *comm = pid_proc_comm(pid);
@@ -73,6 +76,7 @@ void shut(pid_t pid) {
73 } 76 }
74 } 77 }
75 78
79 EUID_ROOT();
76 printf("Sending SIGTERM to %u\n", pid); 80 printf("Sending SIGTERM to %u\n", pid);
77 kill(pid, SIGTERM); 81 kill(pid, SIGTERM);
78 sleep(2); 82 sleep(2);
diff --git a/src/firejail/syscall.c b/src/firejail/syscall.c
index 50d59391e..985cc8bb8 100644
--- a/src/firejail/syscall.c
+++ b/src/firejail/syscall.c
@@ -103,6 +103,8 @@ int syscall_check_list(const char *slist, void (*callback)(int syscall, int arg)
103} 103}
104 104
105void syscall_print(void) { 105void syscall_print(void) {
106 EUID_ASSERT();
107
106 int i; 108 int i;
107 int elems = sizeof(syslist) / sizeof(syslist[0]); 109 int elems = sizeof(syslist) / sizeof(syslist[0]);
108 for (i = 0; i < elems; i++) { 110 for (i = 0; i < elems; i++) {
diff --git a/src/firejail/user.c b/src/firejail/user.c
index e5f7848e8..a2f34392c 100644
--- a/src/firejail/user.c
+++ b/src/firejail/user.c
@@ -26,6 +26,7 @@
26 26
27 27
28void check_user(int argc, char **argv) { 28void check_user(int argc, char **argv) {
29 EUID_ASSERT();
29 int i; 30 int i;
30 char *user = NULL; 31 char *user = NULL;
31 32
diff --git a/src/firejail/util.c b/src/firejail/util.c
index d969f6439..a74693c7a 100644
--- a/src/firejail/util.c
+++ b/src/firejail/util.c
@@ -321,6 +321,8 @@ char *split_comma(char *str) {
321 321
322 322
323int not_unsigned(const char *str) { 323int not_unsigned(const char *str) {
324 EUID_ASSERT();
325
324 int rv = 0; 326 int rv = 0;
325 const char *ptr = str; 327 const char *ptr = str;
326 while (*ptr != ' ' && *ptr != '\t' && *ptr != '\0') { 328 while (*ptr != ' ' && *ptr != '\t' && *ptr != '\0') {
@@ -399,6 +401,7 @@ int find_child(pid_t parent, pid_t *child) {
399 401
400 402
401void extract_command_name(int index, char **argv) { 403void extract_command_name(int index, char **argv) {
404 EUID_ASSERT();
402 assert(argv); 405 assert(argv);
403 assert(argv[index]); 406 assert(argv[index]);
404 407
diff --git a/src/include/euid_common.h b/src/include/euid_common.h
index 1cba548ab..f07cf2868 100644
--- a/src/include/euid_common.h
+++ b/src/include/euid_common.h
@@ -23,9 +23,16 @@
23#include <stdio.h> 23#include <stdio.h>
24#include <sys/types.h> 24#include <sys/types.h>
25#include <unistd.h> 25#include <unistd.h>
26#include <assert.h>
27
28#define EUID_ASSERT() { \
29 if (getuid() != 0) \
30 assert(geteuid() != 0); \
31}
26 32
27extern uid_t firejail_uid; 33extern uid_t firejail_uid;
28extern uid_t firejail_uid_switch; 34
35
29 36
30static inline void EUID_ROOT(void) { 37static inline void EUID_ROOT(void) {
31 if (seteuid(0) == -1) 38 if (seteuid(0) == -1)