aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.in6
-rwxr-xr-xgcov.sh8
-rw-r--r--src/firejail/caps.c77
-rw-r--r--src/firejail/firejail.h2
-rw-r--r--src/firejail/fs.c3
-rw-r--r--src/firejail/main.c6
-rw-r--r--src/firejail/profile.c6
-rw-r--r--src/lib/common.c19
-rw-r--r--src/lib/libnetlink.c46
-rw-r--r--src/lib/pid.c34
-rwxr-xr-xsrc/tools/unchrootbin9720 -> 0 bytes
-rw-r--r--src/tools/unchroot.c125
-rwxr-xr-xtest/chroot/chroot-resolvconf.exp14
-rwxr-xr-xtest/chroot/chroot.sh21
-rwxr-xr-xtest/chroot/configure46
-rwxr-xr-xtest/chroot/fs_chroot.exp26
-rwxr-xr-xtest/chroot/unchroot-as-root.exp27
-rw-r--r--test/chroot/unchroot.c40
-rwxr-xr-xtest/environment/dns.exp47
-rwxr-xr-xtest/filters/caps-print.exp103
-rwxr-xr-xtest/filters/caps.exp73
-rw-r--r--test/filters/caps1.profile1
-rw-r--r--test/filters/caps2.profile1
-rw-r--r--test/filters/caps3.profile1
-rwxr-xr-xtest/filters/filters.sh3
-rwxr-xr-xtest/fs/fs.sh3
-rw-r--r--test/fs/user-dirs.dirs15
-rwxr-xr-xtest/fs/whitelist-downloads.exp49
-rwxr-xr-xtest/utils/audit.exp79
-rwxr-xr-xtest/utils/utils.sh3
30 files changed, 578 insertions, 306 deletions
diff --git a/Makefile.in b/Makefile.in
index d1f03c788..8251f9882 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -249,6 +249,10 @@ test: test-profiles test-fcopy test-fs test-utils test-environment test-apps te
249# with them you will need to restart your computer. 249# with them you will need to restart your computer.
250########################################## 250##########################################
251 251
252# requires root access
253test-chroot:
254 cd test/chroot; ./chroot.sh | grep testing
255
252# Huge appimage files, not included in "make dist" archive 256# Huge appimage files, not included in "make dist" archive
253test-appimage: 257test-appimage:
254 cd test/appimage; ./appimage.sh | grep TESTING 258 cd test/appimage; ./appimage.sh | grep TESTING
@@ -268,6 +272,6 @@ test-overlay:
268 272
269# For testing hidepid system, the command to set it up is "mount -o remount,rw,hidepid=2 /proc" 273# For testing hidepid system, the command to set it up is "mount -o remount,rw,hidepid=2 /proc"
270 274
271test-all: test-root test-network test-appimage test-overlay test-fcopy test 275test-all: test-root test-chroot test-network test-appimage test-overlay
272 echo "TEST COMPLETE" 276 echo "TEST COMPLETE"
273 \ No newline at end of file 277 \ No newline at end of file
diff --git a/gcov.sh b/gcov.sh
index 900b7ca41..c5c385dd3 100755
--- a/gcov.sh
+++ b/gcov.sh
@@ -13,9 +13,9 @@ gcov_init() {
13} 13}
14 14
15generate() { 15generate() {
16 lcov --capture -d src/firejail -d src/firemon -d src/fcopy -d src/fseccomp -d src/fnet -d src/ftee -d src/lib -d src/firecfg --output-file gcov-file 16 lcov -q --capture -d src/firejail -d src/firemon -d src/fcopy -d src/fseccomp -d src/fnet -d src/ftee -d src/lib -d src/firecfg --output-file gcov-file
17 rm -fr gcov-dir 17 rm -fr gcov-dir
18 genhtml gcov-file --output-directory gcov-dir 18 genhtml -q gcov-file --output-directory gcov-dir
19} 19}
20 20
21gcov_init 21gcov_init
@@ -29,6 +29,10 @@ make test-root
29generate 29generate
30sleep 2 30sleep 2
31 31
32make test-chroot
33generate
34sleep 2
35
32make test-network 36make test-network
33generate 37generate
34sleep 2 38sleep 2
diff --git a/src/firejail/caps.c b/src/firejail/caps.c
index ba811cada..6cfa36629 100644
--- a/src/firejail/caps.c
+++ b/src/firejail/caps.c
@@ -181,12 +181,10 @@ static int caps_find_name(const char *name) {
181} 181}
182 182
183// return 1 if error, 0 if OK 183// return 1 if error, 0 if OK
184int caps_check_list(const char *clist, void (*callback)(int)) { 184void caps_check_list(const char *clist, void (*callback)(int)) {
185 // don't allow empty lists 185 // don't allow empty lists
186 if (clist == NULL || *clist == '\0') { 186 if (clist == NULL || *clist == '\0')
187 fprintf(stderr, "Error: empty capabilities lists are not allowed\n"); 187 goto errexit;
188 return -1;
189 }
190 188
191 // work on a copy of the string 189 // work on a copy of the string
192 char *str = strdup(clist); 190 char *str = strdup(clist);
@@ -201,11 +199,8 @@ int caps_check_list(const char *clist, void (*callback)(int)) {
201 else if (*ptr == ',') { 199 else if (*ptr == ',') {
202 *ptr = '\0'; 200 *ptr = '\0';
203 int nr = caps_find_name(start); 201 int nr = caps_find_name(start);
204 if (nr == -1) { 202 if (nr == -1)
205 fprintf(stderr, "Error: capability %s not found\n", start); 203 goto errexit;
206 free(str);
207 return -1;
208 }
209 else if (callback != NULL) 204 else if (callback != NULL)
210 callback(nr); 205 callback(nr);
211 206
@@ -215,17 +210,18 @@ int caps_check_list(const char *clist, void (*callback)(int)) {
215 } 210 }
216 if (*start != '\0') { 211 if (*start != '\0') {
217 int nr = caps_find_name(start); 212 int nr = caps_find_name(start);
218 if (nr == -1) { 213 if (nr == -1)
219 fprintf(stderr, "Error: capability %s not found\n", start); 214 goto errexit;
220 free(str);
221 return -1;
222 }
223 else if (callback != NULL) 215 else if (callback != NULL)
224 callback(nr); 216 callback(nr);
225 } 217 }
226 218
227 free(str); 219 free(str);
228 return 0; 220 return;
221
222errexit:
223 fprintf(stderr, "Error: capability \"%s\" not found\n", start);
224 exit(1);
229} 225}
230 226
231void caps_print(void) { 227void caps_print(void) {
@@ -256,49 +252,53 @@ void caps_print(void) {
256// enabled by default 252// enabled by default
257int caps_default_filter(void) { 253int caps_default_filter(void) {
258 // drop capabilities 254 // drop capabilities
259 if (prctl(PR_CAPBSET_DROP, CAP_SYS_MODULE, 0, 0, 0) && arg_debug) 255 if (prctl(PR_CAPBSET_DROP, CAP_SYS_MODULE, 0, 0, 0))
260 fprintf(stderr, "Warning: cannot drop CAP_SYS_MODULE"); 256 goto errexit;
261 else if (arg_debug) 257 else if (arg_debug)
262 printf("Drop CAP_SYS_MODULE\n"); 258 printf("Drop CAP_SYS_MODULE\n");
263 259
264 if (prctl(PR_CAPBSET_DROP, CAP_SYS_RAWIO, 0, 0, 0) && arg_debug) 260 if (prctl(PR_CAPBSET_DROP, CAP_SYS_RAWIO, 0, 0, 0))
265 fprintf(stderr, "Warning: cannot drop CAP_SYS_RAWIO"); 261 goto errexit;
266 else if (arg_debug) 262 else if (arg_debug)
267 printf("Drop CAP_SYS_RAWIO\n"); 263 printf("Drop CAP_SYS_RAWIO\n");
268 264
269 if (prctl(PR_CAPBSET_DROP, CAP_SYS_BOOT, 0, 0, 0) && arg_debug) 265 if (prctl(PR_CAPBSET_DROP, CAP_SYS_BOOT, 0, 0, 0))
270 fprintf(stderr, "Warning: cannot drop CAP_SYS_BOOT"); 266 goto errexit;
271 else if (arg_debug) 267 else if (arg_debug)
272 printf("Drop CAP_SYS_BOOT\n"); 268 printf("Drop CAP_SYS_BOOT\n");
273 269
274 if (prctl(PR_CAPBSET_DROP, CAP_SYS_NICE, 0, 0, 0) && arg_debug) 270 if (prctl(PR_CAPBSET_DROP, CAP_SYS_NICE, 0, 0, 0))
275 fprintf(stderr, "Warning: cannot drop CAP_SYS_NICE"); 271 goto errexit;
276 else if (arg_debug) 272 else if (arg_debug)
277 printf("Drop CAP_SYS_NICE\n"); 273 printf("Drop CAP_SYS_NICE\n");
278 274
279 if (prctl(PR_CAPBSET_DROP, CAP_SYS_TTY_CONFIG, 0, 0, 0) && arg_debug) 275 if (prctl(PR_CAPBSET_DROP, CAP_SYS_TTY_CONFIG, 0, 0, 0))
280 fprintf(stderr, "Warning: cannot drop CAP_SYS_TTY_CONFIG"); 276 goto errexit;
281 else if (arg_debug) 277 else if (arg_debug)
282 printf("Drop CAP_SYS_TTY_CONFIG\n"); 278 printf("Drop CAP_SYS_TTY_CONFIG\n");
283 279
284#ifdef CAP_SYSLOG 280#ifdef CAP_SYSLOG
285 if (prctl(PR_CAPBSET_DROP, CAP_SYSLOG, 0, 0, 0) && arg_debug) 281 if (prctl(PR_CAPBSET_DROP, CAP_SYSLOG, 0, 0, 0))
286 fprintf(stderr, "Warning: cannot drop CAP_SYSLOG"); 282 goto errexit;
287 else if (arg_debug) 283 else if (arg_debug)
288 printf("Drop CAP_SYSLOG\n"); 284 printf("Drop CAP_SYSLOG\n");
289#endif 285#endif
290 286
291 if (prctl(PR_CAPBSET_DROP, CAP_MKNOD, 0, 0, 0) && arg_debug) 287 if (prctl(PR_CAPBSET_DROP, CAP_MKNOD, 0, 0, 0))
292 fprintf(stderr, "Warning: cannot drop CAP_MKNOD"); 288 goto errexit;
293 else if (arg_debug) 289 else if (arg_debug)
294 printf("Drop CAP_MKNOD\n"); 290 printf("Drop CAP_MKNOD\n");
295 291
296 if (prctl(PR_CAPBSET_DROP, CAP_SYS_ADMIN, 0, 0, 0) && arg_debug) 292 if (prctl(PR_CAPBSET_DROP, CAP_SYS_ADMIN, 0, 0, 0))
297 fprintf(stderr, "Warning: cannot drop CAP_SYS_ADMIN"); 293 goto errexit;
298 else if (arg_debug) 294 else if (arg_debug)
299 printf("Drop CAP_SYS_ADMIN\n"); 295 printf("Drop CAP_SYS_ADMIN\n");
300 296
301 return 0; 297 return 0;
298
299errexit:
300 fprintf(stderr, "Error: cannot drop capabilities\n");
301 exit(1);
302} 302}
303 303
304void caps_drop_all(void) { 304void caps_drop_all(void) {
@@ -359,19 +359,14 @@ static uint64_t extract_caps(int pid) {
359 EUID_ASSERT(); 359 EUID_ASSERT();
360 360
361 char *file; 361 char *file;
362 if (asprintf(&file, "/proc/%d/status", pid) == -1) { 362 if (asprintf(&file, "/proc/%d/status", pid) == -1)
363 errExit("asprintf"); 363 errExit("asprintf");
364 exit(1);
365 }
366 364
367 EUID_ROOT(); // grsecurity 365 EUID_ROOT(); // grsecurity
368 FILE *fp = fopen(file, "r"); 366 FILE *fp = fopen(file, "r");
369 EUID_USER(); // grsecurity 367 EUID_USER(); // grsecurity
370 if (!fp) { 368 if (!fp)
371 printf("Error: cannot open %s\n", file); 369 goto errexit;
372 free(file);
373 exit(1);
374 }
375 370
376 char buf[MAXBUF]; 371 char buf[MAXBUF];
377 while (fgets(buf, MAXBUF, fp)) { 372 while (fgets(buf, MAXBUF, fp)) {
@@ -385,6 +380,8 @@ static uint64_t extract_caps(int pid) {
385 } 380 }
386 } 381 }
387 fclose(fp); 382 fclose(fp);
383
384errexit:
388 free(file); 385 free(file);
389 fprintf(stderr, "Error: cannot read caps configuration\n"); 386 fprintf(stderr, "Error: cannot read caps configuration\n");
390 exit(1); 387 exit(1);
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h
index 2e031ce04..4ae3cfd9f 100644
--- a/src/firejail/firejail.h
+++ b/src/firejail/firejail.h
@@ -508,7 +508,7 @@ int caps_default_filter(void);
508void caps_print(void); 508void caps_print(void);
509void caps_drop_all(void); 509void caps_drop_all(void);
510void caps_set(uint64_t caps); 510void caps_set(uint64_t caps);
511int caps_check_list(const char *clist, void (*callback)(int)); 511void caps_check_list(const char *clist, void (*callback)(int));
512void caps_drop_list(const char *clist); 512void caps_drop_list(const char *clist);
513void caps_keep_list(const char *clist); 513void caps_keep_list(const char *clist);
514void caps_print_filter(pid_t pid); 514void caps_print_filter(pid_t pid);
diff --git a/src/firejail/fs.c b/src/firejail/fs.c
index 5774ebf6a..8c776bad5 100644
--- a/src/firejail/fs.c
+++ b/src/firejail/fs.c
@@ -1042,6 +1042,9 @@ void fs_chroot(const char *rootdir) {
1042 if (chroot(rootdir) < 0) 1042 if (chroot(rootdir) < 0)
1043 errExit("chroot"); 1043 errExit("chroot");
1044 1044
1045 // create all other /run/firejail files and directories
1046 preproc_build_firejail_dir();
1047
1045 if (checkcfg(CFG_CHROOT_DESKTOP)) { 1048 if (checkcfg(CFG_CHROOT_DESKTOP)) {
1046 // update /var directory in order to support multiple sandboxes running on the same root directory 1049 // update /var directory in order to support multiple sandboxes running on the same root directory
1047// if (!arg_private_dev) 1050// if (!arg_private_dev)
diff --git a/src/firejail/main.c b/src/firejail/main.c
index ff7b762cd..111a1d751 100644
--- a/src/firejail/main.c
+++ b/src/firejail/main.c
@@ -1186,8 +1186,7 @@ int main(int argc, char **argv) {
1186 if (!arg_caps_list) 1186 if (!arg_caps_list)
1187 errExit("strdup"); 1187 errExit("strdup");
1188 // verify caps list and exit if problems 1188 // verify caps list and exit if problems
1189 if (caps_check_list(arg_caps_list, NULL)) 1189 caps_check_list(arg_caps_list, NULL);
1190 return 1;
1191 } 1190 }
1192 else if (strncmp(argv[i], "--caps.keep=", 12) == 0) { 1191 else if (strncmp(argv[i], "--caps.keep=", 12) == 0) {
1193 arg_caps_keep = 1; 1192 arg_caps_keep = 1;
@@ -1195,8 +1194,7 @@ int main(int argc, char **argv) {
1195 if (!arg_caps_list) 1194 if (!arg_caps_list)
1196 errExit("strdup"); 1195 errExit("strdup");
1197 // verify caps list and exit if problems 1196 // verify caps list and exit if problems
1198 if (caps_check_list(arg_caps_list, NULL)) 1197 caps_check_list(arg_caps_list, NULL);
1199 return 1;
1200 } 1198 }
1201 1199
1202 1200
diff --git a/src/firejail/profile.c b/src/firejail/profile.c
index 688fa9609..abb8bd9b6 100644
--- a/src/firejail/profile.c
+++ b/src/firejail/profile.c
@@ -570,8 +570,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
570 if (!arg_caps_list) 570 if (!arg_caps_list)
571 errExit("strdup"); 571 errExit("strdup");
572 // verify caps list and exit if problems 572 // verify caps list and exit if problems
573 if (caps_check_list(arg_caps_list, NULL)) 573 caps_check_list(arg_caps_list, NULL);
574 exit(1);
575 return 0; 574 return 0;
576 } 575 }
577 576
@@ -582,8 +581,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
582 if (!arg_caps_list) 581 if (!arg_caps_list)
583 errExit("strdup"); 582 errExit("strdup");
584 // verify caps list and exit if problems 583 // verify caps list and exit if problems
585 if (caps_check_list(arg_caps_list, NULL)) 584 caps_check_list(arg_caps_list, NULL);
586 exit(1);
587 return 0; 585 return 0;
588 } 586 }
589 587
diff --git a/src/lib/common.c b/src/lib/common.c
index 2f2340963..add4ff087 100644
--- a/src/lib/common.c
+++ b/src/lib/common.c
@@ -39,22 +39,23 @@ int join_namespace(pid_t pid, char *type) {
39 errExit("asprintf"); 39 errExit("asprintf");
40 40
41 int fd = open(path, O_RDONLY); 41 int fd = open(path, O_RDONLY);
42 if (fd < 0) { 42 if (fd < 0)
43 free(path); 43 goto errout;
44 fprintf(stderr, "Error: cannot open /proc/%u/ns/%s.\n", pid, type);
45 return -1;
46 }
47 44
48 if (syscall(__NR_setns, fd, 0) < 0) { 45 if (syscall(__NR_setns, fd, 0) < 0) {
49 free(path);
50 fprintf(stderr, "Error: cannot join namespace %s.\n", type);
51 close(fd); 46 close(fd);
52 return -1; 47 goto errout;
53 } 48 }
54 49
55 close(fd); 50 close(fd);
56 free(path); 51 free(path);
57 return 0; 52 return 0;
53
54errout:
55 free(path);
56 fprintf(stderr, "Error: cannot join namespace %s\\n", type);
57 return -1;
58
58} 59}
59 60
60// return 1 if error 61// return 1 if error
@@ -187,8 +188,6 @@ char *pid_proc_cmdline(const pid_t pid) {
187 for (i = 0; i < len; i++) { 188 for (i = 0; i < len; i++) {
188 if (buffer[i] == '\0') 189 if (buffer[i] == '\0')
189 buffer[i] = ' '; 190 buffer[i] = ' ';
190// if (buffer[i] >= 0x80) // execv in progress!!!
191// return NULL;
192 } 191 }
193 192
194 // return a malloc copy of the command line 193 // return a malloc copy of the command line
diff --git a/src/lib/libnetlink.c b/src/lib/libnetlink.c
index 836cf417d..417ef2c5f 100644
--- a/src/lib/libnetlink.c
+++ b/src/lib/libnetlink.c
@@ -105,6 +105,7 @@ int rtnl_open(struct rtnl_handle *rth, unsigned subscriptions)
105 return rtnl_open_byproto(rth, subscriptions, NETLINK_ROUTE); 105 return rtnl_open_byproto(rth, subscriptions, NETLINK_ROUTE);
106} 106}
107 107
108#if 0
108int rtnl_wilddump_request(struct rtnl_handle *rth, int family, int type) 109int rtnl_wilddump_request(struct rtnl_handle *rth, int family, int type)
109{ 110{
110 return rtnl_wilddump_req_filter(rth, family, type, RTEXT_FILTER_VF); 111 return rtnl_wilddump_req_filter(rth, family, type, RTEXT_FILTER_VF);
@@ -303,6 +304,7 @@ int rtnl_dump_filter(struct rtnl_handle *rth,
303 304
304 return rtnl_dump_filter_l(rth, a); 305 return rtnl_dump_filter_l(rth, a);
305} 306}
307#endif
306 308
307int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, 309int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
308 unsigned groups, struct nlmsghdr *answer) 310 unsigned groups, struct nlmsghdr *answer)
@@ -422,6 +424,7 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
422 } 424 }
423} 425}
424 426
427#if 0
425int rtnl_listen(struct rtnl_handle *rtnl, 428int rtnl_listen(struct rtnl_handle *rtnl,
426 rtnl_filter_t handler, 429 rtnl_filter_t handler,
427 void *jarg) 430 void *jarg)
@@ -580,7 +583,7 @@ int addattrstrz(struct nlmsghdr *n, int maxlen, int type, const char *str)
580{ 583{
581 return addattr_l(n, maxlen, type, str, strlen(str)+1); 584 return addattr_l(n, maxlen, type, str, strlen(str)+1);
582} 585}
583 586#endif
584 587
585 588
586int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data, 589int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
@@ -632,46 +635,8 @@ printf("\tdata length: %d\n", alen);
632 return 0; 635 return 0;
633} 636}
634 637
635#if 0
636int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
637 int alen)
638{
639printf("%s: adding type %d, length %d ", __FUNCTION__, type, alen);
640if (type == IFLA_INFO_KIND) {
641if (alen)
642 printf("(IFLA_INFO_KIND %s)\n", (char *)data);
643else
644printf("(VETH_INFO_PEER)\n");
645}
646else if (type == IFLA_IFNAME) {
647printf("(IFLA_IFNAME %s)\n", (char *) data);
648}
649else if (type == IFLA_NET_NS_PID) {
650printf("(IFLA_NET_NS_PID %u)\n", *((unsigned *) data));
651}
652else if (type == IFLA_LINKINFO)
653printf("(IFLA_LINKINFO)\n");
654else if (type == IFLA_INFO_DATA)
655printf("(IFLA_INFO_DATA)\n");
656else
657 printf("\n");
658
659 int len = RTA_LENGTH(alen);
660 struct rtattr *rta;
661
662 if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) {
663 fprintf(stderr, "addattr_l ERROR: message exceeded bound of %d\n",maxlen);
664 return -1;
665 }
666 rta = NLMSG_TAIL(n);
667 rta->rta_type = type;
668 rta->rta_len = len;
669 memcpy(RTA_DATA(rta), data, alen);
670 n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
671 return 0;
672}
673#endif
674 638
639#if 0
675int addraw_l(struct nlmsghdr *n, int maxlen, const void *data, int len) 640int addraw_l(struct nlmsghdr *n, int maxlen, const void *data, int len)
676{ 641{
677 if ((int)(NLMSG_ALIGN(n->nlmsg_len) + NLMSG_ALIGN(len)) > maxlen) { 642 if ((int)(NLMSG_ALIGN(n->nlmsg_len) + NLMSG_ALIGN(len)) > maxlen) {
@@ -802,3 +767,4 @@ int __parse_rtattr_nested_compat(struct rtattr *tb[], int max, struct rtattr *rt
802 memset(tb, 0, sizeof(struct rtattr *) * (max + 1)); 767 memset(tb, 0, sizeof(struct rtattr *) * (max + 1));
803 return 0; 768 return 0;
804} 769}
770#endif
diff --git a/src/lib/pid.c b/src/lib/pid.c
index ed583c51d..42687274e 100644
--- a/src/lib/pid.c
+++ b/src/lib/pid.c
@@ -34,10 +34,9 @@ int max_pids=32769;
34void pid_getmem(unsigned pid, unsigned *rss, unsigned *shared) { 34void pid_getmem(unsigned pid, unsigned *rss, unsigned *shared) {
35 // open stat file 35 // open stat file
36 char *file; 36 char *file;
37 if (asprintf(&file, "/proc/%u/statm", pid) == -1) { 37 if (asprintf(&file, "/proc/%u/statm", pid) == -1)
38 perror("asprintf"); 38 errExit("asprintf");
39 exit(1); 39
40 }
41 FILE *fp = fopen(file, "r"); 40 FILE *fp = fopen(file, "r");
42 if (!fp) { 41 if (!fp) {
43 free(file); 42 free(file);
@@ -59,10 +58,9 @@ void pid_getmem(unsigned pid, unsigned *rss, unsigned *shared) {
59void pid_get_cpu_time(unsigned pid, unsigned *utime, unsigned *stime) { 58void pid_get_cpu_time(unsigned pid, unsigned *utime, unsigned *stime) {
60 // open stat file 59 // open stat file
61 char *file; 60 char *file;
62 if (asprintf(&file, "/proc/%u/stat", pid) == -1) { 61 if (asprintf(&file, "/proc/%u/stat", pid) == -1)
63 perror("asprintf"); 62 errExit("asprintf");
64 exit(1); 63
65 }
66 FILE *fp = fopen(file, "r"); 64 FILE *fp = fopen(file, "r");
67 if (!fp) { 65 if (!fp) {
68 free(file); 66 free(file);
@@ -93,10 +91,9 @@ myexit:
93unsigned long long pid_get_start_time(unsigned pid) { 91unsigned long long pid_get_start_time(unsigned pid) {
94 // open stat file 92 // open stat file
95 char *file; 93 char *file;
96 if (asprintf(&file, "/proc/%u/stat", pid) == -1) { 94 if (asprintf(&file, "/proc/%u/stat", pid) == -1)
97 perror("asprintf"); 95 errExit("asprintf");
98 exit(1); 96
99 }
100 FILE *fp = fopen(file, "r"); 97 FILE *fp = fopen(file, "r");
101 if (!fp) { 98 if (!fp) {
102 free(file); 99 free(file);
@@ -138,10 +135,8 @@ uid_t pid_get_uid(pid_t pid) {
138 135
139 // open status file 136 // open status file
140 char *file; 137 char *file;
141 if (asprintf(&file, "/proc/%u/status", pid) == -1) { 138 if (asprintf(&file, "/proc/%u/status", pid) == -1)
142 perror("asprintf"); 139 errExit("asprintf");
143 exit(1);
144 }
145 140
146 FILE *fp = fopen(file, "r"); 141 FILE *fp = fopen(file, "r");
147 if (!fp) { 142 if (!fp) {
@@ -316,10 +311,9 @@ void pid_read(pid_t mon_pid) {
316 311
317 // open stat file 312 // open stat file
318 char *file; 313 char *file;
319 if (asprintf(&file, "/proc/%u/status", pid) == -1) { 314 if (asprintf(&file, "/proc/%u/status", pid) == -1)
320 perror("asprintf"); 315 errExit("asprintf");
321 exit(1); 316
322 }
323 FILE *fp = fopen(file, "r"); 317 FILE *fp = fopen(file, "r");
324 if (!fp) { 318 if (!fp) {
325 free(file); 319 free(file);
diff --git a/src/tools/unchroot b/src/tools/unchroot
deleted file mode 100755
index d32ce2682..000000000
--- a/src/tools/unchroot
+++ /dev/null
Binary files differ
diff --git a/src/tools/unchroot.c b/src/tools/unchroot.c
deleted file mode 100644
index 21731296e..000000000
--- a/src/tools/unchroot.c
+++ /dev/null
@@ -1,125 +0,0 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <errno.h>
4#include <fcntl.h>
5#include <string.h>
6#include <unistd.h>
7#include <sys/stat.h>
8#include <sys/types.h>
9
10/*
11 ** You should set NEED_FCHDIR to 1 if the chroot() on your
12 ** system changes the working directory of the calling
13 ** process to the same directory as the process was chroot()ed
14 ** to.
15 **
16 ** It is known that you do not need to set this value if you
17 ** running on Solaris 2.7 and below.
18 **
19 */
20#define NEED_FCHDIR 0
21
22#define TEMP_DIR "waterbuffalo"
23
24/* Break out of a chroot() environment in C */
25
26int main() {
27 int x; /* Used to move up a directory tree */
28 int done=0; /* Are we done yet ? */
29#ifdef NEED_FCHDIR
30 int dir_fd; /* File descriptor to directory */
31#endif
32 struct stat sbuf; /* The stat() buffer */
33
34 /*
35 ** First we create the temporary directory if it doesn't exist
36 */
37 if (stat(TEMP_DIR,&sbuf)<0) {
38 if (errno==ENOENT) {
39 if (mkdir(TEMP_DIR,0755)<0) {
40 fprintf(stderr,"Failed to create %s - %s\n", TEMP_DIR,
41 strerror(errno));
42 exit(1);
43 }
44 }
45 else {
46 fprintf(stderr,"Failed to stat %s - %s\n", TEMP_DIR,
47 strerror(errno));
48 exit(1);
49 }
50 }
51 else if (!S_ISDIR(sbuf.st_mode)) {
52 fprintf(stderr,"Error - %s is not a directory!\n",TEMP_DIR);
53 exit(1);
54 }
55
56#ifdef NEED_FCHDIR
57 /*
58 ** Now we open the current working directory
59 **
60 ** Note: Only required if chroot() changes the calling program's
61 ** working directory to the directory given to chroot().
62 **
63 */
64 if ((dir_fd=open(".",O_RDONLY))<0) {
65 fprintf(stderr,"Failed to open \".\" for reading - %s\n",
66 strerror(errno));
67 exit(1);
68 }
69#endif
70
71 /*
72 ** Next we chroot() to the temporary directory
73 */
74 if (chroot(TEMP_DIR)<0) {
75 fprintf(stderr,"Failed to chroot to %s - %s\n",TEMP_DIR,
76 strerror(errno));
77 exit(1);
78 }
79
80#ifdef NEED_FCHDIR
81 /*
82 ** Partially break out of the chroot by doing an fchdir()
83 **
84 ** This only partially breaks out of the chroot() since whilst
85 ** our current working directory is outside of the chroot() jail,
86 ** our root directory is still within it. Thus anything which refers
87 ** to "/" will refer to files under the chroot() point.
88 **
89 ** Note: Only required if chroot() changes the calling program's
90 ** working directory to the directory given to chroot().
91 **
92 */
93 if (fchdir(dir_fd)<0) {
94 fprintf(stderr,"Failed to fchdir - %s\n",
95 strerror(errno));
96 exit(1);
97 }
98 close(dir_fd);
99#endif
100
101 /*
102 ** Completely break out of the chroot by recursing up the directory
103 ** tree and doing a chroot to the current working directory (which will
104 ** be the real "/" at that point). We just do a chdir("..") lots of
105 ** times (1024 times for luck :). If we hit the real root directory before
106 ** we have finished the loop below it doesn't matter as .. in the root
107 ** directory is the same as . in the root.
108 **
109 ** We do the final break out by doing a chroot(".") which sets the root
110 ** directory to the current working directory - at this point the real
111 ** root directory.
112 */
113 for(x=0;x<1024;x++) {
114 chdir("..");
115 }
116 chroot(".");
117
118 /*
119 ** We're finally out - so exec a shell in interactive mode
120 */
121 if (execl("/bin/sh","-i",NULL)<0) {
122 fprintf(stderr,"Failed to exec - %s\n",strerror(errno));
123 exit(1);
124 }
125}
diff --git a/test/chroot/chroot-resolvconf.exp b/test/chroot/chroot-resolvconf.exp
deleted file mode 100755
index 2d0da2fb0..000000000
--- a/test/chroot/chroot-resolvconf.exp
+++ /dev/null
@@ -1,14 +0,0 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --chroot=/tmp/chroot /bin/bash\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "invalid /tmp/chroot/etc/resolv.conf file"
11}
12
13puts "\nall done\n"
14
diff --git a/test/chroot/chroot.sh b/test/chroot/chroot.sh
new file mode 100755
index 000000000..34bff2a67
--- /dev/null
+++ b/test/chroot/chroot.sh
@@ -0,0 +1,21 @@
1#!/bin/bash
2# This file is part of Firejail project
3# Copyright (C) 2014-2016 Firejail Authors
4# License GPL v2
5
6export MALLOC_CHECK_=3
7export MALLOC_PERTURB_=$(($RANDOM % 255 + 1))
8
9rm -f unchroot
10gcc -o unchroot unchroot.c
11sudo ./configure
12
13echo "TESTING: chroot (test/chroot/fs_chroot.exp)"
14./fs_chroot.exp
15
16echo "TESTING: unchroot as root (test/chroot/unchroot-as-root.exp)"
17sudo ./unchroot-as-root.exp
18
19
20
21rm -f unchroot
diff --git a/test/chroot/configure b/test/chroot/configure
new file mode 100755
index 000000000..ba8238803
--- /dev/null
+++ b/test/chroot/configure
@@ -0,0 +1,46 @@
1#!/bin/bash
2
3# build a very small chroot
4ROOTDIR="/tmp/chroot" # default chroot directory
5DEFAULT_FILES="/bin/bash /bin/sh " # basic chroot files
6DEFAULT_FILES+="/etc/passwd /etc/nsswitch.conf /etc/group "
7DEFAULT_FILES+=`find /lib -name libnss*` # files required by glibc
8DEFAULT_FILES+=" /bin/cp /bin/ls /bin/cat /bin/ps /bin/netstat /bin/ping /sbin/ifconfig /usr/bin/touch /bin/ip /bin/hostname /bin/grep /usr/bin/dig /usr/bin/openssl /usr/bin/id /usr/bin/getent /usr/bin/whoami /usr/bin/wc /usr/bin/wget /bin/umount"
9
10rm -fr $ROOTDIR
11mkdir -p $ROOTDIR/{root,bin,lib,lib64,usr,home,etc,dev/shm,tmp,var/run,var/tmp,var/lock,var/log,proc}
12chmod 777 $ROOTDIR/tmp
13mkdir -p $ROOTDIR/etc/firejail
14mkdir -p $ROOTDIR/home/netblue/.config/firejail
15chown netblue:netblue $ROOTDIR/home/netblue
16chown netblue:netblue $ROOTDIR/home/netblue/.config
17cp /home/netblue/.Xauthority $ROOTDIR/home/netblue/.
18cp -a /etc/skel $ROOTDIR/etc/.
19mkdir $ROOTDIR/home/someotheruser
20mkdir $ROOTDIR/boot
21mkdir $ROOTDIR/selinux
22cp /etc/passwd $ROOTDIR/etc/.
23cp /etc/group $ROOTDIR/etc/.
24cp /etc/hosts $ROOTDIR/etc/.
25cp /etc/hostname $ROOTDIR/etc/.
26mkdir -p $ROOTDIR/usr/lib/x86_64-linux-gnu
27cp -a /usr/lib/x86_64-linux-gnu/openssl-1.0.0 $ROOTDIR/usr/lib/x86_64-linux-gnu/.
28cp -a /usr/lib/ssl $ROOTDIR/usr/lib/.
29touch $ROOTDIR/var/log/syslog
30touch $ROOTDIR/var/tmp/somefile
31SORTED=`for FILE in $* $DEFAULT_FILES; do echo " $FILE "; ldd $FILE | grep -v dynamic | cut -d " " -f 3; done | sort -u`
32for FILE in $SORTED
33do
34 cp --parents $FILE $ROOTDIR
35done
36cp --parents /lib64/ld-linux-x86-64.so.2 $ROOTDIR
37cp --parents /lib/ld-linux.so.2 $ROOTDIR
38cp unchroot $ROOTDIR/.
39touch $ROOTDIR/this-is-my-chroot
40
41cd $ROOTDIR; find .
42mkdir -p usr/lib/firejail/
43cp /usr/lib/firejail/libtrace.so usr/lib/firejail/.
44
45
46echo "To enter the chroot directory run: firejail --chroot=$ROOTDIR"
diff --git a/test/chroot/fs_chroot.exp b/test/chroot/fs_chroot.exp
index aeb5669e1..295ff8ff9 100755
--- a/test/chroot/fs_chroot.exp
+++ b/test/chroot/fs_chroot.exp
@@ -20,19 +20,14 @@ expect {
20sleep 1 20sleep 1
21send -- "bash\r" 21send -- "bash\r"
22sleep 1 22sleep 1
23send -- "ls /; pwd\r" 23send -- "ls /\r"
24expect { 24expect {
25 timeout {puts "TESTING ERROR 0.2\n";exit} 25 timeout {puts "TESTING ERROR 0.2\n";exit}
26 "this-is-my-chroot" 26 "this-is-my-chroot"
27} 27}
28expect { 28after 100
29 timeout {puts "TESTING ERROR 0.3\n";exit}
30 "home"
31}
32
33 29
34 30send -- "ps aux\r"
35send -- "ps aux; pwd\r"
36expect { 31expect {
37 timeout {puts "TESTING ERROR 1\n";exit} 32 timeout {puts "TESTING ERROR 1\n";exit}
38 "/bin/bash" 33 "/bin/bash"
@@ -45,23 +40,14 @@ expect {
45 timeout {puts "TESTING ERROR 3\n";exit} 40 timeout {puts "TESTING ERROR 3\n";exit}
46 "ps aux" 41 "ps aux"
47} 42}
48expect { 43after 100
49 timeout {puts "TESTING ERROR 4\n";exit}
50 "home"
51}
52sleep 1
53 44
54 45send -- "ps aux | wc -l; pwd\r"
55send -- "ps aux |wc -l; pwd\r"
56expect { 46expect {
57 timeout {puts "TESTING ERROR 5\n";exit} 47 timeout {puts "TESTING ERROR 5\n";exit}
58 "6" 48 "6"
59} 49}
60expect { 50after 100
61 timeout {puts "TESTING ERROR 6\n";exit}
62 "home"
63}
64sleep 1
65 51
66 52
67puts "all done\n" 53puts "all done\n"
diff --git a/test/chroot/unchroot-as-root.exp b/test/chroot/unchroot-as-root.exp
new file mode 100755
index 000000000..9f8a1d784
--- /dev/null
+++ b/test/chroot/unchroot-as-root.exp
@@ -0,0 +1,27 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --chroot=/tmp/chroot\r"
8expect {
9 timeout {puts "TESTING ERROR 0\n";exit}
10 "Error: --chroot option is not available on Grsecurity systems" {puts "\nall done\n"; exit}
11 "Child process initialized" {puts "chroot available\n"};
12}
13sleep 1
14
15send -- "cd /\r"
16after 100
17
18
19send -- "./unchroot\r"
20expect {
21 timeout {puts "TESTING ERROR 1\n";exit}
22 "Bad system call"
23}
24after 100
25
26puts "all done\n"
27
diff --git a/test/chroot/unchroot.c b/test/chroot/unchroot.c
new file mode 100644
index 000000000..1982e07f3
--- /dev/null
+++ b/test/chroot/unchroot.c
@@ -0,0 +1,40 @@
1// simple unchroot example from http://linux-vserver.org/Secure_chroot_Barrier
2#include <unistd.h>
3#include <stdlib.h>
4#include <stdio.h>
5#include <sys/types.h>
6#include <sys/stat.h>
7
8void die(char *msg) {
9 perror(msg);
10 exit(1);
11}
12
13int main(int argc, char *argv[])
14{
15 int i;
16
17 if (chdir("/") != 0)
18 die("chdir(/)");
19
20 if (mkdir("baz", 0777) != 0)
21 ; //die("mkdir(baz)");
22
23 if (chroot("baz") != 0)
24 die("chroot(baz)");
25
26 for (i=0; i<50; i++) {
27 if (chdir("..") != 0)
28 die("chdir(..)");
29 }
30
31 if (chroot(".") != 0)
32 die("chroot(.)");
33
34 printf("Exploit seems to work. =)\n");
35
36 execl("/bin/bash", "bash", "-i", (char *)0);
37 die("exec bash");
38
39 exit(0);
40}
diff --git a/test/environment/dns.exp b/test/environment/dns.exp
index a6a7171eb..40403aade 100755
--- a/test/environment/dns.exp
+++ b/test/environment/dns.exp
@@ -4,6 +4,31 @@ set timeout 30
4spawn $env(SHELL) 4spawn $env(SHELL)
5match_max 100000 5match_max 100000
6 6
7send -- "firejail --dns=8.8.4.4 --dns=8.8.8.8 --dns=4.2.2.1\r"
8expect {
9 timeout {puts "TESTING ERROR 2.1\n";exit}
10 "Child process initialized"
11}
12sleep 1
13
14send -- "cat /etc/resolv.conf\r"
15expect {
16 timeout {puts "TESTING ERROR 2.2\n";exit}
17 "nameserver 8.8.4.4"
18}
19expect {
20 timeout {puts "TESTING ERROR 2.3\n";exit}
21 "nameserver 8.8.8.8"
22}
23expect {
24 timeout {puts "TESTING ERROR 2.4\n";exit}
25 "nameserver 4.2.2.1"
26}
27after 100
28send -- "exit\r"
29after 100
30
31
7# no chroot 32# no chroot
8send -- "firejail --trace --dns=208.67.222.222 wget -q debian.org\r" 33send -- "firejail --trace --dns=208.67.222.222 wget -q debian.org\r"
9expect { 34expect {
@@ -27,28 +52,6 @@ after 100
27send -- "rm index.html\r" 52send -- "rm index.html\r"
28after 100 53after 100
29send -- "exit\r" 54send -- "exit\r"
30sleep 1
31
32send -- "firejail --dns=8.8.4.4 --dns=8.8.8.8 --dns=4.2.2.1\r"
33expect {
34 timeout {puts "TESTING ERROR 2.1\n";exit}
35 "Child process initialized"
36}
37sleep 1
38
39send -- "cat /etc/resolv.conf\r"
40expect {
41 timeout {puts "TESTING ERROR 2.2\n";exit}
42 "nameserver 8.8.4.4"
43}
44expect {
45 timeout {puts "TESTING ERROR 2.3\n";exit}
46 "nameserver 8.8.8.8"
47}
48expect {
49 timeout {puts "TESTING ERROR 2.4\n";exit}
50 "nameserver 4.2.2.1"
51}
52after 100 55after 100
53 56
54puts "\nall done\n" 57puts "\nall done\n"
diff --git a/test/filters/caps-print.exp b/test/filters/caps-print.exp
new file mode 100755
index 000000000..d9d662239
--- /dev/null
+++ b/test/filters/caps-print.exp
@@ -0,0 +1,103 @@
1#!/usr/bin/expect -f
2# This file is part of Firejail project
3# Copyright (C) 2014-2016 Firejail Authors
4# License GPL v2
5
6set timeout 10
7spawn $env(SHELL)
8match_max 100000
9
10send -- "firejail --name=test --noprofile --caps --debug\r"
11expect {
12 timeout {puts "TESTING ERROR 0\n";exit}
13 "Drop CAP_SYS_MODULE"
14}
15expect {
16 timeout {puts "TESTING ERROR 1\n";exit}
17 "Drop CAP_SYS_RAWIO"
18}
19expect {
20 timeout {puts "TESTING ERROR 2\n";exit}
21 "Drop CAP_SYS_BOOT"
22}
23expect {
24 timeout {puts "TESTING ERROR 3\n";exit}
25 "Drop CAP_SYS_NICE"
26}
27expect {
28 timeout {puts "TESTING ERROR 4\n";exit}
29 "Drop CAP_SYS_TTY_CONFIG"
30}
31expect {
32 timeout {puts "TESTING ERROR 5\n";exit}
33 "Drop CAP_SYSLOG"
34}
35expect {
36 timeout {puts "TESTING ERROR 6\n";exit}
37 "Drop CAP_MKNOD"
38}
39expect {
40 timeout {puts "TESTING ERROR 7\n";exit}
41 "Drop CAP_SYS_ADMIN"
42}
43expect {
44 timeout {puts "TESTING ERROR 8\n";exit}
45 "Child process initialized"
46}
47sleep 1
48
49spawn $env(SHELL)
50send -- "firejail --caps.print=test\r"
51expect {
52 timeout {puts "TESTING ERROR 9\n";exit}
53 "chown - enabled"
54}
55expect {
56 timeout {puts "TESTING ERROR 10\n";exit}
57 "setgid - enabled"
58}
59expect {
60 timeout {puts "TESTING ERROR 11\n";exit}
61 "setuid - enabled"
62}
63expect {
64 timeout {puts "TESTING ERROR 12\n";exit}
65 "mknod - disabled"
66}
67expect {
68 timeout {puts "TESTING ERROR 13\n";exit}
69 "syslog - disabled"
70}
71after 100
72
73send -- "firejail --debug-caps\r"
74expect {
75 timeout {puts "TESTING ERROR 9\n";exit}
76 "21 - sys_admin"
77}
78expect {
79 timeout {puts "TESTING ERROR 9\n";exit}
80 "22 - sys_boot"
81}
82expect {
83 timeout {puts "TESTING ERROR 9\n";exit}
84 "23 - sys_nice"
85}
86expect {
87 timeout {puts "TESTING ERROR 9\n";exit}
88 "24 - sys_resource"
89}
90after 100
91
92send -- "firejail --caps.keep=\"bla bla bla\"\r"
93expect {
94 timeout {puts "TESTING ERROR 10\n";exit}
95 "capability"
96}
97expect {
98 timeout {puts "TESTING ERROR 11\n";exit}
99 "not found"
100}
101
102after 100
103puts "\nall done\n"
diff --git a/test/filters/caps.exp b/test/filters/caps.exp
index 7f7cf7dd1..2954f2e58 100755
--- a/test/filters/caps.exp
+++ b/test/filters/caps.exp
@@ -12,7 +12,7 @@ expect {
12 timeout {puts "TESTING ERROR 1\n";exit} 12 timeout {puts "TESTING ERROR 1\n";exit}
13 "Child process initialized" 13 "Child process initialized"
14} 14}
15sleep 2 15after 100
16 16
17send -- "cat /proc/self/status\r" 17send -- "cat /proc/self/status\r"
18expect { 18expect {
@@ -31,7 +31,7 @@ expect {
31 timeout {puts "TESTING ERROR 4\n";exit} 31 timeout {puts "TESTING ERROR 4\n";exit}
32 "Child process initialized" 32 "Child process initialized"
33} 33}
34sleep 2 34after 100
35 35
36send -- "cat /proc/self/status\r" 36send -- "cat /proc/self/status\r"
37expect { 37expect {
@@ -50,7 +50,7 @@ expect {
50 timeout {puts "TESTING ERROR 7\n";exit} 50 timeout {puts "TESTING ERROR 7\n";exit}
51 "Child process initialized" 51 "Child process initialized"
52} 52}
53sleep 2 53after 100
54 54
55send -- "cat /proc/self/status\r" 55send -- "cat /proc/self/status\r"
56expect { 56expect {
@@ -66,7 +66,74 @@ expect {
66 "Seccomp:" 66 "Seccomp:"
67} 67}
68send -- "exit\r" 68send -- "exit\r"
69sleep 1
70
71
72send -- "firejail --profile=caps1.profile --debug\r"
73expect {
74 timeout {puts "TESTING ERROR 11\n";exit}
75 "Drop CAP_SYS_MODULE"
76}
77expect {
78 timeout {puts "TESTING ERROR 12\n";exit}
79 "Drop CAP_SYS_ADMIN"
80}
81expect {
82 timeout {puts "TESTING ERROR 13\n";exit}
83 "Drop CAP_" {puts "TESTING ERROR 14\n";exit}
84 "Child process initialized"
85}
69after 100 86after 100
87send -- "exit\r"
88sleep 1
70 89
71 90
91## tofix: possible problem with caps.keep in profile files
92##send -- "firejail --caps.keep=chown,fowner --noprofile\r"
93#send -- "firejail --profile=caps2.profile\r"
94#expect {
95# timeout {puts "TESTING ERROR 15\n";exit}
96# "Child process initialized"
97#}
98#after 100
99#
100#send -- "cat /proc/self/status\r"
101#expect {
102# timeout {puts "TESTING ERROR 16\n";exit}
103# "CapBnd: 0000000000000009"
104#}
105#expect {
106# timeout {puts "TESTING ERROR 17\n";exit}
107# "Seccomp:"
108#}
109#send -- "exit\r"
110#sleep 1
111
112#send -- "firejail --caps.drop=chown,dac_override,dac_read_search,fowner --noprofile\r"
113send -- "firejail --profile=caps3.profile\r"
114expect {
115 timeout {puts "TESTING ERROR 18\n";exit}
116 "Child process initialized"
117}
118after 100
119
120send -- "cat /proc/self/status\r"
121expect {
122 timeout {puts "TESTING ERROR 19\n";exit}
123 "CapBnd:"
124}
125expect {
126 timeout {puts "TESTING ERROR 20\n";exit}
127 "fffffff0"
128}
129expect {
130 timeout {puts "TESTING ERROR 21\n";exit}
131 "Seccomp:"
132}
133send -- "exit\r"
134sleep 1
135
136
137
138after 100
72puts "\nall done\n" 139puts "\nall done\n"
diff --git a/test/filters/caps1.profile b/test/filters/caps1.profile
new file mode 100644
index 000000000..8b0c3b340
--- /dev/null
+++ b/test/filters/caps1.profile
@@ -0,0 +1 @@
caps
diff --git a/test/filters/caps2.profile b/test/filters/caps2.profile
new file mode 100644
index 000000000..4f0016fad
--- /dev/null
+++ b/test/filters/caps2.profile
@@ -0,0 +1 @@
caps.drop chown,dac_override,dac_read_search,fowner \ No newline at end of file
diff --git a/test/filters/caps3.profile b/test/filters/caps3.profile
new file mode 100644
index 000000000..4f0016fad
--- /dev/null
+++ b/test/filters/caps3.profile
@@ -0,0 +1 @@
caps.drop chown,dac_override,dac_read_search,fowner \ No newline at end of file
diff --git a/test/filters/filters.sh b/test/filters/filters.sh
index 5c7c98b3e..fea4a0296 100755
--- a/test/filters/filters.sh
+++ b/test/filters/filters.sh
@@ -12,6 +12,9 @@ echo "TESTING: noroot (test/filters/noroot.exp)"
12echo "TESTING: capabilities (test/filters/caps.exp)" 12echo "TESTING: capabilities (test/filters/caps.exp)"
13./caps.exp 13./caps.exp
14 14
15echo "TESTING: capabilities print (test/filters/caps-print.exp)"
16./caps-print.exp
17
15rm -f seccomp-test-file 18rm -f seccomp-test-file
16if [ "$(uname -m)" = "x86_64" ]; then 19if [ "$(uname -m)" = "x86_64" ]; then
17 echo "TESTING: fseccomp (test/filters/fseccomp.exp)" 20 echo "TESTING: fseccomp (test/filters/fseccomp.exp)"
diff --git a/test/fs/fs.sh b/test/fs/fs.sh
index 1c5473f79..d9a425661 100755
--- a/test/fs/fs.sh
+++ b/test/fs/fs.sh
@@ -61,6 +61,9 @@ echo "TESTING: whitelist empty (test/fs/whitelist-empty.exp)"
61echo "TESTING: private whitelist (test/fs/private-whitelist.exp)" 61echo "TESTING: private whitelist (test/fs/private-whitelist.exp)"
62./private-whitelist.exp 62./private-whitelist.exp
63 63
64echo "TESTING: whitelist ~/Downloads (test/fs/whitelist-downloads.exp)"
65./whitelist-downloads.exp
66
64echo "TESTING: invalid filename (test/fs/invalid_filename.exp)" 67echo "TESTING: invalid filename (test/fs/invalid_filename.exp)"
65./invalid_filename.exp 68./invalid_filename.exp
66 69
diff --git a/test/fs/user-dirs.dirs b/test/fs/user-dirs.dirs
new file mode 100644
index 000000000..0d19da4e4
--- /dev/null
+++ b/test/fs/user-dirs.dirs
@@ -0,0 +1,15 @@
1# This file is written by xdg-user-dirs-update
2# If you want to change or add directories, just edit the line you're
3# interested in. All local changes will be retained on the next run
4# Format is XDG_xxx_DIR="$HOME/yyy", where yyy is a shell-escaped
5# homedir-relative path, or XDG_xxx_DIR="/yyy", where /yyy is an
6# absolute path. No other format is supported.
7#
8XDG_DESKTOP_DIR="$HOME/Desktop"
9XDG_DOWNLOAD_DIR="$HOME/Downloads"
10XDG_TEMPLATES_DIR="$HOME/Templates"
11XDG_PUBLICSHARE_DIR="$HOME/Public"
12XDG_DOCUMENTS_DIR="$HOME/Documents"
13XDG_MUSIC_DIR="$HOME/Music"
14XDG_PICTURES_DIR="$HOME/Pictures"
15XDG_VIDEOS_DIR="$HOME/Videos"
diff --git a/test/fs/whitelist-downloads.exp b/test/fs/whitelist-downloads.exp
new file mode 100755
index 000000000..6af318d2b
--- /dev/null
+++ b/test/fs/whitelist-downloads.exp
@@ -0,0 +1,49 @@
1#!/usr/bin/expect -f
2# This file is part of Firejail project
3# Copyright (C) 2014-2016 Firejail Authors
4# License GPL v2
5
6set timeout 10
7spawn $env(SHELL)
8match_max 100000
9
10send -- "cp user-dirs.dirs /tmp/.\r"
11after 100
12
13send -- "firejail --private --noprofile\r"
14expect {
15 timeout {puts "TESTING ERROR 0\n";exit}
16 "Child process initialized"
17}
18after 100
19
20send -- "firejail --force --profile=/etc/firejail/firefox.profile\r"
21expect {
22 timeout {puts "TESTING ERROR 1\n";exit}
23 "cannot whitelist Downloads directory"
24}
25expect {
26 timeout {puts "TESTING ERROR 2\n";exit}
27 "Child process initialized"
28}
29after 100
30
31send -- "exit\r"
32after 100
33
34send -- "cp /tmp/user-dirs.dirs ~/.config/.\r"
35after 100
36
37send -- "firejail --force --profile=/etc/firejail/firefox.profile\r"
38expect {
39 timeout {puts "TESTING ERROR 3\n";exit}
40 "cannot whitelist Downloads directory"
41}
42expect {
43 timeout {puts "TESTING ERROR 4\n";exit}
44 "Child process initialized"
45}
46after 100
47
48puts "\nall done\n"
49
diff --git a/test/utils/audit.exp b/test/utils/audit.exp
new file mode 100755
index 000000000..931b46981
--- /dev/null
+++ b/test/utils/audit.exp
@@ -0,0 +1,79 @@
1#!/usr/bin/expect -f
2# This file is part of Firejail project
3# Copyright (C) 2014-2016 Firejail Authors
4# License GPL v2
5
6set timeout 10
7spawn $env(SHELL)
8match_max 100000
9
10send -- "firejail --audit\r"
11expect {
12 timeout {puts "TESTING ERROR 0\n";exit}
13 "Firejail Audit"
14}
15expect {
16 timeout {puts "TESTING ERROR 1\n";exit}
17 "is running in a PID namespace"
18}
19expect {
20 timeout {puts "TESTING ERROR 2\n";exit}
21 "container/sandbox firejail"
22}
23expect {
24 timeout {puts "TESTING ERROR 3\n";exit}
25 "seccomp BPF enabled"
26}
27expect {
28 timeout {puts "TESTING ERROR 4\n";exit}
29 "all capabilities are disabled"
30}
31expect {
32 timeout {puts "TESTING ERROR 5\n";exit}
33 "dev directory seems to be fully populated"
34}
35after 100
36
37
38send -- "firejail --audit=/usr/lib/firejail/faudit\r"
39expect {
40 timeout {puts "TESTING ERROR 6\n";exit}
41 "Firejail Audit"
42}
43expect {
44 timeout {puts "TESTING ERROR 7\n";exit}
45 "is running in a PID namespace"
46}
47expect {
48 timeout {puts "TESTING ERROR 8\n";exit}
49 "container/sandbox firejail"
50}
51expect {
52 timeout {puts "TESTING ERROR 9\n";exit}
53 "seccomp BPF enabled"
54}
55expect {
56 timeout {puts "TESTING ERROR 10\n";exit}
57 "all capabilities are disabled"
58}
59expect {
60 timeout {puts "TESTING ERROR 11\n";exit}
61 "dev directory seems to be fully populated"
62}
63after 100
64
65send -- "firejail --audit=blablabla\r"
66expect {
67 timeout {puts "TESTING ERROR 12\n";exit}
68 "cannot find the audit program"
69}
70after 100
71
72send -- "firejail --audit=\r"
73expect {
74 timeout {puts "TESTING ERROR 12\n";exit}
75 "invalid audit program"
76}
77after 100
78
79puts "\nall done\n"
diff --git a/test/utils/utils.sh b/test/utils/utils.sh
index 804e5ae0f..04702597f 100755
--- a/test/utils/utils.sh
+++ b/test/utils/utils.sh
@@ -6,6 +6,9 @@
6export MALLOC_CHECK_=3 6export MALLOC_CHECK_=3
7export MALLOC_PERTURB_=$(($RANDOM % 255 + 1)) 7export MALLOC_PERTURB_=$(($RANDOM % 255 + 1))
8 8
9echo "TESTING: audit (test/utils/audit.exp)"
10./audit.exp
11
9echo "TESTING: version (test/utils/version.exp)" 12echo "TESTING: version (test/utils/version.exp)"
10./version.exp 13./version.exp
11 14