aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar Fred-Barclay <Fred-Barclay@users.noreply.github.com>2017-09-19 23:26:22 -0500
committerLibravatar Fred-Barclay <Fred-Barclay@users.noreply.github.com>2017-09-19 23:26:22 -0500
commit88c3a266eaaab9a41fe56c7c012ced5d6c33c6d2 (patch)
treeff4ab558330f8c566ddf7e9909a57e71913a232a /src
parentFix private-bit filter for firefox on Arch (diff)
parentadd nogroups (diff)
downloadfirejail-88c3a266eaaab9a41fe56c7c012ced5d6c33c6d2.tar.gz
firejail-88c3a266eaaab9a41fe56c7c012ced5d6c33c6d2.tar.zst
firejail-88c3a266eaaab9a41fe56c7c012ced5d6c33c6d2.zip
Merge branch 'master' of https://github.com/netblue30/firejail
Diffstat (limited to 'src')
-rw-r--r--src/fbuilder/Makefile.in45
-rw-r--r--src/fbuilder/build_bin.c121
-rw-r--r--src/fbuilder/build_fs.c280
-rw-r--r--src/fbuilder/build_home.c199
-rw-r--r--src/fbuilder/build_profile.c165
-rw-r--r--src/fbuilder/build_seccomp.c191
-rw-r--r--src/fbuilder/fbuilder.h68
-rw-r--r--src/fbuilder/filedb.c79
-rw-r--r--src/fbuilder/main.c71
-rw-r--r--src/fbuilder/utils.c72
-rw-r--r--src/fcopy/main.c19
-rw-r--r--src/firecfg/firecfg.config42
-rw-r--r--src/firecfg/main.c34
-rw-r--r--src/firejail/main.c22
-rw-r--r--src/firejail/usage.c1
-rw-r--r--src/firejail/util.c2
-rw-r--r--src/libtrace/libtrace.c12
-rw-r--r--src/man/firejail.txt12
18 files changed, 1422 insertions, 13 deletions
diff --git a/src/fbuilder/Makefile.in b/src/fbuilder/Makefile.in
new file mode 100644
index 000000000..dd8e2ce6e
--- /dev/null
+++ b/src/fbuilder/Makefile.in
@@ -0,0 +1,45 @@
1all: fbuilder
2
3CC=@CC@
4prefix=@prefix@
5exec_prefix=@exec_prefix@
6libdir=@libdir@
7sysconfdir=@sysconfdir@
8
9VERSION=@PACKAGE_VERSION@
10NAME=@PACKAGE_NAME@
11HAVE_SECCOMP_H=@HAVE_SECCOMP_H@
12HAVE_SECCOMP=@HAVE_SECCOMP@
13HAVE_CHROOT=@HAVE_CHROOT@
14HAVE_BIND=@HAVE_BIND@
15HAVE_FATAL_WARNINGS=@HAVE_FATAL_WARNINGS@
16HAVE_NETWORK=@HAVE_NETWORK@
17HAVE_USERNS=@HAVE_USERNS@
18HAVE_X11=@HAVE_X11@
19HAVE_FILE_TRANSFER=@HAVE_FILE_TRANSFER@
20HAVE_WHITELIST=@HAVE_WHITELIST@
21HAVE_GLOBALCFG=@HAVE_GLOBALCFG@
22HAVE_APPARMOR=@HAVE_APPARMOR@
23HAVE_OVERLAYFS=@HAVE_OVERLAYFS@
24HAVE_PRIVATE_HOME=@HAVE_PRIVATE_HOME@
25EXTRA_LDFLAGS +=@EXTRA_LDFLAGS@
26HAVE_GCOV=@HAVE_GCOV@
27EXTRA_LDFLAGS +=@EXTRA_LDFLAGS@
28
29H_FILE_LIST = $(sort $(wildcard *.[h]))
30C_FILE_LIST = $(sort $(wildcard *.c))
31OBJS = $(C_FILE_LIST:.c=.o)
32BINOBJS = $(foreach file, $(OBJS), $file)
33CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' $(HAVE_GCOV) -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)/firejail"' -DLIBDIR='"$(libdir)"' $(HAVE_X11) $(HAVE_PRIVATE_HOME) $(HAVE_APPARMOR) $(HAVE_OVERLAYFS) $(HAVE_SECCOMP) $(HAVE_GLOBALCFG) $(HAVE_SECCOMP_H) $(HAVE_CHROOT) $(HAVE_NETWORK) $(HAVE_USERNS) $(HAVE_BIND) $(HAVE_FILE_TRANSFER) $(HAVE_WHITELIST) -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -pie -Wformat -Wformat-security
34LDFLAGS += -pie -Wl,-z,relro -Wl,-z,now -lpthread
35
36%.o : %.c $(H_FILE_LIST) ../include/common.h ../include/syscall.h
37 $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@
38
39fbuilder: $(OBJS)
40 $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(EXTRA_LDFLAGS)
41
42clean:; rm -f *.o fbuilder *.gcov *.gcda *.gcno
43
44distclean: clean
45 rm -fr Makefile
diff --git a/src/fbuilder/build_bin.c b/src/fbuilder/build_bin.c
new file mode 100644
index 000000000..7d0e2cb7c
--- /dev/null
+++ b/src/fbuilder/build_bin.c
@@ -0,0 +1,121 @@
1/*
2 * Copyright (C) 2014-2017 Firejail Authors
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "fbuilder.h"
21
22static FileDB *bin_out = NULL;
23
24static void process_bin(const char *fname) {
25 assert(fname);
26
27 // process trace file
28 FILE *fp = fopen(fname, "r");
29 if (!fp) {
30 fprintf(stderr, "Error: cannot open %s\n", fname);
31 exit(1);
32 }
33
34 char buf[MAX_BUF];
35 while (fgets(buf, MAX_BUF, fp)) {
36 // remove \n
37 char *ptr = strchr(buf, '\n');
38 if (ptr)
39 *ptr = '\0';
40
41 // parse line: 4:galculator:access /etc/fonts/conf.d:0
42 // number followed by :
43 ptr = buf;
44 if (!isdigit(*ptr))
45 continue;
46 while (isdigit(*ptr))
47 ptr++;
48 if (*ptr != ':')
49 continue;
50 ptr++;
51
52 // next :
53 ptr = strchr(ptr, ':');
54 if (!ptr)
55 continue;
56 ptr++;
57 if (strncmp(ptr, "exec ", 5) == 0)
58 ptr += 5;
59 else
60 continue;
61 if (strncmp(ptr, "/bin/", 5) == 0)
62 ptr += 5;
63 else if (strncmp(ptr, "/sbin/", 6) == 0)
64 ptr += 6;
65 else if (strncmp(ptr, "/usr/bin/", 9) == 0)
66 ptr += 9;
67 else if (strncmp(ptr, "/usr/sbin/", 10) == 0)
68 ptr += 10;
69 else if (strncmp(ptr, "/usr/local/bin/", 15) == 0)
70 ptr += 15;
71 else if (strncmp(ptr, "/usr/local/sbin/", 16) == 0)
72 ptr += 16;
73 else if (strncmp(ptr, "/usr/games/", 11) == 0)
74 ptr += 12;
75 else if (strncmp(ptr, "/usr/local/games/", 17) == 0)
76 ptr += 17;
77 else
78 continue;
79
80 // end of filename
81 char *ptr2 = strchr(ptr, ':');
82 if (!ptr2)
83 continue;
84 *ptr2 = '\0';
85
86 bin_out = filedb_add(bin_out, ptr);
87 }
88
89 fclose(fp);
90}
91
92
93// process fname, fname.1, fname.2, fname.3, fname.4, fname.5
94void build_bin(const char *fname) {
95 assert(fname);
96
97 // run fname
98 process_bin(fname);
99
100 // run all the rest
101 struct stat s;
102 int i;
103 for (i = 1; i <= 5; i++) {
104 char *newname;
105 if (asprintf(&newname, "%s.%d", fname, i) == -1)
106 errExit("asprintf");
107 if (stat(newname, &s) == 0)
108 process_bin(newname);
109 free(newname);
110 }
111
112 if (bin_out) {
113 printf("# private-bin ");
114 FileDB *ptr = bin_out;
115 while (ptr) {
116 printf("%s,", ptr->fname);
117 ptr = ptr->next;
118 }
119 printf("\n");
120 }
121}
diff --git a/src/fbuilder/build_fs.c b/src/fbuilder/build_fs.c
new file mode 100644
index 000000000..dcd86e069
--- /dev/null
+++ b/src/fbuilder/build_fs.c
@@ -0,0 +1,280 @@
1/*
2 * Copyright (C) 2014-2017 Firejail Authors
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20
21#include "fbuilder.h"
22
23// common file processing function, using the callback for each line in the file
24static void process_file(const char *fname, const char *dir, void (*callback)(char *)) {
25 assert(fname);
26 assert(dir);
27 assert(callback);
28
29 int dir_len = strlen(dir);
30
31 // process trace file
32 FILE *fp = fopen(fname, "r");
33 if (!fp) {
34 fprintf(stderr, "Error: cannot open %s\n", fname);
35 exit(1);
36 }
37
38 char buf[MAX_BUF];
39 while (fgets(buf, MAX_BUF, fp)) {
40 // remove \n
41 char *ptr = strchr(buf, '\n');
42 if (ptr)
43 *ptr = '\0';
44
45 // parse line: 4:galculator:access /etc/fonts/conf.d:0
46 // number followed by :
47 ptr = buf;
48 if (!isdigit(*ptr))
49 continue;
50 while (isdigit(*ptr))
51 ptr++;
52 if (*ptr != ':')
53 continue;
54 ptr++;
55
56 // next :
57 ptr = strchr(ptr, ':');
58 if (!ptr)
59 continue;
60 ptr++;
61 if (strncmp(ptr, "access ", 7) == 0)
62 ptr += 7;
63 else if (strncmp(ptr, "fopen ", 6) == 0)
64 ptr += 6;
65 else if (strncmp(ptr, "fopen64 ", 8) == 0)
66 ptr += 8;
67 else if (strncmp(ptr, "open64 ", 7) == 0)
68 ptr += 7;
69 else if (strncmp(ptr, "open ", 5) == 0)
70 ptr += 5;
71 else
72 continue;
73 if (strncmp(ptr, dir, dir_len) != 0)
74 continue;
75
76 // end of filename
77 char *ptr2 = strchr(ptr, ':');
78 if (!ptr2)
79 continue;
80 *ptr2 = '\0';
81
82 callback(ptr);
83 }
84
85 fclose(fp);
86}
87
88// process fname, fname.1, fname.2, fname.3, fname.4, fname.5
89static void process_files(const char *fname, const char *dir, void (*callback)(char *)) {
90 assert(fname);
91 assert(dir);
92 assert(callback);
93
94 // run fname
95 process_file(fname, dir, callback);
96
97 // run all the rest
98 struct stat s;
99 int i;
100 for (i = 1; i <= 5; i++) {
101 char *newname;
102 if (asprintf(&newname, "%s.%d", fname, i) == -1)
103 errExit("asprintf");
104 if (stat(newname, &s) == 0)
105 process_file(newname, dir, callback);
106 free(newname);
107 }
108}
109
110//*******************************************
111// etc directory
112//*******************************************
113static FileDB *etc_out = NULL;
114
115static void etc_callback(char *ptr) {
116 // skip firejail directory
117 if (strncmp(ptr, "/etc/firejail", 13) == 0)
118 return;
119
120 // add only top files and directories
121 ptr += 5; // skip "/etc/"
122 char *end = strchr(ptr, '/');
123 if (end)
124 *end = '\0';
125 etc_out = filedb_add(etc_out, ptr);
126}
127
128void build_etc(const char *fname) {
129 assert(fname);
130
131 process_files(fname, "/etc", etc_callback);
132
133 printf("private-etc ");
134 if (etc_out == NULL)
135 printf("none\n");
136 else {
137 FileDB *ptr = etc_out;
138 while (ptr) {
139 printf("%s,", ptr->fname);
140 ptr = ptr->next;
141 }
142 printf("\n");
143 }
144}
145
146//*******************************************
147// var directory
148//*******************************************
149static FileDB *var_out = NULL;
150static void var_callback(char *ptr) {
151 if (strcmp(ptr, "/var/lib") == 0)
152 ;
153 else if (strcmp(ptr, "/var/cache") == 0)
154 ;
155 else if (strncmp(ptr, "/var/lib/menu-xdg", 17) == 0)
156 var_out = filedb_add(var_out, "/var/lib/menu-xdg");
157 else if (strncmp(ptr, "/var/cache/fontconfig", 21) == 0)
158 var_out = filedb_add(var_out, "/var/cache/fontconfig");
159 else
160 var_out = filedb_add(var_out, ptr);
161}
162
163void build_var(const char *fname) {
164 assert(fname);
165
166 process_files(fname, "/var", var_callback);
167
168 if (var_out == NULL)
169 printf("blacklist /var\n");
170 else
171 filedb_print(var_out, "whitelist ");
172}
173
174//*******************************************
175// tmp directory
176//*******************************************
177static FileDB *tmp_out = NULL;
178static void tmp_callback(char *ptr) {
179 filedb_add(tmp_out, ptr);
180}
181
182void build_tmp(const char *fname) {
183 assert(fname);
184
185 process_files(fname, "/tmp", tmp_callback);
186
187 if (tmp_out == NULL)
188 printf("private-tmp\n");
189 else {
190 printf("\n");
191 printf("# private-tmp\n");
192 printf("# File accessed in /tmp directory:\n");
193 printf("# ");
194 FileDB *ptr = tmp_out;
195 while (ptr) {
196 printf("%s,", ptr->fname);
197 ptr = ptr->next;
198 }
199 printf("\n");
200 }
201}
202
203//*******************************************
204// dev directory
205//*******************************************
206static char *dev_skip[] = {
207 "/dev/zero",
208 "/dev/null",
209 "/dev/full",
210 "/dev/random",
211 "/dev/urandom",
212 "/dev/tty",
213 "/dev/snd",
214 "/dev/dri",
215 "/dev/pts",
216 "/dev/nvidia0",
217 "/dev/nvidia1",
218 "/dev/nvidia2",
219 "/dev/nvidia3",
220 "/dev/nvidia4",
221 "/dev/nvidia5",
222 "/dev/nvidia6",
223 "/dev/nvidia7",
224 "/dev/nvidia8",
225 "/dev/nvidia9",
226 "/dev/nvidiactl",
227 "/dev/nvidia-modeset",
228 "/dev/nvidia-uvm",
229 "/dev/video0",
230 "/dev/video1",
231 "/dev/video2",
232 "/dev/video3",
233 "/dev/video4",
234 "/dev/video5",
235 "/dev/video6",
236 "/dev/video7",
237 "/dev/video8",
238 "/dev/video9",
239 "/dev/dvb",
240 "/dev/sr0",
241 NULL
242};
243
244static FileDB *dev_out = NULL;
245static void dev_callback(char *ptr) {
246 // skip private-dev devices
247 int i = 0;
248 int found = 0;
249 while (dev_skip[i]) {
250 if (strcmp(ptr, dev_skip[i]) == 0) {
251 found = 1;
252 break;
253 }
254 i++;
255 }
256 if (!found)
257 filedb_add(dev_out, ptr);
258}
259
260void build_dev(const char *fname) {
261 assert(fname);
262
263 process_files(fname, "/tmp", tmp_callback);
264
265 if (dev_out == NULL)
266 printf("private-dev\n");
267 else {
268 printf("\n");
269 printf("# private-dev\n");
270 printf("# This is the list of devices accessed (on top of regular private-dev devices:\n");
271 printf("# ");
272 FileDB *ptr = dev_out;
273 while (ptr) {
274 printf("%s,", ptr->fname);
275 ptr = ptr->next;
276 }
277 printf("\n");
278 }
279}
280
diff --git a/src/fbuilder/build_home.c b/src/fbuilder/build_home.c
new file mode 100644
index 000000000..947f172d8
--- /dev/null
+++ b/src/fbuilder/build_home.c
@@ -0,0 +1,199 @@
1/*
2 * Copyright (C) 2014-2017 Firejail Authors
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20
21#include "fbuilder.h"
22
23static FileDB *db_skip = NULL;
24static FileDB *db_out = NULL;
25
26static void load_whitelist_common(void) {
27 FILE *fp = fopen("/etc/firejail/whitelist-common.inc", "r");
28 if (!fp) {
29 fprintf(stderr, "Error: cannot open whitelist-common.inc\n");
30 exit(1);
31 }
32
33 char buf[MAX_BUF];
34 while (fgets(buf, MAX_BUF, fp)) {
35 if (strncmp(buf, "whitelist ~/", 12) != 0)
36 continue;
37 char *fn = buf + 12;
38 char *ptr = strchr(buf, '\n');
39 if (!ptr)
40 continue;
41 *ptr = '\0';
42
43 // add the file to skip list
44 db_skip = filedb_add(db_skip, fn);
45 }
46
47 fclose(fp);
48}
49
50void process_home(const char *fname, char *home, int home_len) {
51 assert(fname);
52 assert(home);
53 assert(home_len);
54
55 // process trace file
56 FILE *fp = fopen(fname, "r");
57 if (!fp) {
58 fprintf(stderr, "Error: cannot open %s\n", fname);
59 exit(1);
60 }
61
62 char buf[MAX_BUF];
63 while (fgets(buf, MAX_BUF, fp)) {
64 // remove \n
65 char *ptr = strchr(buf, '\n');
66 if (ptr)
67 *ptr = '\0';
68
69 // parse line: 4:galculator:access /etc/fonts/conf.d:0
70 // number followed by :
71 ptr = buf;
72 if (!isdigit(*ptr))
73 continue;
74 while (isdigit(*ptr))
75 ptr++;
76 if (*ptr != ':')
77 continue;
78 ptr++;
79
80 // next :
81 ptr = strchr(ptr, ':');
82 if (!ptr)
83 continue;
84 ptr++;
85 if (strncmp(ptr, "access /home", 12) == 0)
86 ptr += 7;
87 else if (strncmp(ptr, "fopen /home", 11) == 0)
88 ptr += 6;
89 else if (strncmp(ptr, "fopen64 /home", 13) == 0)
90 ptr += 8;
91 else if (strncmp(ptr, "open64 /home", 12) == 0)
92 ptr += 7;
93 else if (strncmp(ptr, "open /home", 10) == 0)
94 ptr += 5;
95 else
96 continue;
97
98 // end of filename
99 char *ptr2 = strchr(ptr, ':');
100 if (!ptr2)
101 continue;
102 *ptr2 = '\0';
103
104 // check home directory
105 if (strncmp(ptr, home, home_len) != 0)
106 continue;
107 if (strcmp(ptr, home) == 0)
108 continue;
109 ptr += home_len + 1;
110
111 // skip files handled automatically by firejail
112 if (strcmp(ptr, ".Xauthority") == 0 ||
113 strcmp(ptr, ".Xdefaults-debian") == 0 ||
114 strncmp(ptr, ".config/pulse/", 13) == 0 ||
115 strncmp(ptr, ".pulse/", 7) == 0 ||
116 strncmp(ptr, ".bash_hist", 10) == 0 ||
117 strcmp(ptr, ".bashrc") == 0)
118 continue;
119
120
121 // try to find the relevant directory for this file
122 char *dir = extract_dir(ptr);
123 char *toadd = (dir)? dir: ptr;
124
125 // skip some dot directories
126 if (strcmp(toadd, ".config") == 0 ||
127 strcmp(toadd, ".local") == 0 ||
128 strcmp(toadd, ".local/share") == 0 ||
129 strcmp(toadd, ".cache") == 0) {
130 if (dir)
131 free(dir);
132 continue;
133 }
134
135 // clean .cache entries
136 if (strncmp(toadd, ".cache/", 7) == 0) {
137 char *ptr2 = toadd + 7;
138 ptr2 = strchr(ptr2, '/');
139 if (ptr2)
140 *ptr2 = '\0';
141 }
142
143 // skip files and directories in whitelist-common.inc
144 if (filedb_find(db_skip, toadd)) {
145 if (dir)
146 free(dir);
147 continue;
148 }
149
150 // add the file to out list
151 db_out = filedb_add(db_out, toadd);
152 if (dir)
153 free(dir);
154
155 }
156 fclose(fp);
157}
158
159
160// process fname, fname.1, fname.2, fname.3, fname.4, fname.5
161void build_home(const char *fname) {
162 assert(fname);
163
164 // load whitelist common
165 load_whitelist_common();
166
167 // find user home directory
168 struct passwd *pw = getpwuid(getuid());
169 if (!pw)
170 errExit("getpwuid");
171 char *home = pw->pw_dir;
172 if (!home)
173 errExit("getpwuid");
174 int home_len = strlen(home);
175
176 // run fname
177 process_home(fname, home, home_len);
178
179 // run all the rest
180 struct stat s;
181 int i;
182 for (i = 1; i <= 5; i++) {
183 char *newname;
184 if (asprintf(&newname, "%s.%d", fname, i) == -1)
185 errExit("asprintf");
186 if (stat(newname, &s) == 0)
187 process_home(newname, home, home_len);
188 free(newname);
189 }
190
191 // print the out list if any
192 if (db_out) {
193 filedb_print(db_out, "whitelist ~/");
194 printf("include /etc/firejail/whitelist-common.inc\n");
195 }
196 else
197 printf("private\n");
198
199} \ No newline at end of file
diff --git a/src/fbuilder/build_profile.c b/src/fbuilder/build_profile.c
new file mode 100644
index 000000000..3f5fe48ca
--- /dev/null
+++ b/src/fbuilder/build_profile.c
@@ -0,0 +1,165 @@
1/*
2 * Copyright (C) 2014-2017 Firejail Authors
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20
21#include "fbuilder.h"
22#include <sys/wait.h>
23#include <fcntl.h>
24
25#define TRACE_OUTPUT "/tmp/firejail-trace"
26#define STRACE_OUTPUT "/tmp/firejail-strace"
27
28static char *cmdlist[] = {
29 "/usr/bin/firejail",
30 "--quiet",
31 "--output=" TRACE_OUTPUT,
32 "--noprofile",
33 "--caps.drop=all",
34 "--nonewprivs",
35 "--trace",
36 "--shell=none",
37 "/usr/bin/strace", // also used as a marker in build_profile()
38 "-c",
39 "-f",
40 "-o" STRACE_OUTPUT,
41};
42
43static void clear_tmp_files(void) {
44 unlink(STRACE_OUTPUT);
45 unlink(TRACE_OUTPUT);
46
47 // run all the rest
48 int i;
49 for (i = 1; i <= 5; i++) {
50 char *newname;
51 if (asprintf(&newname, "%s.%d", TRACE_OUTPUT, i) == -1)
52 errExit("asprintf");
53 unlink(newname);
54 free(newname);
55 }
56
57}
58
59void build_profile(int argc, char **argv, int index) {
60 // next index is the application name
61 if (index >= argc) {
62 fprintf(stderr, "Error: application name missing\n");
63 exit(1);
64 }
65
66 // clean /tmp files
67 clear_tmp_files();
68
69 // detect strace
70 int have_strace = 0;
71 if (access("/usr/bin/strace", X_OK) == 0)
72 have_strace = 1;
73
74 // calculate command length
75 int len = (int) sizeof(cmdlist) / sizeof(char*) + argc - index + 1;
76 if (arg_debug)
77 printf("command len %d + %d + 1\n", (int) (sizeof(cmdlist) / sizeof(char*)), argc - index);
78 char *cmd[len];
79
80 // build command
81 int i = 0;
82 for (i = 0; i < (int) sizeof(cmdlist) / sizeof(char*); i++) {
83 // skip strace if not installed
84 if (have_strace == 0 && strcmp(cmdlist[i], "/usr/bin/strace") == 0)
85 break;
86 cmd[i] = cmdlist[i];
87 }
88
89 int i2 = index;
90 for (; i < (len - 1); i++, i2++)
91 cmd[i] = argv[i2];
92 cmd[i] = NULL;
93
94 if (arg_debug) {
95 for (i = 0; i < len; i++)
96 printf("\t%s\n", cmd[i]);
97 }
98
99 // fork and execute
100 pid_t child = fork();
101 if (child == -1)
102 errExit("fork");
103 if (child == 0) {
104 int rv = execvp(cmd[0], cmd);
105 errExit("execv");
106 }
107
108 // wait for all processes to finish
109 int status;
110 if (waitpid(child, &status, 0) != child)
111 errExit("waitpid");
112
113 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
114 printf("\n\n\n");
115 printf("############################################\n");
116 printf("# %s profile\n", argv[index]);
117 printf("############################################\n");
118 printf("# Persistent global definitions\n");
119 printf("# include /etc/firejail/globals.local\n");
120 printf("\n");
121
122 printf("### basic blacklisting\n");
123 printf("include /etc/firejail/disable-common.inc\n");
124 printf("# include /etc/firejail/disable-devel.inc\n");
125 printf("include /etc/firejail/disable-passwdmgr.inc\n");
126 printf("# include /etc/firejail/disable-programs.inc\n");
127 printf("\n");
128
129 printf("### home directory whitelisting\n");
130 build_home(TRACE_OUTPUT);
131 printf("\n");
132
133 printf("### filesystem\n");
134 build_tmp(TRACE_OUTPUT);
135 build_dev(TRACE_OUTPUT);
136 build_etc(TRACE_OUTPUT);
137 build_var(TRACE_OUTPUT);
138 build_bin(TRACE_OUTPUT);
139 printf("\n");
140
141 printf("### security filters\n");
142 printf("caps.drop all\n");
143 printf("nonewprivs\n");
144 printf("seccomp\n");
145 if (have_strace)
146 build_seccomp(STRACE_OUTPUT);
147 else {
148 printf("# If you install strace on your system, Firejail will also create a\n");
149 printf("# whitelisted seccomp filter.\n");
150 }
151 printf("\n");
152
153 printf("### network\n");
154 build_protocol(TRACE_OUTPUT);
155 printf("\n");
156
157 printf("### environment\n");
158 printf("shell none\n");
159
160 }
161 else {
162 fprintf(stderr, "Error: cannot run the sandbox\n");
163 exit(1);
164 }
165}
diff --git a/src/fbuilder/build_seccomp.c b/src/fbuilder/build_seccomp.c
new file mode 100644
index 000000000..18a767518
--- /dev/null
+++ b/src/fbuilder/build_seccomp.c
@@ -0,0 +1,191 @@
1/*
2 * Copyright (C) 2014-2017 Firejail Authors
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20
21#include "fbuilder.h"
22
23void build_seccomp(const char *fname) {
24 assert(fname);
25
26 FILE *fp = fopen(fname, "r");
27 if (!fp) {
28 fprintf(stderr, "Error: cannot open %s\n", fname);
29 exit(1);
30 }
31
32 char buf[MAX_BUF];
33 int line = 1;
34 int position = 0;
35 int cnt = 0;
36 while (fgets(buf, MAX_BUF, fp)) {
37 // remove \n
38 char *ptr = strchr(buf, '\n');
39 if (ptr)
40 *ptr = '\0';
41
42 // first line:
43 //% time seconds usecs/call calls errors syscall
44 if (line == 1) {
45 // extract syscall position
46 ptr = strstr(buf, "syscall");
47 if (*buf != '%' || ptr == NULL) {
48 // skip this line, it could be garbage from strace
49 continue;
50 }
51 position = (int) (ptr - buf);
52 }
53 else if (line == 2) {
54 if (*buf != '-') {
55 fprintf(stderr, "Error: invalid strace output\n%s\n", buf);
56 exit(1);
57 }
58 }
59 else {
60 // get out on the next "----" line
61 if (*buf == '-')
62 break;
63
64 if (line == 3)
65 printf("# seccomp.keep %s", buf + position);
66 else
67 printf(",%s", buf + position);
68 cnt++;
69 }
70 line++;
71 }
72 printf("\n");
73 printf("# %d syscalls total\n", cnt);
74 printf("# Probably you will need to add more syscalls to seccomp.keep. Look for\n");
75 printf("# seccomp errors in /var/log/syslog or /var/log/audit/audit.log while\n");
76 printf("# running your sandbox.\n");
77
78 fclose(fp);
79}
80
81//***************************************
82// protocol
83//***************************************
84int unix_s = 0;
85int inet = 0;
86int inet6 = 0;
87int netlink = 0;
88int packet = 0;
89static void process_protocol(const char *fname) {
90 assert(fname);
91
92 // process trace file
93 FILE *fp = fopen(fname, "r");
94 if (!fp) {
95 fprintf(stderr, "Error: cannot open %s\n", fname);
96 exit(1);
97 }
98
99 char buf[MAX_BUF];
100 while (fgets(buf, MAX_BUF, fp)) {
101 // remove \n
102 char *ptr = strchr(buf, '\n');
103 if (ptr)
104 *ptr = '\0';
105
106 // parse line: 4:galculator:access /etc/fonts/conf.d:0
107 // number followed by :
108 ptr = buf;
109 if (!isdigit(*ptr))
110 continue;
111 while (isdigit(*ptr))
112 ptr++;
113 if (*ptr != ':')
114 continue;
115 ptr++;
116
117 // next :
118 ptr = strchr(ptr, ':');
119 if (!ptr)
120 continue;
121 ptr++;
122 if (strncmp(ptr, "socket ", 7) == 0)
123 ptr += 7;
124 else
125 continue;
126
127 if (strncmp(ptr, "AF_LOCAL ", 9) == 0)
128 unix_s = 1;
129 else if (strncmp(ptr, "AF_INET ", 8) == 0)
130 inet = 1;
131 else if (strncmp(ptr, "AF_INET6 ", 9) == 0)
132 inet6 = 1;
133 else if (strncmp(ptr, "AF_NETLINK ", 9) == 0)
134 netlink = 1;
135 else if (strncmp(ptr, "AF_PACKET ", 9) == 0)
136 packet = 1;
137 }
138
139 fclose(fp);
140}
141
142
143// process fname, fname.1, fname.2, fname.3, fname.4, fname.5
144void build_protocol(const char *fname) {
145 assert(fname);
146
147 // run fname
148 process_protocol(fname);
149
150 // run all the rest
151 struct stat s;
152 int i;
153 for (i = 1; i <= 5; i++) {
154 char *newname;
155 if (asprintf(&newname, "%s.%d", fname, i) == -1)
156 errExit("asprintf");
157 if (stat(newname, &s) == 0)
158 process_protocol(newname);
159 free(newname);
160 }
161
162 int net = 0;
163 if (unix_s || inet || inet6 || netlink || packet) {
164 printf("protocol ");
165 if (unix_s)
166 printf("unix,");
167 if (inet) {
168 printf("inet,");
169 net = 1;
170 }
171 if (inet6) {
172 printf("inet6,");
173 net = 1;
174 }
175 if (netlink)
176 printf("netlink,");
177 if (packet) {
178 printf("packet");
179 net = 1;
180 }
181 printf("\n");
182 }
183
184 if (net == 0)
185 printf("net none\n");
186 else {
187 printf("# net eth0\n");
188 printf("netfilter\n");
189 }
190}
191
diff --git a/src/fbuilder/fbuilder.h b/src/fbuilder/fbuilder.h
new file mode 100644
index 000000000..c448f3e06
--- /dev/null
+++ b/src/fbuilder/fbuilder.h
@@ -0,0 +1,68 @@
1/*
2 * Copyright (C) 2014-2017 Firejail Authors
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20
21#ifndef FBUILDER_H
22#define FBUILDER_H
23#include "../include/common.h"
24#include <sys/types.h>
25#include <pwd.h>
26#include <sys/types.h>
27#include <sys/stat.h>
28
29
30#define MAX_BUF 4096
31// main.c
32extern int arg_debug;
33
34// build_profile.c
35void build_profile(int argc, char **argv, int index);
36
37// build_seccomp.c
38void build_seccomp(const char *fname);
39void build_protocol(const char *fname);
40
41// build_fs.c
42void build_etc(const char *fname);
43void build_var(const char *fname);
44void build_tmp(const char *fname);
45void build_dev(const char *fname);
46
47// build_bin.c
48void build_bin(const char *fname);
49
50// build_home.c
51void build_home(const char *fname);
52
53// utils.c
54int is_dir(const char *fname);
55char *extract_dir(char *fname);
56
57// filedb.c
58typedef struct filedb_t {
59 struct filedb_t *next;
60 char *fname; // file name
61 int len; // length of file name
62} FileDB;
63
64FileDB *filedb_add(FileDB *head, const char *fname);
65FileDB *filedb_find(FileDB *head, const char *fname);
66void filedb_print(FileDB *head, const char *prefix);
67
68#endif \ No newline at end of file
diff --git a/src/fbuilder/filedb.c b/src/fbuilder/filedb.c
new file mode 100644
index 000000000..a76fbc961
--- /dev/null
+++ b/src/fbuilder/filedb.c
@@ -0,0 +1,79 @@
1/*
2 * Copyright (C) 2014-2017 Firejail Authors
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20
21#include "fbuilder.h"
22
23FileDB *filedb_find(FileDB *head, const char *fname) {
24 FileDB *ptr = head;
25 int found = 0;
26 int len = strlen(fname);
27
28 while (ptr) {
29 // exact name
30 if (strcmp(fname, ptr->fname) == 0) {
31 found = 1;
32 break;
33 }
34
35 // parent directory in the list
36 if (len > ptr->len &&
37 fname[ptr->len] == '/' &&
38 strncmp(ptr->fname, fname, ptr->len) == 0) {
39 found = 1;
40 break;
41 }
42
43 ptr = ptr->next;
44 }
45
46 if (found)
47 return ptr;
48
49 return NULL;
50}
51
52FileDB *filedb_add(FileDB *head, const char *fname) {
53 assert(fname);
54
55 // don't add it if it is already there or if the parent directory is already in the list
56 if (filedb_find(head, fname))
57 return head;
58
59 // add a new entry
60 FileDB *entry = malloc(sizeof(FileDB));
61 if (!entry)
62 errExit("malloc");
63 memset(entry, 0, sizeof(FileDB));
64 entry->fname = strdup(fname);
65 if (!entry->fname)
66 errExit("strdup");
67 entry->len = strlen(entry->fname);
68 entry->next = head;
69 return entry;
70};
71
72void filedb_print(FileDB *head, const char *prefix) {
73 FileDB *ptr = head;
74 while (ptr) {
75 printf("%s%s\n", prefix, ptr->fname);
76 ptr = ptr->next;
77 }
78}
79
diff --git a/src/fbuilder/main.c b/src/fbuilder/main.c
new file mode 100644
index 000000000..83217ef98
--- /dev/null
+++ b/src/fbuilder/main.c
@@ -0,0 +1,71 @@
1/*
2 * Copyright (C) 2014-2017 Firejail Authors
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "fbuilder.h"
21int arg_debug = 0;
22
23static void usage(void) {
24 printf("Firejail profile builder\n");
25 printf("Usage: firejail [--debug] --build program-and-arguments\n");
26}
27
28int main(int argc, char **argv) {
29#if 0
30{
31system("cat /proc/self/status");
32int i;
33for (i = 0; i < argc; i++)
34 printf("*%s* ", argv[i]);
35printf("\n");
36}
37#endif
38
39 int i;
40 int prog_index = 0;
41
42 // parse arguments and extract program index
43 for (i = 1; i < argc; i++) {
44 if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-?") ==0) {
45 usage();
46 return 0;
47 }
48 else if (strcmp(argv[i], "--debug") == 0)
49 arg_debug = 1;
50 else if (strcmp(argv[i], "--build") == 0)
51 ; // do nothing, this is passed down from firejail
52 else {
53 if (*argv[i] == '-') {
54 fprintf(stderr, "Error fbuilder: invalid program\n");
55 usage();
56 exit(1);
57 }
58 prog_index = i;
59 break;
60 }
61 }
62
63 if (prog_index == 0) {
64 fprintf(stderr, "Error fbuilder: program and arguments required\n");
65 usage();
66 exit(1);
67 }
68
69 build_profile(argc, argv, prog_index);
70 return 0;
71}
diff --git a/src/fbuilder/utils.c b/src/fbuilder/utils.c
new file mode 100644
index 000000000..902290899
--- /dev/null
+++ b/src/fbuilder/utils.c
@@ -0,0 +1,72 @@
1/*
2 * Copyright (C) 2014-2017 Firejail Authors
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20
21#include "fbuilder.h"
22
23// todo: duplicated from src/firejail/util.c - remove dplication
24// return 1 if the file is a directory
25int is_dir(const char *fname) {
26 assert(fname);
27 if (*fname == '\0')
28 return 0;
29
30 // if fname doesn't end in '/', add one
31 int rv;
32 struct stat s;
33 if (fname[strlen(fname) - 1] == '/')
34 rv = stat(fname, &s);
35 else {
36 char *tmp;
37 if (asprintf(&tmp, "%s/", fname) == -1) {
38 fprintf(stderr, "Error: cannot allocate memory, %s:%d\n", __FILE__, __LINE__);
39 errExit("asprintf");
40 }
41 rv = stat(tmp, &s);
42 free(tmp);
43 }
44
45 if (rv == -1)
46 return 0;
47
48 if (S_ISDIR(s.st_mode))
49 return 1;
50
51 return 0;
52}
53
54// return NULL if fname is already a directory, or if no directory found
55char *extract_dir(char *fname) {
56 assert(fname);
57 if (is_dir(fname))
58 return NULL;
59
60 char *name = strdup(fname);
61 if (!name)
62 errExit("strdup");
63
64 char *ptr = strrchr(name, '/');
65 if (!ptr) {
66 free(name);
67 return NULL;
68 }
69 *ptr = '\0';
70
71 return name;
72}
diff --git a/src/fcopy/main.c b/src/fcopy/main.c
index da5ade428..e7b4ffa8a 100644
--- a/src/fcopy/main.c
+++ b/src/fcopy/main.c
@@ -22,6 +22,7 @@
22#include <fcntl.h> 22#include <fcntl.h>
23#include <ftw.h> 23#include <ftw.h>
24#include <errno.h> 24#include <errno.h>
25#include <pwd.h>
25 26
26int arg_quiet = 0; 27int arg_quiet = 0;
27static int arg_follow_link = 0; 28static int arg_follow_link = 0;
@@ -199,10 +200,22 @@ static char *check(const char *src) {
199 if (!rsrc || stat(rsrc, &s) == -1) 200 if (!rsrc || stat(rsrc, &s) == -1)
200 goto errexit; 201 goto errexit;
201 202
202 // check uid 203 // on systems with systemd-resolved installed /etc/resolve.conf is a symlink to
204 // /run/systemd/resolve/resolv.conf; this file is owned by systemd-resolve user
203 // checking gid will fail for files with a larger group such as /usr/bin/mutt_dotlock 205 // checking gid will fail for files with a larger group such as /usr/bin/mutt_dotlock
204 if (s.st_uid != getuid()/* || s.st_gid != getgid()*/) 206 uid_t user = getuid();
205 goto errexit; 207 if (user == 0 && strcmp(rsrc, "/run/systemd/resolve/resolv.conf") == 0) {
208 // check user systemd-resolve
209 struct passwd *p = getpwnam("systemd-resolve");
210 if (!p)
211 goto errexit;
212 if (s.st_uid != user && s.st_uid != p->pw_uid)
213 goto errexit;
214 }
215 else {
216 if (s.st_uid != user)
217 goto errexit;
218 }
206 219
207 // dir, link, regular file 220 // dir, link, regular file
208 if (S_ISDIR(s.st_mode) || S_ISREG(s.st_mode) || S_ISLNK(s.st_mode)) 221 if (S_ISDIR(s.st_mode) || S_ISREG(s.st_mode) || S_ISLNK(s.st_mode))
diff --git a/src/firecfg/firecfg.config b/src/firecfg/firecfg.config
index 79b263823..95fc14d04 100644
--- a/src/firecfg/firecfg.config
+++ b/src/firecfg/firecfg.config
@@ -8,15 +8,20 @@
8Cyberfox 8Cyberfox
9FossaMail 9FossaMail
10Mathematica 10Mathematica
11Natron
11Telegram 12Telegram
13Viber
12VirtualBox 14VirtualBox
13Wire 15Wire
14Xephyr 16Xephyr
15abrowser 17abrowser
16akregator 18akregator
17amarok 19amarok
20amule
18android-studio 21android-studio
19apktool 22apktool
23ardour4
24ardour5
20arduino 25arduino
21ark 26ark
22arm 27arm
@@ -34,18 +39,33 @@ bitlbee
34bleachbit 39bleachbit
35blender 40blender
36bless 41bless
42brackets
37brasero 43brasero
38brave 44brave
39calibre 45calibre
46calligra
47calligraauthor
48calligraconverter
49calligraflow
50calligraplan
51calligraplanwork
52calligrasheets
53calligrastage
54calligrawords
40catfish 55catfish
41cherrytree 56cherrytree
42chromium 57chromium
43chromium-browser 58chromium-browser
59cin
60clamdscan
61clamdtop
62clamscan
44claws-mail 63claws-mail
45clementine 64clementine
46clipit 65clipit
47cmus 66cmus
48conkeror 67conkeror
68conky
49corebird 69corebird
50cvlc 70cvlc
51cyberfox 71cyberfox
@@ -61,6 +81,8 @@ display
61dnscrypt-proxy 81dnscrypt-proxy
62dnsmasq 82dnsmasq
63dolphin 83dolphin
84dooble
85dooble-qt4
64dosbox 86dosbox
65dragon 87dragon
66dropbox 88dropbox
@@ -85,6 +107,9 @@ flashpeak-slimjet
85flowblade 107flowblade
86fontforge 108fontforge
87franz 109franz
110freecad
111freecadcmd
112freshclam
88frozen-bubble 113frozen-bubble
89gajim 114gajim
90galculator 115galculator
@@ -118,6 +143,7 @@ google-chrome
118google-chrome-beta 143google-chrome-beta
119google-chrome-stable 144google-chrome-stable
120google-chrome-unstable 145google-chrome-unstable
146google-earth
121google-play-music-desktop-player 147google-play-music-desktop-player
122gpa 148gpa
123gpicview 149gpicview
@@ -137,6 +163,7 @@ icecat
137icedove 163icedove
138iceweasel 164iceweasel
139idea.sh 165idea.sh
166imagej
140img2txt 167img2txt
141inkscape 168inkscape
142inox 169inox
@@ -145,8 +172,10 @@ iridium-browser
145jd-gui 172jd-gui
146jitsi 173jitsi
147k3b 174k3b
175karbon
148kate 176kate
149kcalc 177kcalc
178kdenlive
150keepass 179keepass
151keepass2 180keepass2
152keepassx 181keepassx
@@ -157,12 +186,15 @@ kmail
157knotes 186knotes
158kodi 187kodi
159konversation 188konversation
189krita
160ktorrent 190ktorrent
161kwrite 191kwrite
162leafpad 192leafpad
163less 193less
164libreoffice 194libreoffice
165liferea 195liferea
196linphone
197lmms
166localc 198localc
167lodraw 199lodraw
168loffice 200loffice
@@ -176,6 +208,7 @@ luminance-hdr
176lximage-qt 208lximage-qt
177lxmusic 209lxmusic
178lynx 210lynx
211macrofusion
179mate-calc 212mate-calc
180mate-calculator 213mate-calculator
181mate-color-select 214mate-color-select
@@ -196,6 +229,7 @@ mupdf
196mupen64plus 229mupen64plus
197musescore 230musescore
198mutt 231mutt
232natron
199nautilus 233nautilus
200netsurf 234netsurf
201neverball 235neverball
@@ -234,13 +268,16 @@ rambox
234ranger 268ranger
235remmina 269remmina
236rhythmbox 270rhythmbox
271ricochet
237riot-web 272riot-web
238ristretto 273ristretto
274rocketchat
239rtorrent 275rtorrent
240scribus 276scribus
241sdat2img 277sdat2img
242seamonkey 278seamonkey
243seamonkey-bin 279seamonkey-bin
280shotcut
244silentarmy 281silentarmy
245simple-scan 282simple-scan
246simutrans 283simutrans
@@ -261,9 +298,12 @@ stellarium
261strings 298strings
262supertux2 299supertux2
263synfigstudio 300synfigstudio
301teamspeak3
264telegram 302telegram
265telegram-desktop 303telegram-desktop
304terasology
266thunderbird 305thunderbird
306tor-browser-en
267totem 307totem
268tracker 308tracker
269transmission-cli 309transmission-cli
@@ -304,6 +344,7 @@ xfce4-dict
304xfce4-notes 344xfce4-notes
305xiphos 345xiphos
306xmms 346xmms
347xmr-stak-cpu
307xonotic 348xonotic
308xonotic-glx 349xonotic-glx
309xonotic-sdl 350xonotic-sdl
@@ -314,5 +355,6 @@ xreader
314xviewer 355xviewer
315yandex-browser 356yandex-browser
316youtube-dl 357youtube-dl
358zart
317zathura 359zathura
318zoom 360zoom
diff --git a/src/firecfg/main.c b/src/firecfg/main.c
index 1ecfbf524..82b30c2c5 100644
--- a/src/firecfg/main.c
+++ b/src/firecfg/main.c
@@ -330,23 +330,39 @@ static void set_links(void) {
330 free(firejail_exec); 330 free(firejail_exec);
331} 331}
332 332
333int have_profile(const char *filename) { 333// look for a profile file in /etc/firejail diectory and in homedir/.config/firejail directory
334static int have_profile(const char *filename, const char *homedir) {
335 assert(filename);
336 assert(homedir);
337printf("test #%s# #%s#\n", filename, homedir);
338
334 // remove .desktop extension 339 // remove .desktop extension
335 char *f1 = strdup(filename); 340 char *f1 = strdup(filename);
336 if (!f1) 341 if (!f1)
337 errExit("strdup"); 342 errExit("strdup");
338 f1[strlen(filename) - 8] = '\0'; 343 f1[strlen(filename) - 8] = '\0';
344printf("#%s#\n", f1);
339 345
340 // build profile name 346 // build profile name
341 char *profname; 347 char *profname1;
342 if (asprintf(&profname, "%s/%s.profile", SYSCONFDIR, f1) == -1) 348 char *profname2;
349 if (asprintf(&profname1, "%s/%s.profile", SYSCONFDIR, f1) == -1)
343 errExit("asprintf"); 350 errExit("asprintf");
344 351 if (asprintf(&profname2, "%s/./configure/firejail/%s.profile", homedir, f1) == -1)
345 struct stat s; 352 errExit("asprintf");
346 int rv = stat(profname, &s); 353printf("#%s#\n", profname1);
354printf("#%s#\n", profname2);
355
356 int rv = 0;
357 if (access(profname1, R_OK) == 0)
358 rv = 1;
359 else if (access(profname2, R_OK) == 0)
360 rv == 1;
361
347 free(f1); 362 free(f1);
348 free(profname); 363 free(profname1);
349 return (rv == 0)? 1: 0; 364 free(profname2);
365 return rv;
350} 366}
351 367
352static void fix_desktop_files(char *homedir) { 368static void fix_desktop_files(char *homedir) {
@@ -411,7 +427,7 @@ static void fix_desktop_files(char *homedir) {
411 errExit("stat"); 427 errExit("stat");
412 428
413 // no profile in /etc/firejail, no desktop file fixing 429 // no profile in /etc/firejail, no desktop file fixing
414 if (!have_profile(filename)) 430 if (!have_profile(filename, homedir))
415 continue; 431 continue;
416 432
417 /* coverity[toctou] */ 433 /* coverity[toctou] */
diff --git a/src/firejail/main.c b/src/firejail/main.c
index 399770142..1b49c5fb3 100644
--- a/src/firejail/main.c
+++ b/src/firejail/main.c
@@ -849,6 +849,24 @@ static int check_arg(int argc, char **argv, const char *argument) {
849 return found; 849 return found;
850} 850}
851 851
852static void run_builder(int argc, char **argv) {
853 EUID_ASSERT();
854
855 // drop privileges
856 if (setgid(getgid()) < 0)
857 errExit("setgid/getgid");
858 if (setuid(getuid()) < 0)
859 errExit("setuid/getuid");
860 assert(getenv("LD_PRELOAD") == NULL);
861
862 argv[0] = LIBDIR "/firejail/fbuilder";
863 execvp(argv[0], argv);
864
865 perror("execvp");
866 exit(1);
867}
868
869
852//******************************************* 870//*******************************************
853// Main program 871// Main program
854//******************************************* 872//*******************************************
@@ -907,6 +925,10 @@ int main(int argc, char **argv) {
907 git_uninstall(); // this function will not return 925 git_uninstall(); // this function will not return
908#endif 926#endif
909 927
928 // profile builder
929 if (check_arg(argc, argv, "--build"))
930 run_builder(argc, argv); // this function will not return
931
910 // check argv[0] symlink wrapper if this is not a login shell 932 // check argv[0] symlink wrapper if this is not a login shell
911 if (*argv[0] != '-') 933 if (*argv[0] != '-')
912 run_symlink(argc, argv); // this function will not return 934 run_symlink(argc, argv); // this function will not return
diff --git a/src/firejail/usage.c b/src/firejail/usage.c
index fc7dbd69c..f09eb6416 100644
--- a/src/firejail/usage.c
+++ b/src/firejail/usage.c
@@ -44,6 +44,7 @@ void usage(void) {
44 printf(" --bind=filename1,filename2 - mount-bind filename1 on top of filename2.\n"); 44 printf(" --bind=filename1,filename2 - mount-bind filename1 on top of filename2.\n");
45#endif 45#endif
46 printf(" --blacklist=filename - blacklist directory or file.\n"); 46 printf(" --blacklist=filename - blacklist directory or file.\n");
47 printf(" --build - build a whitelisted profile for the application.\n");
47 printf(" -c - execute command and exit.\n"); 48 printf(" -c - execute command and exit.\n");
48 printf(" --caps - enable default Linux capabilities filter.\n"); 49 printf(" --caps - enable default Linux capabilities filter.\n");
49 printf(" --caps.drop=all - drop all capabilities.\n"); 50 printf(" --caps.drop=all - drop all capabilities.\n");
diff --git a/src/firejail/util.c b/src/firejail/util.c
index 3e0729620..4d1c94c25 100644
--- a/src/firejail/util.c
+++ b/src/firejail/util.c
@@ -196,7 +196,7 @@ static int copy_file_by_fd(int src, int dst) {
196 done += rv; 196 done += rv;
197 } 197 }
198 } 198 }
199 fflush(0); 199// fflush(0);
200 return 0; 200 return 0;
201} 201}
202 202
diff --git a/src/libtrace/libtrace.c b/src/libtrace/libtrace.c
index 5cdb254a3..04cf64997 100644
--- a/src/libtrace/libtrace.c
+++ b/src/libtrace/libtrace.c
@@ -673,3 +673,15 @@ int setresgid(gid_t rgid, gid_t egid, gid_t sgid) {
673 673
674 return rv; 674 return rv;
675} 675}
676
677// every time a new process is started, this gets called
678// it can be used to build things like private-bin
679__attribute__((constructor))
680static void log_exec(int argc, char** argv) {
681 static char buf[PATH_MAX + 1];
682 int rv = readlink("/proc/self/exe", buf, PATH_MAX);
683 if (rv != -1) {
684 buf[rv] = '\0'; // readlink does not add a '\0' at the end
685 printf("%u:%s:exec %s:0\n", pid(), name(), buf);
686 }
687}
diff --git a/src/man/firejail.txt b/src/man/firejail.txt
index 2dd3abbb7..f205bfa30 100644
--- a/src/man/firejail.txt
+++ b/src/man/firejail.txt
@@ -154,6 +154,18 @@ $ firejail "\-\-blacklist=/home/username/My Virtual Machines"
154.br 154.br
155$ firejail \-\-blacklist=/home/username/My\\ Virtual\\ Machines 155$ firejail \-\-blacklist=/home/username/My\\ Virtual\\ Machines
156.TP 156.TP
157\fB\-\-build
158The command builds a whitelisted profile. If /usr/bin/strace is installed on the system, it also
159builds a whitelisted seccomp profile. The program is run in a very relaxed sandbox,
160with only --caps.drop=all and --nonewprivs. Programs that raise user privileges are not supported
161in order to allow strace to run. Chromium and Chromium-based browsers will not work.
162.br
163
164.br
165Example:
166.br
167$ firejail --build vlc ~/Videos/test.mp4
168.TP
157\fB\-c 169\fB\-c
158Execute command and exit. 170Execute command and exit.
159.TP 171.TP