aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/fbuilder/build_bin.c121
-rw-r--r--src/fbuilder/build_profile.c4
-rw-r--r--src/fbuilder/fbuilder.h3
-rw-r--r--src/firecfg/firecfg.config5
-rw-r--r--src/firecfg/main.c104
-rw-r--r--src/firejail/util.c2
-rw-r--r--src/libtrace/libtrace.c12
-rw-r--r--src/man/firejail.txt6
8 files changed, 239 insertions, 18 deletions
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_profile.c b/src/fbuilder/build_profile.c
index 5fca22648..3f5fe48ca 100644
--- a/src/fbuilder/build_profile.c
+++ b/src/fbuilder/build_profile.c
@@ -33,6 +33,7 @@ static char *cmdlist[] = {
33 "--caps.drop=all", 33 "--caps.drop=all",
34 "--nonewprivs", 34 "--nonewprivs",
35 "--trace", 35 "--trace",
36 "--shell=none",
36 "/usr/bin/strace", // also used as a marker in build_profile() 37 "/usr/bin/strace", // also used as a marker in build_profile()
37 "-c", 38 "-c",
38 "-f", 39 "-f",
@@ -56,8 +57,6 @@ static void clear_tmp_files(void) {
56} 57}
57 58
58void build_profile(int argc, char **argv, int index) { 59void build_profile(int argc, char **argv, int index) {
59 unlink("/tmp/strace-output");
60
61 // next index is the application name 60 // next index is the application name
62 if (index >= argc) { 61 if (index >= argc) {
63 fprintf(stderr, "Error: application name missing\n"); 62 fprintf(stderr, "Error: application name missing\n");
@@ -136,6 +135,7 @@ void build_profile(int argc, char **argv, int index) {
136 build_dev(TRACE_OUTPUT); 135 build_dev(TRACE_OUTPUT);
137 build_etc(TRACE_OUTPUT); 136 build_etc(TRACE_OUTPUT);
138 build_var(TRACE_OUTPUT); 137 build_var(TRACE_OUTPUT);
138 build_bin(TRACE_OUTPUT);
139 printf("\n"); 139 printf("\n");
140 140
141 printf("### security filters\n"); 141 printf("### security filters\n");
diff --git a/src/fbuilder/fbuilder.h b/src/fbuilder/fbuilder.h
index a9049ea2d..c448f3e06 100644
--- a/src/fbuilder/fbuilder.h
+++ b/src/fbuilder/fbuilder.h
@@ -44,6 +44,9 @@ void build_var(const char *fname);
44void build_tmp(const char *fname); 44void build_tmp(const char *fname);
45void build_dev(const char *fname); 45void build_dev(const char *fname);
46 46
47// build_bin.c
48void build_bin(const char *fname);
49
47// build_home.c 50// build_home.c
48void build_home(const char *fname); 51void build_home(const char *fname);
49 52
diff --git a/src/firecfg/firecfg.config b/src/firecfg/firecfg.config
index 5d6afe68b..5a36f5e3e 100644
--- a/src/firecfg/firecfg.config
+++ b/src/firecfg/firecfg.config
@@ -20,6 +20,7 @@ amarok
20amule 20amule
21android-studio 21android-studio
22apktool 22apktool
23arch-audit
23ardour4 24ardour4
24ardour5 25ardour5
25arduino 26arduino
@@ -65,6 +66,7 @@ clementine
65clipit 66clipit
66cmus 67cmus
67conkeror 68conkeror
69conky
68corebird 70corebird
69cvlc 71cvlc
70cyberfox 72cyberfox
@@ -97,6 +99,7 @@ evolution
97exiftool 99exiftool
98fbreader 100fbreader
99feh 101feh
102ffmpeg
100file-roller 103file-roller
101filezilla 104filezilla
102firefox 105firefox
@@ -290,7 +293,7 @@ soundconverter
290spotify 293spotify
291sqlitebrowser 294sqlitebrowser
292ssh 295ssh
293ssh-agent 296# ssh-agent - problems on Arch with Fish shell (#1568)
294start-tor-browser 297start-tor-browser
295steam 298steam
296stellarium 299stellarium
diff --git a/src/firecfg/main.c b/src/firecfg/main.c
index 1ecfbf524..5928b9ae5 100644
--- a/src/firecfg/main.c
+++ b/src/firecfg/main.c
@@ -31,6 +31,7 @@
31#include <errno.h> 31#include <errno.h>
32#include <sys/mman.h> 32#include <sys/mman.h>
33#include <pwd.h> 33#include <pwd.h>
34#include <dirent.h>
34 35
35#include "../include/common.h" 36#include "../include/common.h"
36static int arg_debug = 0; 37static int arg_debug = 0;
@@ -277,7 +278,8 @@ static void set_file(const char *name, const char *firejail_exec) {
277 free(fname); 278 free(fname);
278} 279}
279 280
280static void set_links(void) { 281// parse /usr/lib/firejail/firecfg.cfg file
282static void set_links_firecfg(void) {
281 char *cfgfile; 283 char *cfgfile;
282 if (asprintf(&cfgfile, "%s/firejail/firecfg.config", LIBDIR) == -1) 284 if (asprintf(&cfgfile, "%s/firejail/firecfg.config", LIBDIR) == -1)
283 errExit("asprintf"); 285 errExit("asprintf");
@@ -286,12 +288,13 @@ static void set_links(void) {
286 if (asprintf(&firejail_exec, "%s/bin/firejail", PREFIX) == -1) 288 if (asprintf(&firejail_exec, "%s/bin/firejail", PREFIX) == -1)
287 errExit("asprintf"); 289 errExit("asprintf");
288 290
291 // parse /usr/lib/firejail/firecfg.cfg file
289 FILE *fp = fopen(cfgfile, "r"); 292 FILE *fp = fopen(cfgfile, "r");
290 if (!fp) { 293 if (!fp) {
291 fprintf(stderr, "Error: cannot open %s\n", cfgfile); 294 fprintf(stderr, "Error: cannot open %s\n", cfgfile);
292 exit(1); 295 exit(1);
293 } 296 }
294 printf("Configuring symlinks in /usr/local/bin\n"); 297 printf("Configuring symlinks in /usr/local/bin based on firecfg.config\n");
295 298
296 char buf[MAX_BUF]; 299 char buf[MAX_BUF];
297 int lineno = 0; 300 int lineno = 0;
@@ -330,7 +333,69 @@ static void set_links(void) {
330 free(firejail_exec); 333 free(firejail_exec);
331} 334}
332 335
333int have_profile(const char *filename) { 336// parse ~/.config/firejail/ directory
337static void set_links_homedir(const char *homedir) {
338 assert(homedir);
339
340 // check firejail config directory
341 char *dirname;
342 if (asprintf(&dirname, "%s/.config/firejail", homedir) == -1)
343 errExit("asprintf");
344 struct stat s;
345 if (stat(dirname, &s) != 0) {
346 free(dirname);
347 return;
348 }
349
350 char *firejail_exec;
351 if (asprintf(&firejail_exec, "%s/bin/firejail", PREFIX) == -1)
352 errExit("asprintf");
353
354 // parse ~/.config/firejail/ directory
355 printf("\nConfiguring symlinks in /usr/local/bin based on local firejail config directory\n");
356
357 DIR *dir = opendir(dirname);
358 if (!dir) {
359 fprintf(stderr, "Error: cannot open ~/.config/firejail directory\n");
360 free(dirname);
361 return;
362 }
363
364 struct dirent *entry;
365 while ((entry = readdir(dir))) {
366 if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
367 continue;
368
369 char *exec = strdup(entry->d_name);
370 if (!exec)
371 errExit("strdup");
372 char *ptr = strrchr(exec, '.');
373 if (!ptr) {
374 free(exec);
375 continue;
376 }
377 if (strcmp(ptr, ".profile") != 0) {
378 free(exec);
379 continue;
380 }
381
382 *ptr = '\0';
383 set_file(exec, firejail_exec);
384 free(exec);
385 }
386 closedir(dir);
387
388 free(firejail_exec);
389}
390
391// look for a profile file in /etc/firejail diectory and in homedir/.config/firejail directory
392static int have_profile(const char *filename, const char *homedir) {
393 assert(filename);
394 assert(homedir);
395
396 if (arg_debug)
397 printf("checking profile for %s\n", filename);
398
334 // remove .desktop extension 399 // remove .desktop extension
335 char *f1 = strdup(filename); 400 char *f1 = strdup(filename);
336 if (!f1) 401 if (!f1)
@@ -338,15 +403,29 @@ int have_profile(const char *filename) {
338 f1[strlen(filename) - 8] = '\0'; 403 f1[strlen(filename) - 8] = '\0';
339 404
340 // build profile name 405 // build profile name
341 char *profname; 406 char *profname1;
342 if (asprintf(&profname, "%s/%s.profile", SYSCONFDIR, f1) == -1) 407 char *profname2;
408 if (asprintf(&profname1, "%s/%s.profile", SYSCONFDIR, f1) == -1)
409 errExit("asprintf");
410 if (asprintf(&profname2, "%s/.config/firejail/%s.profile", homedir, f1) == -1)
343 errExit("asprintf"); 411 errExit("asprintf");
344 412
345 struct stat s; 413 int rv = 0;
346 int rv = stat(profname, &s); 414 if (access(profname1, R_OK) == 0) {
415 if (arg_debug)
416 printf("found %s\n", profname1);
417 rv = 1;
418 }
419 else if (access(profname2, R_OK) == 0) {
420 if (arg_debug)
421 printf("found %s\n", profname2);
422 rv = 1;
423 }
424
347 free(f1); 425 free(f1);
348 free(profname); 426 free(profname1);
349 return (rv == 0)? 1: 0; 427 free(profname2);
428 return rv;
350} 429}
351 430
352static void fix_desktop_files(char *homedir) { 431static void fix_desktop_files(char *homedir) {
@@ -411,7 +490,7 @@ static void fix_desktop_files(char *homedir) {
411 errExit("stat"); 490 errExit("stat");
412 491
413 // no profile in /etc/firejail, no desktop file fixing 492 // no profile in /etc/firejail, no desktop file fixing
414 if (!have_profile(filename)) 493 if (!have_profile(filename, homedir))
415 continue; 494 continue;
416 495
417 /* coverity[toctou] */ 496 /* coverity[toctou] */
@@ -599,7 +678,7 @@ int main(int argc, char **argv) {
599 } 678 }
600 } 679 }
601 } 680 }
602 set_links(); 681 set_links_firecfg();
603 682
604 683
605 684
@@ -623,6 +702,9 @@ int main(int argc, char **argv) {
623 goto errexit; 702 goto errexit;
624 } 703 }
625 704
705 // running as root
706 set_links_homedir(home);
707
626 // drop permissions 708 // drop permissions
627 if (setgroups(0, NULL) < 0) 709 if (setgroups(0, NULL) < 0)
628 errExit("setgroups"); 710 errExit("setgroups");
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 f205bfa30..9bbb224e1 100644
--- a/src/man/firejail.txt
+++ b/src/man/firejail.txt
@@ -1338,13 +1338,13 @@ $ ps
1338.br 1338.br
1339 48 pts/0 00:00:00 ps 1339 48 pts/0 00:00:00 ps
1340.br 1340.br
1341$ 1341$
1342.br 1342.br
1343 1343
1344 1344
1345.TP 1345.TP
1346\fB\-\-private-dev 1346\fB\-\-private-dev
1347Create a new /dev directory. Only dri, null, full, zero, tty, pts, ptmx, random, snd, urandom, video, log and shm devices are available. 1347Create a new /dev directory. Only disc, dri, null, full, zero, tty, pts, ptmx, random, snd, urandom, video, log and shm devices are available.
1348.br 1348.br
1349 1349
1350.br 1350.br
@@ -1358,7 +1358,7 @@ Child process initialized
1358.br 1358.br
1359$ ls /dev 1359$ ls /dev
1360.br 1360.br
1361dri full log null ptmx pts random shm snd tty urandom zero 1361cdrom cdrw dri dvd dvdrw full log null ptmx pts random shm snd sr0 tty urandom zero
1362.br 1362.br
1363$ 1363$
1364.TP 1364.TP