diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/firejail/fs_whitelist.c | 94 | ||||
-rw-r--r-- | src/firejail/main.c | 2 | ||||
-rw-r--r-- | src/firejail/util.c | 4 | ||||
-rw-r--r-- | src/man/firejail.txt | 9 |
4 files changed, 105 insertions, 4 deletions
diff --git a/src/firejail/fs_whitelist.c b/src/firejail/fs_whitelist.c index d018554d5..95238a956 100644 --- a/src/firejail/fs_whitelist.c +++ b/src/firejail/fs_whitelist.c | |||
@@ -27,11 +27,84 @@ | |||
27 | #include <fcntl.h> | 27 | #include <fcntl.h> |
28 | #include <errno.h> | 28 | #include <errno.h> |
29 | 29 | ||
30 | static char *dentry[] = { | ||
31 | "Downloads", | ||
32 | "Загрузки", | ||
33 | "Téléchargement", | ||
34 | NULL | ||
35 | }; | ||
36 | |||
37 | #define MAXBUF 4098 | ||
38 | static char *resolve_downloads(void) { | ||
39 | char *fname; | ||
40 | struct stat s; | ||
41 | |||
42 | // try a well known download directory name | ||
43 | int i = 0; | ||
44 | while (dentry[i] != NULL) { | ||
45 | if (asprintf(&fname, "%s/%s", cfg.homedir, dentry[i]) == -1) | ||
46 | errExit("asprintf"); | ||
47 | |||
48 | if (stat(fname, &s) == 0) { | ||
49 | free(fname); | ||
50 | if (arg_debug) | ||
51 | printf("Downloads directory resolved as \"Downloads\"\n"); | ||
52 | |||
53 | char *rv; | ||
54 | if (asprintf(&rv, "whitelist ~/%s", dentry[i]) == -1) | ||
55 | errExit("asprintf"); | ||
56 | return rv; | ||
57 | } | ||
58 | free(fname); | ||
59 | i++; | ||
60 | } | ||
61 | |||
62 | // try a name form ~/.config/user-dirs.dirs | ||
63 | if (asprintf(&fname, "%s/.config/user-dirs.dirs", cfg.homedir) == -1) | ||
64 | errExit("asprintf"); | ||
65 | FILE *fp = fopen(fname, "r"); | ||
66 | if (!fp) { | ||
67 | free(fname); | ||
68 | return NULL; | ||
69 | } | ||
70 | free(fname); | ||
71 | |||
72 | // extract downloads directory | ||
73 | char buf[MAXBUF]; | ||
74 | while (fgets(buf, MAXBUF, fp)) { | ||
75 | char *ptr = buf; | ||
76 | |||
77 | // skip blanks | ||
78 | while (*ptr == ' ' || *ptr == '\t') | ||
79 | ptr++; | ||
80 | if (*ptr == '\0' || *ptr == '\n' || *ptr == '#') | ||
81 | continue; | ||
82 | |||
83 | if (strncmp(ptr, "XDG_DOWNLOAD_DIR=\"$HOME/", 24) == 0) { | ||
84 | char *ptr1 = strchr(ptr + 24, '"'); | ||
85 | if (ptr1) { | ||
86 | *ptr1 = '\0'; | ||
87 | fclose(fp); | ||
88 | if (arg_debug) | ||
89 | printf("Downloads directory resolved as \"%s\"\n", ptr + 24); | ||
90 | |||
91 | char *rv; | ||
92 | if (asprintf(&rv, "whitelist ~/%s", ptr + 24) == -1) | ||
93 | errExit("asprintf"); | ||
94 | return rv; | ||
95 | } | ||
96 | } | ||
97 | } | ||
98 | fclose(fp); | ||
99 | |||
100 | return NULL; | ||
101 | } | ||
102 | |||
30 | static int mkpath(const char* path, mode_t mode) { | 103 | static int mkpath(const char* path, mode_t mode) { |
31 | assert(path && *path); | 104 | assert(path && *path); |
32 | 105 | ||
33 | mode |= 0111; | 106 | mode |= 0111; |
34 | 107 | ||
35 | // create directories with uid/gid as root or as current user if inside home directory | 108 | // create directories with uid/gid as root or as current user if inside home directory |
36 | uid_t uid = getuid(); | 109 | uid_t uid = getuid(); |
37 | gid_t gid = getgid(); | 110 | gid_t gid = getgid(); |
@@ -211,6 +284,25 @@ void fs_whitelist(void) { | |||
211 | continue; | 284 | continue; |
212 | } | 285 | } |
213 | 286 | ||
287 | // resolve ${DOWNLOADS} | ||
288 | if (strcmp(entry->data + 10, "${DOWNLOADS}") == 0) { | ||
289 | char *tmp = resolve_downloads(); | ||
290 | if (tmp) | ||
291 | entry->data = tmp; | ||
292 | else { | ||
293 | *entry->data = '\0'; | ||
294 | fprintf(stderr, "***\n"); | ||
295 | fprintf(stderr, "*** Error: cannot whitelist Downloads directory\n"); | ||
296 | fprintf(stderr, "***\n"); | ||
297 | fprintf(stderr, "*** Any file saved in this directory will be lost when the sandbox is closed.\n"); | ||
298 | fprintf(stderr, "*** Please contact the developer. Workaround:\n"); | ||
299 | fprintf(stderr, "***\n"); | ||
300 | fprintf(stderr, "*** firejail --ignore=whitelist program-name\n"); | ||
301 | fprintf(stderr, "***\n"); | ||
302 | continue; | ||
303 | } | ||
304 | } | ||
305 | |||
214 | // replace ~/ or ${HOME} into /home/username | 306 | // replace ~/ or ${HOME} into /home/username |
215 | new_name = expand_home(entry->data + 10, cfg.homedir); | 307 | new_name = expand_home(entry->data + 10, cfg.homedir); |
216 | assert(new_name); | 308 | assert(new_name); |
diff --git a/src/firejail/main.c b/src/firejail/main.c index 02eab1a86..2981683aa 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c | |||
@@ -737,7 +737,7 @@ int main(int argc, char **argv) { | |||
737 | } | 737 | } |
738 | else if (strncmp(argv[i], "--ignore=", 9) == 0) { | 738 | else if (strncmp(argv[i], "--ignore=", 9) == 0) { |
739 | if (custom_profile) { | 739 | if (custom_profile) { |
740 | fprintf(stderr, "Error: please use --profile after --include\n"); | 740 | fprintf(stderr, "Error: please use --profile after --ignore\n"); |
741 | exit(1); | 741 | exit(1); |
742 | } | 742 | } |
743 | 743 | ||
diff --git a/src/firejail/util.c b/src/firejail/util.c index 0d9479a02..45f7ec364 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c | |||
@@ -574,13 +574,15 @@ void invalid_filename(const char *fname) { | |||
574 | assert(fname); | 574 | assert(fname); |
575 | const char *ptr = fname; | 575 | const char *ptr = fname; |
576 | 576 | ||
577 | if (arg_debug && arg_debug_check_filename) | 577 | if (arg_debug_check_filename) |
578 | printf("Checking filename %s\n", fname); | 578 | printf("Checking filename %s\n", fname); |
579 | 579 | ||
580 | if (strncmp(ptr, "${HOME}", 7) == 0) | 580 | if (strncmp(ptr, "${HOME}", 7) == 0) |
581 | ptr = fname + 7; | 581 | ptr = fname + 7; |
582 | else if (strncmp(ptr, "${PATH}", 7) == 0) | 582 | else if (strncmp(ptr, "${PATH}", 7) == 0) |
583 | ptr = fname + 7; | 583 | ptr = fname + 7; |
584 | else if (strcmp(fname, "${DOWNLOADS}") == 0) | ||
585 | return; | ||
584 | 586 | ||
585 | int len = strlen(ptr); | 587 | int len = strlen(ptr); |
586 | // file globbing ('*') is allowed | 588 | // file globbing ('*') is allowed |
diff --git a/src/man/firejail.txt b/src/man/firejail.txt index 39e0dbaf7..4f9f0cba9 100644 --- a/src/man/firejail.txt +++ b/src/man/firejail.txt | |||
@@ -155,8 +155,15 @@ Define a custom whitelist Linux capabilities filter. | |||
155 | Example: | 155 | Example: |
156 | .br | 156 | .br |
157 | $ sudo firejail \-\-caps.keep=chown,net_bind_service,setgid,\\ | 157 | $ sudo firejail \-\-caps.keep=chown,net_bind_service,setgid,\\ |
158 | setuid "/etc/init.d/nginx start && sleep inf" | 158 | setuid /etc/init.d/nginx start |
159 | .br | ||
159 | 160 | ||
161 | .br | ||
162 | A short note about mixing \-\-whitelist and \-\-read-only options. Whitelisted directories | ||
163 | should be made read-only independently. Making a parent directory read-only, will not | ||
164 | make the whitelist read-only. Example: | ||
165 | .br | ||
166 | $ firejail --whitelist=~/work --read-only=~/ --read-only=~/work | ||
160 | .TP | 167 | .TP |
161 | \fB\-\-caps.print=name | 168 | \fB\-\-caps.print=name |
162 | Print the caps filter for the sandbox identified by name. | 169 | Print the caps filter for the sandbox identified by name. |