diff options
Diffstat (limited to 'src/firejail/output.c')
-rw-r--r-- | src/firejail/output.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/src/firejail/output.c b/src/firejail/output.c new file mode 100644 index 000000000..32adac108 --- /dev/null +++ b/src/firejail/output.c | |||
@@ -0,0 +1,84 @@ | |||
1 | #include "firejail.h" | ||
2 | #include <sys/types.h> | ||
3 | #include <sys/stat.h> | ||
4 | #include <unistd.h> | ||
5 | |||
6 | void check_output(int argc, char **argv) { | ||
7 | int i; | ||
8 | char *outfile = NULL; | ||
9 | // drop_privs(0); | ||
10 | |||
11 | int found = 0; | ||
12 | for (i = 1; i < argc; i++) { | ||
13 | if (strncmp(argv[i], "--output=", 9) == 0) { | ||
14 | found = 1; | ||
15 | outfile = argv[i] + 9; | ||
16 | |||
17 | // do not accept directories, links, and files with ".." | ||
18 | if (strstr(outfile, "..") || is_link(outfile) || is_dir(outfile)) { | ||
19 | fprintf(stderr, "Error: invalid output file. Links, directories and files with \"..\" are not allowed.\n"); | ||
20 | exit(1); | ||
21 | } | ||
22 | |||
23 | struct stat s; | ||
24 | if (stat(outfile, &s) == 0) { | ||
25 | // check permissions | ||
26 | if (s.st_uid != getuid() || s.st_gid != getgid()) { | ||
27 | fprintf(stderr, "Error: the output file needs to be owned by the current user.\n"); | ||
28 | exit(1); | ||
29 | } | ||
30 | |||
31 | // check hard links | ||
32 | if (s.st_nlink != 1) { | ||
33 | fprintf(stderr, "Error: no hard links allowed.\n"); | ||
34 | exit(1); | ||
35 | } | ||
36 | } | ||
37 | |||
38 | // drop privileges and try to open the file for writing | ||
39 | drop_privs(0); | ||
40 | /* coverity[toctou] */ | ||
41 | FILE *fp = fopen(outfile, "a"); | ||
42 | if (!fp) { | ||
43 | fprintf(stderr, "Error: cannot open output file %s\n", outfile); | ||
44 | exit(1); | ||
45 | } | ||
46 | fclose(fp); | ||
47 | break; | ||
48 | } | ||
49 | } | ||
50 | if (!found) | ||
51 | return; | ||
52 | |||
53 | |||
54 | // build the new command line | ||
55 | int len = 0; | ||
56 | for (i = 0; i < argc; i++) { | ||
57 | len += strlen(argv[i]) + 1; // + ' ' | ||
58 | } | ||
59 | len += 50 + strlen(outfile); // tee command | ||
60 | |||
61 | char *cmd = malloc(len + 1); // + '\0' | ||
62 | if (!cmd) | ||
63 | errExit("malloc"); | ||
64 | |||
65 | char *ptr = cmd; | ||
66 | for (i = 0; i < argc; i++) { | ||
67 | if (strncmp(argv[i], "--output=", 9) == 0) | ||
68 | continue; | ||
69 | ptr += sprintf(ptr, "%s ", argv[i]); | ||
70 | } | ||
71 | sprintf(ptr, "| %s/lib/firejail/ftee %s", PREFIX, outfile); | ||
72 | |||
73 | // run command | ||
74 | char *a[4]; | ||
75 | a[0] = "/bin/bash"; | ||
76 | a[1] = "-c"; | ||
77 | a[2] = cmd; | ||
78 | a[3] = NULL; | ||
79 | |||
80 | execvp(a[0], a); | ||
81 | |||
82 | perror("execvp"); | ||
83 | exit(1); | ||
84 | } | ||