aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar netblue30 <netblue30@yahoo.com>2016-11-20 17:52:30 -0500
committerLibravatar netblue30 <netblue30@yahoo.com>2016-11-20 17:52:30 -0500
commit62b9173095929c7ef21b9fb2385f54ceba956aa7 (patch)
tree01cd4400eda9486b7160cf7d306149f92b6ca3e8
parentchroot testing (diff)
downloadfirejail-62b9173095929c7ef21b9fb2385f54ceba956aa7.tar.gz
firejail-62b9173095929c7ef21b9fb2385f54ceba956aa7.tar.zst
firejail-62b9173095929c7ef21b9fb2385f54ceba956aa7.zip
caps testing
-rw-r--r--src/firejail/caps.c77
-rw-r--r--src/firejail/firejail.h2
-rw-r--r--src/firejail/main.c6
-rw-r--r--src/firejail/profile.c6
-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
10 files changed, 221 insertions, 52 deletions
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/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/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)"