aboutsummaryrefslogtreecommitdiffstats
path: root/src/firejail/output.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/firejail/output.c')
-rw-r--r--src/firejail/output.c84
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
6void 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}