diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/fbuilder/build_bin.c | 121 | ||||
-rw-r--r-- | src/fbuilder/build_profile.c | 4 | ||||
-rw-r--r-- | src/fbuilder/fbuilder.h | 3 | ||||
-rw-r--r-- | src/firecfg/firecfg.config | 5 | ||||
-rw-r--r-- | src/firecfg/main.c | 104 | ||||
-rw-r--r-- | src/firejail/util.c | 2 | ||||
-rw-r--r-- | src/libtrace/libtrace.c | 12 | ||||
-rw-r--r-- | src/man/firejail.txt | 6 |
8 files changed, 239 insertions, 18 deletions
diff --git a/src/fbuilder/build_bin.c b/src/fbuilder/build_bin.c new file mode 100644 index 000000000..7d0e2cb7c --- /dev/null +++ b/src/fbuilder/build_bin.c | |||
@@ -0,0 +1,121 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014-2017 Firejail Authors | ||
3 | * | ||
4 | * This file is part of firejail project | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | */ | ||
20 | #include "fbuilder.h" | ||
21 | |||
22 | static FileDB *bin_out = NULL; | ||
23 | |||
24 | static void process_bin(const char *fname) { | ||
25 | assert(fname); | ||
26 | |||
27 | // process trace file | ||
28 | FILE *fp = fopen(fname, "r"); | ||
29 | if (!fp) { | ||
30 | fprintf(stderr, "Error: cannot open %s\n", fname); | ||
31 | exit(1); | ||
32 | } | ||
33 | |||
34 | char buf[MAX_BUF]; | ||
35 | while (fgets(buf, MAX_BUF, fp)) { | ||
36 | // remove \n | ||
37 | char *ptr = strchr(buf, '\n'); | ||
38 | if (ptr) | ||
39 | *ptr = '\0'; | ||
40 | |||
41 | // parse line: 4:galculator:access /etc/fonts/conf.d:0 | ||
42 | // number followed by : | ||
43 | ptr = buf; | ||
44 | if (!isdigit(*ptr)) | ||
45 | continue; | ||
46 | while (isdigit(*ptr)) | ||
47 | ptr++; | ||
48 | if (*ptr != ':') | ||
49 | continue; | ||
50 | ptr++; | ||
51 | |||
52 | // next : | ||
53 | ptr = strchr(ptr, ':'); | ||
54 | if (!ptr) | ||
55 | continue; | ||
56 | ptr++; | ||
57 | if (strncmp(ptr, "exec ", 5) == 0) | ||
58 | ptr += 5; | ||
59 | else | ||
60 | continue; | ||
61 | if (strncmp(ptr, "/bin/", 5) == 0) | ||
62 | ptr += 5; | ||
63 | else if (strncmp(ptr, "/sbin/", 6) == 0) | ||
64 | ptr += 6; | ||
65 | else if (strncmp(ptr, "/usr/bin/", 9) == 0) | ||
66 | ptr += 9; | ||
67 | else if (strncmp(ptr, "/usr/sbin/", 10) == 0) | ||
68 | ptr += 10; | ||
69 | else if (strncmp(ptr, "/usr/local/bin/", 15) == 0) | ||
70 | ptr += 15; | ||
71 | else if (strncmp(ptr, "/usr/local/sbin/", 16) == 0) | ||
72 | ptr += 16; | ||
73 | else if (strncmp(ptr, "/usr/games/", 11) == 0) | ||
74 | ptr += 12; | ||
75 | else if (strncmp(ptr, "/usr/local/games/", 17) == 0) | ||
76 | ptr += 17; | ||
77 | else | ||
78 | continue; | ||
79 | |||
80 | // end of filename | ||
81 | char *ptr2 = strchr(ptr, ':'); | ||
82 | if (!ptr2) | ||
83 | continue; | ||
84 | *ptr2 = '\0'; | ||
85 | |||
86 | bin_out = filedb_add(bin_out, ptr); | ||
87 | } | ||
88 | |||
89 | fclose(fp); | ||
90 | } | ||
91 | |||
92 | |||
93 | // process fname, fname.1, fname.2, fname.3, fname.4, fname.5 | ||
94 | void build_bin(const char *fname) { | ||
95 | assert(fname); | ||
96 | |||
97 | // run fname | ||
98 | process_bin(fname); | ||
99 | |||
100 | // run all the rest | ||
101 | struct stat s; | ||
102 | int i; | ||
103 | for (i = 1; i <= 5; i++) { | ||
104 | char *newname; | ||
105 | if (asprintf(&newname, "%s.%d", fname, i) == -1) | ||
106 | errExit("asprintf"); | ||
107 | if (stat(newname, &s) == 0) | ||
108 | process_bin(newname); | ||
109 | free(newname); | ||
110 | } | ||
111 | |||
112 | if (bin_out) { | ||
113 | printf("# private-bin "); | ||
114 | FileDB *ptr = bin_out; | ||
115 | while (ptr) { | ||
116 | printf("%s,", ptr->fname); | ||
117 | ptr = ptr->next; | ||
118 | } | ||
119 | printf("\n"); | ||
120 | } | ||
121 | } | ||
diff --git a/src/fbuilder/build_profile.c b/src/fbuilder/build_profile.c index 5fca22648..3f5fe48ca 100644 --- a/src/fbuilder/build_profile.c +++ b/src/fbuilder/build_profile.c | |||
@@ -33,6 +33,7 @@ static char *cmdlist[] = { | |||
33 | "--caps.drop=all", | 33 | "--caps.drop=all", |
34 | "--nonewprivs", | 34 | "--nonewprivs", |
35 | "--trace", | 35 | "--trace", |
36 | "--shell=none", | ||
36 | "/usr/bin/strace", // also used as a marker in build_profile() | 37 | "/usr/bin/strace", // also used as a marker in build_profile() |
37 | "-c", | 38 | "-c", |
38 | "-f", | 39 | "-f", |
@@ -56,8 +57,6 @@ static void clear_tmp_files(void) { | |||
56 | } | 57 | } |
57 | 58 | ||
58 | void build_profile(int argc, char **argv, int index) { | 59 | void build_profile(int argc, char **argv, int index) { |
59 | unlink("/tmp/strace-output"); | ||
60 | |||
61 | // next index is the application name | 60 | // next index is the application name |
62 | if (index >= argc) { | 61 | if (index >= argc) { |
63 | fprintf(stderr, "Error: application name missing\n"); | 62 | fprintf(stderr, "Error: application name missing\n"); |
@@ -136,6 +135,7 @@ void build_profile(int argc, char **argv, int index) { | |||
136 | build_dev(TRACE_OUTPUT); | 135 | build_dev(TRACE_OUTPUT); |
137 | build_etc(TRACE_OUTPUT); | 136 | build_etc(TRACE_OUTPUT); |
138 | build_var(TRACE_OUTPUT); | 137 | build_var(TRACE_OUTPUT); |
138 | build_bin(TRACE_OUTPUT); | ||
139 | printf("\n"); | 139 | printf("\n"); |
140 | 140 | ||
141 | printf("### security filters\n"); | 141 | printf("### security filters\n"); |
diff --git a/src/fbuilder/fbuilder.h b/src/fbuilder/fbuilder.h index a9049ea2d..c448f3e06 100644 --- a/src/fbuilder/fbuilder.h +++ b/src/fbuilder/fbuilder.h | |||
@@ -44,6 +44,9 @@ void build_var(const char *fname); | |||
44 | void build_tmp(const char *fname); | 44 | void build_tmp(const char *fname); |
45 | void build_dev(const char *fname); | 45 | void build_dev(const char *fname); |
46 | 46 | ||
47 | // build_bin.c | ||
48 | void build_bin(const char *fname); | ||
49 | |||
47 | // build_home.c | 50 | // build_home.c |
48 | void build_home(const char *fname); | 51 | void build_home(const char *fname); |
49 | 52 | ||
diff --git a/src/firecfg/firecfg.config b/src/firecfg/firecfg.config index 5d6afe68b..5a36f5e3e 100644 --- a/src/firecfg/firecfg.config +++ b/src/firecfg/firecfg.config | |||
@@ -20,6 +20,7 @@ amarok | |||
20 | amule | 20 | amule |
21 | android-studio | 21 | android-studio |
22 | apktool | 22 | apktool |
23 | arch-audit | ||
23 | ardour4 | 24 | ardour4 |
24 | ardour5 | 25 | ardour5 |
25 | arduino | 26 | arduino |
@@ -65,6 +66,7 @@ clementine | |||
65 | clipit | 66 | clipit |
66 | cmus | 67 | cmus |
67 | conkeror | 68 | conkeror |
69 | conky | ||
68 | corebird | 70 | corebird |
69 | cvlc | 71 | cvlc |
70 | cyberfox | 72 | cyberfox |
@@ -97,6 +99,7 @@ evolution | |||
97 | exiftool | 99 | exiftool |
98 | fbreader | 100 | fbreader |
99 | feh | 101 | feh |
102 | ffmpeg | ||
100 | file-roller | 103 | file-roller |
101 | filezilla | 104 | filezilla |
102 | firefox | 105 | firefox |
@@ -290,7 +293,7 @@ soundconverter | |||
290 | spotify | 293 | spotify |
291 | sqlitebrowser | 294 | sqlitebrowser |
292 | ssh | 295 | ssh |
293 | ssh-agent | 296 | # ssh-agent - problems on Arch with Fish shell (#1568) |
294 | start-tor-browser | 297 | start-tor-browser |
295 | steam | 298 | steam |
296 | stellarium | 299 | stellarium |
diff --git a/src/firecfg/main.c b/src/firecfg/main.c index 1ecfbf524..5928b9ae5 100644 --- a/src/firecfg/main.c +++ b/src/firecfg/main.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <errno.h> | 31 | #include <errno.h> |
32 | #include <sys/mman.h> | 32 | #include <sys/mman.h> |
33 | #include <pwd.h> | 33 | #include <pwd.h> |
34 | #include <dirent.h> | ||
34 | 35 | ||
35 | #include "../include/common.h" | 36 | #include "../include/common.h" |
36 | static int arg_debug = 0; | 37 | static int arg_debug = 0; |
@@ -277,7 +278,8 @@ static void set_file(const char *name, const char *firejail_exec) { | |||
277 | free(fname); | 278 | free(fname); |
278 | } | 279 | } |
279 | 280 | ||
280 | static void set_links(void) { | 281 | // parse /usr/lib/firejail/firecfg.cfg file |
282 | static void set_links_firecfg(void) { | ||
281 | char *cfgfile; | 283 | char *cfgfile; |
282 | if (asprintf(&cfgfile, "%s/firejail/firecfg.config", LIBDIR) == -1) | 284 | if (asprintf(&cfgfile, "%s/firejail/firecfg.config", LIBDIR) == -1) |
283 | errExit("asprintf"); | 285 | errExit("asprintf"); |
@@ -286,12 +288,13 @@ static void set_links(void) { | |||
286 | if (asprintf(&firejail_exec, "%s/bin/firejail", PREFIX) == -1) | 288 | if (asprintf(&firejail_exec, "%s/bin/firejail", PREFIX) == -1) |
287 | errExit("asprintf"); | 289 | errExit("asprintf"); |
288 | 290 | ||
291 | // parse /usr/lib/firejail/firecfg.cfg file | ||
289 | FILE *fp = fopen(cfgfile, "r"); | 292 | FILE *fp = fopen(cfgfile, "r"); |
290 | if (!fp) { | 293 | if (!fp) { |
291 | fprintf(stderr, "Error: cannot open %s\n", cfgfile); | 294 | fprintf(stderr, "Error: cannot open %s\n", cfgfile); |
292 | exit(1); | 295 | exit(1); |
293 | } | 296 | } |
294 | printf("Configuring symlinks in /usr/local/bin\n"); | 297 | printf("Configuring symlinks in /usr/local/bin based on firecfg.config\n"); |
295 | 298 | ||
296 | char buf[MAX_BUF]; | 299 | char buf[MAX_BUF]; |
297 | int lineno = 0; | 300 | int lineno = 0; |
@@ -330,7 +333,69 @@ static void set_links(void) { | |||
330 | free(firejail_exec); | 333 | free(firejail_exec); |
331 | } | 334 | } |
332 | 335 | ||
333 | int have_profile(const char *filename) { | 336 | // parse ~/.config/firejail/ directory |
337 | static void set_links_homedir(const char *homedir) { | ||
338 | assert(homedir); | ||
339 | |||
340 | // check firejail config directory | ||
341 | char *dirname; | ||
342 | if (asprintf(&dirname, "%s/.config/firejail", homedir) == -1) | ||
343 | errExit("asprintf"); | ||
344 | struct stat s; | ||
345 | if (stat(dirname, &s) != 0) { | ||
346 | free(dirname); | ||
347 | return; | ||
348 | } | ||
349 | |||
350 | char *firejail_exec; | ||
351 | if (asprintf(&firejail_exec, "%s/bin/firejail", PREFIX) == -1) | ||
352 | errExit("asprintf"); | ||
353 | |||
354 | // parse ~/.config/firejail/ directory | ||
355 | printf("\nConfiguring symlinks in /usr/local/bin based on local firejail config directory\n"); | ||
356 | |||
357 | DIR *dir = opendir(dirname); | ||
358 | if (!dir) { | ||
359 | fprintf(stderr, "Error: cannot open ~/.config/firejail directory\n"); | ||
360 | free(dirname); | ||
361 | return; | ||
362 | } | ||
363 | |||
364 | struct dirent *entry; | ||
365 | while ((entry = readdir(dir))) { | ||
366 | if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) | ||
367 | continue; | ||
368 | |||
369 | char *exec = strdup(entry->d_name); | ||
370 | if (!exec) | ||
371 | errExit("strdup"); | ||
372 | char *ptr = strrchr(exec, '.'); | ||
373 | if (!ptr) { | ||
374 | free(exec); | ||
375 | continue; | ||
376 | } | ||
377 | if (strcmp(ptr, ".profile") != 0) { | ||
378 | free(exec); | ||
379 | continue; | ||
380 | } | ||
381 | |||
382 | *ptr = '\0'; | ||
383 | set_file(exec, firejail_exec); | ||
384 | free(exec); | ||
385 | } | ||
386 | closedir(dir); | ||
387 | |||
388 | free(firejail_exec); | ||
389 | } | ||
390 | |||
391 | // look for a profile file in /etc/firejail diectory and in homedir/.config/firejail directory | ||
392 | static int have_profile(const char *filename, const char *homedir) { | ||
393 | assert(filename); | ||
394 | assert(homedir); | ||
395 | |||
396 | if (arg_debug) | ||
397 | printf("checking profile for %s\n", filename); | ||
398 | |||
334 | // remove .desktop extension | 399 | // remove .desktop extension |
335 | char *f1 = strdup(filename); | 400 | char *f1 = strdup(filename); |
336 | if (!f1) | 401 | if (!f1) |
@@ -338,15 +403,29 @@ int have_profile(const char *filename) { | |||
338 | f1[strlen(filename) - 8] = '\0'; | 403 | f1[strlen(filename) - 8] = '\0'; |
339 | 404 | ||
340 | // build profile name | 405 | // build profile name |
341 | char *profname; | 406 | char *profname1; |
342 | if (asprintf(&profname, "%s/%s.profile", SYSCONFDIR, f1) == -1) | 407 | char *profname2; |
408 | if (asprintf(&profname1, "%s/%s.profile", SYSCONFDIR, f1) == -1) | ||
409 | errExit("asprintf"); | ||
410 | if (asprintf(&profname2, "%s/.config/firejail/%s.profile", homedir, f1) == -1) | ||
343 | errExit("asprintf"); | 411 | errExit("asprintf"); |
344 | 412 | ||
345 | struct stat s; | 413 | int rv = 0; |
346 | int rv = stat(profname, &s); | 414 | if (access(profname1, R_OK) == 0) { |
415 | if (arg_debug) | ||
416 | printf("found %s\n", profname1); | ||
417 | rv = 1; | ||
418 | } | ||
419 | else if (access(profname2, R_OK) == 0) { | ||
420 | if (arg_debug) | ||
421 | printf("found %s\n", profname2); | ||
422 | rv = 1; | ||
423 | } | ||
424 | |||
347 | free(f1); | 425 | free(f1); |
348 | free(profname); | 426 | free(profname1); |
349 | return (rv == 0)? 1: 0; | 427 | free(profname2); |
428 | return rv; | ||
350 | } | 429 | } |
351 | 430 | ||
352 | static void fix_desktop_files(char *homedir) { | 431 | static void fix_desktop_files(char *homedir) { |
@@ -411,7 +490,7 @@ static void fix_desktop_files(char *homedir) { | |||
411 | errExit("stat"); | 490 | errExit("stat"); |
412 | 491 | ||
413 | // no profile in /etc/firejail, no desktop file fixing | 492 | // no profile in /etc/firejail, no desktop file fixing |
414 | if (!have_profile(filename)) | 493 | if (!have_profile(filename, homedir)) |
415 | continue; | 494 | continue; |
416 | 495 | ||
417 | /* coverity[toctou] */ | 496 | /* coverity[toctou] */ |
@@ -599,7 +678,7 @@ int main(int argc, char **argv) { | |||
599 | } | 678 | } |
600 | } | 679 | } |
601 | } | 680 | } |
602 | set_links(); | 681 | set_links_firecfg(); |
603 | 682 | ||
604 | 683 | ||
605 | 684 | ||
@@ -623,6 +702,9 @@ int main(int argc, char **argv) { | |||
623 | goto errexit; | 702 | goto errexit; |
624 | } | 703 | } |
625 | 704 | ||
705 | // running as root | ||
706 | set_links_homedir(home); | ||
707 | |||
626 | // drop permissions | 708 | // drop permissions |
627 | if (setgroups(0, NULL) < 0) | 709 | if (setgroups(0, NULL) < 0) |
628 | errExit("setgroups"); | 710 | errExit("setgroups"); |
diff --git a/src/firejail/util.c b/src/firejail/util.c index 3e0729620..4d1c94c25 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c | |||
@@ -196,7 +196,7 @@ static int copy_file_by_fd(int src, int dst) { | |||
196 | done += rv; | 196 | done += rv; |
197 | } | 197 | } |
198 | } | 198 | } |
199 | fflush(0); | 199 | // fflush(0); |
200 | return 0; | 200 | return 0; |
201 | } | 201 | } |
202 | 202 | ||
diff --git a/src/libtrace/libtrace.c b/src/libtrace/libtrace.c index 5cdb254a3..04cf64997 100644 --- a/src/libtrace/libtrace.c +++ b/src/libtrace/libtrace.c | |||
@@ -673,3 +673,15 @@ int setresgid(gid_t rgid, gid_t egid, gid_t sgid) { | |||
673 | 673 | ||
674 | return rv; | 674 | return rv; |
675 | } | 675 | } |
676 | |||
677 | // every time a new process is started, this gets called | ||
678 | // it can be used to build things like private-bin | ||
679 | __attribute__((constructor)) | ||
680 | static void log_exec(int argc, char** argv) { | ||
681 | static char buf[PATH_MAX + 1]; | ||
682 | int rv = readlink("/proc/self/exe", buf, PATH_MAX); | ||
683 | if (rv != -1) { | ||
684 | buf[rv] = '\0'; // readlink does not add a '\0' at the end | ||
685 | printf("%u:%s:exec %s:0\n", pid(), name(), buf); | ||
686 | } | ||
687 | } | ||
diff --git a/src/man/firejail.txt b/src/man/firejail.txt index f205bfa30..9bbb224e1 100644 --- a/src/man/firejail.txt +++ b/src/man/firejail.txt | |||
@@ -1338,13 +1338,13 @@ $ ps | |||
1338 | .br | 1338 | .br |
1339 | 48 pts/0 00:00:00 ps | 1339 | 48 pts/0 00:00:00 ps |
1340 | .br | 1340 | .br |
1341 | $ | 1341 | $ |
1342 | .br | 1342 | .br |
1343 | 1343 | ||
1344 | 1344 | ||
1345 | .TP | 1345 | .TP |
1346 | \fB\-\-private-dev | 1346 | \fB\-\-private-dev |
1347 | Create a new /dev directory. Only dri, null, full, zero, tty, pts, ptmx, random, snd, urandom, video, log and shm devices are available. | 1347 | Create a new /dev directory. Only disc, dri, null, full, zero, tty, pts, ptmx, random, snd, urandom, video, log and shm devices are available. |
1348 | .br | 1348 | .br |
1349 | 1349 | ||
1350 | .br | 1350 | .br |
@@ -1358,7 +1358,7 @@ Child process initialized | |||
1358 | .br | 1358 | .br |
1359 | $ ls /dev | 1359 | $ ls /dev |
1360 | .br | 1360 | .br |
1361 | dri full log null ptmx pts random shm snd tty urandom zero | 1361 | cdrom cdrw dri dvd dvdrw full log null ptmx pts random shm snd sr0 tty urandom zero |
1362 | .br | 1362 | .br |
1363 | $ | 1363 | $ |
1364 | .TP | 1364 | .TP |