diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/firejail/cgroup.c | 2 | ||||
-rw-r--r-- | src/firejail/firejail.h | 1 | ||||
-rw-r--r-- | src/firejail/fs_bin.c | 6 | ||||
-rw-r--r-- | src/firejail/fs_etc.c | 2 | ||||
-rw-r--r-- | src/firejail/fs_home.c | 6 | ||||
-rw-r--r-- | src/firejail/join.c | 23 | ||||
-rw-r--r-- | src/firejail/main.c | 6 | ||||
-rw-r--r-- | src/firejail/netfilter.c | 2 | ||||
-rw-r--r-- | src/firejail/output.c | 1 | ||||
-rw-r--r-- | src/firejail/profile.c | 23 | ||||
-rw-r--r-- | src/firejail/util.c | 20 |
11 files changed, 67 insertions, 25 deletions
diff --git a/src/firejail/cgroup.c b/src/firejail/cgroup.c index 4d64d3fd8..9e6a2e549 100644 --- a/src/firejail/cgroup.c +++ b/src/firejail/cgroup.c | |||
@@ -78,6 +78,8 @@ errout: | |||
78 | 78 | ||
79 | 79 | ||
80 | void set_cgroup(const char *path) { | 80 | void set_cgroup(const char *path) { |
81 | invalid_filename(path); | ||
82 | |||
81 | // path starts with /sys/fs/cgroup | 83 | // path starts with /sys/fs/cgroup |
82 | if (strncmp(path, "/sys/fs/cgroup", 14) != 0) | 84 | if (strncmp(path, "/sys/fs/cgroup", 14) != 0) |
83 | goto errout; | 85 | goto errout; |
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 2e82dabc9..d3cfb1e96 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -296,6 +296,7 @@ void notify_other(int fd); | |||
296 | char *expand_home(const char *path, const char* homedir); | 296 | char *expand_home(const char *path, const char* homedir); |
297 | const char *gnu_basename(const char *path); | 297 | const char *gnu_basename(const char *path); |
298 | uid_t pid_get_uid(pid_t pid); | 298 | uid_t pid_get_uid(pid_t pid); |
299 | void invalid_filename(const char *fname); | ||
299 | 300 | ||
300 | // fs_var.c | 301 | // fs_var.c |
301 | void fs_var_log(void); // mounting /var/log | 302 | void fs_var_log(void); // mounting /var/log |
diff --git a/src/firejail/fs_bin.c b/src/firejail/fs_bin.c index dcfdadb6b..668223755 100644 --- a/src/firejail/fs_bin.c +++ b/src/firejail/fs_bin.c | |||
@@ -35,6 +35,8 @@ static char *paths[] = { | |||
35 | // return 1 if found, 0 if not found | 35 | // return 1 if found, 0 if not found |
36 | static char *check_dir_or_file(const char *name) { | 36 | static char *check_dir_or_file(const char *name) { |
37 | assert(name); | 37 | assert(name); |
38 | invalid_filename(name); | ||
39 | |||
38 | struct stat s; | 40 | struct stat s; |
39 | char *fname = NULL; | 41 | char *fname = NULL; |
40 | 42 | ||
@@ -52,8 +54,10 @@ static char *check_dir_or_file(const char *name) { | |||
52 | i++; | 54 | i++; |
53 | } | 55 | } |
54 | 56 | ||
55 | if (!fname) | 57 | if (!fname) { |
58 | fprintf(stderr, "Warning: file %s not found\n", name); | ||
56 | return NULL; | 59 | return NULL; |
60 | } | ||
57 | 61 | ||
58 | free(fname); | 62 | free(fname); |
59 | return paths[i]; | 63 | return paths[i]; |
diff --git a/src/firejail/fs_etc.c b/src/firejail/fs_etc.c index ea6f4fe6d..8e5fe1b86 100644 --- a/src/firejail/fs_etc.c +++ b/src/firejail/fs_etc.c | |||
@@ -26,6 +26,8 @@ | |||
26 | 26 | ||
27 | static void check_dir_or_file(const char *name) { | 27 | static void check_dir_or_file(const char *name) { |
28 | assert(name); | 28 | assert(name); |
29 | invalid_filename(name); | ||
30 | |||
29 | struct stat s; | 31 | struct stat s; |
30 | char *fname; | 32 | char *fname; |
31 | if (asprintf(&fname, "/etc/%s", name) == -1) | 33 | if (asprintf(&fname, "/etc/%s", name) == -1) |
diff --git a/src/firejail/fs_home.c b/src/firejail/fs_home.c index 21a2e83e5..1144e90e8 100644 --- a/src/firejail/fs_home.c +++ b/src/firejail/fs_home.c | |||
@@ -254,6 +254,10 @@ void fs_private(void) { | |||
254 | static void check_dir_or_file(const char *name) { | 254 | static void check_dir_or_file(const char *name) { |
255 | assert(name); | 255 | assert(name); |
256 | struct stat s; | 256 | struct stat s; |
257 | |||
258 | invalid_filename(name); | ||
259 | |||
260 | |||
257 | char *fname = expand_home(name, cfg.homedir); | 261 | char *fname = expand_home(name, cfg.homedir); |
258 | if (!fname) { | 262 | if (!fname) { |
259 | fprintf(stderr, "Error: file %s not found.\n", name); | 263 | fprintf(stderr, "Error: file %s not found.\n", name); |
@@ -318,6 +322,8 @@ void fs_check_home_list(void) { | |||
318 | 322 | ||
319 | // check new private home directory (--private= option) - exit if it fails | 323 | // check new private home directory (--private= option) - exit if it fails |
320 | void fs_check_private_dir(void) { | 324 | void fs_check_private_dir(void) { |
325 | invalid_filename(cfg.home_private); | ||
326 | |||
321 | // Expand the home directory | 327 | // Expand the home directory |
322 | char *tmp = expand_home(cfg.home_private, cfg.homedir); | 328 | char *tmp = expand_home(cfg.home_private, cfg.homedir); |
323 | cfg.home_private = realpath(tmp, NULL); | 329 | cfg.home_private = realpath(tmp, NULL); |
diff --git a/src/firejail/join.c b/src/firejail/join.c index acd17366a..35e302bf0 100644 --- a/src/firejail/join.c +++ b/src/firejail/join.c | |||
@@ -306,10 +306,25 @@ void join(pid_t pid, const char *homedir, int argc, char **argv, int index) { | |||
306 | if (setenv("PROMPT_COMMAND", "export PS1=\"\\[\\e[1;32m\\][\\u@\\h \\W]\\$\\[\\e[0m\\] \"", 1) < 0) | 306 | if (setenv("PROMPT_COMMAND", "export PS1=\"\\[\\e[1;32m\\][\\u@\\h \\W]\\$\\[\\e[0m\\] \"", 1) < 0) |
307 | errExit("setenv"); | 307 | errExit("setenv"); |
308 | 308 | ||
309 | // run icmdline trough /bin/bash | 309 | // run cmdline trough /bin/bash |
310 | if (cfg.command_line == NULL) | 310 | if (cfg.command_line == NULL) { |
311 | // replace the process with a regular bash session | 311 | struct stat s; |
312 | execlp("/bin/bash", "/bin/bash", NULL); | 312 | |
313 | // replace the process with a shell | ||
314 | if (stat("/bin/bash", &s) == 0) | ||
315 | execlp("/bin/bash", "/bin/bash", NULL); | ||
316 | else if (stat("/usr/bin/zsh", &s) == 0) | ||
317 | execlp("/usr/bin/zsh", "/usr/bin/zsh", NULL); | ||
318 | else if (stat("/bin/csh", &s) == 0) | ||
319 | execlp("/bin/csh", "/bin/csh", NULL); | ||
320 | else if (stat("/bin/sh", &s) == 0) | ||
321 | execlp("/bin/sh", "/bin/sh", NULL); | ||
322 | |||
323 | // no shell found, print an error and exit | ||
324 | fprintf(stderr, "Error: no POSIX shell found\n"); | ||
325 | sleep(5); | ||
326 | exit(1); | ||
327 | } | ||
313 | else { | 328 | else { |
314 | // run the command supplied by the user | 329 | // run the command supplied by the user |
315 | int cwd = 0; | 330 | int cwd = 0; |
diff --git a/src/firejail/main.c b/src/firejail/main.c index 8d2664c16..422a39128 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c | |||
@@ -586,6 +586,7 @@ int main(int argc, char **argv) { | |||
586 | fprintf(stderr, "Error: only a cgroup can be defined\n"); | 586 | fprintf(stderr, "Error: only a cgroup can be defined\n"); |
587 | exit(1); | 587 | exit(1); |
588 | } | 588 | } |
589 | |||
589 | arg_cgroup = 1; | 590 | arg_cgroup = 1; |
590 | cfg.cgroup = strdup(argv[i] + 9); | 591 | cfg.cgroup = strdup(argv[i] + 9); |
591 | if (!cfg.cgroup) | 592 | if (!cfg.cgroup) |
@@ -683,6 +684,8 @@ int main(int argc, char **argv) { | |||
683 | fprintf(stderr, "Error: --noprofile and --profile options are mutually exclusive\n"); | 684 | fprintf(stderr, "Error: --noprofile and --profile options are mutually exclusive\n"); |
684 | exit(1); | 685 | exit(1); |
685 | } | 686 | } |
687 | invalid_filename(argv[i] + 10); | ||
688 | |||
686 | // multiple profile files are allowed! | 689 | // multiple profile files are allowed! |
687 | char *ptr = argv[i] + 10; | 690 | char *ptr = argv[i] + 10; |
688 | if (is_dir(ptr) || is_link(ptr) || strstr(ptr, "..")) { | 691 | if (is_dir(ptr) || is_link(ptr) || strstr(ptr, "..")) { |
@@ -712,6 +715,7 @@ int main(int argc, char **argv) { | |||
712 | fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n"); | 715 | fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n"); |
713 | exit(1); | 716 | exit(1); |
714 | } | 717 | } |
718 | invalid_filename(argv[i] + 9); | ||
715 | 719 | ||
716 | // extract chroot dirname | 720 | // extract chroot dirname |
717 | cfg.chrootdir = argv[i] + 9; | 721 | cfg.chrootdir = argv[i] + 9; |
@@ -1042,6 +1046,8 @@ int main(int argc, char **argv) { | |||
1042 | fprintf(stderr, "Error: --shell=none was already specified.\n"); | 1046 | fprintf(stderr, "Error: --shell=none was already specified.\n"); |
1043 | return 1; | 1047 | return 1; |
1044 | } | 1048 | } |
1049 | invalid_filename(argv[i] + 8); | ||
1050 | |||
1045 | if (arg_csh || arg_zsh || cfg.shell) { | 1051 | if (arg_csh || arg_zsh || cfg.shell) { |
1046 | fprintf(stderr, "Error: only one user shell can be specified\n"); | 1052 | fprintf(stderr, "Error: only one user shell can be specified\n"); |
1047 | return 1; | 1053 | return 1; |
diff --git a/src/firejail/netfilter.c b/src/firejail/netfilter.c index 8601a5696..3f667c871 100644 --- a/src/firejail/netfilter.c +++ b/src/firejail/netfilter.c | |||
@@ -39,6 +39,8 @@ static char *client_filter = | |||
39 | "COMMIT\n"; | 39 | "COMMIT\n"; |
40 | 40 | ||
41 | void check_netfilter_file(const char *fname) { | 41 | void check_netfilter_file(const char *fname) { |
42 | invalid_filename(fname); | ||
43 | |||
42 | if (is_dir(fname) || is_link(fname) || strstr(fname, "..")) { | 44 | if (is_dir(fname) || is_link(fname) || strstr(fname, "..")) { |
43 | fprintf(stderr, "Error: invalid network filter file\n"); | 45 | fprintf(stderr, "Error: invalid network filter file\n"); |
44 | exit(1); | 46 | exit(1); |
diff --git a/src/firejail/output.c b/src/firejail/output.c index 94a05ac4a..c2ab9f157 100644 --- a/src/firejail/output.c +++ b/src/firejail/output.c | |||
@@ -31,6 +31,7 @@ void check_output(int argc, char **argv) { | |||
31 | for (i = 1; i < argc; i++) { | 31 | for (i = 1; i < argc; i++) { |
32 | if (strncmp(argv[i], "--output=", 9) == 0) { | 32 | if (strncmp(argv[i], "--output=", 9) == 0) { |
33 | found = 1; | 33 | found = 1; |
34 | invalid_filename(argv[i] + 9); | ||
34 | outfile = argv[i] + 9; | 35 | outfile = argv[i] + 9; |
35 | 36 | ||
36 | // do not accept directories, links, and files with ".." | 37 | // do not accept directories, links, and files with ".." |
diff --git a/src/firejail/profile.c b/src/firejail/profile.c index 2e3790b3c..e6c31bc0a 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c | |||
@@ -61,23 +61,6 @@ int profile_find(const char *name, const char *dir) { | |||
61 | //*************************************************** | 61 | //*************************************************** |
62 | // run-time profiles | 62 | // run-time profiles |
63 | //*************************************************** | 63 | //*************************************************** |
64 | static void check_file_name(char *ptr, int lineno) { | ||
65 | if (strncmp(ptr, "${HOME}", 7) == 0) | ||
66 | ptr += 7; | ||
67 | else if (strncmp(ptr, "${PATH}", 7) == 0) | ||
68 | ptr += 7; | ||
69 | |||
70 | int len = strlen(ptr); | ||
71 | // file globbing ('*') is allowed | ||
72 | if (strcspn(ptr, "\\&!?\"'<>%^(){}[];,") != (size_t)len) { | ||
73 | if (lineno == 0) | ||
74 | fprintf(stderr, "Error: \"%s\" is an invalid filename\n", ptr); | ||
75 | else | ||
76 | fprintf(stderr, "Error: line %d in the custom profile is invalid\n", lineno); | ||
77 | exit(1); | ||
78 | } | ||
79 | } | ||
80 | |||
81 | 64 | ||
82 | // check profile line; if line == 0, this was generated from a command line option | 65 | // check profile line; if line == 0, this was generated from a command line option |
83 | // return 1 if the command is to be added to the linked list of profile commands | 66 | // return 1 if the command is to be added to the linked list of profile commands |
@@ -281,8 +264,8 @@ int profile_check_line(char *ptr, int lineno) { | |||
281 | } | 264 | } |
282 | 265 | ||
283 | // check directories | 266 | // check directories |
284 | check_file_name(dname1, lineno); | 267 | invalid_filename(dname1); |
285 | check_file_name(dname2, lineno); | 268 | invalid_filename(dname2); |
286 | if (strstr(dname1, "..") || strstr(dname2, "..")) { | 269 | if (strstr(dname1, "..") || strstr(dname2, "..")) { |
287 | fprintf(stderr, "Error: invalid file name.\n"); | 270 | fprintf(stderr, "Error: invalid file name.\n"); |
288 | exit(1); | 271 | exit(1); |
@@ -361,7 +344,7 @@ int profile_check_line(char *ptr, int lineno) { | |||
361 | } | 344 | } |
362 | 345 | ||
363 | // some characters just don't belong in filenames | 346 | // some characters just don't belong in filenames |
364 | check_file_name(ptr, lineno); | 347 | invalid_filename(ptr); |
365 | if (strstr(ptr, "..")) { | 348 | if (strstr(ptr, "..")) { |
366 | if (lineno == 0) | 349 | if (lineno == 0) |
367 | fprintf(stderr, "Error: \"%s\" is an invalid filename\n", ptr); | 350 | fprintf(stderr, "Error: \"%s\" is an invalid filename\n", ptr); |
diff --git a/src/firejail/util.c b/src/firejail/util.c index 9ad937f55..d2e6c2799 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c | |||
@@ -535,3 +535,23 @@ uid_t pid_get_uid(pid_t pid) { | |||
535 | } | 535 | } |
536 | return rv; | 536 | return rv; |
537 | } | 537 | } |
538 | |||
539 | void invalid_filename(const char *fname) { | ||
540 | assert(fname); | ||
541 | const char *ptr = fname; | ||
542 | |||
543 | if (arg_debug) | ||
544 | printf("Checking filename %s\n", fname); | ||
545 | |||
546 | if (strncmp(ptr, "${HOME}", 7) == 0) | ||
547 | ptr = fname + 7; | ||
548 | else if (strncmp(ptr, "${PATH}", 7) == 0) | ||
549 | ptr = fname + 7; | ||
550 | |||
551 | int len = strlen(ptr); | ||
552 | // file globbing ('*') is allowed | ||
553 | if (strcspn(ptr, "\\&!?\"'<>%^(){}[];,") != (size_t)len) { | ||
554 | fprintf(stderr, "Error: \"%s\" is an invalid filename\n", ptr); | ||
555 | exit(1); | ||
556 | } | ||
557 | } | ||