diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/fcopy/main.c | 16 | ||||
-rw-r--r-- | src/firejail/appimage.c | 2 | ||||
-rw-r--r-- | src/firejail/cgroup.c | 2 | ||||
-rw-r--r-- | src/firejail/firejail.h | 2 | ||||
-rw-r--r-- | src/firejail/fs_bin.c | 55 | ||||
-rw-r--r-- | src/firejail/fs_etc.c | 2 | ||||
-rw-r--r-- | src/firejail/fs_home.c | 4 | ||||
-rw-r--r-- | src/firejail/fs_hostname.c | 2 | ||||
-rw-r--r-- | src/firejail/fs_mkdir.c | 4 | ||||
-rw-r--r-- | src/firejail/main.c | 16 | ||||
-rw-r--r-- | src/firejail/netfilter.c | 2 | ||||
-rw-r--r-- | src/firejail/netns.c | 2 | ||||
-rw-r--r-- | src/firejail/output.c | 2 | ||||
-rw-r--r-- | src/firejail/profile.c | 10 | ||||
-rw-r--r-- | src/firejail/util.c | 19 |
15 files changed, 106 insertions, 34 deletions
diff --git a/src/fcopy/main.c b/src/fcopy/main.c index e7b4ffa8a..cbb551125 100644 --- a/src/fcopy/main.c +++ b/src/fcopy/main.c | |||
@@ -41,6 +41,11 @@ static void copy_file(const char *srcname, const char *destname, mode_t mode, ui | |||
41 | assert(destname); | 41 | assert(destname); |
42 | mode &= 07777; | 42 | mode &= 07777; |
43 | 43 | ||
44 | // don't copy the file if it is already there | ||
45 | struct stat s; | ||
46 | if (stat(destname, &s) == 0) | ||
47 | return; | ||
48 | |||
44 | // open source | 49 | // open source |
45 | int src = open(srcname, O_RDONLY); | 50 | int src = open(srcname, O_RDONLY); |
46 | if (src < 0) { | 51 | if (src < 0) { |
@@ -113,10 +118,18 @@ void copy_link(const char *target, const char *linkpath, mode_t mode, uid_t uid, | |||
113 | (void) mode; | 118 | (void) mode; |
114 | (void) uid; | 119 | (void) uid; |
115 | (void) gid; | 120 | (void) gid; |
121 | |||
122 | // if the link is already there, don't create it | ||
123 | struct stat s; | ||
124 | if (stat(linkpath, &s) == 0) | ||
125 | return; | ||
126 | |||
116 | char *rp = realpath(target, NULL); | 127 | char *rp = realpath(target, NULL); |
117 | if (rp) { | 128 | if (rp) { |
118 | if (symlink(rp, linkpath) == -1) | 129 | if (symlink(rp, linkpath) == -1) { |
130 | free(rp); | ||
119 | goto errout; | 131 | goto errout; |
132 | } | ||
120 | free(rp); | 133 | free(rp); |
121 | } | 134 | } |
122 | else | 135 | else |
@@ -129,6 +142,7 @@ errout: | |||
129 | } | 142 | } |
130 | 143 | ||
131 | 144 | ||
145 | |||
132 | static int first = 1; | 146 | static int first = 1; |
133 | static int fs_copydir(const char *infname, const struct stat *st, int ftype, struct FTW *sftw) { | 147 | static int fs_copydir(const char *infname, const struct stat *st, int ftype, struct FTW *sftw) { |
134 | (void) st; | 148 | (void) st; |
diff --git a/src/firejail/appimage.c b/src/firejail/appimage.c index 0f7ab40ff..2a045f628 100644 --- a/src/firejail/appimage.c +++ b/src/firejail/appimage.c | |||
@@ -45,7 +45,7 @@ void appimage_set(const char *appimage) { | |||
45 | 45 | ||
46 | #ifdef LOOP_CTL_GET_FREE | 46 | #ifdef LOOP_CTL_GET_FREE |
47 | // check appimage file | 47 | // check appimage file |
48 | invalid_filename(appimage); | 48 | invalid_filename(appimage, 0); // no globbing |
49 | if (access(appimage, R_OK) == -1) { | 49 | if (access(appimage, R_OK) == -1) { |
50 | fprintf(stderr, "Error: cannot access AppImage file\n"); | 50 | fprintf(stderr, "Error: cannot access AppImage file\n"); |
51 | exit(1); | 51 | exit(1); |
diff --git a/src/firejail/cgroup.c b/src/firejail/cgroup.c index 70f07dd23..8d6496aab 100644 --- a/src/firejail/cgroup.c +++ b/src/firejail/cgroup.c | |||
@@ -72,7 +72,7 @@ errout: | |||
72 | void set_cgroup(const char *path) { | 72 | void set_cgroup(const char *path) { |
73 | EUID_ASSERT(); | 73 | EUID_ASSERT(); |
74 | 74 | ||
75 | invalid_filename(path); | 75 | invalid_filename(path, 0); // no globbing |
76 | 76 | ||
77 | // path starts with /sys/fs/cgroup | 77 | // path starts with /sys/fs/cgroup |
78 | if (strncmp(path, "/sys/fs/cgroup", 14) != 0) | 78 | if (strncmp(path, "/sys/fs/cgroup", 14) != 0) |
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index b9eb68fb0..e10a5d346 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -499,7 +499,7 @@ void notify_other(int fd); | |||
499 | char *expand_home(const char *path, const char* homedir); | 499 | char *expand_home(const char *path, const char* homedir); |
500 | const char *gnu_basename(const char *path); | 500 | const char *gnu_basename(const char *path); |
501 | uid_t pid_get_uid(pid_t pid); | 501 | uid_t pid_get_uid(pid_t pid); |
502 | void invalid_filename(const char *fname); | 502 | void invalid_filename(const char *fname, int globbing); |
503 | uid_t get_group_id(const char *group); | 503 | uid_t get_group_id(const char *group); |
504 | int remove_directory(const char *path); | 504 | int remove_directory(const char *path); |
505 | void flush_stdin(void); | 505 | void flush_stdin(void); |
diff --git a/src/firejail/fs_bin.c b/src/firejail/fs_bin.c index 9aa227caf..6bd7ecd17 100644 --- a/src/firejail/fs_bin.c +++ b/src/firejail/fs_bin.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <sys/types.h> | 23 | #include <sys/types.h> |
24 | #include <sys/wait.h> | 24 | #include <sys/wait.h> |
25 | #include <unistd.h> | 25 | #include <unistd.h> |
26 | #include <glob.h> | ||
26 | 27 | ||
27 | static char *paths[] = { | 28 | static char *paths[] = { |
28 | "/usr/local/bin", | 29 | "/usr/local/bin", |
@@ -146,11 +147,13 @@ errexit: | |||
146 | } | 147 | } |
147 | 148 | ||
148 | static void duplicate(char *fname, FILE *fplist) { | 149 | static void duplicate(char *fname, FILE *fplist) { |
150 | assert(fname); | ||
151 | |||
149 | if (*fname == '~' || strstr(fname, "..")) { | 152 | if (*fname == '~' || strstr(fname, "..")) { |
150 | fprintf(stderr, "Error: \"%s\" is an invalid filename\n", fname); | 153 | fprintf(stderr, "Error: \"%s\" is an invalid filename\n", fname); |
151 | exit(1); | 154 | exit(1); |
152 | } | 155 | } |
153 | invalid_filename(fname); | 156 | invalid_filename(fname, 0); // no globbing |
154 | 157 | ||
155 | char *full_path; | 158 | char *full_path; |
156 | if (*fname == '/') { | 159 | if (*fname == '/') { |
@@ -203,6 +206,52 @@ static void duplicate(char *fname, FILE *fplist) { | |||
203 | free(full_path); | 206 | free(full_path); |
204 | } | 207 | } |
205 | 208 | ||
209 | static void globbing(char *fname, FILE *fplist) { | ||
210 | assert(fname); | ||
211 | |||
212 | // go directly to duplicate() if no globbing char is present - see man 7 glob | ||
213 | if (strrchr(fname, '*') == NULL && | ||
214 | strrchr(fname, '[') == NULL && | ||
215 | strrchr(fname, '?') == NULL) | ||
216 | return duplicate(fname, fplist); | ||
217 | |||
218 | // loop through paths[] | ||
219 | int i = 0; | ||
220 | while (paths[i]) { | ||
221 | // private-bin-no-local can be disabled in /etc/firejail/firejail.config | ||
222 | if (checkcfg(CFG_PRIVATE_BIN_NO_LOCAL) && strstr(paths[i], "local/")) { | ||
223 | i++; | ||
224 | continue; | ||
225 | } | ||
226 | |||
227 | // check file | ||
228 | char *pattern; | ||
229 | if (asprintf(&pattern, "%s/%s", paths[i], fname) == -1) | ||
230 | errExit("asprintf"); | ||
231 | |||
232 | // globbing | ||
233 | glob_t globbuf; | ||
234 | int globerr = glob(pattern, GLOB_NOCHECK | GLOB_NOSORT | GLOB_PERIOD, NULL, &globbuf); | ||
235 | if (globerr) { | ||
236 | fprintf(stderr, "Error: failed to glob private-bin pattern %s\n", pattern); | ||
237 | exit(1); | ||
238 | } | ||
239 | |||
240 | size_t j; | ||
241 | for (j = 0; j < globbuf.gl_pathc; j++) { | ||
242 | assert(globbuf.gl_pathv[j]); | ||
243 | // testing for GLOB_NOCHECK - no pattern matched returns the original pattern | ||
244 | if (strcmp(globbuf.gl_pathv[j], pattern) == 0) | ||
245 | continue; | ||
246 | |||
247 | duplicate(globbuf.gl_pathv[j], fplist); | ||
248 | } | ||
249 | |||
250 | globfree(&globbuf); | ||
251 | free(pattern); | ||
252 | i++; | ||
253 | } | ||
254 | } | ||
206 | 255 | ||
207 | void fs_private_bin_list(void) { | 256 | void fs_private_bin_list(void) { |
208 | char *private_list = cfg.bin_private_keep; | 257 | char *private_list = cfg.bin_private_keep; |
@@ -228,9 +277,9 @@ void fs_private_bin_list(void) { | |||
228 | } | 277 | } |
229 | 278 | ||
230 | char *ptr = strtok(dlist, ","); | 279 | char *ptr = strtok(dlist, ","); |
231 | duplicate(ptr, fplist); | 280 | globbing(ptr, fplist); |
232 | while ((ptr = strtok(NULL, ",")) != NULL) | 281 | while ((ptr = strtok(NULL, ",")) != NULL) |
233 | duplicate(ptr, fplist); | 282 | globbing(ptr, fplist); |
234 | free(dlist); | 283 | free(dlist); |
235 | fs_logger_print(); | 284 | fs_logger_print(); |
236 | if (fplist) | 285 | if (fplist) |
diff --git a/src/firejail/fs_etc.c b/src/firejail/fs_etc.c index b0835d50b..9502844b2 100644 --- a/src/firejail/fs_etc.c +++ b/src/firejail/fs_etc.c | |||
@@ -103,7 +103,7 @@ static void duplicate(const char *fname, const char *private_dir, const char *pr | |||
103 | fprintf(stderr, "Error: \"%s\" is an invalid filename\n", fname); | 103 | fprintf(stderr, "Error: \"%s\" is an invalid filename\n", fname); |
104 | exit(1); | 104 | exit(1); |
105 | } | 105 | } |
106 | invalid_filename(fname); | 106 | invalid_filename(fname, 0); // no globbing |
107 | 107 | ||
108 | char *src; | 108 | char *src; |
109 | if (asprintf(&src, "%s/%s", private_dir, fname) == -1) | 109 | if (asprintf(&src, "%s/%s", private_dir, fname) == -1) |
diff --git a/src/firejail/fs_home.c b/src/firejail/fs_home.c index 9e3678c33..0de003e58 100644 --- a/src/firejail/fs_home.c +++ b/src/firejail/fs_home.c | |||
@@ -325,7 +325,7 @@ void fs_private(void) { | |||
325 | // check new private home directory (--private= option) - exit if it fails | 325 | // check new private home directory (--private= option) - exit if it fails |
326 | void fs_check_private_dir(void) { | 326 | void fs_check_private_dir(void) { |
327 | EUID_ASSERT(); | 327 | EUID_ASSERT(); |
328 | invalid_filename(cfg.home_private); | 328 | invalid_filename(cfg.home_private, 0); // no globbing |
329 | 329 | ||
330 | // Expand the home directory | 330 | // Expand the home directory |
331 | char *tmp = expand_home(cfg.home_private, cfg.homedir); | 331 | char *tmp = expand_home(cfg.home_private, cfg.homedir); |
@@ -367,7 +367,7 @@ static char *check_dir_or_file(const char *name) { | |||
367 | assert(name); | 367 | assert(name); |
368 | 368 | ||
369 | // basic checks | 369 | // basic checks |
370 | invalid_filename(name); | 370 | invalid_filename(name, 0); // no globbing |
371 | if (arg_debug) | 371 | if (arg_debug) |
372 | printf("Private home: checking %s\n", name); | 372 | printf("Private home: checking %s\n", name); |
373 | 373 | ||
diff --git a/src/firejail/fs_hostname.c b/src/firejail/fs_hostname.c index 42255070c..0cf715fe2 100644 --- a/src/firejail/fs_hostname.c +++ b/src/firejail/fs_hostname.c | |||
@@ -129,7 +129,7 @@ void fs_resolvconf(void) { | |||
129 | 129 | ||
130 | char *fs_check_hosts_file(const char *fname) { | 130 | char *fs_check_hosts_file(const char *fname) { |
131 | assert(fname); | 131 | assert(fname); |
132 | invalid_filename(fname); | 132 | invalid_filename(fname, 0); // no globbing |
133 | char *rv = expand_home(fname, cfg.homedir); | 133 | char *rv = expand_home(fname, cfg.homedir); |
134 | 134 | ||
135 | // no a link | 135 | // no a link |
diff --git a/src/firejail/fs_mkdir.c b/src/firejail/fs_mkdir.c index 20ffe825a..7975ae323 100644 --- a/src/firejail/fs_mkdir.c +++ b/src/firejail/fs_mkdir.c | |||
@@ -59,7 +59,7 @@ void fs_mkdir(const char *name) { | |||
59 | EUID_ASSERT(); | 59 | EUID_ASSERT(); |
60 | 60 | ||
61 | // check directory name | 61 | // check directory name |
62 | invalid_filename(name); | 62 | invalid_filename(name, 0); // no globbing |
63 | char *expanded = expand_home(name, cfg.homedir); | 63 | char *expanded = expand_home(name, cfg.homedir); |
64 | if (strncmp(expanded, cfg.homedir, strlen(cfg.homedir)) != 0 && | 64 | if (strncmp(expanded, cfg.homedir, strlen(cfg.homedir)) != 0 && |
65 | strncmp(expanded, "/tmp", 4) != 0) { | 65 | strncmp(expanded, "/tmp", 4) != 0) { |
@@ -99,7 +99,7 @@ void fs_mkfile(const char *name) { | |||
99 | EUID_ASSERT(); | 99 | EUID_ASSERT(); |
100 | 100 | ||
101 | // check file name | 101 | // check file name |
102 | invalid_filename(name); | 102 | invalid_filename(name, 0); // no globbing |
103 | char *expanded = expand_home(name, cfg.homedir); | 103 | char *expanded = expand_home(name, cfg.homedir); |
104 | if (strncmp(expanded, cfg.homedir, strlen(cfg.homedir)) != 0 && | 104 | if (strncmp(expanded, cfg.homedir, strlen(cfg.homedir)) != 0 && |
105 | strncmp(expanded, "/tmp", 4) != 0) { | 105 | strncmp(expanded, "/tmp", 4) != 0) { |
diff --git a/src/firejail/main.c b/src/firejail/main.c index 54cbf1526..458bba6f6 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c | |||
@@ -572,7 +572,7 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
572 | exit(1); | 572 | exit(1); |
573 | } | 573 | } |
574 | char *path = argv[i + 1]; | 574 | char *path = argv[i + 1]; |
575 | invalid_filename(path); | 575 | invalid_filename(path, 0); // no globbing |
576 | if (strstr(path, "..")) { | 576 | if (strstr(path, "..")) { |
577 | fprintf(stderr, "Error: invalid file name %s\n", path); | 577 | fprintf(stderr, "Error: invalid file name %s\n", path); |
578 | exit(1); | 578 | exit(1); |
@@ -596,13 +596,13 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
596 | exit(1); | 596 | exit(1); |
597 | } | 597 | } |
598 | char *path1 = argv[i + 1]; | 598 | char *path1 = argv[i + 1]; |
599 | invalid_filename(path1); | 599 | invalid_filename(path1, 0); // no globbing |
600 | if (strstr(path1, "..")) { | 600 | if (strstr(path1, "..")) { |
601 | fprintf(stderr, "Error: invalid file name %s\n", path1); | 601 | fprintf(stderr, "Error: invalid file name %s\n", path1); |
602 | exit(1); | 602 | exit(1); |
603 | } | 603 | } |
604 | char *path2 = argv[i + 2]; | 604 | char *path2 = argv[i + 2]; |
605 | invalid_filename(path2); | 605 | invalid_filename(path2, 0); // no globbing |
606 | if (strstr(path2, "..")) { | 606 | if (strstr(path2, "..")) { |
607 | fprintf(stderr, "Error: invalid file name %s\n", path2); | 607 | fprintf(stderr, "Error: invalid file name %s\n", path2); |
608 | exit(1); | 608 | exit(1); |
@@ -626,7 +626,7 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
626 | exit(1); | 626 | exit(1); |
627 | } | 627 | } |
628 | char *path = argv[i + 1]; | 628 | char *path = argv[i + 1]; |
629 | invalid_filename(path); | 629 | invalid_filename(path, 0); // no globbing |
630 | if (strstr(path, "..")) { | 630 | if (strstr(path, "..")) { |
631 | fprintf(stderr, "Error: invalid file name %s\n", path); | 631 | fprintf(stderr, "Error: invalid file name %s\n", path); |
632 | exit(1); | 632 | exit(1); |
@@ -1434,7 +1434,7 @@ int main(int argc, char **argv) { | |||
1434 | } | 1434 | } |
1435 | 1435 | ||
1436 | // check name | 1436 | // check name |
1437 | invalid_filename(subdirname); | 1437 | invalid_filename(subdirname, 0); // no globbing |
1438 | if (strstr(subdirname, "..") || strstr(subdirname, "/")) { | 1438 | if (strstr(subdirname, "..") || strstr(subdirname, "/")) { |
1439 | fprintf(stderr, "Error: invalid overlay name\n"); | 1439 | fprintf(stderr, "Error: invalid overlay name\n"); |
1440 | exit(1); | 1440 | exit(1); |
@@ -1483,7 +1483,7 @@ int main(int argc, char **argv) { | |||
1483 | exit(1); | 1483 | exit(1); |
1484 | } | 1484 | } |
1485 | custom_profile_dir = expand_home(argv[i] + 15, cfg.homedir); | 1485 | custom_profile_dir = expand_home(argv[i] + 15, cfg.homedir); |
1486 | invalid_filename(custom_profile_dir); | 1486 | invalid_filename(custom_profile_dir, 0); // no globbing |
1487 | if (!is_dir(custom_profile_dir) || is_link(custom_profile_dir) || strstr(custom_profile_dir, "..")) { | 1487 | if (!is_dir(custom_profile_dir) || is_link(custom_profile_dir) || strstr(custom_profile_dir, "..")) { |
1488 | fprintf(stderr, "Error: invalid profile path\n"); | 1488 | fprintf(stderr, "Error: invalid profile path\n"); |
1489 | exit(1); | 1489 | exit(1); |
@@ -1542,7 +1542,7 @@ int main(int argc, char **argv) { | |||
1542 | } | 1542 | } |
1543 | 1543 | ||
1544 | 1544 | ||
1545 | invalid_filename(argv[i] + 9); | 1545 | invalid_filename(argv[i] + 9, 0); // no globbing |
1546 | 1546 | ||
1547 | // extract chroot dirname | 1547 | // extract chroot dirname |
1548 | cfg.chrootdir = argv[i] + 9; | 1548 | cfg.chrootdir = argv[i] + 9; |
@@ -2193,7 +2193,7 @@ int main(int argc, char **argv) { | |||
2193 | fprintf(stderr, "Error: --shell=none was already specified.\n"); | 2193 | fprintf(stderr, "Error: --shell=none was already specified.\n"); |
2194 | return 1; | 2194 | return 1; |
2195 | } | 2195 | } |
2196 | invalid_filename(argv[i] + 8); | 2196 | invalid_filename(argv[i] + 8, 0); // no globbing |
2197 | 2197 | ||
2198 | if (cfg.shell) { | 2198 | if (cfg.shell) { |
2199 | fprintf(stderr, "Error: only one user shell can be specified\n"); | 2199 | fprintf(stderr, "Error: only one user shell can be specified\n"); |
diff --git a/src/firejail/netfilter.c b/src/firejail/netfilter.c index 14b3b54a6..cb0d9d7af 100644 --- a/src/firejail/netfilter.c +++ b/src/firejail/netfilter.c | |||
@@ -45,7 +45,7 @@ static char *client_filter = | |||
45 | 45 | ||
46 | void check_netfilter_file(const char *fname) { | 46 | void check_netfilter_file(const char *fname) { |
47 | EUID_ASSERT(); | 47 | EUID_ASSERT(); |
48 | invalid_filename(fname); | 48 | invalid_filename(fname, 0); // no globbing |
49 | 49 | ||
50 | if (is_dir(fname) || is_link(fname) || strstr(fname, "..") || access(fname, R_OK )) { | 50 | if (is_dir(fname) || is_link(fname) || strstr(fname, "..") || access(fname, R_OK )) { |
51 | fprintf(stderr, "Error: invalid network filter file %s\n", fname); | 51 | fprintf(stderr, "Error: invalid network filter file %s\n", fname); |
diff --git a/src/firejail/netns.c b/src/firejail/netns.c index fdd108652..f52613490 100644 --- a/src/firejail/netns.c +++ b/src/firejail/netns.c | |||
@@ -49,7 +49,7 @@ void check_netns(const char *nsname) { | |||
49 | fprintf(stderr, "Error: invalid netns name %s\n", nsname); | 49 | fprintf(stderr, "Error: invalid netns name %s\n", nsname); |
50 | exit(1); | 50 | exit(1); |
51 | } | 51 | } |
52 | invalid_filename(nsname); | 52 | invalid_filename(nsname, 0); // no globbing |
53 | char *control_file = netns_control_file(nsname); | 53 | char *control_file = netns_control_file(nsname); |
54 | 54 | ||
55 | EUID_ASSERT(); | 55 | EUID_ASSERT(); |
diff --git a/src/firejail/output.c b/src/firejail/output.c index b99604ec4..4f68b8ca3 100644 --- a/src/firejail/output.c +++ b/src/firejail/output.c | |||
@@ -48,7 +48,7 @@ void check_output(int argc, char **argv) { | |||
48 | drop_privs(0); | 48 | drop_privs(0); |
49 | char *outfile = argv[outindex]; | 49 | char *outfile = argv[outindex]; |
50 | outfile += (enable_stderr)? 16:9; | 50 | outfile += (enable_stderr)? 16:9; |
51 | invalid_filename(outfile); | 51 | invalid_filename(outfile, 0); // no globbing |
52 | 52 | ||
53 | // do not accept directories, links, and files with ".." | 53 | // do not accept directories, links, and files with ".." |
54 | if (strstr(outfile, "..") || is_link(outfile) || is_dir(outfile)) { | 54 | if (strstr(outfile, "..") || is_link(outfile) || is_dir(outfile)) { |
diff --git a/src/firejail/profile.c b/src/firejail/profile.c index 789a8b060..a1c94579c 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c | |||
@@ -925,7 +925,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
925 | } | 925 | } |
926 | 926 | ||
927 | // check name | 927 | // check name |
928 | invalid_filename(subdirname); | 928 | invalid_filename(subdirname, 0); // no globbing |
929 | if (strstr(subdirname, "..") || strstr(subdirname, "/")) { | 929 | if (strstr(subdirname, "..") || strstr(subdirname, "/")) { |
930 | fprintf(stderr, "Error: invalid overlay name\n"); | 930 | fprintf(stderr, "Error: invalid overlay name\n"); |
931 | exit(1); | 931 | exit(1); |
@@ -993,8 +993,8 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
993 | } | 993 | } |
994 | 994 | ||
995 | // check directories | 995 | // check directories |
996 | invalid_filename(dname1); | 996 | invalid_filename(dname1, 0); // no globbing |
997 | invalid_filename(dname2); | 997 | invalid_filename(dname2, 0); // no globbing |
998 | if (strstr(dname1, "..") || strstr(dname2, "..")) { | 998 | if (strstr(dname1, "..") || strstr(dname2, "..")) { |
999 | fprintf(stderr, "Error: invalid file name.\n"); | 999 | fprintf(stderr, "Error: invalid file name.\n"); |
1000 | exit(1); | 1000 | exit(1); |
@@ -1123,7 +1123,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
1123 | } | 1123 | } |
1124 | 1124 | ||
1125 | // some characters just don't belong in filenames | 1125 | // some characters just don't belong in filenames |
1126 | invalid_filename(ptr); | 1126 | invalid_filename(ptr, 1); // globbing |
1127 | if (strstr(ptr, "..")) { | 1127 | if (strstr(ptr, "..")) { |
1128 | if (lineno == 0) | 1128 | if (lineno == 0) |
1129 | fprintf(stderr, "Error: \"%s\" is an invalid filename\n", ptr); | 1129 | fprintf(stderr, "Error: \"%s\" is an invalid filename\n", ptr); |
@@ -1170,7 +1170,7 @@ void profile_read(const char *fname) { | |||
1170 | } | 1170 | } |
1171 | 1171 | ||
1172 | // check file | 1172 | // check file |
1173 | invalid_filename(fname); | 1173 | invalid_filename(fname, 0); // no globbing |
1174 | if (strlen(fname) == 0 || is_dir(fname)) { | 1174 | if (strlen(fname) == 0 || is_dir(fname)) { |
1175 | fprintf(stderr, "Error: invalid profile file\n"); | 1175 | fprintf(stderr, "Error: invalid profile file\n"); |
1176 | exit(1); | 1176 | exit(1); |
diff --git a/src/firejail/util.c b/src/firejail/util.c index 4d1c94c25..559f7ee48 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c | |||
@@ -747,7 +747,7 @@ uid_t pid_get_uid(pid_t pid) { | |||
747 | } | 747 | } |
748 | 748 | ||
749 | 749 | ||
750 | void invalid_filename(const char *fname) { | 750 | void invalid_filename(const char *fname, int globbing) { |
751 | // EUID_ASSERT(); | 751 | // EUID_ASSERT(); |
752 | assert(fname); | 752 | assert(fname); |
753 | const char *ptr = fname; | 753 | const char *ptr = fname; |
@@ -763,10 +763,19 @@ void invalid_filename(const char *fname) { | |||
763 | return; | 763 | return; |
764 | 764 | ||
765 | int len = strlen(ptr); | 765 | int len = strlen(ptr); |
766 | // file globbing ('*') is allowed | 766 | |
767 | if (strcspn(ptr, "\\&!?\"'<>%^(){}[];,") != (size_t)len) { | 767 | if (globbing) { |
768 | fprintf(stderr, "Error: \"%s\" is an invalid filename\n", ptr); | 768 | // file globbing ('*?[]') is allowed |
769 | exit(1); | 769 | if (strcspn(ptr, "\\&!\"'<>%^(){};,") != (size_t)len) { |
770 | fprintf(stderr, "Error: \"%s\" is an invalid filename\n", ptr); | ||
771 | exit(1); | ||
772 | } | ||
773 | } | ||
774 | else { | ||
775 | if (strcspn(ptr, "\\&!?\"'<>%^(){};,*[]") != (size_t)len) { | ||
776 | fprintf(stderr, "Error: \"%s\" is an invalid filename\n", ptr); | ||
777 | exit(1); | ||
778 | } | ||
770 | } | 779 | } |
771 | } | 780 | } |
772 | 781 | ||