diff options
-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 | 2 | ||||
-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 |
14 files changed, 40 insertions, 31 deletions
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 bea195f36..e64bde857 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -497,7 +497,7 @@ void notify_other(int fd); | |||
497 | char *expand_home(const char *path, const char* homedir); | 497 | char *expand_home(const char *path, const char* homedir); |
498 | const char *gnu_basename(const char *path); | 498 | const char *gnu_basename(const char *path); |
499 | uid_t pid_get_uid(pid_t pid); | 499 | uid_t pid_get_uid(pid_t pid); |
500 | void invalid_filename(const char *fname); | 500 | void invalid_filename(const char *fname, int globbing); |
501 | uid_t get_group_id(const char *group); | 501 | uid_t get_group_id(const char *group); |
502 | int remove_directory(const char *path); | 502 | int remove_directory(const char *path); |
503 | void flush_stdin(void); | 503 | void flush_stdin(void); |
diff --git a/src/firejail/fs_bin.c b/src/firejail/fs_bin.c index 5a4b0a161..f6c83ef26 100644 --- a/src/firejail/fs_bin.c +++ b/src/firejail/fs_bin.c | |||
@@ -153,7 +153,7 @@ static void duplicate(char *fname, FILE *fplist) { | |||
153 | fprintf(stderr, "Error: \"%s\" is an invalid filename\n", fname); | 153 | fprintf(stderr, "Error: \"%s\" is an invalid filename\n", fname); |
154 | exit(1); | 154 | exit(1); |
155 | } | 155 | } |
156 | invalid_filename(fname); | 156 | invalid_filename(fname, 0); // no globbing |
157 | 157 | ||
158 | char *full_path; | 158 | char *full_path; |
159 | if (*fname == '/') { | 159 | if (*fname == '/') { |
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 c9edcec29..9f963d203 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c | |||
@@ -571,7 +571,7 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
571 | exit(1); | 571 | exit(1); |
572 | } | 572 | } |
573 | char *path = argv[i + 1]; | 573 | char *path = argv[i + 1]; |
574 | invalid_filename(path); | 574 | invalid_filename(path, 0); // no globbing |
575 | if (strstr(path, "..")) { | 575 | if (strstr(path, "..")) { |
576 | fprintf(stderr, "Error: invalid file name %s\n", path); | 576 | fprintf(stderr, "Error: invalid file name %s\n", path); |
577 | exit(1); | 577 | exit(1); |
@@ -595,13 +595,13 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
595 | exit(1); | 595 | exit(1); |
596 | } | 596 | } |
597 | char *path1 = argv[i + 1]; | 597 | char *path1 = argv[i + 1]; |
598 | invalid_filename(path1); | 598 | invalid_filename(path1, 0); // no globbing |
599 | if (strstr(path1, "..")) { | 599 | if (strstr(path1, "..")) { |
600 | fprintf(stderr, "Error: invalid file name %s\n", path1); | 600 | fprintf(stderr, "Error: invalid file name %s\n", path1); |
601 | exit(1); | 601 | exit(1); |
602 | } | 602 | } |
603 | char *path2 = argv[i + 2]; | 603 | char *path2 = argv[i + 2]; |
604 | invalid_filename(path2); | 604 | invalid_filename(path2, 0); // no globbing |
605 | if (strstr(path2, "..")) { | 605 | if (strstr(path2, "..")) { |
606 | fprintf(stderr, "Error: invalid file name %s\n", path2); | 606 | fprintf(stderr, "Error: invalid file name %s\n", path2); |
607 | exit(1); | 607 | exit(1); |
@@ -625,7 +625,7 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
625 | exit(1); | 625 | exit(1); |
626 | } | 626 | } |
627 | char *path = argv[i + 1]; | 627 | char *path = argv[i + 1]; |
628 | invalid_filename(path); | 628 | invalid_filename(path, 0); // no globbing |
629 | if (strstr(path, "..")) { | 629 | if (strstr(path, "..")) { |
630 | fprintf(stderr, "Error: invalid file name %s\n", path); | 630 | fprintf(stderr, "Error: invalid file name %s\n", path); |
631 | exit(1); | 631 | exit(1); |
@@ -1433,7 +1433,7 @@ int main(int argc, char **argv) { | |||
1433 | } | 1433 | } |
1434 | 1434 | ||
1435 | // check name | 1435 | // check name |
1436 | invalid_filename(subdirname); | 1436 | invalid_filename(subdirname, 0); // no globbing |
1437 | if (strstr(subdirname, "..") || strstr(subdirname, "/")) { | 1437 | if (strstr(subdirname, "..") || strstr(subdirname, "/")) { |
1438 | fprintf(stderr, "Error: invalid overlay name\n"); | 1438 | fprintf(stderr, "Error: invalid overlay name\n"); |
1439 | exit(1); | 1439 | exit(1); |
@@ -1482,7 +1482,7 @@ int main(int argc, char **argv) { | |||
1482 | exit(1); | 1482 | exit(1); |
1483 | } | 1483 | } |
1484 | custom_profile_dir = expand_home(argv[i] + 15, cfg.homedir); | 1484 | custom_profile_dir = expand_home(argv[i] + 15, cfg.homedir); |
1485 | invalid_filename(custom_profile_dir); | 1485 | invalid_filename(custom_profile_dir, 0); // no globbing |
1486 | if (!is_dir(custom_profile_dir) || is_link(custom_profile_dir) || strstr(custom_profile_dir, "..")) { | 1486 | if (!is_dir(custom_profile_dir) || is_link(custom_profile_dir) || strstr(custom_profile_dir, "..")) { |
1487 | fprintf(stderr, "Error: invalid profile path\n"); | 1487 | fprintf(stderr, "Error: invalid profile path\n"); |
1488 | exit(1); | 1488 | exit(1); |
@@ -1541,7 +1541,7 @@ int main(int argc, char **argv) { | |||
1541 | } | 1541 | } |
1542 | 1542 | ||
1543 | 1543 | ||
1544 | invalid_filename(argv[i] + 9); | 1544 | invalid_filename(argv[i] + 9, 0); // no globbing |
1545 | 1545 | ||
1546 | // extract chroot dirname | 1546 | // extract chroot dirname |
1547 | cfg.chrootdir = argv[i] + 9; | 1547 | cfg.chrootdir = argv[i] + 9; |
@@ -2192,7 +2192,7 @@ int main(int argc, char **argv) { | |||
2192 | fprintf(stderr, "Error: --shell=none was already specified.\n"); | 2192 | fprintf(stderr, "Error: --shell=none was already specified.\n"); |
2193 | return 1; | 2193 | return 1; |
2194 | } | 2194 | } |
2195 | invalid_filename(argv[i] + 8); | 2195 | invalid_filename(argv[i] + 8, 0); // no globbing |
2196 | 2196 | ||
2197 | if (cfg.shell) { | 2197 | if (cfg.shell) { |
2198 | fprintf(stderr, "Error: only one user shell can be specified\n"); | 2198 | 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 6880bcaa7..8aabac6fa 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); |
@@ -1118,7 +1118,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
1118 | } | 1118 | } |
1119 | 1119 | ||
1120 | // some characters just don't belong in filenames | 1120 | // some characters just don't belong in filenames |
1121 | invalid_filename(ptr); | 1121 | invalid_filename(ptr, 1); // globbing |
1122 | if (strstr(ptr, "..")) { | 1122 | if (strstr(ptr, "..")) { |
1123 | if (lineno == 0) | 1123 | if (lineno == 0) |
1124 | fprintf(stderr, "Error: \"%s\" is an invalid filename\n", ptr); | 1124 | fprintf(stderr, "Error: \"%s\" is an invalid filename\n", ptr); |
@@ -1165,7 +1165,7 @@ void profile_read(const char *fname) { | |||
1165 | } | 1165 | } |
1166 | 1166 | ||
1167 | // check file | 1167 | // check file |
1168 | invalid_filename(fname); | 1168 | invalid_filename(fname, 0); // no globbing |
1169 | if (strlen(fname) == 0 || is_dir(fname)) { | 1169 | if (strlen(fname) == 0 || is_dir(fname)) { |
1170 | fprintf(stderr, "Error: invalid profile file\n"); | 1170 | fprintf(stderr, "Error: invalid profile file\n"); |
1171 | exit(1); | 1171 | 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 | ||