diff options
Diffstat (limited to 'src/fbuilder/build_profile.c')
-rw-r--r-- | src/fbuilder/build_profile.c | 182 |
1 files changed, 67 insertions, 115 deletions
diff --git a/src/fbuilder/build_profile.c b/src/fbuilder/build_profile.c index fb53f70a6..941f43562 100644 --- a/src/fbuilder/build_profile.c +++ b/src/fbuilder/build_profile.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2014-2021 Firejail Authors | 2 | * Copyright (C) 2014-2022 Firejail Authors |
3 | * | 3 | * |
4 | * This file is part of firejail project | 4 | * This file is part of firejail project |
5 | * | 5 | * |
@@ -22,22 +22,6 @@ | |||
22 | #include <sys/wait.h> | 22 | #include <sys/wait.h> |
23 | 23 | ||
24 | #define TRACE_OUTPUT "/tmp/firejail-trace.XXXXXX" | 24 | #define TRACE_OUTPUT "/tmp/firejail-trace.XXXXXX" |
25 | #define STRACE_OUTPUT "/tmp/firejail-strace.XXXXXX" | ||
26 | |||
27 | /* static char *cmdlist[] = { */ | ||
28 | /* "/usr/bin/firejail", */ | ||
29 | /* "--quiet", */ | ||
30 | /* "--output=" TRACE_OUTPUT, */ | ||
31 | /* "--noprofile", */ | ||
32 | /* "--caps.drop=all", */ | ||
33 | /* "--nonewprivs", */ | ||
34 | /* "--trace", */ | ||
35 | /* "--shell=none", */ | ||
36 | /* "/usr/bin/strace", // also used as a marker in build_profile() */ | ||
37 | /* "-c", */ | ||
38 | /* "-f", */ | ||
39 | /* "-o" STRACE_OUTPUT, */ | ||
40 | /* }; */ | ||
41 | 25 | ||
42 | void build_profile(int argc, char **argv, int index, FILE *fp) { | 26 | void build_profile(int argc, char **argv, int index, FILE *fp) { |
43 | // next index is the application name | 27 | // next index is the application name |
@@ -47,78 +31,42 @@ void build_profile(int argc, char **argv, int index, FILE *fp) { | |||
47 | } | 31 | } |
48 | 32 | ||
49 | char trace_output[] = "/tmp/firejail-trace.XXXXXX"; | 33 | char trace_output[] = "/tmp/firejail-trace.XXXXXX"; |
50 | char strace_output[] = "/tmp/firejail-strace.XXXXXX"; | ||
51 | |||
52 | int tfile = mkstemp(trace_output); | 34 | int tfile = mkstemp(trace_output); |
53 | int stfile = mkstemp(strace_output); | 35 | if(tfile == -1) |
54 | if(tfile == -1 || stfile == -1) | ||
55 | errExit("mkstemp"); | 36 | errExit("mkstemp"); |
56 | |||
57 | // close the files, firejail/strace will overwrite them! | ||
58 | close(tfile); | 37 | close(tfile); |
59 | close(stfile); | ||
60 | |||
61 | 38 | ||
62 | char *output; | 39 | char *output; |
63 | char *stroutput; | ||
64 | if(asprintf(&output,"--trace=%s",trace_output) == -1) | 40 | if(asprintf(&output,"--trace=%s",trace_output) == -1) |
65 | errExit("asprintf"); | 41 | errExit("asprintf"); |
66 | if(asprintf(&stroutput,"-o%s",strace_output) == -1) | ||
67 | errExit("asprintf"); | ||
68 | |||
69 | char *cmdlist[] = { | ||
70 | BINDIR "/firejail", | ||
71 | "--quiet", | ||
72 | "--noprofile", | ||
73 | "--caps.drop=all", | ||
74 | "--nonewprivs", | ||
75 | output, | ||
76 | "--shell=none", | ||
77 | "/usr/bin/strace", // also used as a marker in build_profile() | ||
78 | "-c", | ||
79 | "-f", | ||
80 | stroutput, | ||
81 | }; | ||
82 | |||
83 | // detect strace and check if Yama LSM allows us to use it | ||
84 | int have_strace = 0; | ||
85 | int have_yama_permission = 1; | ||
86 | if (access("/usr/bin/strace", X_OK) == 0) { | ||
87 | have_strace = 1; | ||
88 | FILE *ps = fopen("/proc/sys/kernel/yama/ptrace_scope", "r"); | ||
89 | if (ps) { | ||
90 | unsigned val; | ||
91 | if (fscanf(ps, "%u", &val) == 1) | ||
92 | have_yama_permission = (val < 2); | ||
93 | fclose(ps); | ||
94 | } | ||
95 | } | ||
96 | 42 | ||
97 | // calculate command length | 43 | // calculate command length |
98 | unsigned len = (int) sizeof(cmdlist) / sizeof(char*) + argc - index + 1; | 44 | unsigned len = 64; // plenty of space for firejail command line |
99 | if (arg_debug) | 45 | len += argc - index; // program command line |
100 | printf("command len %d + %d + 1\n", (int) (sizeof(cmdlist) / sizeof(char*)), argc - index); | 46 | len += 1; // NULL |
101 | char *cmd[len]; | ||
102 | cmd[0] = cmdlist[0]; // explicit assignment to clean scan-build error | ||
103 | 47 | ||
104 | // build command | 48 | // build command |
105 | // skip strace if not installed, or no permission to use it | 49 | char *cmd[len]; |
106 | int skip_strace = !(have_strace && have_yama_permission); | 50 | unsigned curr_len = 0; |
107 | unsigned i = 0; | 51 | cmd[curr_len++] = BINDIR "/firejail"; |
108 | for (i = 0; i < (int) sizeof(cmdlist) / sizeof(char*); i++) { | 52 | cmd[curr_len++] = "--quiet"; |
109 | if (skip_strace && strcmp(cmdlist[i], "/usr/bin/strace") == 0) | 53 | cmd[curr_len++] = "--noprofile"; |
110 | break; | 54 | cmd[curr_len++] = "--caps.drop=all"; |
111 | cmd[i] = cmdlist[i]; | 55 | cmd[curr_len++] = "--seccomp=!chroot"; |
112 | } | 56 | cmd[curr_len++] = "--shell=none"; |
113 | 57 | cmd[curr_len++] = output; | |
114 | int i2 = index; | 58 | if (arg_appimage) |
115 | for (; i < (len - 1); i++, i2++) | 59 | cmd[curr_len++] = "--appimage"; |
116 | cmd[i] = argv[i2]; | 60 | |
117 | assert(i < len); | 61 | int i; |
118 | cmd[i] = NULL; | 62 | for (i = index; i < argc; i++) |
63 | cmd[curr_len++] = argv[i]; | ||
64 | |||
65 | assert(curr_len < len); | ||
66 | cmd[curr_len] = NULL; | ||
119 | 67 | ||
120 | if (arg_debug) { | 68 | if (arg_debug) { |
121 | for (i = 0; i < len; i++) | 69 | for (i = 0; cmd[i]; i++) |
122 | printf("%s%s\n", (i)?"\t":"", cmd[i]); | 70 | printf("%s%s\n", (i)?"\t":"", cmd[i]); |
123 | } | 71 | } |
124 | 72 | ||
@@ -140,14 +88,14 @@ void build_profile(int argc, char **argv, int index, FILE *fp) { | |||
140 | 88 | ||
141 | if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { | 89 | if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { |
142 | if (fp == stdout) | 90 | if (fp == stdout) |
143 | printf("--- Built profile beings after this line ---\n"); | 91 | printf("--- Built profile begins after this line ---\n"); |
144 | fprintf(fp, "# Save this file as \"application.profile\" (change \"application\" with the\n"); | 92 | fprintf(fp, "# Save this file as \"application.profile\" (change \"application\" with the\n"); |
145 | fprintf(fp, "# program name) in ~/.config/firejail directory. Firejail will find it\n"); | 93 | fprintf(fp, "# program name) in ~/.config/firejail directory. Firejail will find it\n"); |
146 | fprintf(fp, "# automatically every time you sandbox your application.\n#\n"); | 94 | fprintf(fp, "# automatically every time you sandbox your application.\n#\n"); |
147 | fprintf(fp, "# Run \"firejail application\" to test it. In the file there are\n"); | 95 | fprintf(fp, "# Run \"firejail application\" to test it. In the file there are\n"); |
148 | fprintf(fp, "# some other commands you can try. Enable them by removing the \"#\".\n"); | 96 | fprintf(fp, "# some other commands you can try. Enable them by removing the \"#\".\n\n"); |
149 | 97 | ||
150 | fprintf(fp, "\n# Firejail profile for %s\n", argv[index]); | 98 | fprintf(fp, "# Firejail profile for %s\n", argv[index]); |
151 | fprintf(fp, "# Persistent local customizations\n"); | 99 | fprintf(fp, "# Persistent local customizations\n"); |
152 | fprintf(fp, "#include %s.local\n", argv[index]); | 100 | fprintf(fp, "#include %s.local\n", argv[index]); |
153 | fprintf(fp, "# Persistent global definitions\n"); | 101 | fprintf(fp, "# Persistent global definitions\n"); |
@@ -158,58 +106,62 @@ void build_profile(int argc, char **argv, int index, FILE *fp) { | |||
158 | fprintf(fp, "### Enable as many of them as you can! A very important one is\n"); | 106 | fprintf(fp, "### Enable as many of them as you can! A very important one is\n"); |
159 | fprintf(fp, "### \"disable-exec.inc\". This will make among other things your home\n"); | 107 | fprintf(fp, "### \"disable-exec.inc\". This will make among other things your home\n"); |
160 | fprintf(fp, "### and /tmp directories non-executable.\n"); | 108 | fprintf(fp, "### and /tmp directories non-executable.\n"); |
161 | fprintf(fp, "include disable-common.inc\n"); | 109 | fprintf(fp, "include disable-common.inc\t# dangerous directories like ~/.ssh and ~/.gnupg\n"); |
162 | fprintf(fp, "#include disable-devel.inc\n"); | 110 | fprintf(fp, "#include disable-devel.inc\t# development tools such as gcc and gdb\n"); |
163 | fprintf(fp, "#include disable-exec.inc\n"); | 111 | fprintf(fp, "#include disable-exec.inc\t# non-executable directories such as /var, /tmp, and /home\n"); |
164 | fprintf(fp, "#include disable-interpreters.inc\n"); | 112 | fprintf(fp, "#include disable-interpreters.inc\t# perl, python, lua etc.\n"); |
165 | fprintf(fp, "include disable-passwdmgr.inc\n"); | 113 | fprintf(fp, "include disable-programs.inc\t# user configuration for programs such as firefox, vlc etc.\n"); |
166 | fprintf(fp, "include disable-programs.inc\n"); | 114 | fprintf(fp, "#include disable-shell.inc\t# sh, bash, zsh etc.\n"); |
167 | fprintf(fp, "#include disable-xdg.inc\n"); | 115 | fprintf(fp, "#include disable-xdg.inc\t# standard user directories: Documents, Pictures, Videos, Music\n"); |
168 | fprintf(fp, "\n"); | 116 | fprintf(fp, "\n"); |
169 | 117 | ||
170 | fprintf(fp, "### Home Directory Whitelisting ###\n"); | 118 | fprintf(fp, "### Home Directory Whitelisting ###\n"); |
171 | fprintf(fp, "### If something goes wrong, this section is the first one to comment out.\n"); | 119 | fprintf(fp, "### If something goes wrong, this section is the first one to comment out.\n"); |
172 | fprintf(fp, "### Instead, you'll have to relay on the basic blacklisting above.\n"); | 120 | fprintf(fp, "### Instead, you'll have to relay on the basic blacklisting above.\n"); |
173 | build_home(trace_output, fp); | 121 | build_home(trace_output, fp); |
122 | fprintf(fp, "\n"); | ||
174 | 123 | ||
175 | fprintf(fp, "\n### The Rest of the Filesystem ###\n"); | 124 | fprintf(fp, "### Filesystem Whitelisting ###\n"); |
176 | build_share(trace_output, fp); | 125 | build_share(trace_output, fp); |
126 | //todo: include whitelist-runuser-common.inc | ||
177 | build_var(trace_output, fp); | 127 | build_var(trace_output, fp); |
178 | build_bin(trace_output, fp); | 128 | fprintf(fp, "\n"); |
179 | build_dev(trace_output, fp); | ||
180 | fprintf(fp, "#nodvd\n"); | ||
181 | fprintf(fp, "#noinput\n"); | ||
182 | fprintf(fp, "#notv\n"); | ||
183 | fprintf(fp, "#nou2f\n"); | ||
184 | fprintf(fp, "#novideo\n"); | ||
185 | build_etc(trace_output, fp); | ||
186 | build_tmp(trace_output, fp); | ||
187 | 129 | ||
188 | fprintf(fp, "\n### Security Filters ###\n"); | 130 | fprintf(fp, "#apparmor\t# if you have AppArmor running, try this one!\n"); |
189 | fprintf(fp, "#apparmor\n"); | ||
190 | fprintf(fp, "caps.drop all\n"); | 131 | fprintf(fp, "caps.drop all\n"); |
132 | fprintf(fp, "ipc-namespace\n"); | ||
191 | fprintf(fp, "netfilter\n"); | 133 | fprintf(fp, "netfilter\n"); |
192 | fprintf(fp, "#nogroups\n"); | 134 | fprintf(fp, "#no3d\t# disable 3D acceleration\n"); |
193 | fprintf(fp, "#noroot\n"); | 135 | fprintf(fp, "#nodvd\t# disable DVD and CD devices\n"); |
136 | fprintf(fp, "#nogroups\t# disable supplementary user groups\n"); | ||
137 | fprintf(fp, "#noinput\t# disable input devices\n"); | ||
194 | fprintf(fp, "nonewprivs\n"); | 138 | fprintf(fp, "nonewprivs\n"); |
139 | fprintf(fp, "noroot\n"); | ||
140 | fprintf(fp, "#notv\t# disable DVB TV devices\n"); | ||
141 | fprintf(fp, "#nou2f\t# disable U2F devices\n"); | ||
142 | fprintf(fp, "#novideo\t# disable video capture devices\n"); | ||
195 | build_protocol(trace_output, fp); | 143 | build_protocol(trace_output, fp); |
144 | fprintf(fp, "seccomp !chroot\t# allowing chroot, just in case this is an Electron app\n"); | ||
145 | fprintf(fp, "shell none\n"); | ||
146 | fprintf(fp, "tracelog\n"); | ||
147 | fprintf(fp, "\n"); | ||
148 | |||
149 | fprintf(fp, "#disable-mnt\t# no access to /mnt, /media, /run/mount and /run/media\n"); | ||
150 | build_bin(trace_output, fp); | ||
151 | fprintf(fp, "#private-cache\t# run with an empty ~/.cache directory\n"); | ||
152 | build_dev(trace_output, fp); | ||
153 | build_etc(trace_output, fp); | ||
154 | fprintf(fp, "#private-lib\n"); | ||
155 | build_tmp(trace_output, fp); | ||
156 | fprintf(fp, "\n"); | ||
157 | |||
158 | fprintf(fp, "#dbus-user none\n"); | ||
159 | fprintf(fp, "#dbus-system none\n"); | ||
160 | fprintf(fp, "\n"); | ||
161 | fprintf(fp, "#memory-deny-write-execute\n"); | ||
196 | 162 | ||
197 | fprintf(fp, "seccomp\n"); | 163 | if (!arg_debug) |
198 | if (!have_strace) { | ||
199 | fprintf(fp, "### If you install strace on your system, Firejail will also create a\n"); | ||
200 | fprintf(fp, "### whitelisted seccomp filter.\n"); | ||
201 | } | ||
202 | else if (!have_yama_permission) | ||
203 | fprintf(fp, "### Yama security module prevents creation of a whitelisted seccomp filter\n"); | ||
204 | else | ||
205 | build_seccomp(strace_output, fp); | ||
206 | fprintf(fp, "#shell none\n"); | ||
207 | fprintf(fp, "#tracelog\n"); | ||
208 | |||
209 | if (!arg_debug) { | ||
210 | unlink(trace_output); | 164 | unlink(trace_output); |
211 | unlink(strace_output); | ||
212 | } | ||
213 | } | 165 | } |
214 | else { | 166 | else { |
215 | fprintf(stderr, "Error: cannot run the sandbox\n"); | 167 | fprintf(stderr, "Error: cannot run the sandbox\n"); |