diff options
42 files changed, 623 insertions, 255 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) | |||
23 | CFLAGS += -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 | 23 | CFLAGS += -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 |
24 | LDFLAGS += -pie -Wl,-z,relro -Wl,-z,now -lpthread | 24 | LDFLAGS += -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 | ||
29 | firejail: $(OBJS) ../lib/libnetlink.o ../lib/common.o | 29 | firejail: $(OBJS) ../lib/libnetlink.o ../lib/common.o |
diff --git a/src/firejail/caps.c b/src/firejail/caps.c index 1c4ac8d37..d623c5fd3 100644 --- a/src/firejail/caps.c +++ b/src/firejail/caps.c | |||
@@ -240,6 +240,7 @@ int caps_check_list(const char *clist, void (*callback)(int)) { | |||
240 | } | 240 | } |
241 | 241 | ||
242 | void caps_print(void) { | 242 | void caps_print(void) { |
243 | EUID_ASSERT(); | ||
243 | int i; | 244 | int i; |
244 | int elems = sizeof(capslist) / sizeof(capslist[0]); | 245 | int elems = sizeof(capslist) / sizeof(capslist[0]); |
245 | 246 | ||
@@ -364,6 +365,8 @@ void caps_keep_list(const char *clist) { | |||
364 | 365 | ||
365 | #define MAXBUF 4098 | 366 | #define MAXBUF 4098 |
366 | static uint64_t extract_caps(int pid) { | 367 | static uint64_t extract_caps(int pid) { |
368 | EUID_ASSERT(); | ||
369 | |||
367 | char *file; | 370 | char *file; |
368 | if (asprintf(&file, "/proc/%d/status", pid) == -1) { | 371 | if (asprintf(&file, "/proc/%d/status", pid) == -1) { |
369 | errExit("asprintf"); | 372 | errExit("asprintf"); |
@@ -396,6 +399,7 @@ static uint64_t extract_caps(int pid) { | |||
396 | 399 | ||
397 | 400 | ||
398 | void caps_print_filter_name(const char *name) { | 401 | void caps_print_filter_name(const char *name) { |
402 | EUID_ASSERT(); | ||
399 | if (!name || strlen(name) == 0) { | 403 | if (!name || strlen(name) == 0) { |
400 | fprintf(stderr, "Error: invalid sandbox name\n"); | 404 | fprintf(stderr, "Error: invalid sandbox name\n"); |
401 | exit(1); | 405 | exit(1); |
@@ -410,6 +414,8 @@ void caps_print_filter_name(const char *name) { | |||
410 | } | 414 | } |
411 | 415 | ||
412 | void caps_print_filter(pid_t pid) { | 416 | void 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 | ||
73 | void set_cgroup(const char *path) { | 73 | void 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/cpu.c b/src/firejail/cpu.c index bfad1dc25..23906ae48 100644 --- a/src/firejail/cpu.c +++ b/src/firejail/cpu.c | |||
@@ -40,6 +40,8 @@ static void set_cpu(const char *str) { | |||
40 | } | 40 | } |
41 | 41 | ||
42 | void read_cpu_list(const char *str) { | 42 | void read_cpu_list(const char *str) { |
43 | EUID_ASSERT(); | ||
44 | |||
43 | char *tmp = strdup(str); | 45 | char *tmp = strdup(str); |
44 | if (tmp == NULL) | 46 | if (tmp == NULL) |
45 | errExit("strdup"); | 47 | errExit("strdup"); |
diff --git a/src/firejail/env.c b/src/firejail/env.c index cccab966d..54a6b0036 100644 --- a/src/firejail/env.c +++ b/src/firejail/env.c | |||
@@ -86,7 +86,9 @@ void env_ibus_load(void) { | |||
86 | *ptr = '\0'; | 86 | *ptr = '\0'; |
87 | if (arg_debug) | 87 | if (arg_debug) |
88 | printf("%s\n", buf); | 88 | printf("%s\n", buf); |
89 | EUID_USER(); | ||
89 | env_store(buf); | 90 | env_store(buf); |
91 | EUID_ROOT(); | ||
90 | } | 92 | } |
91 | 93 | ||
92 | fclose(fp); | 94 | fclose(fp); |
@@ -125,6 +127,7 @@ void env_defaults(void) { | |||
125 | 127 | ||
126 | // parse and store the environment setting | 128 | // parse and store the environment setting |
127 | void env_store(const char *str) { | 129 | void env_store(const char *str) { |
130 | EUID_ASSERT(); | ||
128 | assert(str); | 131 | assert(str); |
129 | 132 | ||
130 | // some basic checking | 133 | // 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 | ||
174 | int errno_highest_nr(void) { | 174 | int 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 | ||
185 | int errno_find_name(const char *name) { | 185 | int 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 | ||
207 | void errno_print(void) { | 209 | void 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/firejail.h b/src/firejail/firejail.h index 2662cc1d7..4babc58e7 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -20,10 +20,15 @@ | |||
20 | #ifndef FIREJAIL_H | 20 | #ifndef FIREJAIL_H |
21 | #define FIREJAIL_H | 21 | #define FIREJAIL_H |
22 | #include "../include/common.h" | 22 | #include "../include/common.h" |
23 | #include "../include/euid_common.h" | ||
24 | |||
23 | 25 | ||
24 | // filesystem | 26 | // filesystem |
25 | #define RUN_FIREJAIL_BASEDIR "/run" | 27 | #define RUN_FIREJAIL_BASEDIR "/run" |
26 | #define RUN_FIREJAIL_DIR "/run/firejail" | 28 | #define RUN_FIREJAIL_DIR "/run/firejail" |
29 | #define RUN_FIREJAIL_NAME_DIR "/run/firejail/name" | ||
30 | #define RUN_FIREJAIL_NETWORK_DIR "/run/firejail/network" | ||
31 | #define RUN_FIREJAIL_BANDWIDTH_DIR "/run/firejail/bandwidth" | ||
27 | #define RUN_NETWORK_LOCK_FILE "/run/firejail/firejail.lock" | 32 | #define RUN_NETWORK_LOCK_FILE "/run/firejail/firejail.lock" |
28 | #define RUN_RO_DIR "/run/firejail/firejail.ro.dir" | 33 | #define RUN_RO_DIR "/run/firejail/firejail.ro.dir" |
29 | #define RUN_RO_FILE "/run/firejail/firejail.ro.file" | 34 | #define RUN_RO_FILE "/run/firejail/firejail.ro.file" |
diff --git a/src/firejail/fs.c b/src/firejail/fs.c index c3e9890b4..92cf4c1bc 100644 --- a/src/firejail/fs.c +++ b/src/firejail/fs.c | |||
@@ -73,6 +73,12 @@ void fs_build_firejail_dir(void) { | |||
73 | if (chmod(RUN_FIREJAIL_BASEDIR, 0755) < 0) | 73 | if (chmod(RUN_FIREJAIL_BASEDIR, 0755) < 0) |
74 | errExit("chmod"); | 74 | errExit("chmod"); |
75 | } | 75 | } |
76 | else { // check /tmp/firejail directory belongs to root end exit if doesn't! | ||
77 | if (s.st_uid != 0 || s.st_gid != 0) { | ||
78 | fprintf(stderr, "Error: non-root %s directory, exiting...\n", RUN_FIREJAIL_DIR); | ||
79 | exit(1); | ||
80 | } | ||
81 | } | ||
76 | 82 | ||
77 | if (stat(RUN_FIREJAIL_DIR, &s)) { | 83 | if (stat(RUN_FIREJAIL_DIR, &s)) { |
78 | if (arg_debug) | 84 | if (arg_debug) |
@@ -86,11 +92,39 @@ void fs_build_firejail_dir(void) { | |||
86 | if (chmod(RUN_FIREJAIL_DIR, 0755) < 0) | 92 | if (chmod(RUN_FIREJAIL_DIR, 0755) < 0) |
87 | errExit("chmod"); | 93 | errExit("chmod"); |
88 | } | 94 | } |
89 | else { // check /tmp/firejail directory belongs to root end exit if doesn't! | 95 | |
90 | if (s.st_uid != 0 || s.st_gid != 0) { | 96 | if (stat(RUN_FIREJAIL_NETWORK_DIR, &s)) { |
91 | fprintf(stderr, "Error: non-root %s directory, exiting...\n", RUN_FIREJAIL_DIR); | 97 | if (arg_debug) |
92 | exit(1); | 98 | printf("Creating %s directory\n", RUN_FIREJAIL_NETWORK_DIR); |
93 | } | 99 | |
100 | if (mkdir(RUN_FIREJAIL_NETWORK_DIR, 0755) == -1) | ||
101 | errExit("mkdir"); | ||
102 | if (chown(RUN_FIREJAIL_NETWORK_DIR, 0, 0) < 0) | ||
103 | errExit("chown"); | ||
104 | if (chmod(RUN_FIREJAIL_NETWORK_DIR, 0755) < 0) | ||
105 | errExit("chmod"); | ||
106 | } | ||
107 | |||
108 | if (stat(RUN_FIREJAIL_BANDWIDTH_DIR, &s)) { | ||
109 | if (arg_debug) | ||
110 | printf("Creating %s directory\n", RUN_FIREJAIL_BANDWIDTH_DIR); | ||
111 | if (mkdir(RUN_FIREJAIL_BANDWIDTH_DIR, 0755) == -1) | ||
112 | errExit("mkdir"); | ||
113 | if (chown(RUN_FIREJAIL_BANDWIDTH_DIR, 0, 0) < 0) | ||
114 | errExit("chown"); | ||
115 | if (chmod(RUN_FIREJAIL_BANDWIDTH_DIR, 0755) < 0) | ||
116 | errExit("chmod"); | ||
117 | } | ||
118 | |||
119 | if (stat(RUN_FIREJAIL_NAME_DIR, &s)) { | ||
120 | if (arg_debug) | ||
121 | printf("Creating %s directory\n", RUN_FIREJAIL_NAME_DIR); | ||
122 | if (mkdir(RUN_FIREJAIL_NAME_DIR, 0755) == -1) | ||
123 | errExit("mkdir"); | ||
124 | if (chown(RUN_FIREJAIL_NAME_DIR, 0, 0) < 0) | ||
125 | errExit("chown"); | ||
126 | if (chmod(RUN_FIREJAIL_NAME_DIR, 0755) < 0) | ||
127 | errExit("chmod"); | ||
94 | } | 128 | } |
95 | 129 | ||
96 | create_empty_dir(); | 130 | create_empty_dir(); |
@@ -853,6 +887,7 @@ void fs_overlayfs(void) { | |||
853 | #ifdef HAVE_CHROOT | 887 | #ifdef HAVE_CHROOT |
854 | // return 1 if error | 888 | // return 1 if error |
855 | int fs_check_chroot_dir(const char *rootdir) { | 889 | int fs_check_chroot_dir(const char *rootdir) { |
890 | EUID_ASSERT(); | ||
856 | assert(rootdir); | 891 | assert(rootdir); |
857 | struct stat s; | 892 | struct stat s; |
858 | char *name; | 893 | 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 | ||
66 | void fs_check_bin_list(void) { | 66 | void 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_etc.c b/src/firejail/fs_etc.c index c3a247331..5a8bf6904 100644 --- a/src/firejail/fs_etc.c +++ b/src/firejail/fs_etc.c | |||
@@ -57,6 +57,7 @@ static int check_dir_or_file(const char *name) { | |||
57 | } | 57 | } |
58 | 58 | ||
59 | void fs_check_etc_list(void) { | 59 | void fs_check_etc_list(void) { |
60 | EUID_ASSERT(); | ||
60 | if (strstr(cfg.etc_private_keep, "..")) { | 61 | if (strstr(cfg.etc_private_keep, "..")) { |
61 | fprintf(stderr, "Error: invalid private etc list\n"); | 62 | fprintf(stderr, "Error: invalid private etc list\n"); |
62 | exit(1); | 63 | 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 |
340 | void fs_check_private_dir(void) { | 340 | void 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 | ||
124 | void fs_logger_print_log_name(const char *name) { | 124 | void 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 | ||
138 | void fs_logger_print_log(pid_t pid) { | 140 | void 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 | ||
27 | void fs_mkdir(const char *name) { | 27 | void 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 | ||
68 | doexit: | 48 | doexit: |
69 | free(expanded); | 49 | free(expanded); |
diff --git a/src/firejail/join.c b/src/firejail/join.c index b05e25387..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 | ||
32 | static void extract_command(int argc, char **argv, int index) { | 32 | static 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,20 +180,23 @@ static void extract_user_namespace(pid_t pid) { | |||
179 | } | 180 | } |
180 | 181 | ||
181 | void join_name(const char *name, const char *homedir, int argc, char **argv, int index) { | 182 | void 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); |
185 | } | 187 | } |
188 | |||
186 | pid_t pid; | 189 | pid_t pid; |
187 | if (name2pid(name, &pid)) { | 190 | if (name2pid(name, &pid)) { |
188 | fprintf(stderr, "Error: cannot find sandbox %s\n", name); | 191 | fprintf(stderr, "Error: cannot find sandbox %s\n", name); |
189 | exit(1); | 192 | exit(1); |
190 | } | 193 | } |
191 | |||
192 | join(pid, homedir, argc, argv, index); | 194 | join(pid, homedir, argc, argv, index); |
193 | } | 195 | } |
194 | 196 | ||
195 | void join(pid_t pid, const char *homedir, int argc, char **argv, int index) { | 197 | void 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 7a3cf0aad..676df6a14 100644 --- a/src/firejail/list.c +++ b/src/firejail/list.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include "firejail.h" | 20 | #include "firejail.h" |
21 | 21 | ||
22 | void top(void) { | 22 | void top(void) { |
23 | drop_privs(1); | 23 | EUID_ASSERT(); |
24 | 24 | ||
25 | char *arg[4]; | 25 | char *arg[4]; |
26 | arg[0] = "bash"; | 26 | arg[0] = "bash"; |
@@ -31,7 +31,7 @@ void top(void) { | |||
31 | } | 31 | } |
32 | 32 | ||
33 | void netstats(void) { | 33 | void netstats(void) { |
34 | drop_privs(1); | 34 | EUID_ASSERT(); |
35 | 35 | ||
36 | char *arg[4]; | 36 | char *arg[4]; |
37 | arg[0] = "bash"; | 37 | arg[0] = "bash"; |
@@ -42,7 +42,7 @@ void netstats(void) { | |||
42 | } | 42 | } |
43 | 43 | ||
44 | void list(void) { | 44 | void list(void) { |
45 | drop_privs(1); | 45 | EUID_ASSERT(); |
46 | 46 | ||
47 | char *arg[4]; | 47 | char *arg[4]; |
48 | arg[0] = "bash"; | 48 | arg[0] = "bash"; |
@@ -53,7 +53,7 @@ void list(void) { | |||
53 | } | 53 | } |
54 | 54 | ||
55 | void tree(void) { | 55 | void tree(void) { |
56 | drop_privs(1); | 56 | EUID_ASSERT(); |
57 | 57 | ||
58 | char *arg[4]; | 58 | char *arg[4]; |
59 | arg[0] = "bash"; | 59 | arg[0] = "bash"; |
diff --git a/src/firejail/main.c b/src/firejail/main.c index 6fd011868..fe4027a55 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c | |||
@@ -45,6 +45,8 @@ printf("time %s:%d %u\n", __FILE__, __LINE__, (uint32_t) systick); | |||
45 | } | 45 | } |
46 | #endif | 46 | #endif |
47 | 47 | ||
48 | uid_t firejail_uid = 0; | ||
49 | |||
48 | #define STACK_SIZE (1024 * 1024) | 50 | #define STACK_SIZE (1024 * 1024) |
49 | static char child_stack[STACK_SIZE]; // space for child's stack | 51 | static char child_stack[STACK_SIZE]; // space for child's stack |
50 | Config cfg; // configuration | 52 | Config cfg; // configuration |
@@ -102,6 +104,9 @@ int fullargc = 0; | |||
102 | static pid_t child = 0; | 104 | static pid_t child = 0; |
103 | pid_t sandbox_pid; | 105 | pid_t sandbox_pid; |
104 | 106 | ||
107 | static void set_name_file(uid_t pid); | ||
108 | static void delete_name_file(uid_t pid); | ||
109 | |||
105 | static void myexit(int rv) { | 110 | static void myexit(int rv) { |
106 | logmsg("exiting..."); | 111 | logmsg("exiting..."); |
107 | if (!arg_command && !arg_quiet) | 112 | if (!arg_command && !arg_quiet) |
@@ -110,6 +115,7 @@ static void myexit(int rv) { | |||
110 | // delete sandbox files in shared memory | 115 | // delete sandbox files in shared memory |
111 | bandwidth_shm_del_file(sandbox_pid); // bandwidth file | 116 | bandwidth_shm_del_file(sandbox_pid); // bandwidth file |
112 | network_shm_del_file(sandbox_pid); // network map file | 117 | network_shm_del_file(sandbox_pid); // network map file |
118 | delete_name_file(sandbox_pid); | ||
113 | 119 | ||
114 | exit(rv); | 120 | exit(rv); |
115 | } | 121 | } |
@@ -122,38 +128,6 @@ static void my_handler(int s){ | |||
122 | myexit(1); | 128 | myexit(1); |
123 | } | 129 | } |
124 | 130 | ||
125 | static void extract_user_data(void) { | ||
126 | // check suid | ||
127 | if (geteuid()) { | ||
128 | fprintf(stderr, "Error: the sandbox is not setuid root\n"); | ||
129 | exit(1); | ||
130 | } | ||
131 | |||
132 | struct passwd *pw = getpwuid(getuid()); | ||
133 | if (!pw) | ||
134 | errExit("getpwuid"); | ||
135 | cfg.username = strdup(pw->pw_name); | ||
136 | if (!cfg.username) | ||
137 | errExit("strdup"); | ||
138 | |||
139 | // build home directory name | ||
140 | cfg.homedir = NULL; | ||
141 | if (pw->pw_dir != NULL) { | ||
142 | cfg.homedir = strdup(pw->pw_dir); | ||
143 | if (!cfg.homedir) | ||
144 | errExit("strdup"); | ||
145 | } | ||
146 | else { | ||
147 | fprintf(stderr, "Error: user %s doesn't have a user directory assigned\n", cfg.username); | ||
148 | exit(1); | ||
149 | } | ||
150 | |||
151 | cfg.cwd = getcwd(NULL, 0); | ||
152 | } | ||
153 | |||
154 | |||
155 | |||
156 | |||
157 | static inline Bridge *last_bridge_configured(void) { | 131 | static inline Bridge *last_bridge_configured(void) { |
158 | if (cfg.bridge3.configured) | 132 | if (cfg.bridge3.configured) |
159 | return &cfg.bridge3; | 133 | return &cfg.bridge3; |
@@ -167,8 +141,6 @@ static inline Bridge *last_bridge_configured(void) { | |||
167 | return NULL; | 141 | return NULL; |
168 | } | 142 | } |
169 | 143 | ||
170 | |||
171 | |||
172 | // return 1 if error, 0 if a valid pid was found | 144 | // return 1 if error, 0 if a valid pid was found |
173 | static int read_pid(char *str, pid_t *pid) { | 145 | static int read_pid(char *str, pid_t *pid) { |
174 | char *endptr; | 146 | char *endptr; |
@@ -185,15 +157,43 @@ static int read_pid(char *str, pid_t *pid) { | |||
185 | return 0; | 157 | return 0; |
186 | } | 158 | } |
187 | 159 | ||
188 | static void init_cfg(void) { | 160 | // init configuration |
161 | static void init_cfg(int argc, char **argv) { | ||
162 | EUID_ASSERT(); | ||
189 | memset(&cfg, 0, sizeof(cfg)); | 163 | memset(&cfg, 0, sizeof(cfg)); |
190 | 164 | ||
165 | cfg.original_argv = argv; | ||
166 | cfg.original_argc = argc; | ||
191 | cfg.bridge0.devsandbox = "eth0"; | 167 | cfg.bridge0.devsandbox = "eth0"; |
192 | cfg.bridge1.devsandbox = "eth1"; | 168 | cfg.bridge1.devsandbox = "eth1"; |
193 | cfg.bridge2.devsandbox = "eth2"; | 169 | cfg.bridge2.devsandbox = "eth2"; |
194 | cfg.bridge3.devsandbox = "eth3"; | 170 | cfg.bridge3.devsandbox = "eth3"; |
195 | 171 | ||
196 | 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); | ||
197 | } | 197 | } |
198 | 198 | ||
199 | static void check_network(Bridge *br) { | 199 | static void check_network(Bridge *br) { |
@@ -211,6 +211,7 @@ static void check_network(Bridge *br) { | |||
211 | 211 | ||
212 | #ifdef HAVE_USERNS | 212 | #ifdef HAVE_USERNS |
213 | void check_user_namespace(void) { | 213 | void check_user_namespace(void) { |
214 | EUID_ASSERT(); | ||
214 | if (getuid() == 0) { | 215 | if (getuid() == 0) { |
215 | 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"); |
216 | exit(1); | 217 | exit(1); |
@@ -233,6 +234,8 @@ void check_user_namespace(void) { | |||
233 | 234 | ||
234 | // exit commands | 235 | // exit commands |
235 | static void run_cmd_and_exit(int i, int argc, char **argv) { | 236 | static void run_cmd_and_exit(int i, int argc, char **argv) { |
237 | EUID_ASSERT(); | ||
238 | |||
236 | //************************************* | 239 | //************************************* |
237 | // basic arguments | 240 | // basic arguments |
238 | //************************************* | 241 | //************************************* |
@@ -315,6 +318,7 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
315 | 318 | ||
316 | // extract pid or sandbox name | 319 | // extract pid or sandbox name |
317 | pid_t pid; | 320 | pid_t pid; |
321 | EUID_ROOT(); | ||
318 | if (read_pid(argv[i] + 12, &pid) == 0) | 322 | if (read_pid(argv[i] + 12, &pid) == 0) |
319 | bandwidth_pid(pid, cmd, dev, down, up); | 323 | bandwidth_pid(pid, cmd, dev, down, up); |
320 | else | 324 | else |
@@ -465,6 +469,36 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
465 | 469 | ||
466 | } | 470 | } |
467 | 471 | ||
472 | static void set_name_file(uid_t pid) { | ||
473 | char *fname; | ||
474 | if (asprintf(&fname, "%s/%d", RUN_FIREJAIL_NAME_DIR, pid) == -1) | ||
475 | errExit("asprintf"); | ||
476 | |||
477 | // the file is deleted first | ||
478 | FILE *fp = fopen(fname, "w"); | ||
479 | if (!fp) { | ||
480 | fprintf(stderr, "Error: cannot create %s\n", fname); | ||
481 | exit(1); | ||
482 | } | ||
483 | fprintf(fp, "%s\n", cfg.name); | ||
484 | fclose(fp); | ||
485 | |||
486 | // mode and ownership | ||
487 | if (chown(fname, 0, 0) == -1) | ||
488 | errExit("chown"); | ||
489 | if (chmod(fname, 0644) == -1) | ||
490 | errExit("chmod"); | ||
491 | |||
492 | } | ||
493 | |||
494 | static void delete_name_file(uid_t pid) { | ||
495 | char *fname; | ||
496 | if (asprintf(&fname, "%s/%d", RUN_FIREJAIL_NAME_DIR, pid) == -1) | ||
497 | errExit("asprintf"); | ||
498 | int rv = unlink(fname); | ||
499 | (void) rv; | ||
500 | } | ||
501 | |||
468 | //******************************************* | 502 | //******************************************* |
469 | // Main program | 503 | // Main program |
470 | //******************************************* | 504 | //******************************************* |
@@ -481,11 +515,15 @@ int main(int argc, char **argv) { | |||
481 | int highest_errno = errno_highest_nr(); | 515 | int highest_errno = errno_highest_nr(); |
482 | #endif | 516 | #endif |
483 | 517 | ||
518 | |||
519 | // drop permissions by default and rise them when required | ||
520 | EUID_INIT(); | ||
521 | EUID_USER(); | ||
522 | |||
484 | // check argv[0] symlink wrapper if this is not a login shell | 523 | // check argv[0] symlink wrapper if this is not a login shell |
485 | if (*argv[0] != '-') | 524 | if (*argv[0] != '-') |
486 | run_symlink(argc, argv); | 525 | run_symlink(argc, argv); |
487 | 526 | ||
488 | |||
489 | // check if we already have a sandbox running | 527 | // check if we already have a sandbox running |
490 | int rv = check_kernel_procs(); | 528 | int rv = check_kernel_procs(); |
491 | if (rv == 0) { | 529 | if (rv == 0) { |
@@ -506,21 +544,26 @@ int main(int argc, char **argv) { | |||
506 | } | 544 | } |
507 | } | 545 | } |
508 | 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 | |||
509 | // initialize globals | 555 | // initialize globals |
510 | init_cfg(); | 556 | init_cfg(argc, argv); |
511 | cfg.original_argv = argv; | ||
512 | cfg.original_argc = argc; | ||
513 | 557 | ||
514 | // initialize random number generator | ||
515 | sandbox_pid = getpid(); | ||
516 | time_t t = time(NULL); | ||
517 | srand(t ^ sandbox_pid); | ||
518 | 558 | ||
519 | // check firejail directories | 559 | // check firejail directories |
560 | EUID_ROOT(); | ||
520 | fs_build_firejail_dir(); | 561 | fs_build_firejail_dir(); |
562 | // todo: deprecate shm functions | ||
521 | shm_create_firejail_dir(); | 563 | shm_create_firejail_dir(); |
522 | bandwidth_shm_del_file(sandbox_pid); | 564 | bandwidth_shm_del_file(sandbox_pid); |
523 | 565 | EUID_USER(); | |
566 | |||
524 | // is this a login shell? | 567 | // is this a login shell? |
525 | if (*argv[0] == '-') { | 568 | if (*argv[0] == '-') { |
526 | fullargc = restricted_shell(cfg.username); | 569 | fullargc = restricted_shell(cfg.username); |
@@ -1449,6 +1492,7 @@ int main(int argc, char **argv) { | |||
1449 | 1492 | ||
1450 | // check and assign an IP address - for macvlan it will be done again in the sandbox! | 1493 | // check and assign an IP address - for macvlan it will be done again in the sandbox! |
1451 | if (any_bridge_configured()) { | 1494 | if (any_bridge_configured()) { |
1495 | EUID_ROOT(); | ||
1452 | lockfd = open(RUN_NETWORK_LOCK_FILE, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); | 1496 | lockfd = open(RUN_NETWORK_LOCK_FILE, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); |
1453 | if (lockfd != -1) { | 1497 | if (lockfd != -1) { |
1454 | int rv = fchown(lockfd, 0, 0); | 1498 | int rv = fchown(lockfd, 0, 0); |
@@ -1463,6 +1507,7 @@ int main(int argc, char **argv) { | |||
1463 | 1507 | ||
1464 | // save network mapping in shared memory | 1508 | // save network mapping in shared memory |
1465 | network_shm_set_file(sandbox_pid); | 1509 | network_shm_set_file(sandbox_pid); |
1510 | EUID_USER(); | ||
1466 | } | 1511 | } |
1467 | 1512 | ||
1468 | // create the parent-child communication pipe | 1513 | // create the parent-child communication pipe |
@@ -1480,6 +1525,13 @@ int main(int argc, char **argv) { | |||
1480 | arg_noroot = 0; | 1525 | arg_noroot = 0; |
1481 | } | 1526 | } |
1482 | 1527 | ||
1528 | |||
1529 | // set name file | ||
1530 | EUID_ROOT(); | ||
1531 | if (cfg.name) | ||
1532 | set_name_file(sandbox_pid); | ||
1533 | EUID_USER(); | ||
1534 | |||
1483 | // clone environment | 1535 | // clone environment |
1484 | int flags = CLONE_NEWNS | CLONE_NEWPID | CLONE_NEWUTS | SIGCHLD; | 1536 | int flags = CLONE_NEWNS | CLONE_NEWPID | CLONE_NEWUTS | SIGCHLD; |
1485 | 1537 | ||
@@ -1494,12 +1546,14 @@ int main(int argc, char **argv) { | |||
1494 | else if (arg_debug) | 1546 | else if (arg_debug) |
1495 | printf("Using the local network stack\n"); | 1547 | printf("Using the local network stack\n"); |
1496 | 1548 | ||
1549 | EUID_ROOT(); | ||
1497 | child = clone(sandbox, | 1550 | child = clone(sandbox, |
1498 | child_stack + STACK_SIZE, | 1551 | child_stack + STACK_SIZE, |
1499 | flags, | 1552 | flags, |
1500 | NULL); | 1553 | NULL); |
1501 | if (child == -1) | 1554 | if (child == -1) |
1502 | errExit("clone"); | 1555 | errExit("clone"); |
1556 | EUID_USER(); | ||
1503 | 1557 | ||
1504 | if (!arg_command && !arg_quiet) { | 1558 | if (!arg_command && !arg_quiet) { |
1505 | printf("Parent pid %u, child pid %u\n", sandbox_pid, child); | 1559 | printf("Parent pid %u, child pid %u\n", sandbox_pid, child); |
@@ -1508,7 +1562,8 @@ int main(int argc, char **argv) { | |||
1508 | printf("The new log directory is /proc/%d/root/var/log\n", child); | 1562 | printf("The new log directory is /proc/%d/root/var/log\n", child); |
1509 | } | 1563 | } |
1510 | 1564 | ||
1511 | 1565 | ||
1566 | EUID_ROOT(); | ||
1512 | if (!arg_nonetwork) { | 1567 | if (!arg_nonetwork) { |
1513 | // create veth pair or macvlan device | 1568 | // create veth pair or macvlan device |
1514 | if (cfg.bridge0.configured) { | 1569 | if (cfg.bridge0.configured) { |
@@ -1554,6 +1609,7 @@ int main(int argc, char **argv) { | |||
1554 | net_move_interface(cfg.interface3.dev, child); | 1609 | net_move_interface(cfg.interface3.dev, child); |
1555 | } | 1610 | } |
1556 | } | 1611 | } |
1612 | EUID_USER(); | ||
1557 | 1613 | ||
1558 | // close each end of the unused pipes | 1614 | // close each end of the unused pipes |
1559 | close(parent_to_child_fds[0]); | 1615 | close(parent_to_child_fds[0]); |
@@ -1576,7 +1632,9 @@ int main(int argc, char **argv) { | |||
1576 | uid_t uid = getuid(); | 1632 | uid_t uid = getuid(); |
1577 | if (asprintf(&map, "%d %d 1", uid, uid) == -1) | 1633 | if (asprintf(&map, "%d %d 1", uid, uid) == -1) |
1578 | errExit("asprintf"); | 1634 | errExit("asprintf"); |
1635 | EUID_ROOT(); | ||
1579 | update_map(map, map_path); | 1636 | update_map(map, map_path); |
1637 | EUID_USER(); | ||
1580 | free(map); | 1638 | free(map); |
1581 | free(map_path); | 1639 | free(map_path); |
1582 | 1640 | ||
@@ -1586,7 +1644,9 @@ int main(int argc, char **argv) { | |||
1586 | gid_t gid = getgid(); | 1644 | gid_t gid = getgid(); |
1587 | if (asprintf(&map, "%d %d 1", gid, gid) == -1) | 1645 | if (asprintf(&map, "%d %d 1", gid, gid) == -1) |
1588 | errExit("asprintf"); | 1646 | errExit("asprintf"); |
1647 | EUID_ROOT(); | ||
1589 | update_map(map, map_path); | 1648 | update_map(map, map_path); |
1649 | EUID_USER(); | ||
1590 | free(map); | 1650 | free(map); |
1591 | free(map_path); | 1651 | free(map_path); |
1592 | } | 1652 | } |
@@ -1595,9 +1655,13 @@ int main(int argc, char **argv) { | |||
1595 | notify_other(parent_to_child_fds[1]); | 1655 | notify_other(parent_to_child_fds[1]); |
1596 | close(parent_to_child_fds[1]); | 1656 | close(parent_to_child_fds[1]); |
1597 | 1657 | ||
1658 | EUID_ROOT(); | ||
1598 | if (lockfd != -1) | 1659 | if (lockfd != -1) |
1599 | flock(lockfd, LOCK_UN); | 1660 | flock(lockfd, LOCK_UN); |
1600 | 1661 | ||
1662 | // create name file under /run/firejail | ||
1663 | |||
1664 | |||
1601 | // handle CTRL-C in parent | 1665 | // handle CTRL-C in parent |
1602 | signal (SIGINT, my_handler); | 1666 | signal (SIGINT, my_handler); |
1603 | signal (SIGTERM, my_handler); | 1667 | signal (SIGTERM, my_handler); |
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 | ||
46 | void check_netfilter_file(const char *fname) { | 46 | void 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 | ||
167 | void net_check_cfg(void) { | 167 | void 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 | ||
225 | void net_dns_print_name(const char *name) { | 226 | void 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 |
240 | void net_dns_print(pid_t pid) { | 242 | void 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 |
28 | int check_kernel_procs(void) { | 28 | int 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 | ||
99 | void run_no_sandbox(int argc, char **argv) { | 101 | void 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 | ||
25 | void check_output(int argc, char **argv) { | 25 | void 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..112454396 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c | |||
@@ -25,6 +25,7 @@ | |||
25 | 25 | ||
26 | // find and read the profile specified by name from dir directory | 26 | // find and read the profile specified by name from dir directory |
27 | int profile_find(const char *name, const char *dir) { | 27 | int profile_find(const char *name, const char *dir) { |
28 | EUID_ASSERT(); | ||
28 | assert(name); | 29 | assert(name); |
29 | assert(dir); | 30 | assert(dir); |
30 | 31 | ||
@@ -66,6 +67,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 | 67 | // 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 | 68 | // return 0 if the command was already executed inside the function |
68 | int profile_check_line(char *ptr, int lineno, const char *fname) { | 69 | int profile_check_line(char *ptr, int lineno, const char *fname) { |
70 | EUID_ASSERT(); | ||
71 | |||
69 | // check ignore list | 72 | // check ignore list |
70 | int i; | 73 | int i; |
71 | for (i = 0; i < MAX_PROFILE_IGNORE; i++) { | 74 | for (i = 0; i < MAX_PROFILE_IGNORE; i++) { |
@@ -458,6 +461,8 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
458 | 461 | ||
459 | // add a profile entry in cfg.profile list; use str to populate the list | 462 | // add a profile entry in cfg.profile list; use str to populate the list |
460 | void profile_add(char *str) { | 463 | void profile_add(char *str) { |
464 | EUID_ASSERT(); | ||
465 | |||
461 | ProfileEntry *prf = malloc(sizeof(ProfileEntry)); | 466 | ProfileEntry *prf = malloc(sizeof(ProfileEntry)); |
462 | if (!prf) | 467 | if (!prf) |
463 | errExit("malloc"); | 468 | errExit("malloc"); |
@@ -479,6 +484,8 @@ void profile_add(char *str) { | |||
479 | // read a profile file | 484 | // read a profile file |
480 | static int include_level = 0; | 485 | static int include_level = 0; |
481 | void profile_read(const char *fname) { | 486 | void profile_read(const char *fname) { |
487 | EUID_ASSERT(); | ||
488 | |||
482 | // exit program if maximum include level was reached | 489 | // exit program if maximum include level was reached |
483 | if (include_level > MAX_INCLUDE_LEVEL) { | 490 | if (include_level > MAX_INCLUDE_LEVEL) { |
484 | fprintf(stderr, "Error: maximum profile include level was reached\n"); | 491 | 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 |
103 | void protocol_list(void) { | 103 | void 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 |
119 | void protocol_store(const char *prlist) { | 121 | void 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 |
310 | void protocol_print_filter_name(const char *name) { | 313 | void 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 |
331 | void protocol_print_filter(pid_t pid) { | 336 | void 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 | ||
26 | int restricted_shell(const char *user) { | 26 | int 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 | ||
25 | void run_symlink(int argc, char **argv) { | 25 | void 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 | ||
802 | void seccomp_print_filter_name(const char *name) { | 802 | void 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 | ||
816 | void seccomp_print_filter(pid_t pid) { | 817 | void 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 | ||
26 | void shut_name(const char *name) { | 26 | void 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 | ||
41 | void shut(pid_t pid) { | 42 | void 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 | ||
105 | void syscall_print(void) { | 105 | void 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 | ||
28 | void check_user(int argc, char **argv) { | 28 | void 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..3463095f9 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c | |||
@@ -258,6 +258,7 @@ int is_link(const char *fname) { | |||
258 | 258 | ||
259 | // remove multiple spaces and return allocated memory | 259 | // remove multiple spaces and return allocated memory |
260 | char *line_remove_spaces(const char *buf) { | 260 | char *line_remove_spaces(const char *buf) { |
261 | EUID_ASSERT(); | ||
261 | assert(buf); | 262 | assert(buf); |
262 | if (strlen(buf) == 0) | 263 | if (strlen(buf) == 0) |
263 | return NULL; | 264 | return NULL; |
@@ -307,6 +308,7 @@ char *line_remove_spaces(const char *buf) { | |||
307 | 308 | ||
308 | 309 | ||
309 | char *split_comma(char *str) { | 310 | char *split_comma(char *str) { |
311 | EUID_ASSERT(); | ||
310 | if (str == NULL || *str == '\0') | 312 | if (str == NULL || *str == '\0') |
311 | return NULL; | 313 | return NULL; |
312 | char *ptr = strchr(str, ','); | 314 | char *ptr = strchr(str, ','); |
@@ -321,6 +323,8 @@ char *split_comma(char *str) { | |||
321 | 323 | ||
322 | 324 | ||
323 | int not_unsigned(const char *str) { | 325 | int not_unsigned(const char *str) { |
326 | EUID_ASSERT(); | ||
327 | |||
324 | int rv = 0; | 328 | int rv = 0; |
325 | const char *ptr = str; | 329 | const char *ptr = str; |
326 | while (*ptr != ' ' && *ptr != '\t' && *ptr != '\0') { | 330 | while (*ptr != ' ' && *ptr != '\t' && *ptr != '\0') { |
@@ -338,6 +342,7 @@ int not_unsigned(const char *str) { | |||
338 | #define BUFLEN 4096 | 342 | #define BUFLEN 4096 |
339 | // find the first child for this parent; return 1 if error | 343 | // find the first child for this parent; return 1 if error |
340 | int find_child(pid_t parent, pid_t *child) { | 344 | int find_child(pid_t parent, pid_t *child) { |
345 | EUID_ASSERT(); | ||
341 | *child = 0; // use it to flag a found child | 346 | *child = 0; // use it to flag a found child |
342 | 347 | ||
343 | DIR *dir; | 348 | DIR *dir; |
@@ -399,6 +404,7 @@ int find_child(pid_t parent, pid_t *child) { | |||
399 | 404 | ||
400 | 405 | ||
401 | void extract_command_name(int index, char **argv) { | 406 | void extract_command_name(int index, char **argv) { |
407 | EUID_ASSERT(); | ||
402 | assert(argv); | 408 | assert(argv); |
403 | assert(argv[index]); | 409 | assert(argv[index]); |
404 | 410 | ||
@@ -527,8 +533,7 @@ void notify_other(int fd) { | |||
527 | // directory (supplied). | 533 | // directory (supplied). |
528 | // The return value is allocated using malloc and must be freed by the caller. | 534 | // The return value is allocated using malloc and must be freed by the caller. |
529 | // The function returns NULL if there are any errors. | 535 | // The function returns NULL if there are any errors. |
530 | char *expand_home(const char *path, const char* homedir) | 536 | char *expand_home(const char *path, const char* homedir) { |
531 | { | ||
532 | assert(path); | 537 | assert(path); |
533 | assert(homedir); | 538 | assert(homedir); |
534 | 539 | ||
@@ -551,8 +556,7 @@ char *expand_home(const char *path, const char* homedir) | |||
551 | // Equivalent to the GNU version of basename, which is incompatible with | 556 | // Equivalent to the GNU version of basename, which is incompatible with |
552 | // the POSIX basename. A few lines of code saves any portability pain. | 557 | // the POSIX basename. A few lines of code saves any portability pain. |
553 | // https://www.gnu.org/software/libc/manual/html_node/Finding-Tokens-in-a-String.html#index-basename | 558 | // https://www.gnu.org/software/libc/manual/html_node/Finding-Tokens-in-a-String.html#index-basename |
554 | const char *gnu_basename(const char *path) | 559 | const char *gnu_basename(const char *path) { |
555 | { | ||
556 | const char *last_slash = strrchr(path, '/'); | 560 | const char *last_slash = strrchr(path, '/'); |
557 | if (!last_slash) | 561 | if (!last_slash) |
558 | return path; | 562 | return path; |
@@ -560,6 +564,7 @@ const char *gnu_basename(const char *path) | |||
560 | } | 564 | } |
561 | 565 | ||
562 | uid_t pid_get_uid(pid_t pid) { | 566 | uid_t pid_get_uid(pid_t pid) { |
567 | EUID_ASSERT(); | ||
563 | uid_t rv = 0; | 568 | uid_t rv = 0; |
564 | 569 | ||
565 | // open status file | 570 | // open status file |
@@ -603,6 +608,7 @@ uid_t pid_get_uid(pid_t pid) { | |||
603 | } | 608 | } |
604 | 609 | ||
605 | void invalid_filename(const char *fname) { | 610 | void invalid_filename(const char *fname) { |
611 | EUID_ASSERT(); | ||
606 | assert(fname); | 612 | assert(fname); |
607 | const char *ptr = fname; | 613 | const char *ptr = fname; |
608 | 614 | ||
diff --git a/src/include/euid_common.h b/src/include/euid_common.h new file mode 100644 index 000000000..f07cf2868 --- /dev/null +++ b/src/include/euid_common.h | |||
@@ -0,0 +1,55 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014-2016 netblue30 (netblue30@yahoo.com) | ||
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 EUID_COMMON_H | ||
22 | #define EUID_COMMON_H | ||
23 | #include <stdio.h> | ||
24 | #include <sys/types.h> | ||
25 | #include <unistd.h> | ||
26 | #include <assert.h> | ||
27 | |||
28 | #define EUID_ASSERT() { \ | ||
29 | if (getuid() != 0) \ | ||
30 | assert(geteuid() != 0); \ | ||
31 | } | ||
32 | |||
33 | extern uid_t firejail_uid; | ||
34 | |||
35 | |||
36 | |||
37 | static inline void EUID_ROOT(void) { | ||
38 | if (seteuid(0) == -1) | ||
39 | fprintf(stderr, "Error: cannot switch euid to root\n"); | ||
40 | } | ||
41 | |||
42 | static inline void EUID_USER(void) { | ||
43 | if (seteuid(firejail_uid) == -1) | ||
44 | fprintf(stderr, "Error: cannot switch euid to user\n"); | ||
45 | } | ||
46 | |||
47 | static inline void EUID_PRINT(void) { | ||
48 | printf("debug: uid %d, euid %d\n", getuid(), geteuid()); | ||
49 | } | ||
50 | |||
51 | static inline void EUID_INIT(void) { | ||
52 | firejail_uid = getuid(); | ||
53 | } | ||
54 | |||
55 | #endif | ||
diff --git a/src/lib/common.c b/src/lib/common.c index d23cd589e..f321c5a47 100644 --- a/src/lib/common.c +++ b/src/lib/common.c | |||
@@ -58,6 +58,7 @@ int join_namespace(pid_t pid, char *type) { | |||
58 | } | 58 | } |
59 | 59 | ||
60 | // return 1 if error | 60 | // return 1 if error |
61 | // this function requires root access - todo: fix it! | ||
61 | int name2pid(const char *name, pid_t *pid) { | 62 | int name2pid(const char *name, pid_t *pid) { |
62 | pid_t parent = getpid(); | 63 | pid_t parent = getpid(); |
63 | 64 | ||
@@ -94,53 +95,34 @@ int name2pid(const char *name, pid_t *pid) { | |||
94 | free(comm); | 95 | free(comm); |
95 | } | 96 | } |
96 | 97 | ||
97 | char *cmd = pid_proc_cmdline(newpid); | 98 | // look for the sandbox name in /run/firejail/name/<PID> |
98 | if (cmd) { | 99 | // todo: use RUN_FIREJAIL_NAME_DIR define from src/firejail/firejail.h |
99 | // mark the end of the name | 100 | char *fname; |
100 | char *ptr = strstr(cmd, "--name="); | 101 | if (asprintf(&fname, "/run/firejail/name/%d", newpid) == -1) |
101 | char *start = ptr; | 102 | errExit("asprintf"); |
102 | if (!ptr) { | 103 | FILE *fp = fopen(fname, "r"); |
103 | free(cmd); | 104 | if (fp) { |
104 | 105 | char buf[BUFLEN]; | |
105 | // extract name for /run/mnt/firejail/fslogger file | 106 | if (fgets(buf, BUFLEN, fp)) { |
106 | char *fname; | 107 | // remove \n |
107 | if (asprintf(&fname, "/proc/%d/root/run/firejail/mnt/fslogger", newpid) == -1) | 108 | char *ptr = strchr(buf, '\n'); |
108 | errExit("asprintf"); | 109 | if (ptr) { |
109 | 110 | *ptr = '\0'; | |
110 | struct stat s; | 111 | if (strcmp(buf, name) == 0) { |
111 | if (stat(fname, &s) == 0) { | 112 | // we found it! |
112 | FILE *fp = fopen(fname, "r"); | ||
113 | if (fp) { | ||
114 | char buf[BUFLEN]; | ||
115 | if (fgets(buf, BUFLEN, fp)) { | ||
116 | if (strncmp(buf, "sandbox name: ", 14) == 0) { | ||
117 | char *ptr2 = buf + 14; | ||
118 | if (strncmp(name, ptr2, strlen(name)) == 0) { | ||
119 | fclose(fp); | ||
120 | *pid = newpid; | ||
121 | closedir(dir); | ||
122 | return 0; | ||
123 | } | ||
124 | } | ||
125 | } | ||
126 | fclose(fp); | 113 | fclose(fp); |
114 | free(fname); | ||
115 | *pid = newpid; | ||
116 | closedir(dir); | ||
117 | return 0; | ||
127 | } | 118 | } |
128 | } | 119 | } |
129 | 120 | else | |
130 | continue; | 121 | fprintf(stderr, "Error: invalid %s\n", fname); |
131 | } | 122 | } |
132 | while (*ptr != ' ' && *ptr != '\t' && *ptr != '\0') | 123 | fclose(fp); |
133 | ptr++; | ||
134 | *ptr = '\0'; | ||
135 | int rv = strcmp(start + 7, name); | ||
136 | if (rv == 0) { | ||
137 | free(cmd); | ||
138 | *pid = newpid; | ||
139 | closedir(dir); | ||
140 | return 0; | ||
141 | } | ||
142 | free(cmd); | ||
143 | } | 124 | } |
125 | free(fname); | ||
144 | } | 126 | } |
145 | closedir(dir); | 127 | closedir(dir); |
146 | return 1; | 128 | return 1; |
diff --git a/test/env.exp b/test/env.exp index d2edb0477..d7aee3c64 100755 --- a/test/env.exp +++ b/test/env.exp | |||
@@ -12,17 +12,17 @@ expect { | |||
12 | } | 12 | } |
13 | sleep 1 | 13 | sleep 1 |
14 | 14 | ||
15 | send -- "env | grep ENV\r" | 15 | send -- "env | grep ENV1\r" |
16 | expect { | 16 | expect { |
17 | timeout {puts "TESTING ERROR 1\n";exit} | 17 | timeout {puts "TESTING ERROR 1\n";exit} |
18 | "ENV1" | 18 | "ENV1" |
19 | } | 19 | } |
20 | send -- "env | grep ENV\r" | 20 | send -- "env | grep ENV2\r" |
21 | expect { | 21 | expect { |
22 | timeout {puts "TESTING ERROR 2\n";exit} | 22 | timeout {puts "TESTING ERROR 2\n";exit} |
23 | "ENV2" | 23 | "ENV2" |
24 | } | 24 | } |
25 | send -- "env | grep ENV\r" | 25 | send -- "env | grep ENV3\r" |
26 | expect { | 26 | expect { |
27 | timeout {puts "TESTING ERROR 3\n";exit} | 27 | timeout {puts "TESTING ERROR 3\n";exit} |
28 | "ENV3" | 28 | "ENV3" |
@@ -52,4 +52,4 @@ expect { | |||
52 | "Werror" | 52 | "Werror" |
53 | } | 53 | } |
54 | 54 | ||
55 | puts "\n" | 55 | puts "\nall done\n" |
diff --git a/test/features/3.11.exp b/test/features/3.11.exp new file mode 100755 index 000000000..3a5e38257 --- /dev/null +++ b/test/features/3.11.exp | |||
@@ -0,0 +1,171 @@ | |||
1 | #!/usr/bin/expect -f | ||
2 | # | ||
3 | # mkdir | ||
4 | # | ||
5 | |||
6 | set timeout 10 | ||
7 | spawn $env(SHELL) | ||
8 | match_max 100000 | ||
9 | set overlay [lindex $argv 0] | ||
10 | set chroot [lindex $argv 1] | ||
11 | |||
12 | # | ||
13 | # N | ||
14 | # | ||
15 | send -- "rm -fr ~/firejail-xy76_u9\r" | ||
16 | sleep 1 | ||
17 | |||
18 | send -- "firejail --profile=3.11.profile\r" | ||
19 | expect { | ||
20 | timeout {puts "TESTING ERROR 0\n";exit} | ||
21 | "Child process initialized" | ||
22 | } | ||
23 | sleep 1 | ||
24 | |||
25 | send -- "ls -l ~ | grep firejail-xy76_u9\r" | ||
26 | expect { | ||
27 | timeout {puts "TESTING ERROR 1\n";exit} | ||
28 | "drwx------" | ||
29 | } | ||
30 | expect { | ||
31 | timeout {puts "TESTING ERROR 2\n";exit} | ||
32 | "netblue netblue" { puts "Debian\n"} | ||
33 | "netblue users" { puts "Arch\n"} | ||
34 | } | ||
35 | expect { | ||
36 | timeout {puts "TESTING ERROR 3\n";exit} | ||
37 | "firejail-xy76_u9" | ||
38 | } | ||
39 | after 100 | ||
40 | |||
41 | send -- "ls -l ~/firejail-xy76_u9\r" | ||
42 | expect { | ||
43 | timeout {puts "TESTING ERROR 4\n";exit} | ||
44 | "drwx------" | ||
45 | } | ||
46 | expect { | ||
47 | timeout {puts "TESTING ERROR 5\n";exit} | ||
48 | "netblue netblue" { puts "Debian\n"} | ||
49 | "netblue users" { puts "Arch\n"} | ||
50 | } | ||
51 | expect { | ||
52 | timeout {puts "TESTING ERROR 6\n";exit} | ||
53 | "testdir" | ||
54 | } | ||
55 | after 100 | ||
56 | |||
57 | send -- "exit\r" | ||
58 | sleep 1 | ||
59 | send -- "rm -fr ~/firejail-xy76_u9\r" | ||
60 | sleep 1 | ||
61 | |||
62 | # | ||
63 | # O | ||
64 | # | ||
65 | if { $overlay == "overlay" } { | ||
66 | send -- "rm -fr ~/firejail-xy76_u9\r" | ||
67 | sleep 1 | ||
68 | |||
69 | send -- "firejail --profile=3.11.profile\r" | ||
70 | expect { | ||
71 | timeout {puts "TESTING ERROR 10\n";exit} | ||
72 | "Child process initialized" | ||
73 | } | ||
74 | sleep 1 | ||
75 | |||
76 | send -- "ls -l ~ | grep firejail-xy76_u9\r" | ||
77 | expect { | ||
78 | timeout {puts "TESTING ERROR 11\n";exit} | ||
79 | "drwx------" | ||
80 | } | ||
81 | expect { | ||
82 | timeout {puts "TESTING ERROR 12\n";exit} | ||
83 | "netblue netblue" { puts "Debian\n"} | ||
84 | "netblue users" { puts "Arch\n"} | ||
85 | } | ||
86 | expect { | ||
87 | timeout {puts "TESTING ERROR 13\n";exit} | ||
88 | "firejail-xy76_u9" | ||
89 | } | ||
90 | after 100 | ||
91 | |||
92 | send -- "ls -l ~/firejail-xy76_u9\r" | ||
93 | expect { | ||
94 | timeout {puts "TESTING ERROR 14\n";exit} | ||
95 | "drwx------" | ||
96 | } | ||
97 | expect { | ||
98 | timeout {puts "TESTING ERROR 15\n";exit} | ||
99 | "netblue netblue" { puts "Debian\n"} | ||
100 | "netblue users" { puts "Arch\n"} | ||
101 | } | ||
102 | expect { | ||
103 | timeout {puts "TESTING ERROR 16\n";exit} | ||
104 | "testdir" | ||
105 | } | ||
106 | after 100 | ||
107 | |||
108 | send -- "exit\r" | ||
109 | sleep 1 | ||
110 | send -- "rm -fr ~/firejail-xy76_u9\r" | ||
111 | sleep 1 | ||
112 | |||
113 | |||
114 | } | ||
115 | |||
116 | # | ||
117 | # C | ||
118 | # | ||
119 | if { $chroot == "chroot" } { | ||
120 | send -- "rm -fr ~/firejail-xy76_u9\r" | ||
121 | sleep 1 | ||
122 | |||
123 | send -- "firejail --profile=3.11.profile\r" | ||
124 | expect { | ||
125 | timeout {puts "TESTING ERROR 20\n";exit} | ||
126 | "Child process initialized" | ||
127 | } | ||
128 | sleep 1 | ||
129 | |||
130 | send -- "ls -l ~ | grep firejail-xy76_u9\r" | ||
131 | expect { | ||
132 | timeout {puts "TESTING ERROR 21\n";exit} | ||
133 | "drwx------" | ||
134 | } | ||
135 | expect { | ||
136 | timeout {puts "TESTING ERROR 22\n";exit} | ||
137 | "netblue netblue" { puts "Debian\n"} | ||
138 | "netblue users" { puts "Arch\n"} | ||
139 | } | ||
140 | expect { | ||
141 | timeout {puts "TESTING ERROR 23\n";exit} | ||
142 | "firejail-xy76_u9" | ||
143 | } | ||
144 | after 100 | ||
145 | |||
146 | send -- "ls -l ~/firejail-xy76_u9\r" | ||
147 | expect { | ||
148 | timeout {puts "TESTING ERROR 24\n";exit} | ||
149 | "drwx------" | ||
150 | } | ||
151 | expect { | ||
152 | timeout {puts "TESTING ERROR 25\n";exit} | ||
153 | "netblue netblue" { puts "Debian\n"} | ||
154 | "netblue users" { puts "Arch\n"} | ||
155 | } | ||
156 | expect { | ||
157 | timeout {puts "TESTING ERROR 26\n";exit} | ||
158 | "testdir" | ||
159 | } | ||
160 | after 100 | ||
161 | |||
162 | send -- "rm -fr ~/firejail-xy76_u9\r" | ||
163 | sleep 1 | ||
164 | |||
165 | send -- "exit\r" | ||
166 | |||
167 | } | ||
168 | |||
169 | |||
170 | puts "\nall done\n" | ||
171 | |||
diff --git a/test/features/3.11.profile b/test/features/3.11.profile new file mode 100644 index 000000000..144733f8f --- /dev/null +++ b/test/features/3.11.profile | |||
@@ -0,0 +1,2 @@ | |||
1 | mkdir ~/firejail-xy76_u9 | ||
2 | mkdir ~/firejail-xy76_u9/testdir | ||
diff --git a/test/features/3.4.exp b/test/features/3.4.exp index 996312334..3f316af5b 100755 --- a/test/features/3.4.exp +++ b/test/features/3.4.exp | |||
@@ -53,7 +53,7 @@ expect { | |||
53 | ".Xauthority" | 53 | ".Xauthority" |
54 | } | 54 | } |
55 | 55 | ||
56 | send -- "ls -al | grep config\r" | 56 | send -- "ls -al | grep .config\r" |
57 | expect { | 57 | expect { |
58 | timeout {puts "TESTING ERROR 1.8\n";exit} | 58 | timeout {puts "TESTING ERROR 1.8\n";exit} |
59 | "netblue" | 59 | "netblue" |
@@ -117,7 +117,7 @@ if { $overlay == "overlay" } { | |||
117 | ".Xauthority" | 117 | ".Xauthority" |
118 | } | 118 | } |
119 | 119 | ||
120 | send -- "ls -al | grep config\r" | 120 | send -- "ls -al | grep .config\r" |
121 | expect { | 121 | expect { |
122 | timeout {puts "TESTING ERROR 3.8\n";exit} | 122 | timeout {puts "TESTING ERROR 3.8\n";exit} |
123 | "netblue" | 123 | "netblue" |
@@ -181,7 +181,7 @@ if { $chroot == "chroot" } { | |||
181 | ".Xauthority" | 181 | ".Xauthority" |
182 | } | 182 | } |
183 | 183 | ||
184 | send -- "ls -al | grep config\r" | 184 | send -- "ls -al | grep .config\r" |
185 | expect { | 185 | expect { |
186 | timeout {puts "TESTING ERROR 5.8\n";exit} | 186 | timeout {puts "TESTING ERROR 5.8\n";exit} |
187 | "netblue" | 187 | "netblue" |
diff --git a/test/features/3.5.exp b/test/features/3.5.exp index d190ef36f..dfa8fae10 100755 --- a/test/features/3.5.exp +++ b/test/features/3.5.exp | |||
@@ -19,10 +19,11 @@ expect { | |||
19 | } | 19 | } |
20 | sleep 1 | 20 | sleep 1 |
21 | 21 | ||
22 | send -- "ls -al /dev | wc -l\r" | 22 | send -- "ls -l /dev | wc -l\r" |
23 | expect { | 23 | expect { |
24 | timeout {puts "TESTING ERROR 1.1\n";exit} | 24 | timeout {puts "TESTING ERROR 1.1\n";exit} |
25 | "14" | 25 | "12" { puts "Debian\n"} |
26 | "11" { puts "Centos\n"} | ||
26 | } | 27 | } |
27 | 28 | ||
28 | after 100 | 29 | after 100 |
@@ -40,10 +41,10 @@ if { $overlay == "overlay" } { | |||
40 | } | 41 | } |
41 | sleep 1 | 42 | sleep 1 |
42 | 43 | ||
43 | send -- "ls -al /dev | wc -l\r" | 44 | send -- "ls -l /dev | wc -l\r" |
44 | expect { | 45 | expect { |
45 | timeout {puts "TESTING ERROR 3.1\n";exit} | 46 | timeout {puts "TESTING ERROR 3.1\n";exit} |
46 | "13" | 47 | "11" |
47 | } | 48 | } |
48 | 49 | ||
49 | after 100 | 50 | after 100 |
@@ -62,10 +63,10 @@ if { $chroot == "chroot" } { | |||
62 | } | 63 | } |
63 | sleep 1 | 64 | sleep 1 |
64 | 65 | ||
65 | send -- "ls -al /dev | wc -l\r" | 66 | send -- "ls -l /dev | wc -l\r" |
66 | expect { | 67 | expect { |
67 | timeout {puts "TESTING ERROR 5.1\n";exit} | 68 | timeout {puts "TESTING ERROR 5.1\n";exit} |
68 | "13" | 69 | "11" |
69 | } | 70 | } |
70 | 71 | ||
71 | after 100 | 72 | after 100 |
diff --git a/test/features/3.9.exp b/test/features/3.9.exp index 1dc556d78..a1797804f 100755 --- a/test/features/3.9.exp +++ b/test/features/3.9.exp | |||
@@ -12,7 +12,7 @@ set chroot [lindex $argv 1] | |||
12 | # | 12 | # |
13 | # N | 13 | # N |
14 | # | 14 | # |
15 | send -- "firejail --noprofile --whitelist=/dev/tty --whitelist=/dev/shm --whitelist=/dev/null\r" | 15 | send -- "firejail --noprofile --whitelist=/dev/tty --whitelist=/dev/null\r" |
16 | expect { | 16 | expect { |
17 | timeout {puts "TESTING ERROR 0\n";exit} | 17 | timeout {puts "TESTING ERROR 0\n";exit} |
18 | "Child process initialized" | 18 | "Child process initialized" |
@@ -22,7 +22,7 @@ sleep 1 | |||
22 | send -- "ls -l /dev | wc -l\r" | 22 | send -- "ls -l /dev | wc -l\r" |
23 | expect { | 23 | expect { |
24 | timeout {puts "TESTING ERROR 1.1\n";exit} | 24 | timeout {puts "TESTING ERROR 1.1\n";exit} |
25 | "4" | 25 | "3" |
26 | } | 26 | } |
27 | 27 | ||
28 | 28 | ||
@@ -35,7 +35,7 @@ sleep 1 | |||
35 | # O | 35 | # O |
36 | # | 36 | # |
37 | if { $overlay == "overlay" } { | 37 | if { $overlay == "overlay" } { |
38 | send -- "firejail --noprofile --overlay --whitelist=/dev/tty --whitelist=/dev/shm --whitelist=/dev/null\r" | 38 | send -- "firejail --noprofile --overlay --whitelist=/dev/tty --whitelist=/dev/null\r" |
39 | expect { | 39 | expect { |
40 | timeout {puts "TESTING ERROR 2\n";exit} | 40 | timeout {puts "TESTING ERROR 2\n";exit} |
41 | "Child process initialized" | 41 | "Child process initialized" |
@@ -45,7 +45,7 @@ if { $overlay == "overlay" } { | |||
45 | send -- "ls -l /dev | wc -l\r" | 45 | send -- "ls -l /dev | wc -l\r" |
46 | expect { | 46 | expect { |
47 | timeout {puts "TESTING ERROR 3.1\n";exit} | 47 | timeout {puts "TESTING ERROR 3.1\n";exit} |
48 | "4" | 48 | "3" |
49 | } | 49 | } |
50 | 50 | ||
51 | 51 | ||
@@ -58,7 +58,7 @@ if { $overlay == "overlay" } { | |||
58 | # C | 58 | # C |
59 | # | 59 | # |
60 | if { $chroot == "chroot" } { | 60 | if { $chroot == "chroot" } { |
61 | send -- "firejail --noprofile --chroot=/tmp/chroot --whitelist=/dev/tty --whitelist=/dev/shm --whitelist=/dev/null\r" | 61 | send -- "firejail --noprofile --chroot=/tmp/chroot --whitelist=/dev/tty --whitelist=/dev/null\r" |
62 | expect { | 62 | expect { |
63 | timeout {puts "TESTING ERROR 4\n";exit} | 63 | timeout {puts "TESTING ERROR 4\n";exit} |
64 | "Child process initialized" | 64 | "Child process initialized" |
@@ -68,7 +68,7 @@ if { $chroot == "chroot" } { | |||
68 | send -- "ls -l /dev | wc -l\r" | 68 | send -- "ls -l /dev | wc -l\r" |
69 | expect { | 69 | expect { |
70 | timeout {puts "TESTING ERROR 5.1\n";exit} | 70 | timeout {puts "TESTING ERROR 5.1\n";exit} |
71 | "4" | 71 | "3" |
72 | } | 72 | } |
73 | 73 | ||
74 | after 100 | 74 | after 100 |
diff --git a/test/features/features.txt b/test/features/features.txt index 4d8821a92..283e85d93 100644 --- a/test/features/features.txt +++ b/test/features/features.txt | |||
@@ -25,6 +25,7 @@ C - chroot filesystem | |||
25 | 1.9 mount namespace | 25 | 1.9 mount namespace |
26 | 1.10 disable /selinux | 26 | 1.10 disable /selinux |
27 | 27 | ||
28 | |||
28 | 2. Networking features | 29 | 2. Networking features |
29 | 30 | ||
30 | 2.1 Hostname (use --hostname=newhostname, do a ping and cat /etc/hostname) | 31 | 2.1 Hostname (use --hostname=newhostname, do a ping and cat /etc/hostname) |
@@ -37,6 +38,7 @@ C - chroot filesystem | |||
37 | 2.5 interface | 38 | 2.5 interface |
38 | 2.6 Default gw (--noprofile --net=eth0 --defaultgw=192.168.1.10, run netstat -rn) | 39 | 2.6 Default gw (--noprofile --net=eth0 --defaultgw=192.168.1.10, run netstat -rn) |
39 | 40 | ||
41 | |||
40 | 3. Filesystem features (use --noprofile) | 42 | 3. Filesystem features (use --noprofile) |
41 | 43 | ||
42 | 3.1 private | 44 | 3.1 private |
@@ -56,6 +58,7 @@ C - chroot filesystem | |||
56 | - N not working on Debian wheezy (32-bit and 64-bit) - todo | 58 | - N not working on Debian wheezy (32-bit and 64-bit) - todo |
57 | 3.10 whitelist tmp | 59 | 3.10 whitelist tmp |
58 | - O not working on Arch Linux - todo | 60 | - O not working on Arch Linux - todo |
61 | 3.11 mkdir | ||
59 | 62 | ||
60 | 63 | ||
61 | 64 | ||
diff --git a/test/features/test.sh b/test/features/test.sh index 495996551..3570dae5a 100755 --- a/test/features/test.sh +++ b/test/features/test.sh | |||
@@ -83,7 +83,7 @@ fi | |||
83 | #################### | 83 | #################### |
84 | # filesystem features | 84 | # filesystem features |
85 | #################### | 85 | #################### |
86 | echo "TESTING: 3.1 private" | 86 | echo "TESTING: 3.1 private (fails on OpenSUSE)" |
87 | ./3.1.exp $OVERLAY $CHROOT | 87 | ./3.1.exp $OVERLAY $CHROOT |
88 | 88 | ||
89 | echo "TESTING: 3.2 read-only" | 89 | echo "TESTING: 3.2 read-only" |
@@ -92,7 +92,7 @@ echo "TESTING: 3.2 read-only" | |||
92 | echo "TESTING: 3.3 blacklist" | 92 | echo "TESTING: 3.3 blacklist" |
93 | ./3.3.exp $OVERLAY $CHROOT | 93 | ./3.3.exp $OVERLAY $CHROOT |
94 | 94 | ||
95 | echo "TESTING: 3.4 whitelist home" | 95 | echo "TESTING: 3.4 whitelist home (fails on OpenSUSE)" |
96 | ./3.4.exp $OVERLAY $CHROOT | 96 | ./3.4.exp $OVERLAY $CHROOT |
97 | 97 | ||
98 | echo "TESTING: 3.5 private-dev" | 98 | echo "TESTING: 3.5 private-dev" |
@@ -113,3 +113,6 @@ echo "TESTING: 3.9 whitelist dev" | |||
113 | echo "TESTING: 3.10 whitelist tmp" | 113 | echo "TESTING: 3.10 whitelist tmp" |
114 | ./3.10.exp $OVERLAY $CHROOT | 114 | ./3.10.exp $OVERLAY $CHROOT |
115 | 115 | ||
116 | echo "TESTING: 3.11 mkdir" | ||
117 | ./3.11.exp $OVERLAY $CHROOT | ||
118 | |||
diff --git a/test/ip6.exp b/test/ip6.exp index 19a822ee2..fba47d095 100755 --- a/test/ip6.exp +++ b/test/ip6.exp | |||
@@ -4,7 +4,7 @@ set timeout 10 | |||
4 | spawn $env(SHELL) | 4 | spawn $env(SHELL) |
5 | match_max 100000 | 5 | match_max 100000 |
6 | 6 | ||
7 | send -- "firejail --debug --noprofile --net=eth0 --ip6=2001:0db8:0:f101::1/64 --netfilter6=ipv6.net\r" | 7 | send -- "firejail --debug --noprofile --net=br0 --ip6=2001:0db8:0:f101::1/64 --netfilter6=ipv6.net\r" |
8 | expect { | 8 | expect { |
9 | timeout {puts "TESTING ERROR 0\n";exit} | 9 | timeout {puts "TESTING ERROR 0\n";exit} |
10 | "Installing network filter" | 10 | "Installing network filter" |
@@ -26,15 +26,16 @@ sleep 2 | |||
26 | send -- "/sbin/ifconfig\r" | 26 | send -- "/sbin/ifconfig\r" |
27 | expect { | 27 | expect { |
28 | timeout {puts "TESTING ERROR 4\n";exit} | 28 | timeout {puts "TESTING ERROR 4\n";exit} |
29 | "inet6 addr" | 29 | "inet6" |
30 | } | 30 | } |
31 | expect { | 31 | expect { |
32 | timeout {puts "TESTING ERROR 5\n";exit} | 32 | timeout {puts "TESTING ERROR 5\n";exit} |
33 | "2001:db8:0:f101::1/64" | 33 | "2001:db8:0:f101::1" |
34 | } | 34 | } |
35 | expect { | 35 | expect { |
36 | timeout {puts "TESTING ERROR 6\n";exit} | 36 | timeout {puts "TESTING ERROR 6\n";exit} |
37 | "Scope:Global" | 37 | "Scope:Global" { puts "Debian\n"} |
38 | "scopeid 0x0<global>" { puts "Arch\n"} | ||
38 | } | 39 | } |
39 | 40 | ||
40 | 41 | ||
diff --git a/test/private-whitelist.exp b/test/private-whitelist.exp index b78eb3b61..f06415c52 100755 --- a/test/private-whitelist.exp +++ b/test/private-whitelist.exp | |||
@@ -18,14 +18,14 @@ expect { | |||
18 | } | 18 | } |
19 | sleep 1 | 19 | sleep 1 |
20 | 20 | ||
21 | send -- "ls -a /tmp | wc\r" | 21 | send -- "ls -a /tmp | wc -l\r" |
22 | expect { | 22 | expect { |
23 | timeout {puts "TESTING ERROR 3\n";exit} | 23 | timeout {puts "TESTING ERROR 3\n";exit} |
24 | "3" | 24 | "3" |
25 | } | 25 | } |
26 | sleep 1 | 26 | sleep 1 |
27 | 27 | ||
28 | send -- "ls -a ~ | wc\r" | 28 | send -- "ls -a ~ | wc -l\r" |
29 | expect { | 29 | expect { |
30 | timeout {puts "TESTING ERROR 4\n";exit} | 30 | timeout {puts "TESTING ERROR 4\n";exit} |
31 | "4" | 31 | "4" |
diff --git a/test/test.sh b/test/test.sh index 923a9b390..93e38edfb 100755 --- a/test/test.sh +++ b/test/test.sh | |||
@@ -6,37 +6,38 @@ | |||
6 | 6 | ||
7 | ./fscheck.sh | 7 | ./fscheck.sh |
8 | 8 | ||
9 | echo "TESTING: nice" | 9 | echo "TESTING: nice (nice.exp)" |
10 | ./nice.exp | 10 | ./nice.exp |
11 | 11 | ||
12 | echo "TESTING: protocol" | 12 | echo "TESTING: protocol (protocol.exp)" |
13 | ./protocol.exp | 13 | ./protocol.exp |
14 | 14 | ||
15 | echo "TESTING: invalid filename" | 15 | echo "TESTING: invalid filename (invalid_filename.exp)" |
16 | ./invalid_filename.exp | 16 | ./invalid_filename.exp |
17 | 17 | ||
18 | echo "TESTING: environment variables" | 18 | echo "TESTING: environment variables (env.exp)" |
19 | ./env.exp | 19 | ./env.exp |
20 | 20 | ||
21 | echo "TESTING: whitelist empty" | 21 | echo "TESTING: whitelist empty (whitelist-empty.exp)" |
22 | ./whitelist-empty.exp | 22 | ./whitelist-empty.exp |
23 | 23 | ||
24 | echo "TESTING: ignore command" | 24 | echo "TESTING: ignore command (ignore.exp)" |
25 | ./ignore.exp | 25 | ./ignore.exp |
26 | 26 | ||
27 | echo "TESTING: private-etc" | 27 | echo "TESTING: private-etc (private-etc.exp)" |
28 | ./private-etc.exp | 28 | ./private-etc.exp |
29 | 29 | ||
30 | echo "TESTING: private-bin" | 30 | echo "TESTING: private-bin (private-bin.exp)" |
31 | ./private-bin.exp | 31 | ./private-bin.exp |
32 | 32 | ||
33 | echo "TESTING: private whitelist" | 33 | echo "TESTING: private whitelist (private-whitelist.exp)" |
34 | echo "TESTING: failing on OpenSUSE" | ||
34 | ./private-whitelist.exp | 35 | ./private-whitelist.exp |
35 | 36 | ||
36 | sleep 1 | 37 | sleep 1 |
37 | rm -fr dir\ with\ space | 38 | rm -fr dir\ with\ space |
38 | mkdir dir\ with\ space | 39 | mkdir dir\ with\ space |
39 | echo "TESTING: blacklist" | 40 | echo "TESTING: blacklist (blacklist.exp)" |
40 | ./blacklist.exp | 41 | ./blacklist.exp |
41 | sleep 1 | 42 | sleep 1 |
42 | rm -fr dir\ with\ space | 43 | rm -fr dir\ with\ space |
@@ -44,31 +45,31 @@ rm -fr dir\ with\ space | |||
44 | ln -s auto auto2 | 45 | ln -s auto auto2 |
45 | ln -s /bin auto3 | 46 | ln -s /bin auto3 |
46 | ln -s /usr/bin auto4 | 47 | ln -s /usr/bin auto4 |
47 | echo "TESTING: blacklist directory link" | 48 | echo "TESTING: blacklist directory link (blacklist-link.exp)" |
48 | ./blacklist-link.exp | 49 | ./blacklist-link.exp |
49 | rm -fr auto2 | 50 | rm -fr auto2 |
50 | rm -fr auto3 | 51 | rm -fr auto3 |
51 | rm -fr auto4 | 52 | rm -fr auto4 |
52 | 53 | ||
53 | 54 | ||
54 | echo "TESTING: version" | 55 | echo "TESTING: version (option_version.exp)" |
55 | ./option_version.exp | 56 | ./option_version.exp |
56 | 57 | ||
57 | echo "TESTING: help" | 58 | echo "TESTING: help (option_help.exp)" |
58 | ./option_help.exp | 59 | ./option_help.exp |
59 | 60 | ||
60 | echo "TESTING: man" | 61 | echo "TESTING: man (opton_man.exp)" |
61 | ./option_man.exp | 62 | ./option_man.exp |
62 | 63 | ||
63 | echo "TESTING: list" | 64 | echo "TESTING: list (option_list.exp)" |
64 | ./option_list.exp | 65 | ./option_list.exp |
65 | 66 | ||
66 | echo "TESTING: tree" | 67 | echo "TESTING: tree (option_tree.exp)" |
67 | ./option_tree.exp | 68 | ./option_tree.exp |
68 | 69 | ||
69 | if [ -f /proc/self/uid_map ]; | 70 | if [ -f /proc/self/uid_map ]; |
70 | then | 71 | then |
71 | echo "TESTING: noroot" | 72 | echo "TESTING: noroot (noroot.exp)" |
72 | ./noroot.exp | 73 | ./noroot.exp |
73 | else | 74 | else |
74 | echo "TESTING: user namespaces not available" | 75 | echo "TESTING: user namespaces not available" |
@@ -81,78 +82,78 @@ cp -- /bin/bash -testdir/. | |||
81 | ./doubledash.exp | 82 | ./doubledash.exp |
82 | rm -fr -- -testdir | 83 | rm -fr -- -testdir |
83 | 84 | ||
84 | echo "TESTING: trace1" | 85 | echo "TESTING: trace1 (option-trace.exp)" |
85 | ./option-trace.exp | 86 | ./option-trace.exp |
86 | 87 | ||
87 | echo "TESTING: trace2" | 88 | echo "TESTING: trace2 (trace.exp)" |
88 | rm -f index.html* | 89 | rm -f index.html* |
89 | ./trace.exp | 90 | ./trace.exp |
90 | rm -f index.html* | 91 | rm -f index.html* |
91 | 92 | ||
92 | echo "TESTING: extract command" | 93 | echo "TESTING: extract command (extract_command.exp)" |
93 | ./extract_command.exp | 94 | ./extract_command.exp |
94 | 95 | ||
95 | echo "TESTING: kmsg access" | 96 | echo "TESTING: kmsg access (kmsg.exp)" |
96 | ./kmsg.exp | 97 | ./kmsg.exp |
97 | 98 | ||
98 | echo "TESTING: rlimit" | 99 | echo "TESTING: rlimit (option_rlimit.exp)" |
99 | ./option_rlimit.exp | 100 | ./option_rlimit.exp |
100 | 101 | ||
101 | echo "TESTING: shutdown" | 102 | echo "TESTING: shutdown (option_shutdown.exp)" |
102 | ./option-shutdown.exp | 103 | ./option-shutdown.exp |
103 | 104 | ||
104 | echo "TESTING: join" | 105 | echo "TESTING: join (opton-join.exp)" |
105 | ./option-join.exp | 106 | ./option-join.exp |
106 | 107 | ||
107 | echo "TESTING: join profile" | 108 | echo "TESTING: join profile (option-join-profile.exp)" |
108 | ./option-join-profile.exp | 109 | ./option-join-profile.exp |
109 | 110 | ||
110 | echo "TESTING: firejail in firejail - single sandbox" | 111 | echo "TESTING: firejail in firejail - single sandbox (firejail-in-firejail.exp)" |
111 | ./firejail-in-firejail.exp | 112 | ./firejail-in-firejail.exp |
112 | 113 | ||
113 | echo "TESTING: firejail in firejail - force new sandbox" | 114 | echo "TESTING: firejail in firejail - force new sandbox (firejail-in-firejail2.exp)" |
114 | ./firejail-in-firejail2.exp | 115 | ./firejail-in-firejail2.exp |
115 | 116 | ||
116 | echo "TESTING: chroot overlay" | 117 | echo "TESTING: chroot overlay (opton_chroot_overlay.exp)" |
117 | ./option_chroot_overlay.exp | 118 | ./option_chroot_overlay.exp |
118 | 119 | ||
119 | echo "TESTING: blacklist directory" | 120 | echo "TESTING: blacklist directory (option_blacklist.exp)" |
120 | ./option_blacklist.exp | 121 | ./option_blacklist.exp |
121 | 122 | ||
122 | echo "TESTING: blacklist file" | 123 | echo "TESTING: blacklist file (opton_blacklist_file.exp)" |
123 | ./option_blacklist_file.exp | 124 | ./option_blacklist_file.exp |
124 | 125 | ||
125 | echo "TESTING: bind as user" | 126 | echo "TESTING: bind as user (option_bind_user.exp)" |
126 | ./option_bind_user.exp | 127 | ./option_bind_user.exp |
127 | 128 | ||
128 | if [ -d /home/bingo ]; | 129 | if [ -d /home/bingo ]; |
129 | then | 130 | then |
130 | echo "TESTING: home sanitize" | 131 | echo "TESTING: home sanitize (opton_version.exp)" |
131 | ./option_version.exp | 132 | ./option_version.exp |
132 | fi | 133 | fi |
133 | 134 | ||
134 | echo "TESTING: chroot as user" | 135 | echo "TESTING: chroot as user (fs_chroot.exp)" |
135 | ./fs_chroot.exp | 136 | ./fs_chroot.exp |
136 | 137 | ||
137 | echo "TESTING: /sys" | 138 | echo "TESTING: /sys (fs_sys.exp)" |
138 | ./fs_sys.exp | 139 | ./fs_sys.exp |
139 | 140 | ||
140 | echo "TESTING: readonly" | 141 | echo "TESTING: readonly (option_readonly.exp)" |
141 | ls -al > tmpreadonly | 142 | ls -al > tmpreadonly |
142 | ./option_readonly.exp | 143 | ./option_readonly.exp |
143 | sleep 5 | 144 | sleep 5 |
144 | rm -f tmpreadonly | 145 | rm -f tmpreadonly |
145 | 146 | ||
146 | echo "TESTING: zsh" | 147 | echo "TESTING: zsh (shell_zsh.exp)" |
147 | ./shell_zsh.exp | 148 | ./shell_zsh.exp |
148 | 149 | ||
149 | echo "TESTING: csh" | 150 | echo "TESTING: csh (shell_csh.exp)" |
150 | ./shell_csh.exp | 151 | ./shell_csh.exp |
151 | 152 | ||
152 | which dash | 153 | which dash |
153 | if [ "$?" -eq 0 ]; | 154 | if [ "$?" -eq 0 ]; |
154 | then | 155 | then |
155 | echo "TESTING: dash" | 156 | echo "TESTING: dash (shell_dash.exp)" |
156 | ./shell_dash.exp | 157 | ./shell_dash.exp |
157 | else | 158 | else |
158 | echo "TESTING: dash not found" | 159 | echo "TESTING: dash not found" |
@@ -160,151 +161,152 @@ fi | |||
160 | 161 | ||
161 | ./test-apps.sh | 162 | ./test-apps.sh |
162 | 163 | ||
163 | echo "TESTING: PID" | 164 | echo "TESTING: PID (pid.exp)" |
164 | ./pid.exp | 165 | ./pid.exp |
165 | 166 | ||
166 | echo "TESTING: output" | 167 | echo "TESTING: output (output.exp)" |
167 | ./output.exp | 168 | ./output.exp |
168 | 169 | ||
169 | echo "TESTING: profile no permissions" | 170 | echo "TESTING: profile no permissions (profile_noperm.exp)" |
170 | ./profile_noperm.exp | 171 | ./profile_noperm.exp |
171 | 172 | ||
172 | echo "TESTING: profile syntax" | 173 | echo "TESTING: profile syntax (profile_syntax.exp)" |
173 | ./profile_syntax.exp | 174 | ./profile_syntax.exp |
174 | 175 | ||
175 | echo "TESTING: profile syntax 2" | 176 | echo "TESTING: profile syntax 2 (profile_syntax2.exp)" |
176 | ./profile_syntax2.exp | 177 | ./profile_syntax2.exp |
177 | 178 | ||
178 | echo "TESTING: profile rlimit" | 179 | echo "TESTING: profile rlimit (profile_rlimit.exp)" |
179 | ./profile_rlimit.exp | 180 | ./profile_rlimit.exp |
180 | 181 | ||
181 | echo "TESTING: profile read-only" | 182 | echo "TESTING: profile read-only (profile_readonly.exp)" |
182 | ./profile_readonly.exp | 183 | ./profile_readonly.exp |
183 | 184 | ||
184 | echo "TESTING: private" | 185 | echo "TESTING: private (private.exp)" |
185 | ./private.exp `whoami` | 186 | ./private.exp `whoami` |
186 | 187 | ||
187 | echo "TESTING: private directory" | 188 | echo "TESTING: private directory (private_dir.exp)" |
188 | rm -fr dirprivate | 189 | rm -fr dirprivate |
189 | mkdir dirprivate | 190 | mkdir dirprivate |
190 | ./private_dir.exp | 191 | ./private_dir.exp |
191 | rm -fr dirprivate | 192 | rm -fr dirprivate |
192 | 193 | ||
193 | echo "TESTING: private directory profile" | 194 | echo "TESTING: private directory profile (private_dir_profile.exp)" |
194 | rm -fr dirprivate | 195 | rm -fr dirprivate |
195 | mkdir dirprivate | 196 | mkdir dirprivate |
196 | ./private_dir_profile.exp | 197 | ./private_dir_profile.exp |
197 | rm -fr dirprivate | 198 | rm -fr dirprivate |
198 | 199 | ||
199 | echo "TESTING: overlayfs" | 200 | echo "TESTING: overlayfs (fs_overlay.exp)" |
200 | ./fs_overlay.exp | 201 | ./fs_overlay.exp |
201 | 202 | ||
202 | echo "TESTING: seccomp debug" | 203 | echo "TESTING: seccomp debug (seccomp-debug.exp)" |
203 | ./seccomp-debug.exp | 204 | ./seccomp-debug.exp |
204 | 205 | ||
205 | echo "TESTING: seccomp errno" | 206 | echo "TESTING: seccomp errno (seccomp-errno.exp)" |
206 | ./seccomp-errno.exp | 207 | ./seccomp-errno.exp |
207 | 208 | ||
208 | echo "TESTING: seccomp su" | 209 | echo "TESTING: seccomp su (seccomp-su.exp)" |
209 | ./seccomp-su.exp | 210 | ./seccomp-su.exp |
210 | 211 | ||
211 | echo "TESTING: seccomp ptrace" | 212 | echo "TESTING: seccomp ptrace (seccomp-ptrace.exp)" |
212 | ./seccomp-ptrace.exp | 213 | ./seccomp-ptrace.exp |
213 | 214 | ||
214 | echo "TESTING: seccomp chmod - seccomp lists" | 215 | echo "TESTING: seccomp chmod - seccomp lists (seccomp-chmod.exp)" |
215 | ./seccomp-chmod.exp | 216 | ./seccomp-chmod.exp |
216 | 217 | ||
217 | echo "TESTING: seccomp chmod profile - seccomp lists" | 218 | echo "TESTING: seccomp chmod profile - seccomp lists (seccomp-chmod-profile.exp)" |
218 | ./seccomp-chmod-profile.exp | 219 | ./seccomp-chmod-profile.exp |
219 | 220 | ||
220 | echo "TESTING: seccomp empty" | 221 | echo "TESTING: seccomp empty (seccomp-empty.exp)" |
221 | ./seccomp-empty.exp | 222 | ./seccomp-empty.exp |
222 | 223 | ||
223 | echo "TESTING: seccomp bad empty" | 224 | echo "TESTING: seccomp bad empty (seccomp-bad-empty.exp)" |
224 | ./seccomp-bad-empty.exp | 225 | ./seccomp-bad-empty.exp |
225 | 226 | ||
226 | echo "TESTING: seccomp dual filter" | 227 | echo "TESTING: seccomp dual filter (seccomp-dualfilter.exp)" |
227 | ./seccomp-dualfilter.exp | 228 | ./seccomp-dualfilter.exp |
228 | 229 | ||
229 | echo "TESTING: read/write /var/tmp" | 230 | echo "TESTING: read/write /var/tmp (fs_var_tmp.exp)" |
230 | ./fs_var_tmp.exp | 231 | ./fs_var_tmp.exp |
231 | 232 | ||
232 | echo "TESTING: read/write /var/lock" | 233 | echo "TESTING: read/write /var/lock (fs_var_lock.exp)" |
233 | ./fs_var_lock.exp | 234 | ./fs_var_lock.exp |
234 | 235 | ||
235 | echo "TESTING: read/write /dev/shm" | 236 | echo "TESTING: read/write /dev/shm (fs_dev_shm.exp)" |
236 | ./fs_dev_shm.exp | 237 | ./fs_dev_shm.exp |
237 | 238 | ||
238 | echo "TESTING: quiet" | 239 | echo "TESTING: quiet (quiet.exp)" |
239 | ./quiet.exp | 240 | ./quiet.exp |
240 | 241 | ||
241 | echo "TESTING: IPv6 support" | 242 | echo "TESTING: IPv6 support (ip6.exp)" |
243 | echo "TESTING: broken on Centos - todo" | ||
242 | ./ip6.exp | 244 | ./ip6.exp |
243 | 245 | ||
244 | echo "TESTING: local network" | 246 | echo "TESTING: local network (net_local.exp)" |
245 | ./net_local.exp | 247 | ./net_local.exp |
246 | 248 | ||
247 | echo "TESTING: no network" | 249 | echo "TESTING: no network (net_none.exp)" |
248 | ./net_none.exp | 250 | ./net_none.exp |
249 | 251 | ||
250 | echo "TESTING: network IP" | 252 | echo "TESTING: network IP (net_ip.exp)" |
251 | ./net_ip.exp | 253 | ./net_ip.exp |
252 | 254 | ||
253 | echo "TESTING: network MAC" | 255 | echo "TESTING: network MAC (net_mac.exp)" |
254 | sleep 2 | 256 | sleep 2 |
255 | ./net_mac.exp | 257 | ./net_mac.exp |
256 | 258 | ||
257 | echo "TESTING: network MTU" | 259 | echo "TESTING: network MTU (net_mtu.exp)" |
258 | ./net_mtu.exp | 260 | ./net_mtu.exp |
259 | 261 | ||
260 | echo "TESTING: network hostname" | 262 | echo "TESTING: network hostname (hostname.exp)" |
261 | ./hostname.exp | 263 | ./hostname.exp |
262 | 264 | ||
263 | echo "TESTING: network bad IP" | 265 | echo "TESTING: network bad IP (net_badip.exp)" |
264 | ./net_badip.exp | 266 | ./net_badip.exp |
265 | 267 | ||
266 | echo "TESTING: network no IP test 1" | 268 | echo "TESTING: network no IP test 1 (net_noip.exp)" |
267 | ./net_noip.exp | 269 | ./net_noip.exp |
268 | 270 | ||
269 | echo "TESTING: network no IP test 2" | 271 | echo "TESTING: network no IP test 2 (net_noip2.exp)" |
270 | ./net_noip2.exp | 272 | ./net_noip2.exp |
271 | 273 | ||
272 | echo "TESTING: network default gateway test 1" | 274 | echo "TESTING: network default gateway test 1 (net_defaultgw.exp)" |
273 | ./net_defaultgw.exp | 275 | ./net_defaultgw.exp |
274 | 276 | ||
275 | echo "TESTING: network default gateway test 2" | 277 | echo "TESTING: network default gateway test 2 (net_defaultgw2.exp)" |
276 | ./net_defaultgw2.exp | 278 | ./net_defaultgw2.exp |
277 | 279 | ||
278 | echo "TESTING: network default gateway test 3" | 280 | echo "TESTING: network default gateway test 3 (net_defaultgw3.exp)" |
279 | ./net_defaultgw3.exp | 281 | ./net_defaultgw3.exp |
280 | 282 | ||
281 | echo "TESTING: netfilter" | 283 | echo "TESTING: netfilter (net_netfilter.exp)" |
282 | ./net_netfilter.exp | 284 | ./net_netfilter.exp |
283 | 285 | ||
284 | echo "TESTING: 4 bridges ARP" | 286 | echo "TESTING: 4 bridges ARP (4bridges_arp.exp)" |
285 | ./4bridges_arp.exp | 287 | ./4bridges_arp.exp |
286 | 288 | ||
287 | echo "TESTING: 4 bridges IP" | 289 | echo "TESTING: 4 bridges IP (4bridges_ip.exp)" |
288 | ./4bridges_ip.exp | 290 | ./4bridges_ip.exp |
289 | 291 | ||
290 | echo "TESTING: login SSH" | 292 | echo "TESTING: login SSH (login_ssh.exp)" |
291 | ./login_ssh.exp | 293 | ./login_ssh.exp |
292 | 294 | ||
293 | echo "TESTING: ARP" | 295 | echo "TESTING: ARP (net_arp.exp)" |
294 | ./net_arp.exp | 296 | ./net_arp.exp |
295 | 297 | ||
296 | echo "TESTING: DNS" | 298 | echo "TESTING: DNS (dns.exp)" |
297 | ./dns.exp | 299 | ./dns.exp |
298 | 300 | ||
299 | echo "TESTING: firemon --arp" | 301 | echo "TESTING: firemon --arp (firemon-arp.exp)" |
300 | ./firemon-arp.exp | 302 | ./firemon-arp.exp |
301 | 303 | ||
302 | echo "TESTING: firemon --route" | 304 | echo "TESTING: firemon --route (firemon-route.exp)" |
303 | ./firemon-route.exp | 305 | ./firemon-route.exp |
304 | 306 | ||
305 | echo "TESTING: firemon --seccomp" | 307 | echo "TESTING: firemon --seccomp (firemon-seccomp.exp)" |
306 | ./firemon-seccomp.exp | 308 | ./firemon-seccomp.exp |
307 | 309 | ||
308 | echo "TESTING: firemon --caps" | 310 | echo "TESTING: firemon --caps (firemon-caps.exp)" |
309 | ./firemon-caps.exp | 311 | ./firemon-caps.exp |
310 | 312 | ||