aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bash_completion/Makefile.in3
-rw-r--r--src/bash_completion/firejail.bash_completion.in4
-rw-r--r--src/common.mk.in5
-rw-r--r--src/faudit/Makefile.in14
-rw-r--r--src/faudit/caps.c78
-rw-r--r--src/faudit/dbus.c131
-rw-r--r--src/faudit/dev.c47
-rw-r--r--src/faudit/faudit.h68
-rw-r--r--src/faudit/files.c75
-rw-r--r--src/faudit/main.c98
-rw-r--r--src/faudit/network.c101
-rw-r--r--src/faudit/pid.c99
-rw-r--r--src/faudit/seccomp.c101
-rw-r--r--src/faudit/syscall.c105
-rw-r--r--src/faudit/x11.c63
-rw-r--r--src/fbuilder/Makefile.in3
-rw-r--r--src/fcopy/Makefile.in3
-rw-r--r--src/fcopy/main.c65
-rw-r--r--src/firecfg/Makefile.in3
-rw-r--r--src/firecfg/firecfg.config6
-rw-r--r--src/firejail/Makefile.in3
-rw-r--r--src/firejail/checkcfg.c17
-rw-r--r--src/firejail/dbus.c2
-rw-r--r--src/firejail/firejail.h7
-rw-r--r--src/firejail/fs_etc.c26
-rw-r--r--src/firejail/fs_lib.c73
-rw-r--r--src/firejail/fs_lib2.c57
-rw-r--r--src/firejail/fs_mkdir.c4
-rw-r--r--src/firejail/join.c2
-rw-r--r--src/firejail/main.c62
-rw-r--r--src/firejail/network_main.c2
-rw-r--r--src/firejail/no_sandbox.c58
-rw-r--r--src/firejail/output.c2
-rw-r--r--src/firejail/profile.c159
-rw-r--r--src/firejail/pulseaudio.c5
-rw-r--r--src/firejail/sandbox.c88
-rw-r--r--src/firejail/sbox.c7
-rw-r--r--src/firejail/usage.c9
-rw-r--r--src/firejail/util.c2
-rw-r--r--src/firemon/Makefile.in3
-rw-r--r--src/fldd/Makefile.in3
-rw-r--r--src/fnet/Makefile.in3
-rw-r--r--src/fnetfilter/Makefile.in3
-rw-r--r--src/fsec-optimize/Makefile.in3
-rw-r--r--src/fsec-print/Makefile.in3
-rw-r--r--src/fseccomp/Makefile.in3
-rw-r--r--src/ftee/Makefile.in3
-rw-r--r--src/jailtest/Makefile.in3
-rw-r--r--src/lib/Makefile.in3
-rw-r--r--src/libpostexecseccomp/Makefile.in3
-rw-r--r--src/libtrace/Makefile.in4
-rw-r--r--src/libtracelog/Makefile.in4
-rw-r--r--src/man/Makefile.in4
-rw-r--r--src/man/firejail-profile.txt4
-rw-r--r--src/man/firejail.txt63
-rw-r--r--src/man/jailtest.txt6
-rw-r--r--src/profstats/Makefile.in3
-rw-r--r--src/zsh_completion/Makefile.in3
-rw-r--r--src/zsh_completion/_firejail.in363
59 files changed, 774 insertions, 1370 deletions
diff --git a/src/bash_completion/Makefile.in b/src/bash_completion/Makefile.in
index d8a393aa4..f7db9e6b4 100644
--- a/src/bash_completion/Makefile.in
+++ b/src/bash_completion/Makefile.in
@@ -1,3 +1,4 @@
1.PHONY: all
1all: firejail.bash_completion 2all: firejail.bash_completion
2 3
3include ../common.mk 4include ../common.mk
@@ -7,8 +8,10 @@ firejail.bash_completion: firejail.bash_completion.in
7 sed "s|_SYSCONFDIR_|$(sysconfdir)|" < $@.tmp > $@ 8 sed "s|_SYSCONFDIR_|$(sysconfdir)|" < $@.tmp > $@
8 rm $@.tmp 9 rm $@.tmp
9 10
11.PHONY: clean
10clean: 12clean:
11 rm -fr firejail.bash_completion 13 rm -fr firejail.bash_completion
12 14
15.PHONY: distclean
13distclean: clean 16distclean: clean
14 rm -fr Makefile 17 rm -fr Makefile
diff --git a/src/bash_completion/firejail.bash_completion.in b/src/bash_completion/firejail.bash_completion.in
index 00f04c310..f68edf380 100644
--- a/src/bash_completion/firejail.bash_completion.in
+++ b/src/bash_completion/firejail.bash_completion.in
@@ -90,10 +90,6 @@ _firejail()
90 _filedir 90 _filedir
91 return 0 91 return 0
92 ;; 92 ;;
93 --audit)
94 _filedir
95 return 0
96 ;;
97 --net) 93 --net)
98 comps=$(__interfaces) 94 comps=$(__interfaces)
99 COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) 95 COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
diff --git a/src/common.mk.in b/src/common.mk.in
index b8a13cd1b..a3df4abb6 100644
--- a/src/common.mk.in
+++ b/src/common.mk.in
@@ -25,6 +25,9 @@ HAVE_GCOV=@HAVE_GCOV@
25HAVE_SELINUX=@HAVE_SELINUX@ 25HAVE_SELINUX=@HAVE_SELINUX@
26HAVE_DBUSPROXY=@HAVE_DBUSPROXY@ 26HAVE_DBUSPROXY=@HAVE_DBUSPROXY@
27HAVE_USERTMPFS=@HAVE_USERTMPFS@ 27HAVE_USERTMPFS=@HAVE_USERTMPFS@
28HAVE_OUTPUT=@HAVE_OUTPUT@
29HAVE_LTS=@HAVE_LTS@
30HAVE_FORCE_NONEWPRIVS=@HAVE_FORCE_NONEWPRIVS@
28 31
29H_FILE_LIST = $(sort $(wildcard *.[h])) 32H_FILE_LIST = $(sort $(wildcard *.[h]))
30C_FILE_LIST = $(sort $(wildcard *.c)) 33C_FILE_LIST = $(sort $(wildcard *.c))
@@ -34,7 +37,7 @@ BINOBJS = $(foreach file, $(OBJS), $file)
34CFLAGS = @CFLAGS@ 37CFLAGS = @CFLAGS@
35CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' $(HAVE_GCOV) 38CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' $(HAVE_GCOV)
36CFLAGS += -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)/firejail"' -DLIBDIR='"$(libdir)"' -DBINDIR='"$(bindir)"' 39CFLAGS += -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)/firejail"' -DLIBDIR='"$(libdir)"' -DBINDIR='"$(bindir)"'
37MANFLAGS = $(HAVE_X11) $(HAVE_PRIVATE_HOME) $(HAVE_APPARMOR) $(HAVE_OVERLAYFS) $(HAVE_USERTMPFS) $(HAVE_DBUSPROXY) $(HAVE_FIRETUNNEL) $(HAVE_GLOBALCFG) $(HAVE_CHROOT) $(HAVE_NETWORK) $(HAVE_USERNS) $(HAVE_FILE_TRANSFER) $(HAVE_WHITELIST) $(HAVE_SELINUX) 40MANFLAGS = $(HAVE_LTS) $(HAVE_OUTPUT) $(HAVE_X11) $(HAVE_PRIVATE_HOME) $(HAVE_APPARMOR) $(HAVE_OVERLAYFS) $(HAVE_USERTMPFS) $(HAVE_DBUSPROXY) $(HAVE_FIRETUNNEL) $(HAVE_GLOBALCFG) $(HAVE_CHROOT) $(HAVE_NETWORK) $(HAVE_USERNS) $(HAVE_FILE_TRANSFER) $(HAVE_WHITELIST) $(HAVE_SELINUX) $(HAVE_FORCE_NONEWPRIVS)
38CFLAGS += $(MANFLAGS) 41CFLAGS += $(MANFLAGS)
39CFLAGS += -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -Wformat -Wformat-security 42CFLAGS += -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -Wformat -Wformat-security
40LDFLAGS += -pie -fPIE -Wl,-z,relro -Wl,-z,now -lpthread 43LDFLAGS += -pie -fPIE -Wl,-z,relro -Wl,-z,now -lpthread
diff --git a/src/faudit/Makefile.in b/src/faudit/Makefile.in
deleted file mode 100644
index 44c121a4c..000000000
--- a/src/faudit/Makefile.in
+++ /dev/null
@@ -1,14 +0,0 @@
1all: faudit
2
3include ../common.mk
4
5%.o : %.c $(H_FILE_LIST)
6 $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(INCLUDE) -c $< -o $@
7
8faudit: $(OBJS)
9 $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(EXTRA_LDFLAGS)
10
11clean:; rm -fr *.o faudit *.gcov *.gcda *.gcno *.plist
12
13distclean: clean
14 rm -fr Makefile
diff --git a/src/faudit/caps.c b/src/faudit/caps.c
deleted file mode 100644
index e9547dc8e..000000000
--- a/src/faudit/caps.c
+++ /dev/null
@@ -1,78 +0,0 @@
1/*
2 * Copyright (C) 2014-2021 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 "faudit.h"
22#include <linux/capability.h>
23
24#define MAXBUF 4098
25static int extract_caps(uint64_t *val) {
26 FILE *fp = fopen("/proc/self/status", "r");
27 if (!fp)
28 return 1;
29
30 char buf[MAXBUF];
31 while (fgets(buf, MAXBUF, fp)) {
32 if (strncmp(buf, "CapBnd:\t", 8) == 0) {
33 char *ptr = buf + 8;
34 unsigned long long tmp;
35 sscanf(ptr, "%llx", &tmp);
36 *val = tmp;
37 fclose(fp);
38 return 0;
39 }
40 }
41
42 fclose(fp);
43 return 1;
44}
45
46// return 1 if the capability is in the map
47static int check_capability(uint64_t map, int cap) {
48 int i;
49 uint64_t mask = 1ULL;
50
51 for (i = 0; i < 64; i++, mask <<= 1) {
52 if ((i == cap) && (mask & map))
53 return 1;
54 }
55
56 return 0;
57}
58
59void caps_test(void) {
60 uint64_t caps_val;
61
62 if (extract_caps(&caps_val)) {
63 printf("SKIP: cannot extract capabilities on this platform.\n");
64 return;
65 }
66
67 if (caps_val) {
68 printf("BAD: the capability map is %llx, it should be all zero. ", (unsigned long long) caps_val);
69 printf("Use \"firejail --caps.drop=all\" to fix it.\n");
70
71 if (check_capability(caps_val, CAP_SYS_ADMIN))
72 printf("UGLY: CAP_SYS_ADMIN is enabled.\n");
73 if (check_capability(caps_val, CAP_SYS_BOOT))
74 printf("UGLY: CAP_SYS_BOOT is enabled.\n");
75 }
76 else
77 printf("GOOD: all capabilities are disabled.\n");
78}
diff --git a/src/faudit/dbus.c b/src/faudit/dbus.c
deleted file mode 100644
index 389504fb8..000000000
--- a/src/faudit/dbus.c
+++ /dev/null
@@ -1,131 +0,0 @@
1/*
2 * Copyright (C) 2014-2021 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 "faudit.h"
21#include "../include/rundefs.h"
22#include <stdarg.h>
23#include <sys/socket.h>
24#include <sys/un.h>
25
26// return 0 if the connection is possible
27int check_unix(const char *sockfile) {
28 assert(sockfile);
29 int rv = -1;
30
31 // open socket
32 int sock = socket(AF_UNIX, SOCK_STREAM, 0);
33 if (sock == -1)
34 return rv;
35
36 // connect
37 struct sockaddr_un remote;
38 memset(&remote, 0, sizeof(struct sockaddr_un));
39 remote.sun_family = AF_UNIX;
40 strncpy(remote.sun_path, sockfile, sizeof(remote.sun_path) - 1);
41 int len = strlen(remote.sun_path) + sizeof(remote.sun_family);
42 if (*sockfile == '@')
43 remote.sun_path[0] = '\0';
44 if (connect(sock, (struct sockaddr *)&remote, len) == 0)
45 rv = 0;
46
47 close(sock);
48 return rv;
49}
50
51static char *test_dbus_env(char *env_var_name) {
52 // check the session bus
53 char *str = getenv(env_var_name);
54 char *found = NULL;
55 if (str) {
56 int rv = 0;
57 char *bus = strdup(str);
58 if (!bus)
59 errExit("strdup");
60 char *sockfile;
61 if ((sockfile = strstr(bus, "unix:abstract=")) != NULL) {
62 sockfile += 13;
63 *sockfile = '@';
64 char *ptr = strchr(sockfile, ',');
65 if (ptr)
66 *ptr = '\0';
67 rv = check_unix(sockfile);
68 *sockfile = '@';
69 if (rv == 0)
70 printf("MAYBE: D-Bus socket %s is available\n", sockfile);
71 else if (rv == -1)
72 printf("GOOD: cannot connect to D-Bus socket %s\n", sockfile);
73 }
74 else if ((sockfile = strstr(bus, "unix:path=")) != NULL) {
75 sockfile += 10;
76 char *ptr = strchr(sockfile, ',');
77 if (ptr)
78 *ptr = '\0';
79 rv = check_unix(sockfile);
80 if (rv == 0) {
81 if (strcmp(RUN_DBUS_USER_SOCKET, sockfile) == 0 ||
82 strcmp(RUN_DBUS_SYSTEM_SOCKET, sockfile) == 0) {
83 printf("GOOD: D-Bus filtering is active on %s\n", sockfile);
84 } else {
85 printf("MAYBE: D-Bus socket %s is available\n", sockfile);
86 }
87 }
88 else if (rv == -1)
89 printf("GOOD: cannot connect to D-Bus socket %s\n", sockfile);
90 found = strdup(sockfile);
91 if (!found)
92 errExit("strdup");
93 }
94 else if (strstr(bus, "tcp:host=") != NULL)
95 printf("UGLY: %s bus configured for TCP communication.\n", env_var_name);
96 else
97 printf("GOOD: cannot find a %s D-Bus socket\n", env_var_name);
98 free(bus);
99 }
100 else
101 printf("MAYBE: %s environment variable not configured.\n", env_var_name);
102 return found;
103}
104
105static void test_default_socket(const char *found, const char *format, ...) {
106 va_list ap;
107 va_start(ap, format);
108 char *sockfile;
109 if (vasprintf(&sockfile, format, ap) == -1)
110 errExit("vasprintf");
111 va_end(ap);
112 if (found != NULL && strcmp(found, sockfile) == 0)
113 goto end;
114 int rv = check_unix(sockfile);
115 if (rv == 0)
116 printf("MAYBE: D-Bus socket %s is available\n", sockfile);
117end:
118 free(sockfile);
119}
120
121void dbus_test(void) {
122 char *found_user = test_dbus_env("DBUS_SESSION_BUS_ADDRESS");
123 test_default_socket(found_user, "/run/user/%d/bus", (int) getuid());
124 test_default_socket(found_user, "/run/user/%d/dbus/user_bus_socket", (int) getuid());
125 if (found_user != NULL)
126 free(found_user);
127 char *found_system = test_dbus_env("DBUS_SYSTEM_BUS_ADDRESS");
128 test_default_socket(found_system, "/run/dbus/system_bus_socket");
129 if (found_system != NULL)
130 free(found_system);
131}
diff --git a/src/faudit/dev.c b/src/faudit/dev.c
deleted file mode 100644
index 61cb1cabe..000000000
--- a/src/faudit/dev.c
+++ /dev/null
@@ -1,47 +0,0 @@
1/*
2 * Copyright (C) 2014-2021 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 "faudit.h"
21#include <dirent.h>
22
23void dev_test(void) {
24 DIR *dir;
25 if (!(dir = opendir("/dev"))) {
26 fprintf(stderr, "Error: cannot open /dev directory\n");
27 return;
28 }
29
30 struct dirent *entry;
31 printf("INFO: files visible in /dev directory: ");
32 int cnt = 0;
33 while ((entry = readdir(dir)) != NULL) {
34 if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
35 continue;
36
37 printf("%s, ", entry->d_name);
38 cnt++;
39 }
40 printf("\n");
41
42 if (cnt > 20)
43 printf("MAYBE: /dev directory seems to be fully populated. Use --private-dev or --whitelist to restrict the access.\n");
44 else
45 printf("GOOD: Access to /dev directory is restricted.\n");
46 closedir(dir);
47}
diff --git a/src/faudit/faudit.h b/src/faudit/faudit.h
deleted file mode 100644
index cfed1504b..000000000
--- a/src/faudit/faudit.h
+++ /dev/null
@@ -1,68 +0,0 @@
1/*
2 * Copyright (C) 2014-2021 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 FAUDIT_H
22#define FAUDIT_H
23#define _GNU_SOURCE
24#include <stdio.h>
25#include <stdlib.h>
26#include <stdint.h>
27#include <string.h>
28#include <unistd.h>
29#include <sys/types.h>
30#include <sys/stat.h>
31#include <sys/mount.h>
32#include <assert.h>
33
34#define errExit(msg) do { char msgout[500]; snprintf(msgout, 500, "Error %s:%s(%d)", msg, __FUNCTION__, __LINE__); perror(msgout); exit(1);} while (0)
35
36// main.c
37extern char *prog;
38
39// pid.c
40void pid_test(void);
41
42// caps.c
43void caps_test(void);
44
45// seccomp.c
46void seccomp_test(void);
47
48// syscall.c
49void syscall_helper(int argc, char **argv);
50void syscall_run(const char *name);
51
52// files.c
53void files_test(void);
54
55// network.c
56void network_test(void);
57
58// dbus.c
59int check_unix(const char *sockfile);
60void dbus_test(void);
61
62// dev.c
63void dev_test(void);
64
65// x11.c
66void x11_test(void);
67
68#endif
diff --git a/src/faudit/files.c b/src/faudit/files.c
deleted file mode 100644
index 73e0a387d..000000000
--- a/src/faudit/files.c
+++ /dev/null
@@ -1,75 +0,0 @@
1/*
2 * Copyright (C) 2014-2021 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 "faudit.h"
21#include <fcntl.h>
22#include <pwd.h>
23
24static char *username = NULL;
25static char *homedir = NULL;
26
27static void check_home_file(const char *name) {
28 assert(homedir);
29
30 char *fname;
31 if (asprintf(&fname, "%s/%s", homedir, name) == -1)
32 errExit("asprintf");
33
34 if (access(fname, R_OK) == 0) {
35 printf("UGLY: I can access files in %s directory. ", fname);
36 printf("Use \"firejail --blacklist=%s\" to block it.\n", fname);
37 }
38 else
39 printf("GOOD: I cannot access files in %s directory.\n", fname);
40
41 free(fname);
42}
43
44void files_test(void) {
45 struct passwd *pw = getpwuid(getuid());
46 if (!pw) {
47 fprintf(stderr, "Error: cannot retrieve user account information\n");
48 return;
49 }
50
51 username = strdup(pw->pw_name);
52 if (!username)
53 errExit("strdup");
54 homedir = strdup(pw->pw_dir);
55 if (!homedir)
56 errExit("strdup");
57
58 // check access to .ssh directory
59 check_home_file(".ssh");
60
61 // check access to .gnupg directory
62 check_home_file(".gnupg");
63
64 // check access to Firefox browser directory
65 check_home_file(".mozilla");
66
67 // check access to Chromium browser directory
68 check_home_file(".config/chromium");
69
70 // check access to Debian Icedove directory
71 check_home_file(".icedove");
72
73 // check access to Thunderbird directory
74 check_home_file(".thunderbird");
75}
diff --git a/src/faudit/main.c b/src/faudit/main.c
deleted file mode 100644
index 605d5ff7b..000000000
--- a/src/faudit/main.c
+++ /dev/null
@@ -1,98 +0,0 @@
1/*
2 * Copyright (C) 2014-2021 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 "faudit.h"
21char *prog;
22
23int main(int argc, char **argv) {
24 // make test-arguments helper
25 if (getenv("FIREJAIL_TEST_ARGUMENTS")) {
26 printf("Arguments:\n");
27
28 int i;
29 for (i = 0; i < argc; i++) {
30 printf("#%s#\n", argv[i]);
31 }
32
33 return 0;
34 }
35
36
37 if (argc != 1) {
38 int i;
39
40 for (i = 1; i < argc; i++) {
41 if (strcmp(argv[i], "syscall") == 0) {
42 syscall_helper(argc, argv);
43 return 0;
44 }
45 }
46 return 1;
47 }
48
49 printf("\n---------------- Firejail Audit: the GOOD, the BAD and the UGLY ----------------\n");
50
51 // extract program name
52 prog = realpath(argv[0], NULL);
53 if (prog == NULL) {
54 prog = strdup("faudit");
55 if (!prog)
56 errExit("strdup");
57 }
58 printf("INFO: starting %s.\n", prog);
59
60
61 // check pid namespace
62 pid_test();
63 printf("\n");
64
65 // check seccomp
66 seccomp_test();
67 printf("\n");
68
69 // check capabilities
70 caps_test();
71 printf("\n");
72
73 // check some well-known problematic files and directories
74 files_test();
75 printf("\n");
76
77 // network
78 network_test();
79 printf("\n");
80
81 // dbus
82 dbus_test();
83 printf("\n");
84
85 // x11 test
86 x11_test();
87 printf("\n");
88
89 // /dev test
90 dev_test();
91 printf("\n");
92
93
94 free(prog);
95 printf("--------------------------------------------------------------------------------\n");
96
97 return 0;
98}
diff --git a/src/faudit/network.c b/src/faudit/network.c
deleted file mode 100644
index 8e799dc19..000000000
--- a/src/faudit/network.c
+++ /dev/null
@@ -1,101 +0,0 @@
1/*
2 * Copyright (C) 2014-2021 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 "faudit.h"
21#include <sys/socket.h>
22#include <arpa/inet.h>
23#include <linux/netlink.h>
24#include <linux/rtnetlink.h>
25
26static void check_ssh(void) {
27 // open socket
28 int sock = socket(AF_INET, SOCK_STREAM, 0);
29 if (sock == -1) {
30 printf("GOOD: SSH server not available on localhost.\n");
31 return;
32 }
33
34 // connect to localhost
35 struct sockaddr_in server;
36 server.sin_addr.s_addr = inet_addr("127.0.0.1");
37 server.sin_family = AF_INET;
38 server.sin_port = htons(22);
39
40 if (connect(sock , (struct sockaddr *)&server , sizeof(server)) < 0)
41 printf("GOOD: SSH server not available on localhost.\n");
42 else {
43 printf("MAYBE: an SSH server is accessible on localhost. ");
44 printf("It could be a good idea to create a new network namespace using \"--net=none\" or \"--net=eth0\".\n");
45 }
46
47 close(sock);
48}
49
50static void check_http(void) {
51 // open socket
52 int sock = socket(AF_INET, SOCK_STREAM, 0);
53 if (sock == -1) {
54 printf("GOOD: HTTP server not available on localhost.\n");
55 return;
56 }
57
58 // connect to localhost
59 struct sockaddr_in server;
60 server.sin_addr.s_addr = inet_addr("127.0.0.1");
61 server.sin_family = AF_INET;
62 server.sin_port = htons(80);
63
64 if (connect(sock , (struct sockaddr *)&server , sizeof(server)) < 0)
65 printf("GOOD: HTTP server not available on localhost.\n");
66 else {
67 printf("MAYBE: an HTTP server is accessible on localhost. ");
68 printf("It could be a good idea to create a new network namespace using \"--net=none\" or \"--net=eth0\".\n");
69 }
70
71 close(sock);
72}
73
74void check_netlink(void) {
75 int sock = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, 0);
76 if (sock == -1) {
77 printf("GOOD: I cannot connect to netlink socket. Network utilities such as iproute2 will not work in the sandbox.\n");
78 return;
79 }
80
81 struct sockaddr_nl local;
82 memset(&local, 0, sizeof(local));
83 local.nl_family = AF_NETLINK;
84 local.nl_groups = 0; //subscriptions;
85
86 if (bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0) {
87 printf("GOOD: I cannot connect to netlink socket. Network utilities such as iproute2 will not work in the sandbox.\n");
88 close(sock);
89 return;
90 }
91
92 close(sock);
93 printf("MAYBE: I can connect to netlink socket. Network utilities such as iproute2 will work fine in the sandbox. ");
94 printf("You can use \"--protocol\" to disable the socket.\n");
95}
96
97void network_test(void) {
98 check_ssh();
99 check_http();
100 check_netlink();
101}
diff --git a/src/faudit/pid.c b/src/faudit/pid.c
deleted file mode 100644
index ec8c37dc7..000000000
--- a/src/faudit/pid.c
+++ /dev/null
@@ -1,99 +0,0 @@
1/*
2 * Copyright (C) 2014-2021 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 "faudit.h"
21
22void pid_test(void) {
23 static char *kern_proc[] = {
24 "kthreadd",
25 "ksoftirqd",
26 "kworker",
27 "rcu_sched",
28 "rcu_bh",
29 NULL // NULL terminated list
30 };
31 int i;
32
33 // look at the first 10 processes
34 int not_visible = 1;
35 for (i = 1; i <= 10; i++) {
36 struct stat s;
37 char *fname;
38 if (asprintf(&fname, "/proc/%d/comm", i) == -1)
39 errExit("asprintf");
40 if (stat(fname, &s) == -1) {
41 free(fname);
42 continue;
43 }
44
45 // open file
46 /* coverity[toctou] */
47 FILE *fp = fopen(fname, "r");
48 if (!fp) {
49 free(fname);
50 continue;
51 }
52
53 // read file
54 char buf[100];
55 if (fgets(buf, 10, fp) == NULL) {
56 fclose(fp);
57 free(fname);
58 continue;
59 }
60 not_visible = 0;
61
62 // clean /n
63 char *ptr;
64 if ((ptr = strchr(buf, '\n')) != NULL)
65 *ptr = '\0';
66
67 // check process name against the kernel list
68 int j = 0;
69 while (kern_proc[j] != NULL) {
70 if (strncmp(buf, kern_proc[j], strlen(kern_proc[j])) == 0) {
71 fclose(fp);
72 free(fname);
73 printf("BAD: Process %d is not running in a PID namespace. ", getpid());
74 printf("Are you sure you're running in a sandbox?\n");
75 return;
76 }
77 j++;
78 }
79
80 fclose(fp);
81 free(fname);
82 }
83
84 pid_t pid = getpid();
85 if (not_visible && pid > 100)
86 printf("BAD: Process %d is not running in a PID namespace.\n", pid);
87 else
88 printf("GOOD: process %d is running in a PID namespace.\n", pid);
89
90 // try to guess the type of container/sandbox
91 char *str = getenv("container");
92 if (str)
93 printf("INFO: container/sandbox %s.\n", str);
94 else {
95 str = getenv("SNAP");
96 if (str)
97 printf("INFO: this is a snap package\n");
98 }
99}
diff --git a/src/faudit/seccomp.c b/src/faudit/seccomp.c
deleted file mode 100644
index d8acee160..000000000
--- a/src/faudit/seccomp.c
+++ /dev/null
@@ -1,101 +0,0 @@
1/*
2 * Copyright (C) 2014-2021 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 "faudit.h"
21
22#define MAXBUF 4098
23static int extract_seccomp(int *val) {
24 FILE *fp = fopen("/proc/self/status", "r");
25 if (!fp)
26 return 1;
27
28 char buf[MAXBUF];
29 while (fgets(buf, MAXBUF, fp)) {
30 if (strncmp(buf, "Seccomp:\t", 9) == 0) {
31 char *ptr = buf + 9;
32 int tmp;
33 sscanf(ptr, "%d", &tmp);
34 *val = tmp;
35 fclose(fp);
36 return 0;
37 }
38 }
39
40 fclose(fp);
41 return 1;
42}
43
44void seccomp_test(void) {
45 int seccomp_status;
46 int rv = extract_seccomp(&seccomp_status);
47
48 if (rv) {
49 printf("INFO: cannot extract seccomp configuration on this platform.\n");
50 return;
51 }
52
53 if (seccomp_status == 0) {
54 printf("BAD: seccomp disabled. Use \"firejail --seccomp\" to enable it.\n");
55 }
56 else if (seccomp_status == 1)
57 printf("GOOD: seccomp strict mode - only read, write, _exit, and sigreturn are allowed.\n");
58 else if (seccomp_status == 2) {
59 printf("GOOD: seccomp BPF enabled.\n");
60
61 printf("checking syscalls: "); fflush(0);
62 printf("mount... "); fflush(0);
63 syscall_run("mount");
64
65 printf("umount2... "); fflush(0);
66 syscall_run("umount2");
67
68 printf("ptrace... "); fflush(0);
69 syscall_run("ptrace");
70
71 printf("swapon... "); fflush(0);
72 syscall_run("swapon");
73
74 printf("swapoff... "); fflush(0);
75 syscall_run("swapoff");
76
77 printf("init_module... "); fflush(0);
78 syscall_run("init_module");
79
80 printf("delete_module... "); fflush(0);
81 syscall_run("delete_module");
82
83 printf("chroot... "); fflush(0);
84 syscall_run("chroot");
85
86 printf("pivot_root... "); fflush(0);
87 syscall_run("pivot_root");
88
89#if defined(__i386__) || defined(__x86_64__)
90 printf("iopl... "); fflush(0);
91 syscall_run("iopl");
92
93 printf("ioperm... "); fflush(0);
94 syscall_run("ioperm");
95#endif
96 printf("\n");
97 }
98 else
99 fprintf(stderr, "Error: unrecognized seccomp mode\n");
100
101}
diff --git a/src/faudit/syscall.c b/src/faudit/syscall.c
deleted file mode 100644
index 11e83a0f5..000000000
--- a/src/faudit/syscall.c
+++ /dev/null
@@ -1,105 +0,0 @@
1/*
2 * Copyright (C) 2014-2021 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 "faudit.h"
21#include <sys/ptrace.h>
22#include <sys/swap.h>
23#if defined(__i386__) || defined(__x86_64__)
24#include <sys/io.h>
25#endif
26#include <sys/wait.h>
27extern int init_module(void *module_image, unsigned long len,
28 const char *param_values);
29extern int finit_module(int fd, const char *param_values,
30 int flags);
31extern int delete_module(const char *name, int flags);
32extern int pivot_root(const char *new_root, const char *put_old);
33
34void syscall_helper(int argc, char **argv) {
35 (void) argc;
36
37 if (argc < 3)
38 return;
39
40 if (strcmp(argv[2], "mount") == 0) {
41 int rv = mount(NULL, NULL, NULL, 0, NULL);
42 (void) rv;
43 printf("\nUGLY: mount syscall permitted.\n");
44 }
45 else if (strcmp(argv[2], "umount2") == 0) {
46 umount2(NULL, 0);
47 printf("\nUGLY: umount2 syscall permitted.\n");
48 }
49 else if (strcmp(argv[2], "ptrace") == 0) {
50 ptrace(0, 0, NULL, NULL);
51 printf("\nUGLY: ptrace syscall permitted.\n");
52 }
53 else if (strcmp(argv[2], "swapon") == 0) {
54 swapon(NULL, 0);
55 printf("\nUGLY: swapon syscall permitted.\n");
56 }
57 else if (strcmp(argv[2], "swapoff") == 0) {
58 swapoff(NULL);
59 printf("\nUGLY: swapoff syscall permitted.\n");
60 }
61 else if (strcmp(argv[2], "init_module") == 0) {
62 init_module(NULL, 0, NULL);
63 printf("\nUGLY: init_module syscall permitted.\n");
64 }
65 else if (strcmp(argv[2], "delete_module") == 0) {
66 delete_module(NULL, 0);
67 printf("\nUGLY: delete_module syscall permitted.\n");
68 }
69 else if (strcmp(argv[2], "chroot") == 0) {
70 int rv = chroot("/blablabla-57281292");
71 (void) rv;
72 printf("\nUGLY: chroot syscall permitted.\n");
73 }
74 else if (strcmp(argv[2], "pivot_root") == 0) {
75 pivot_root(NULL, NULL);
76 printf("\nUGLY: pivot_root syscall permitted.\n");
77 }
78#if defined(__i386__) || defined(__x86_64__)
79 else if (strcmp(argv[2], "iopl") == 0) {
80 iopl(0L);
81 printf("\nUGLY: iopl syscall permitted.\n");
82 }
83 else if (strcmp(argv[2], "ioperm") == 0) {
84 ioperm(0, 0, 0);
85 printf("\nUGLY: ioperm syscall permitted.\n");
86 }
87#endif
88 exit(0);
89}
90
91void syscall_run(const char *name) {
92 assert(prog);
93
94 pid_t child = fork();
95 if (child < 0)
96 errExit("fork");
97 if (child == 0) {
98 execl(prog, prog, "syscall", name, NULL);
99 perror("execl");
100 _exit(1);
101 }
102
103 // wait for the child to finish
104 waitpid(child, NULL, 0);
105}
diff --git a/src/faudit/x11.c b/src/faudit/x11.c
deleted file mode 100644
index 2ffd7bac7..000000000
--- a/src/faudit/x11.c
+++ /dev/null
@@ -1,63 +0,0 @@
1/*
2 * Copyright (C) 2014-2021 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 "faudit.h"
21#include <sys/socket.h>
22#include <dirent.h>
23
24
25void x11_test(void) {
26 // check regular display 0 sockets
27 if (check_unix("/tmp/.X11-unix/X0") == 0)
28 printf("MAYBE: X11 socket /tmp/.X11-unix/X0 is available\n");
29
30 if (check_unix("@/tmp/.X11-unix/X0") == 0)
31 printf("MAYBE: X11 socket @/tmp/.X11-unix/X0 is available\n");
32
33 // check all unix sockets in /tmp/.X11-unix directory
34 DIR *dir;
35 if (!(dir = opendir("/tmp/.X11-unix"))) {
36 // sleep 2 seconds and try again
37 sleep(2);
38 if (!(dir = opendir("/tmp/.X11-unix"))) {
39 ;
40 }
41 }
42
43 if (dir == NULL)
44 printf("GOOD: cannot open /tmp/.X11-unix directory\n");
45 else {
46 struct dirent *entry;
47 while ((entry = readdir(dir)) != NULL) {
48 if (strcmp(entry->d_name, "X0") == 0)
49 continue;
50 if (strcmp(entry->d_name, ".") == 0)
51 continue;
52 if (strcmp(entry->d_name, "..") == 0)
53 continue;
54 char *name;
55 if (asprintf(&name, "/tmp/.X11-unix/%s", entry->d_name) == -1)
56 errExit("asprintf");
57 if (check_unix(name) == 0)
58 printf("MAYBE: X11 socket %s is available\n", name);
59 free(name);
60 }
61 closedir(dir);
62 }
63}
diff --git a/src/fbuilder/Makefile.in b/src/fbuilder/Makefile.in
index 2847ca2cb..6eaee284b 100644
--- a/src/fbuilder/Makefile.in
+++ b/src/fbuilder/Makefile.in
@@ -1,3 +1,4 @@
1.PHONY: all
1all: fbuilder 2all: fbuilder
2 3
3include ../common.mk 4include ../common.mk
@@ -8,7 +9,9 @@ include ../common.mk
8fbuilder: $(OBJS) 9fbuilder: $(OBJS)
9 $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(EXTRA_LDFLAGS) 10 $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(EXTRA_LDFLAGS)
10 11
12.PHONY: clean
11clean:; rm -fr *.o fbuilder *.gcov *.gcda *.gcno *.plist 13clean:; rm -fr *.o fbuilder *.gcov *.gcda *.gcno *.plist
12 14
15.PHONY: distclean
13distclean: clean 16distclean: clean
14 rm -fr Makefile 17 rm -fr Makefile
diff --git a/src/fcopy/Makefile.in b/src/fcopy/Makefile.in
index 85f84aa32..e19f5d3b5 100644
--- a/src/fcopy/Makefile.in
+++ b/src/fcopy/Makefile.in
@@ -1,3 +1,4 @@
1.PHONY: all
1all: fcopy 2all: fcopy
2 3
3include ../common.mk 4include ../common.mk
@@ -8,7 +9,9 @@ include ../common.mk
8fcopy: $(OBJS) ../lib/common.o 9fcopy: $(OBJS) ../lib/common.o
9 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o $(LIBS) $(EXTRA_LDFLAGS) 10 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o $(LIBS) $(EXTRA_LDFLAGS)
10 11
12.PHONY: clean
11clean:; rm -fr *.o fcopy *.gcov *.gcda *.gcno *.plist 13clean:; rm -fr *.o fcopy *.gcov *.gcda *.gcno *.plist
12 14
15.PHONY: distclean
13distclean: clean 16distclean: clean
14 rm -fr Makefile 17 rm -fr Makefile
diff --git a/src/fcopy/main.c b/src/fcopy/main.c
index 01633be59..572e9f601 100644
--- a/src/fcopy/main.c
+++ b/src/fcopy/main.c
@@ -51,8 +51,9 @@ static int selinux_enabled = -1;
51#endif 51#endif
52 52
53// copy from firejail/selinux.c 53// copy from firejail/selinux.c
54static void selinux_relabel_path(const char *path, const char *inside_path) 54static void selinux_relabel_path(const char *path, const char *inside_path) {
55{ 55 assert(path);
56 assert(inside_path);
56#if HAVE_SELINUX 57#if HAVE_SELINUX
57 char procfs_path[64]; 58 char procfs_path[64];
58 char *fcon = NULL; 59 char *fcon = NULL;
@@ -172,6 +173,51 @@ static void mkdir_attr(const char *fname, mode_t mode, uid_t uid, gid_t gid) {
172 } 173 }
173} 174}
174 175
176static char *proc_pid_to_self(const char *target) {
177 assert(target);
178 char *use_target = 0;
179 char *proc_pid = 0;
180
181 if (!(use_target = realpath(target, NULL)))
182 goto done;
183
184 // target is under /proc/<PID>?
185 static const char proc[] = "/proc/";
186 if (strncmp(use_target, proc, sizeof(proc) - 1))
187 goto done;
188
189 int digit = use_target[sizeof(proc) - 1];
190 if (digit < '1' || digit > '9')
191 goto done;
192
193 // check where /proc/self points to
194 static const char proc_self[] = "/proc/self";
195 if (!(proc_pid = realpath(proc_self, NULL)))
196 goto done;
197
198 // redirect /proc/PID/xxx -> /proc/self/XXX
199 size_t pfix = strlen(proc_pid);
200 if (strncmp(use_target, proc_pid, pfix))
201 goto done;
202
203 if (use_target[pfix] != 0 && use_target[pfix] != '/')
204 goto done;
205
206 char *tmp;
207 if (asprintf(&tmp, "%s%s", proc_self, use_target + pfix) != -1) {
208 if (arg_debug)
209 fprintf(stderr, "SYMLINK %s\n --> %s\n", use_target, tmp);
210 free(use_target);
211 use_target = tmp;
212 }
213 else
214 errExit("asprintf");
215
216done:
217 if (proc_pid)
218 free(proc_pid);
219 return use_target;
220}
175 221
176void copy_link(const char *target, const char *linkpath, mode_t mode, uid_t uid, gid_t gid) { 222void copy_link(const char *target, const char *linkpath, mode_t mode, uid_t uid, gid_t gid) {
177 (void) mode; 223 (void) mode;
@@ -183,7 +229,7 @@ void copy_link(const char *target, const char *linkpath, mode_t mode, uid_t uid,
183 if (lstat(linkpath, &s) == 0) 229 if (lstat(linkpath, &s) == 0)
184 return; 230 return;
185 231
186 char *rp = realpath(target, NULL); 232 char *rp = proc_pid_to_self(target);
187 if (rp) { 233 if (rp) {
188 if (symlink(rp, linkpath) == -1) { 234 if (symlink(rp, linkpath) == -1) {
189 free(rp); 235 free(rp);
@@ -227,16 +273,14 @@ static int fs_copydir(const char *infname, const struct stat *st, int ftype, str
227 first = 0; 273 first = 0;
228 else if (!arg_quiet) 274 else if (!arg_quiet)
229 fprintf(stderr, "Warning fcopy: skipping %s, file already present\n", infname); 275 fprintf(stderr, "Warning fcopy: skipping %s, file already present\n", infname);
230 free(outfname); 276 goto out;
231 return 0;
232 } 277 }
233 278
234 // extract mode and ownership 279 // extract mode and ownership
235 if (stat(infname, &s) != 0) { 280 if (stat(infname, &s) != 0) {
236 if (!arg_quiet) 281 if (!arg_quiet)
237 fprintf(stderr, "Warning fcopy: skipping %s, cannot find inode\n", infname); 282 fprintf(stderr, "Warning fcopy: skipping %s, cannot find inode\n", infname);
238 free(outfname); 283 goto out;
239 return 0;
240 } 284 }
241 uid_t uid = s.st_uid; 285 uid_t uid = s.st_uid;
242 gid_t gid = s.st_gid; 286 gid_t gid = s.st_gid;
@@ -246,8 +290,7 @@ static int fs_copydir(const char *infname, const struct stat *st, int ftype, str
246 if ((s.st_size + size_cnt) > copy_limit) { 290 if ((s.st_size + size_cnt) > copy_limit) {
247 fprintf(stderr, "Error fcopy: size limit of %lu MB reached\n", (copy_limit / 1024) / 1024); 291 fprintf(stderr, "Error fcopy: size limit of %lu MB reached\n", (copy_limit / 1024) / 1024);
248 size_limit_reached = 1; 292 size_limit_reached = 1;
249 free(outfname); 293 goto out;
250 return 0;
251 } 294 }
252 295
253 file_cnt++; 296 file_cnt++;
@@ -262,7 +305,8 @@ static int fs_copydir(const char *infname, const struct stat *st, int ftype, str
262 else if (ftype == FTW_SL) { 305 else if (ftype == FTW_SL) {
263 copy_link(infname, outfname, mode, uid, gid); 306 copy_link(infname, outfname, mode, uid, gid);
264 } 307 }
265 308out:
309 free(outfname);
266 return(0); 310 return(0);
267} 311}
268 312
@@ -295,6 +339,7 @@ static char *check(const char *src) {
295 return rsrc; // normal exit from the function 339 return rsrc; // normal exit from the function
296 340
297errexit: 341errexit:
342 free(rsrc);
298 fprintf(stderr, "Error fcopy: invalid file %s\n", src); 343 fprintf(stderr, "Error fcopy: invalid file %s\n", src);
299 exit(1); 344 exit(1);
300} 345}
diff --git a/src/firecfg/Makefile.in b/src/firecfg/Makefile.in
index 40f6b9679..43329be46 100644
--- a/src/firecfg/Makefile.in
+++ b/src/firecfg/Makefile.in
@@ -1,3 +1,4 @@
1.PHONY: all
1all: firecfg 2all: firecfg
2 3
3include ../common.mk 4include ../common.mk
@@ -8,7 +9,9 @@ include ../common.mk
8firecfg: $(OBJS) ../lib/common.o ../lib/firejail_user.o 9firecfg: $(OBJS) ../lib/common.o ../lib/firejail_user.o
9 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o ../lib/firejail_user.o $(LIBS) $(EXTRA_LDFLAGS) 10 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o ../lib/firejail_user.o $(LIBS) $(EXTRA_LDFLAGS)
10 11
12.PHONY: clean
11clean:; rm -fr *.o firecfg *.gcov *.gcda *.gcno *.plist 13clean:; rm -fr *.o firecfg *.gcov *.gcda *.gcno *.plist
12 14
15.PHONY: distclean
13distclean: clean 16distclean: clean
14 rm -fr Makefile 17 rm -fr Makefile
diff --git a/src/firecfg/firecfg.config b/src/firecfg/firecfg.config
index 7c3f16557..16cd59aa5 100644
--- a/src/firecfg/firecfg.config
+++ b/src/firecfg/firecfg.config
@@ -464,7 +464,7 @@ lynx
464lyx 464lyx
465macrofusion 465macrofusion
466magicor 466magicor
467# man 467man
468manaplus 468manaplus
469marker 469marker
470masterpdfeditor 470masterpdfeditor
@@ -553,6 +553,8 @@ neverputt
553newsbeuter 553newsbeuter
554newsboat 554newsboat
555newsflash 555newsflash
556nextcloud
557nextcloud-desktop
556nheko 558nheko
557nicotine 559nicotine
558nitroshare 560nitroshare
@@ -809,6 +811,8 @@ vivaldi-snapshot
809vivaldi-stable 811vivaldi-stable
810vlc 812vlc
811vmware 813vmware
814vmware-player
815vmware-workstation
812vscodium 816vscodium
813vulturesclaw 817vulturesclaw
814vultureseye 818vultureseye
diff --git a/src/firejail/Makefile.in b/src/firejail/Makefile.in
index b9bf13b9c..793d2cdd1 100644
--- a/src/firejail/Makefile.in
+++ b/src/firejail/Makefile.in
@@ -1,3 +1,4 @@
1.PHONY: all
1all: firejail 2all: firejail
2 3
3include ../common.mk 4include ../common.mk
@@ -8,7 +9,9 @@ include ../common.mk
8firejail: $(OBJS) ../lib/libnetlink.o ../lib/common.o ../lib/ldd_utils.o ../lib/firejail_user.o ../lib/errno.o ../lib/syscall.o 9firejail: $(OBJS) ../lib/libnetlink.o ../lib/common.o ../lib/ldd_utils.o ../lib/firejail_user.o ../lib/errno.o ../lib/syscall.o
9 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o ../lib/ldd_utils.o ../lib/firejail_user.o ../lib/errno.o ../lib/syscall.o $(LIBS) $(EXTRA_LDFLAGS) 10 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o ../lib/ldd_utils.o ../lib/firejail_user.o ../lib/errno.o ../lib/syscall.o $(LIBS) $(EXTRA_LDFLAGS)
10 11
12.PHONY: clean
11clean:; rm -fr *.o firejail *.gcov *.gcda *.gcno *.plist 13clean:; rm -fr *.o firejail *.gcov *.gcda *.gcno *.plist
12 14
15.PHONY: distclean
13distclean: clean 16distclean: clean
14 rm -fr Makefile 17 rm -fr Makefile
diff --git a/src/firejail/checkcfg.c b/src/firejail/checkcfg.c
index 71dc364c9..e1613b325 100644
--- a/src/firejail/checkcfg.c
+++ b/src/firejail/checkcfg.c
@@ -269,6 +269,14 @@ errout:
269 269
270void print_compiletime_support(void) { 270void print_compiletime_support(void) {
271 printf("Compile time support:\n"); 271 printf("Compile time support:\n");
272 printf("\t- Always force nonewprivs support is %s\n",
273#ifdef HAVE_FORCE_NONEWPRIVS
274 "enabled"
275#else
276 "disabled"
277#endif
278 );
279
272 printf("\t- AppArmor support is %s\n", 280 printf("\t- AppArmor support is %s\n",
273#ifdef HAVE_APPARMOR 281#ifdef HAVE_APPARMOR
274 "enabled" 282 "enabled"
@@ -333,6 +341,13 @@ void print_compiletime_support(void) {
333#endif 341#endif
334 ); 342 );
335 343
344 printf("\t- output logging is %s\n",
345#ifdef HAVE_OUTPUT
346 "enabled"
347#else
348 "disabled"
349#endif
350 );
336 printf("\t- overlayfs support is %s\n", 351 printf("\t- overlayfs support is %s\n",
337#ifdef HAVE_OVERLAYFS 352#ifdef HAVE_OVERLAYFS
338 "enabled" 353 "enabled"
@@ -380,4 +395,6 @@ void print_compiletime_support(void) {
380 "disabled" 395 "disabled"
381#endif 396#endif
382 ); 397 );
398
399
383} 400}
diff --git a/src/firejail/dbus.c b/src/firejail/dbus.c
index 4b81d7758..658b84537 100644
--- a/src/firejail/dbus.c
+++ b/src/firejail/dbus.c
@@ -111,7 +111,7 @@ static int check_object_path(const char *path) {
111 } 111 }
112 ++p; 112 ++p;
113 } 113 }
114 return in_segment && segments >= 2; 114 return in_segment && segments >= 1;
115} 115}
116 116
117int dbus_check_name(const char *name) { 117int dbus_check_name(const char *name) {
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h
index 719cd74ae..b21b5bef6 100644
--- a/src/firejail/firejail.h
+++ b/src/firejail/firejail.h
@@ -328,8 +328,6 @@ extern int arg_keep_var_tmp; // don't overwrite /var/tmp
328extern int arg_writable_run_user; // writable /run/user 328extern int arg_writable_run_user; // writable /run/user
329extern int arg_writable_var_log; // writable /var/log 329extern int arg_writable_var_log; // writable /var/log
330extern int arg_appimage; // appimage 330extern int arg_appimage; // appimage
331extern int arg_audit; // audit
332extern char *arg_audit_prog; // audit
333extern int arg_apparmor; // apparmor 331extern int arg_apparmor; // apparmor
334extern int arg_allow_debuggers; // allow debuggers 332extern int arg_allow_debuggers; // allow debuggers
335extern int arg_x11_block; // block X11 333extern int arg_x11_block; // block X11
@@ -451,6 +449,9 @@ int profile_check_line(char *ptr, int lineno, const char *fname);
451// add a profile entry in cfg.profile list; use str to populate the list 449// add a profile entry in cfg.profile list; use str to populate the list
452void profile_add(char *str); 450void profile_add(char *str);
453void profile_add_ignore(const char *str); 451void profile_add_ignore(const char *str);
452char *profile_list_normalize(char *list);
453char *profile_list_compress(char *list);
454void profile_list_augment(char **list, const char *items);
454 455
455// list.c 456// list.c
456void list(void); 457void list(void);
@@ -649,6 +650,8 @@ void network_set_run_file(pid_t pid);
649 650
650// fs_etc.c 651// fs_etc.c
651void fs_machineid(void); 652void fs_machineid(void);
653void fs_private_dir_copy(const char *private_dir, const char *private_run_dir, const char *private_list);
654void fs_private_dir_mount(const char *private_dir, const char *private_run_dir);
652void fs_private_dir_list(const char *private_dir, const char *private_run_dir, const char *private_list); 655void fs_private_dir_list(const char *private_dir, const char *private_run_dir, const char *private_list);
653 656
654// no_sandbox.c 657// no_sandbox.c
diff --git a/src/firejail/fs_etc.c b/src/firejail/fs_etc.c
index d152ed2f6..abec25d45 100644
--- a/src/firejail/fs_etc.c
+++ b/src/firejail/fs_etc.c
@@ -18,6 +18,7 @@
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/ 19*/
20#include "firejail.h" 20#include "firejail.h"
21#include <errno.h>
21#include <sys/mount.h> 22#include <sys/mount.h>
22#include <sys/stat.h> 23#include <sys/stat.h>
23#include <sys/types.h> 24#include <sys/types.h>
@@ -138,7 +139,7 @@ static void duplicate(const char *fname, const char *private_dir, const char *pr
138} 139}
139 140
140 141
141void fs_private_dir_list(const char *private_dir, const char *private_run_dir, const char *private_list) { 142void fs_private_dir_copy(const char *private_dir, const char *private_run_dir, const char *private_list) {
142 assert(private_dir); 143 assert(private_dir);
143 assert(private_run_dir); 144 assert(private_run_dir);
144 assert(private_list); 145 assert(private_list);
@@ -147,12 +148,10 @@ void fs_private_dir_list(const char *private_dir, const char *private_run_dir, c
147 struct stat s; 148 struct stat s;
148 if (stat(private_dir, &s) == -1) { 149 if (stat(private_dir, &s) == -1) {
149 if (arg_debug) 150 if (arg_debug)
150 printf("Cannot find %s\n", private_dir); 151 printf("Cannot find %s: %s\n", private_dir, strerror(errno));
151 return; 152 return;
152 } 153 }
153 154
154 timetrace_start();
155
156 // create /run/firejail/mnt/etc directory 155 // create /run/firejail/mnt/etc directory
157 mkdir_attr(private_run_dir, 0755, 0, 0); 156 mkdir_attr(private_run_dir, 0755, 0, 0);
158 selinux_relabel_path(private_run_dir, private_dir); 157 selinux_relabel_path(private_run_dir, private_dir);
@@ -185,9 +184,23 @@ void fs_private_dir_list(const char *private_dir, const char *private_run_dir, c
185 free(dlist); 184 free(dlist);
186 fs_logger_print(); 185 fs_logger_print();
187 } 186 }
187}
188
189void fs_private_dir_mount(const char *private_dir, const char *private_run_dir) {
190 assert(private_dir);
191 assert(private_run_dir);
188 192
189 if (arg_debug) 193 if (arg_debug)
190 printf("Mount-bind %s on top of %s\n", private_run_dir, private_dir); 194 printf("Mount-bind %s on top of %s\n", private_run_dir, private_dir);
195
196 // nothing to do if directory does not exist
197 struct stat s;
198 if (stat(private_dir, &s) == -1) {
199 if (arg_debug)
200 printf("Cannot find %s: %s\n", private_dir, strerror(errno));
201 return;
202 }
203
191 if (mount(private_run_dir, private_dir, NULL, MS_BIND|MS_REC, NULL) < 0) 204 if (mount(private_run_dir, private_dir, NULL, MS_BIND|MS_REC, NULL) < 0)
192 errExit("mount bind"); 205 errExit("mount bind");
193 fs_logger2("mount", private_dir); 206 fs_logger2("mount", private_dir);
@@ -196,6 +209,11 @@ void fs_private_dir_list(const char *private_dir, const char *private_run_dir, c
196 if (mount("tmpfs", private_run_dir, "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME, "mode=755,gid=0") < 0) 209 if (mount("tmpfs", private_run_dir, "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME, "mode=755,gid=0") < 0)
197 errExit("mounting tmpfs"); 210 errExit("mounting tmpfs");
198 fs_logger2("tmpfs", private_run_dir); 211 fs_logger2("tmpfs", private_run_dir);
212}
199 213
214void fs_private_dir_list(const char *private_dir, const char *private_run_dir, const char *private_list) {
215 timetrace_start();
216 fs_private_dir_copy(private_dir, private_run_dir, private_list);
217 fs_private_dir_mount(private_dir, private_run_dir);
200 fmessage("Private %s installed in %0.2f ms\n", private_dir, timetrace_end()); 218 fmessage("Private %s installed in %0.2f ms\n", private_dir, timetrace_end());
201} 219}
diff --git a/src/firejail/fs_lib.c b/src/firejail/fs_lib.c
index 53a8818af..7c5a22699 100644
--- a/src/firejail/fs_lib.c
+++ b/src/firejail/fs_lib.c
@@ -28,6 +28,7 @@
28#define MAXBUF 4096 28#define MAXBUF 4096
29 29
30extern void fslib_install_stdc(void); 30extern void fslib_install_stdc(void);
31extern void fslib_install_firejail(void);
31extern void fslib_install_system(void); 32extern void fslib_install_system(void);
32 33
33static int lib_cnt = 0; 34static int lib_cnt = 0;
@@ -163,33 +164,22 @@ void fslib_duplicate(const char *full_path) {
163 lib_cnt++; 164 lib_cnt++;
164} 165}
165 166
166
167// requires full path for lib 167// requires full path for lib
168// it could be a library or an executable 168// it could be a library or an executable
169// lib is not copied, only libraries used by it 169// lib is not copied, only libraries used by it
170void fslib_copy_libs(const char *full_path) { 170static void fslib_copy_libs(const char *full_path, unsigned mask) {
171 assert(full_path);
172 if (arg_debug || arg_debug_private_lib)
173 printf(" fslib_copy_libs %s\n", full_path);
174
175 // if library/executable does not exist or the user does not have read access to it
176 // print a warning and exit the function.
177 if (access(full_path, R_OK)) {
178 if (arg_debug || arg_debug_private_lib)
179 printf("cannot find %s for private-lib, skipping...\n", full_path);
180 return;
181 }
182
183 // create an empty RUN_LIB_FILE and allow the user to write to it 171 // create an empty RUN_LIB_FILE and allow the user to write to it
184 unlink(RUN_LIB_FILE); // in case is there 172 unlink(RUN_LIB_FILE); // in case is there
185 create_empty_file_as_root(RUN_LIB_FILE, 0644); 173 create_empty_file_as_root(RUN_LIB_FILE, 0644);
186 if (chown(RUN_LIB_FILE, getuid(), getgid())) 174 if (mask & SBOX_USER) {
187 errExit("chown"); 175 if (chown(RUN_LIB_FILE, getuid(), getgid()))
176 errExit("chown");
177 }
188 178
189 // run fldd to extract the list of files 179 // run fldd to extract the list of files
190 if (arg_debug || arg_debug_private_lib) 180 if (arg_debug || arg_debug_private_lib)
191 printf(" running fldd %s\n", full_path); 181 printf(" running fldd %s\n", full_path);
192 sbox_run(SBOX_USER | SBOX_SECCOMP | SBOX_CAPS_NONE, 3, PATH_FLDD, full_path, RUN_LIB_FILE); 182 sbox_run(mask | SBOX_SECCOMP | SBOX_CAPS_NONE, 3, PATH_FLDD, full_path, RUN_LIB_FILE);
193 183
194 // open the list of libraries and install them on by one 184 // open the list of libraries and install them on by one
195 FILE *fp = fopen(RUN_LIB_FILE, "r"); 185 FILE *fp = fopen(RUN_LIB_FILE, "r");
@@ -208,6 +198,34 @@ void fslib_copy_libs(const char *full_path) {
208 unlink(RUN_LIB_FILE); 198 unlink(RUN_LIB_FILE);
209} 199}
210 200
201void fslib_copy_libs_parse_as_root(const char *full_path) {
202 assert(full_path);
203 if (arg_debug || arg_debug_private_lib)
204 printf(" fslib_copy_libs_parse_as_root %s\n", full_path);
205
206 struct stat s;
207 if (stat(full_path, &s)) {
208 if (arg_debug || arg_debug_private_lib)
209 printf("cannot find %s for private-lib, skipping...\n", full_path);
210 return;
211 }
212 fslib_copy_libs(full_path, SBOX_ROOT);
213}
214
215// if library/executable does not exist or the user does not have read access to it
216// print a warning and exit the function.
217void fslib_copy_libs_parse_as_user(const char *full_path) {
218 assert(full_path);
219 if (arg_debug || arg_debug_private_lib)
220 printf(" fslib_copy_libs_parse_as_user %s\n", full_path);
221
222 if (access(full_path, R_OK)) {
223 if (arg_debug || arg_debug_private_lib)
224 printf("cannot find %s for private-lib, skipping...\n", full_path);
225 return;
226 }
227 fslib_copy_libs(full_path, SBOX_USER);
228}
211 229
212void fslib_copy_dir(const char *full_path) { 230void fslib_copy_dir(const char *full_path) {
213 assert(full_path); 231 assert(full_path);
@@ -263,7 +281,7 @@ static void load_library(const char *fname) {
263 access(fname, X_OK) != 0) // don't duplicate executables, just install the libraries 281 access(fname, X_OK) != 0) // don't duplicate executables, just install the libraries
264 fslib_duplicate(fname); 282 fslib_duplicate(fname);
265 283
266 fslib_copy_libs(fname); 284 fslib_copy_libs_parse_as_user(fname);
267 } 285 }
268 } 286 }
269 } 287 }
@@ -406,25 +424,12 @@ void fs_private_lib(void) {
406 printf("Installing standard C library\n"); 424 printf("Installing standard C library\n");
407 fslib_install_stdc(); 425 fslib_install_stdc();
408 426
409 // start timetrace 427 // install other libraries needed by firejail
410 timetrace_start();
411
412 // bring in firejail executable libraries in case we are redirected here by a firejail symlink from /usr/local/bin/firejail
413 if (arg_debug || arg_debug_private_lib) 428 if (arg_debug || arg_debug_private_lib)
414 printf("Installing Firejail libraries\n"); 429 printf("Installing Firejail libraries\n");
415 fslib_install_list(PATH_FIREJAIL); 430 fslib_install_firejail();
416
417 // bring in firejail directory
418 fslib_install_list(LIBDIR "/firejail");
419
420 // bring in dhclient libraries
421 if (any_dhcp()) {
422 if (arg_debug || arg_debug_private_lib)
423 printf("Installing dhclient libraries\n");
424 fslib_install_list(RUN_MNT_DIR "/dhclient");
425 }
426 fmessage("Firejail libraries installed in %0.2f ms\n", timetrace_end());
427 431
432 // start timetrace
428 timetrace_start(); 433 timetrace_start();
429 434
430 // copy the libs in the new lib directory for the main exe 435 // copy the libs in the new lib directory for the main exe
diff --git a/src/firejail/fs_lib2.c b/src/firejail/fs_lib2.c
index 30e993438..d46cfed86 100644
--- a/src/firejail/fs_lib2.c
+++ b/src/firejail/fs_lib2.c
@@ -22,7 +22,8 @@
22#include <sys/stat.h> 22#include <sys/stat.h>
23 23
24extern void fslib_duplicate(const char *full_path); 24extern void fslib_duplicate(const char *full_path);
25extern void fslib_copy_libs(const char *full_path); 25extern void fslib_copy_libs_parse_as_user(const char *full_path);
26extern void fslib_copy_libs_parse_as_root(const char *full_path);
26extern void fslib_copy_dir(const char *full_path); 27extern void fslib_copy_dir(const char *full_path);
27 28
28//*************************************************************** 29//***************************************************************
@@ -123,6 +124,52 @@ void fslib_install_stdc(void) {
123 fmessage("Standard C library installed in %0.2f ms\n", timetrace_end()); 124 fmessage("Standard C library installed in %0.2f ms\n", timetrace_end());
124} 125}
125 126
127//***************************************************************
128// Firejail libraries
129//***************************************************************
130
131static void fdir(void) {
132 fslib_copy_dir(LIBDIR "/firejail");
133
134 // executables and libraries from firejail directory
135 static const char * const fbin[] = {
136 PATH_FCOPY, // currently sufficient to find all needed libraries
137 // PATH_FSECCOMP,
138 // PATH_FSEC_OPTIMIZE,
139 // PATH_FSEC_PRINT,
140 // RUN_FIREJAIL_LIB_DIR "/libtrace.so",
141 // RUN_FIREJAIL_LIB_DIR "/libtracelog.so",
142 // RUN_FIREJAIL_LIB_DIR "/libpostexecseccomp.so",
143 NULL,
144 };
145
146 // need to run fldd as root user, unprivileged users have no read permission on executables
147 int i;
148 for (i = 0; fbin[i]; i++)
149 fslib_copy_libs_parse_as_root(fbin[i]);
150}
151
152void fslib_install_firejail(void) {
153 timetrace_start();
154 // bring in firejail executable libraries, in case we are redirected here
155 // by a firejail symlink from /usr/local/bin/firejail
156 fslib_copy_libs_parse_as_user(PATH_FIREJAIL);
157
158 // bring in firejail directory
159 fdir();
160
161 // bring in dhclient libraries
162 if (any_dhcp())
163 fslib_copy_libs_parse_as_user(RUN_MNT_DIR "/dhclient");
164
165#ifdef HAVE_X11
166 // bring in xauth libraries
167 if (arg_x11_xorg)
168 fslib_copy_libs_parse_as_user("/usr/bin/xauth");
169#endif
170
171 fmessage("Firejail libraries installed in %0.2f ms\n", timetrace_end());
172}
126 173
127//*************************************************************** 174//***************************************************************
128// various system libraries 175// various system libraries
@@ -268,7 +315,7 @@ void fslib_install_system(void) {
268 if (asprintf(&name, "/usr/lib/x86_64-linux-gnu/%s", ptr->dir1) == -1) 315 if (asprintf(&name, "/usr/lib/x86_64-linux-gnu/%s", ptr->dir1) == -1)
269 errExit("asprintf"); 316 errExit("asprintf");
270 if (access(name, R_OK) == 0) { 317 if (access(name, R_OK) == 0) {
271 fslib_copy_libs(name); 318 fslib_copy_libs_parse_as_user(name);
272 fslib_copy_dir(name); 319 fslib_copy_dir(name);
273 } 320 }
274 else { 321 else {
@@ -277,7 +324,7 @@ void fslib_install_system(void) {
277 if (asprintf(&name, "/usr/lib64/%s", ptr->dir1) == -1) 324 if (asprintf(&name, "/usr/lib64/%s", ptr->dir1) == -1)
278 errExit("asprintf"); 325 errExit("asprintf");
279 if (access(name, R_OK) == 0) { 326 if (access(name, R_OK) == 0) {
280 fslib_copy_libs(name); 327 fslib_copy_libs_parse_as_user(name);
281 fslib_copy_dir(name); 328 fslib_copy_dir(name);
282 } 329 }
283 } 330 }
@@ -288,7 +335,7 @@ void fslib_install_system(void) {
288 if (asprintf(&name, "/usr/lib/x86_64-linux-gnu/%s", ptr->dir2) == -1) 335 if (asprintf(&name, "/usr/lib/x86_64-linux-gnu/%s", ptr->dir2) == -1)
289 errExit("asprintf"); 336 errExit("asprintf");
290 if (access(name, R_OK) == 0) { 337 if (access(name, R_OK) == 0) {
291 fslib_copy_libs(name); 338 fslib_copy_libs_parse_as_user(name);
292 fslib_copy_dir(name); 339 fslib_copy_dir(name);
293 } 340 }
294 else { 341 else {
@@ -297,7 +344,7 @@ void fslib_install_system(void) {
297 if (asprintf(&name, "/usr/lib64/%s", ptr->dir2) == -1) 344 if (asprintf(&name, "/usr/lib64/%s", ptr->dir2) == -1)
298 errExit("asprintf"); 345 errExit("asprintf");
299 if (access(name, R_OK) == 0) { 346 if (access(name, R_OK) == 0) {
300 fslib_copy_libs(name); 347 fslib_copy_libs_parse_as_user(name);
301 fslib_copy_dir(name); 348 fslib_copy_dir(name);
302 } 349 }
303 } 350 }
diff --git a/src/firejail/fs_mkdir.c b/src/firejail/fs_mkdir.c
index d1b3b5629..8cfeea582 100644
--- a/src/firejail/fs_mkdir.c
+++ b/src/firejail/fs_mkdir.c
@@ -46,7 +46,7 @@ static void mkdir_recursive(char *path) {
46 struct stat s; 46 struct stat s;
47 47
48 if (chdir("/")) { 48 if (chdir("/")) {
49 fprintf(stderr, "Error: can't chdir to /"); 49 fprintf(stderr, "Error: can't chdir to /\n");
50 return; 50 return;
51 } 51 }
52 52
@@ -63,7 +63,7 @@ static void mkdir_recursive(char *path) {
63 return; 63 return;
64 } 64 }
65 if (chdir(subdir)) { 65 if (chdir(subdir)) {
66 fprintf(stderr, "Error: can't chdir to %s", subdir); 66 fprintf(stderr, "Error: can't chdir to %s\n", subdir);
67 return; 67 return;
68 } 68 }
69 69
diff --git a/src/firejail/join.c b/src/firejail/join.c
index a8011aa14..1575a7469 100644
--- a/src/firejail/join.c
+++ b/src/firejail/join.c
@@ -411,7 +411,7 @@ void join(pid_t pid, int argc, char **argv, int index) {
411 extract_x11_display(parent); 411 extract_x11_display(parent);
412 412
413 int shfd = -1; 413 int shfd = -1;
414 if (!arg_shell_none && !arg_audit) 414 if (!arg_shell_none)
415 shfd = open_shell(); 415 shfd = open_shell();
416 416
417 EUID_ROOT(); 417 EUID_ROOT();
diff --git a/src/firejail/main.c b/src/firejail/main.c
index 61533fcd9..9705c2436 100644
--- a/src/firejail/main.c
+++ b/src/firejail/main.c
@@ -130,8 +130,6 @@ int arg_keep_var_tmp = 0; // don't overwrite /var/tmp
130int arg_writable_run_user = 0; // writable /run/user 130int arg_writable_run_user = 0; // writable /run/user
131int arg_writable_var_log = 0; // writable /var/log 131int arg_writable_var_log = 0; // writable /var/log
132int arg_appimage = 0; // appimage 132int arg_appimage = 0; // appimage
133int arg_audit = 0; // audit
134char *arg_audit_prog = NULL; // audit
135int arg_apparmor = 0; // apparmor 133int arg_apparmor = 0; // apparmor
136int arg_allow_debuggers = 0; // allow debuggers 134int arg_allow_debuggers = 0; // allow debuggers
137int arg_x11_block = 0; // block X11 135int arg_x11_block = 0; // block X11
@@ -297,7 +295,7 @@ static void check_network(Bridge *br) {
297 else if (br->ipsandbox) { // for macvlan check network range 295 else if (br->ipsandbox) { // for macvlan check network range
298 char *rv = in_netrange(br->ipsandbox, br->ip, br->mask); 296 char *rv = in_netrange(br->ipsandbox, br->ip, br->mask);
299 if (rv) { 297 if (rv) {
300 fprintf(stderr, "%s", rv); 298 fprintf(stderr, "%s\n", rv);
301 exit(1); 299 exit(1);
302 } 300 }
303 } 301 }
@@ -1233,10 +1231,12 @@ int main(int argc, char **argv, char **envp) {
1233#endif 1231#endif
1234 } 1232 }
1235 } 1233 }
1234#ifdef HAVE_OUTPUT
1236 else { 1235 else {
1237 // check --output option and execute it; 1236 // check --output option and execute it;
1238 check_output(argc, argv); // the function will not return if --output or --output-stderr option was found 1237 check_output(argc, argv); // the function will not return if --output or --output-stderr option was found
1239 } 1238 }
1239#endif
1240 EUID_ASSERT(); 1240 EUID_ASSERT();
1241 1241
1242 // check for force-nonewprivs in /etc/firejail/firejail.config file 1242 // check for force-nonewprivs in /etc/firejail/firejail.config file
@@ -1285,15 +1285,10 @@ int main(int argc, char **argv, char **envp) {
1285#endif 1285#endif
1286 else if (strncmp(argv[i], "--protocol=", 11) == 0) { 1286 else if (strncmp(argv[i], "--protocol=", 11) == 0) {
1287 if (checkcfg(CFG_SECCOMP)) { 1287 if (checkcfg(CFG_SECCOMP)) {
1288 if (cfg.protocol) { 1288 const char *add = argv[i] + 11;
1289 fwarning("more than one protocol list is present, \"%s\" will be installed\n", cfg.protocol); 1289 profile_list_augment(&cfg.protocol, add);
1290 } 1290 if (arg_debug)
1291 else { 1291 fprintf(stderr, "[option] combined protocol list: \"%s\"\n", cfg.protocol);
1292 // store list
1293 cfg.protocol = strdup(argv[i] + 11);
1294 if (!cfg.protocol)
1295 errExit("strdup");
1296 }
1297 } 1292 }
1298 else 1293 else
1299 exit_err_feature("seccomp"); 1294 exit_err_feature("seccomp");
@@ -1589,7 +1584,26 @@ int main(int argc, char **argv, char **envp) {
1589 profile_add(line); 1584 profile_add(line);
1590 } 1585 }
1591#endif 1586#endif
1592 1587 else if (strncmp(argv[i], "--mkdir=", 8) == 0) {
1588 char *line;
1589 if (asprintf(&line, "mkdir %s", argv[i] + 8) == -1)
1590 errExit("asprintf");
1591 /* Note: Applied both immediately in profile_check_line()
1592 * and later on via fs_blacklist().
1593 */
1594 profile_check_line(line, 0, NULL);
1595 profile_add(line);
1596 }
1597 else if (strncmp(argv[i], "--mkfile=", 9) == 0) {
1598 char *line;
1599 if (asprintf(&line, "mkfile %s", argv[i] + 9) == -1)
1600 errExit("asprintf");
1601 /* Note: Applied both immediately in profile_check_line()
1602 * and later on via fs_blacklist().
1603 */
1604 profile_check_line(line, 0, NULL);
1605 profile_add(line);
1606 }
1593 else if (strncmp(argv[i], "--read-only=", 12) == 0) { 1607 else if (strncmp(argv[i], "--read-only=", 12) == 0) {
1594 char *line; 1608 char *line;
1595 if (asprintf(&line, "read-only %s", argv[i] + 12) == -1) 1609 if (asprintf(&line, "read-only %s", argv[i] + 12) == -1)
@@ -2592,28 +2606,6 @@ int main(int argc, char **argv, char **envp) {
2592 //************************************* 2606 //*************************************
2593 else if (strncmp(argv[i], "--timeout=", 10) == 0) 2607 else if (strncmp(argv[i], "--timeout=", 10) == 0)
2594 cfg.timeout = extract_timeout(argv[i] + 10); 2608 cfg.timeout = extract_timeout(argv[i] + 10);
2595 else if (strcmp(argv[i], "--audit") == 0) {
2596 arg_audit_prog = LIBDIR "/firejail/faudit";
2597 profile_add_ignore("shell none");
2598 arg_audit = 1;
2599 }
2600 else if (strncmp(argv[i], "--audit=", 8) == 0) {
2601 if (strlen(argv[i] + 8) == 0) {
2602 fprintf(stderr, "Error: invalid audit program\n");
2603 exit(1);
2604 }
2605 arg_audit_prog = strdup(argv[i] + 8);
2606 if (!arg_audit_prog)
2607 errExit("strdup");
2608
2609 struct stat s;
2610 if (stat(arg_audit_prog, &s) != 0) {
2611 fprintf(stderr, "Error: cannot find the audit program %s\n", arg_audit_prog);
2612 exit(1);
2613 }
2614 profile_add_ignore("shell none");
2615 arg_audit = 1;
2616 }
2617 else if (strcmp(argv[i], "--appimage") == 0) 2609 else if (strcmp(argv[i], "--appimage") == 0)
2618 arg_appimage = 1; 2610 arg_appimage = 1;
2619 else if (strcmp(argv[i], "--shell=none") == 0) { 2611 else if (strcmp(argv[i], "--shell=none") == 0) {
diff --git a/src/firejail/network_main.c b/src/firejail/network_main.c
index f1ad6430a..ee3c00872 100644
--- a/src/firejail/network_main.c
+++ b/src/firejail/network_main.c
@@ -120,7 +120,7 @@ void net_configure_sandbox_ip(Bridge *br) {
120 // check network range 120 // check network range
121 char *rv = in_netrange(br->ipsandbox, br->ip, br->mask); 121 char *rv = in_netrange(br->ipsandbox, br->ip, br->mask);
122 if (rv) { 122 if (rv) {
123 fprintf(stderr, "%s", rv); 123 fprintf(stderr, "%s\n", rv);
124 exit(1); 124 exit(1);
125 } 125 }
126 // send an ARP request and check if there is anybody on this IP address 126 // send an ARP request and check if there is anybody on this IP address
diff --git a/src/firejail/no_sandbox.c b/src/firejail/no_sandbox.c
index 3120fe527..60a82821e 100644
--- a/src/firejail/no_sandbox.c
+++ b/src/firejail/no_sandbox.c
@@ -168,29 +168,17 @@ void run_no_sandbox(int argc, char **argv) {
168 errExit("setresuid"); 168 errExit("setresuid");
169 169
170 // process limited subset of options 170 // process limited subset of options
171 // and find first non option arg:
172 // - first argument not starting with --,
173 // - whatever follows after -c (example: firejail -c ls)
174 int prog_index = 0;
171 int i; 175 int i;
172 for (i = 0; i < argc; i++) { 176 for (i = 1; i < argc; i++) {
173 if (strcmp(argv[i], "--debug") == 0) 177 if (strcmp(argv[i], "--debug") == 0)
174 arg_debug = 1; 178 arg_debug = 1;
175 else if (strncmp(argv[i], "--shell=", 8) == 0) 179 else if (strncmp(argv[i], "--shell=", 8) == 0)
176 fwarning("shell-related command line options are disregarded - using SHELL environment variable\n"); 180 fwarning("shell-related command line options are disregarded\n");
177 } 181 else if (strcmp(argv[i], "-c") == 0) {
178
179 // use $SHELL to get shell used in sandbox, guess shell otherwise
180 cfg.shell = guess_shell();
181 if (!cfg.shell) {
182 fprintf(stderr, "Error: unable to guess your shell, please set SHELL environment variable\n");
183 exit(1);
184 }
185 else if (arg_debug)
186 printf("Selecting %s as shell\n", cfg.shell);
187
188 int prog_index = 0;
189 // find first non option arg:
190 // - first argument not starting with --,
191 // - whatever follows after -c (example: firejail -c ls)
192 for (i = 1; i < argc; i++) {
193 if (strcmp(argv[i], "-c") == 0) {
194 prog_index = i + 1; 182 prog_index = i + 1;
195 if (prog_index == argc) { 183 if (prog_index == argc) {
196 fprintf(stderr, "Error: option -c requires an argument\n"); 184 fprintf(stderr, "Error: option -c requires an argument\n");
@@ -199,36 +187,36 @@ void run_no_sandbox(int argc, char **argv) {
199 break; 187 break;
200 } 188 }
201 // check first argument not starting with -- 189 // check first argument not starting with --
202 if (strncmp(argv[i],"--",2) != 0) { 190 else if (strncmp(argv[i],"--",2) != 0) {
203 prog_index = i; 191 prog_index = i;
204 break; 192 break;
205 } 193 }
206 } 194 }
207 195
208// if shell is /usr/bin/firejail, replace it with /bin/bash
209// if (strcmp(cfg.shell, PATH_FIREJAIL) == 0) {
210// cfg.shell = "/bin/bash";
211// prog_index = 0;
212// }
213
214 if (prog_index == 0) { 196 if (prog_index == 0) {
215 assert(cfg.command_line == NULL); // runs cfg.shell 197 // got no command, require a shell and try to execute it
198 cfg.shell = guess_shell();
199 if (!cfg.shell) {
200 fprintf(stderr, "Error: unable to guess your shell, please set SHELL environment variable\n");
201 exit(1);
202 }
203
204 assert(cfg.command_line == NULL);
216 cfg.window_title = cfg.shell; 205 cfg.window_title = cfg.shell;
217 } else { 206 } else {
207 // this sandbox might not allow execution of a shell
208 // force --shell=none in order to not break firecfg symbolic links
209 arg_shell_none = 1;
210
218 build_cmdline(&cfg.command_line, &cfg.window_title, argc, argv, prog_index); 211 build_cmdline(&cfg.command_line, &cfg.window_title, argc, argv, prog_index);
219 } 212 }
220 213
214 fwarning("an existing sandbox was detected. "
215 "%s will run without any additional sandboxing features\n", prog_index ? argv[prog_index] : cfg.shell);
216
221 cfg.original_argv = argv; 217 cfg.original_argv = argv;
222 cfg.original_program_index = prog_index; 218 cfg.original_program_index = prog_index;
223 219
224 char *command;
225 if (prog_index == 0)
226 command = cfg.shell;
227 else
228 command = argv[prog_index];
229 fwarning("an existing sandbox was detected. "
230 "%s will run without any additional sandboxing features\n", command);
231
232 arg_quiet = 1; 220 arg_quiet = 1;
233 221
234 start_application(1, -1, NULL); 222 start_application(1, -1, NULL);
diff --git a/src/firejail/output.c b/src/firejail/output.c
index db9728a3d..835dff2db 100644
--- a/src/firejail/output.c
+++ b/src/firejail/output.c
@@ -22,6 +22,7 @@
22#include <sys/stat.h> 22#include <sys/stat.h>
23#include <unistd.h> 23#include <unistd.h>
24 24
25#ifdef HAVE_OUTPUT
25void check_output(int argc, char **argv) { 26void check_output(int argc, char **argv) {
26 EUID_ASSERT(); 27 EUID_ASSERT();
27 28
@@ -149,3 +150,4 @@ void check_output(int argc, char **argv) {
149 perror("execvp"); 150 perror("execvp");
150 exit(1); 151 exit(1);
151} 152}
153#endif
diff --git a/src/firejail/profile.c b/src/firejail/profile.c
index b706839a1..351b760df 100644
--- a/src/firejail/profile.c
+++ b/src/firejail/profile.c
@@ -157,6 +157,10 @@ static int check_nosound(void) {
157 return arg_nosound != 0; 157 return arg_nosound != 0;
158} 158}
159 159
160static int check_private(void) {
161 return arg_private;
162}
163
160static int check_x11(void) { 164static int check_x11(void) {
161 return (arg_x11_block || arg_x11_xorg || env_get("FIREJAIL_X11")); 165 return (arg_x11_block || arg_x11_xorg || env_get("FIREJAIL_X11"));
162} 166}
@@ -174,6 +178,7 @@ Cond conditionals[] = {
174 {"HAS_NET", check_netoptions}, 178 {"HAS_NET", check_netoptions},
175 {"HAS_NODBUS", check_nodbus}, 179 {"HAS_NODBUS", check_nodbus},
176 {"HAS_NOSOUND", check_nosound}, 180 {"HAS_NOSOUND", check_nosound},
181 {"HAS_PRIVATE", check_private},
177 {"HAS_X11", check_x11}, 182 {"HAS_X11", check_x11},
178 {"BROWSER_DISABLE_U2F", check_disable_u2f}, 183 {"BROWSER_DISABLE_U2F", check_disable_u2f},
179 {"BROWSER_ALLOW_DRM", check_allow_drm}, 184 {"BROWSER_ALLOW_DRM", check_allow_drm},
@@ -911,15 +916,10 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
911 916
912 if (strncmp(ptr, "protocol ", 9) == 0) { 917 if (strncmp(ptr, "protocol ", 9) == 0) {
913 if (checkcfg(CFG_SECCOMP)) { 918 if (checkcfg(CFG_SECCOMP)) {
914 if (cfg.protocol) { 919 const char *add = ptr + 9;
915 fwarning("more than one protocol list is present, \"%s\" will be installed\n", cfg.protocol); 920 profile_list_augment(&cfg.protocol, add);
916 return 0; 921 if (arg_debug)
917 } 922 fprintf(stderr, "[profile] combined protocol list: \"%s\"\n", cfg.protocol);
918
919 // store list
920 cfg.protocol = strdup(ptr + 9);
921 if (!cfg.protocol)
922 errExit("strdup");
923 } 923 }
924 else 924 else
925 warning_feature_disabled("seccomp"); 925 warning_feature_disabled("seccomp");
@@ -931,7 +931,6 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
931 return 0; 931 return 0;
932 } 932 }
933 if (strncmp(ptr, "rmenv ", 6) == 0) { 933 if (strncmp(ptr, "rmenv ", 6) == 0) {
934 unsetenv(ptr + 6); // Remove also immediately from Firejail itself
935 env_store(ptr + 6, RMENV); 934 env_store(ptr + 6, RMENV);
936 return 0; 935 return 0;
937 } 936 }
@@ -1774,3 +1773,143 @@ void profile_read(const char *fname) {
1774 } 1773 }
1775 fclose(fp); 1774 fclose(fp);
1776} 1775}
1776
1777char *profile_list_normalize(char *list)
1778{
1779 /* Remove redundant commas.
1780 *
1781 * As result is always shorter than original,
1782 * in-place copying can be used.
1783 */
1784 size_t i = 0;
1785 size_t j = 0;
1786 int c;
1787 while (list[i] == ',')
1788 ++i;
1789 while ((c = list[i++])) {
1790 if (c == ',') {
1791 while (list[i] == ',')
1792 ++i;
1793 if (list[i] == 0)
1794 break;
1795 }
1796 list[j++] = c;
1797 }
1798 list[j] = 0;
1799 return list;
1800}
1801
1802char *profile_list_compress(char *list)
1803{
1804 size_t i;
1805
1806 /* Comma separated list is processed so that:
1807 * "item" -> adds item to list
1808 * "-item" -> removes item from list
1809 * "+item" -> adds item to list
1810 * "=item" -> clear list, add item
1811 *
1812 * For example:
1813 * ,a,,,b,,,c, -> a,b,c
1814 * a,,b,,,c,a -> a,b,c
1815 * a,b,c,-a -> b,c
1816 * a,b,c,-a,a -> b,c,a
1817 * a,+b,c -> a,b,c
1818 * a,b,=c,d -> c,d
1819 * a,b,c,= ->
1820 */
1821 profile_list_normalize(list);
1822
1823 /* Count items: comma count + 1 */
1824 size_t count = 1;
1825 for (i = 0; list[i]; ++i) {
1826 if (list[i] == ',')
1827 ++count;
1828 }
1829
1830 /* Collect items in an array */
1831 char *in[count];
1832 count = 0;
1833 in[count++] = list;
1834 for (i = 0; list[i]; ++i) {
1835 if (list[i] != ',')
1836 continue;
1837 list[i] = 0;
1838 in[count++] = list + i + 1;
1839 }
1840
1841 /* Filter array: add, remove, reset, filter out duplicates */
1842 for (i = 0; i < count; ++i) {
1843 char *item = in[i];
1844 assert(item);
1845
1846 size_t k;
1847 switch (*item) {
1848 case '-':
1849 ++item;
1850 /* Do not include this item */
1851 in[i] = 0;
1852 /* Remove if already included */
1853 for (k = 0; k < i; ++k) {
1854 if (in[k] && !strcmp(in[k], item)) {
1855 in[k] = 0;
1856 break;
1857 }
1858 }
1859 break;
1860 case '+':
1861 /* Allow +/- symmetry */
1862 in[i] = ++item;
1863 /* FALLTHRU */
1864 default:
1865 /* Adding empty item is a NOP */
1866 if (!*item) {
1867 in[i] = 0;
1868 break;
1869 }
1870 /* Include item unless it is already included */
1871 for (k = 0; k < i; ++k) {
1872 if (in[k] && !strcmp(in[k], item)) {
1873 in[i] = 0;
1874 break;
1875 }
1876 }
1877 break;
1878 case '=':
1879 in[i] = ++item;
1880 /* Include non-empty item */
1881 if (!*item)
1882 in[i] = 0;
1883 /* Remove all allready included items */
1884 for (k = 0; k < i; ++k)
1885 in[k] = 0;
1886 break;
1887 }
1888 }
1889
1890 /* Copying back using in-place data works because the
1891 * original order is retained and no item gets longer
1892 * than what it used to be.
1893 */
1894 char *pos = list;
1895 for (i = 0; i < count; ++i) {
1896 char *item = in[i];
1897 if (!item)
1898 continue;
1899 if (pos > list)
1900 *pos++ = ',';
1901 while (*item)
1902 *pos++ = *item++;
1903 }
1904 *pos = 0;
1905 return list;
1906}
1907
1908void profile_list_augment(char **list, const char *items)
1909{
1910 char *tmp = 0;
1911 if (asprintf(&tmp, "%s,%s", *list ?: "", items ?: "") < 0)
1912 errExit("asprintf");
1913 free(*list);
1914 *list = profile_list_compress(tmp);
1915}
diff --git a/src/firejail/pulseaudio.c b/src/firejail/pulseaudio.c
index 08f9a14a7..4b9203c36 100644
--- a/src/firejail/pulseaudio.c
+++ b/src/firejail/pulseaudio.c
@@ -80,8 +80,6 @@ static void pulseaudio_fallback(const char *path) {
80 80
81 fmessage("Cannot mount tmpfs on %s/.config/pulse\n", cfg.homedir); 81 fmessage("Cannot mount tmpfs on %s/.config/pulse\n", cfg.homedir);
82 env_store_name_val("PULSE_CLIENTCONFIG", path, SETENV); 82 env_store_name_val("PULSE_CLIENTCONFIG", path, SETENV);
83 if (setenv("PULSE_CLIENTCONFIG", path, 1) < 0)
84 errExit("setenv");
85} 83}
86 84
87// disable shm in pulseaudio (issue #69) 85// disable shm in pulseaudio (issue #69)
@@ -176,8 +174,7 @@ void pulseaudio_init(void) {
176 char *p; 174 char *p;
177 if (asprintf(&p, "%s/client.conf", homeusercfg) == -1) 175 if (asprintf(&p, "%s/client.conf", homeusercfg) == -1)
178 errExit("asprintf"); 176 errExit("asprintf");
179 if (setenv("PULSE_CLIENTCONFIG", p, 1) < 0) 177 env_store_name_val("PULSE_CLIENTCONFIG", p, SETENV);
180 errExit("setenv");
181 fs_logger2("create", p); 178 fs_logger2("create", p);
182 free(p); 179 free(p);
183 180
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c
index 9a4be5cc0..36a54d6fe 100644
--- a/src/firejail/sandbox.c
+++ b/src/firejail/sandbox.c
@@ -475,23 +475,9 @@ void start_application(int no_sandbox, int fd, char *set_sandbox_status) {
475 } 475 }
476 476
477 //**************************************** 477 //****************************************
478 // audit
479 //****************************************
480 if (arg_audit) {
481 assert(arg_audit_prog);
482
483#ifdef HAVE_GCOV
484 __gcov_dump();
485#endif
486 seccomp_install_filters();
487 if (set_sandbox_status)
488 *set_sandbox_status = SANDBOX_DONE;
489 execl(arg_audit_prog, arg_audit_prog, NULL);
490 }
491 //****************************************
492 // start the program without using a shell 478 // start the program without using a shell
493 //**************************************** 479 //****************************************
494 else if (arg_shell_none) { 480 if (arg_shell_none) {
495 if (arg_debug) { 481 if (arg_debug) {
496 int i; 482 int i;
497 for (i = cfg.original_program_index; i < cfg.original_argc; i++) { 483 for (i = cfg.original_program_index; i < cfg.original_argc; i++) {
@@ -589,12 +575,12 @@ void start_application(int no_sandbox, int fd, char *set_sandbox_status) {
589} 575}
590 576
591static void enforce_filters(void) { 577static void enforce_filters(void) {
578 fmessage("\n** Warning: dropping all Linux capabilities and setting NO_NEW_PRIVS prctl **\n\n");
592 // enforce NO_NEW_PRIVS 579 // enforce NO_NEW_PRIVS
593 arg_nonewprivs = 1; 580 arg_nonewprivs = 1;
594 force_nonewprivs = 1; 581 force_nonewprivs = 1;
595 582
596 // disable all capabilities 583 // disable all capabilities
597 fmessage("\n** Warning: dropping all Linux capabilities **\n\n");
598 arg_caps_drop_all = 1; 584 arg_caps_drop_all = 1;
599 585
600 // drop all supplementary groups; /etc/group file inside chroot 586 // drop all supplementary groups; /etc/group file inside chroot
@@ -795,14 +781,18 @@ int sandbox(void* sandbox_arg) {
795 exit(rv); 781 exit(rv);
796 } 782 }
797 783
798 // need ld.so.preload if tracing or seccomp with any non-default lists 784#ifdef HAVE_FORCE_NONEWPRIVS
799 bool need_preload = arg_trace || arg_tracelog || arg_seccomp_postexec; 785 bool always_enforce_filters = true;
786#else
787 bool always_enforce_filters = false;
788#endif
800 // for --appimage, --chroot and --overlay* we force NO_NEW_PRIVS 789 // for --appimage, --chroot and --overlay* we force NO_NEW_PRIVS
801 // and drop all capabilities 790 // and drop all capabilities
802 if (getuid() != 0 && (arg_appimage || cfg.chrootdir || arg_overlay)) { 791 if (getuid() != 0 && (arg_appimage || cfg.chrootdir || arg_overlay || always_enforce_filters))
803 enforce_filters(); 792 enforce_filters();
804 need_preload = arg_trace || arg_tracelog; 793
805 } 794 // need ld.so.preload if tracing or seccomp with any non-default lists
795 bool need_preload = arg_trace || arg_tracelog || arg_seccomp_postexec;
806 796
807 // trace pre-install 797 // trace pre-install
808 if (need_preload) 798 if (need_preload)
@@ -969,11 +959,35 @@ int sandbox(void* sandbox_arg) {
969 else if (arg_overlay) 959 else if (arg_overlay)
970 fwarning("private-etc feature is disabled in overlay\n"); 960 fwarning("private-etc feature is disabled in overlay\n");
971 else { 961 else {
972 fs_private_dir_list("/etc", RUN_ETC_DIR, cfg.etc_private_keep); 962 /* Current /etc/passwd and /etc/group files are bind
973 fs_private_dir_list("/usr/etc", RUN_USR_ETC_DIR, cfg.etc_private_keep); // openSUSE 963 * mounted filtered versions of originals. Leaving
964 * them underneath private-etc mount causes problems
965 * in devices with older kernels, e.g. attempts to
966 * update the real /etc/passwd file yield EBUSY.
967 *
968 * As we do want to retain filtered /etc content:
969 * 1. duplicate /etc content to RUN_ETC_DIR
970 * 2. unmount bind mounts from /etc
971 * 3. mount RUN_ETC_DIR at /etc
972 */
973 timetrace_start();
974 fs_private_dir_copy("/etc", RUN_ETC_DIR, cfg.etc_private_keep);
975
976 if (umount2("/etc/group", MNT_DETACH) == -1)
977 fprintf(stderr, "/etc/group: unmount: %s\n", strerror(errno));
978 if (umount2("/etc/passwd", MNT_DETACH) == -1)
979 fprintf(stderr, "/etc/passwd: unmount: %s\n", strerror(errno));
980
981 fs_private_dir_mount("/etc", RUN_ETC_DIR);
982 fmessage("Private /etc installed in %0.2f ms\n", timetrace_end());
983
974 // create /etc/ld.so.preload file again 984 // create /etc/ld.so.preload file again
975 if (need_preload) 985 if (need_preload)
976 fs_trace_preload(); 986 fs_trace_preload();
987
988 // openSUSE configuration is split between /etc and /usr/etc
989 // process private-etc a second time
990 fs_private_dir_list("/usr/etc", RUN_USR_ETC_DIR, cfg.etc_private_keep);
977 } 991 }
978 } 992 }
979 993
@@ -1015,23 +1029,11 @@ int sandbox(void* sandbox_arg) {
1015 fs_dev_disable_video(); 1029 fs_dev_disable_video();
1016 1030
1017 //**************************** 1031 //****************************
1018 // install trace
1019 //****************************
1020 if (need_preload)
1021 fs_trace();
1022
1023 //****************************
1024 // set dns 1032 // set dns
1025 //**************************** 1033 //****************************
1026 fs_resolvconf(); 1034 fs_resolvconf();
1027 1035
1028 //**************************** 1036 //****************************
1029 // fs post-processing
1030 //****************************
1031 fs_logger_print();
1032 fs_logger_change_owner();
1033
1034 //****************************
1035 // start dhcp client 1037 // start dhcp client
1036 //**************************** 1038 //****************************
1037 dhcp_start(); 1039 dhcp_start();
@@ -1080,6 +1082,12 @@ int sandbox(void* sandbox_arg) {
1080 save_umask(); 1082 save_umask();
1081 1083
1082 //**************************** 1084 //****************************
1085 // fs post-processing
1086 //****************************
1087 fs_logger_print();
1088 fs_logger_change_owner();
1089
1090 //****************************
1083 // set security filters 1091 // set security filters
1084 //**************************** 1092 //****************************
1085 // save state of nonewprivs 1093 // save state of nonewprivs
@@ -1136,6 +1144,16 @@ int sandbox(void* sandbox_arg) {
1136 fs_remount(RUN_SECCOMP_DIR, MOUNT_READONLY, 0); 1144 fs_remount(RUN_SECCOMP_DIR, MOUNT_READONLY, 0);
1137 seccomp_debug(); 1145 seccomp_debug();
1138 1146
1147 //****************************
1148 // install trace - still need capabilities
1149 //****************************
1150 if (need_preload)
1151 fs_trace();
1152
1153 //****************************
1154 // continue security filters
1155 //****************************
1156
1139 // set capabilities 1157 // set capabilities
1140 set_caps(); 1158 set_caps();
1141 1159
diff --git a/src/firejail/sbox.c b/src/firejail/sbox.c
index 933c93b0d..f9c41f661 100644
--- a/src/firejail/sbox.c
+++ b/src/firejail/sbox.c
@@ -203,15 +203,16 @@ static int __attribute__((noreturn)) sbox_do_exec_v(unsigned filtermask, char *
203 } 203 }
204 } 204 }
205 205
206 if (filtermask & SBOX_ROOT) { 206 if (filtermask & SBOX_USER)
207 drop_privs(1);
208 else if (filtermask & SBOX_ROOT) {
207 // elevate privileges in order to get grsecurity working 209 // elevate privileges in order to get grsecurity working
208 if (setreuid(0, 0)) 210 if (setreuid(0, 0))
209 errExit("setreuid"); 211 errExit("setreuid");
210 if (setregid(0, 0)) 212 if (setregid(0, 0))
211 errExit("setregid"); 213 errExit("setregid");
212 } 214 }
213 else if (filtermask & SBOX_USER) 215 else assert(0);
214 drop_privs(1);
215 216
216 if (arg[0]) { // get rid of scan-build warning 217 if (arg[0]) { // get rid of scan-build warning
217 int fd = open(arg[0], O_PATH | O_CLOEXEC); 218 int fd = open(arg[0], O_PATH | O_CLOEXEC);
diff --git a/src/firejail/usage.c b/src/firejail/usage.c
index 2c6bbf98f..397150158 100644
--- a/src/firejail/usage.c
+++ b/src/firejail/usage.c
@@ -33,7 +33,6 @@ static char *usage_str =
33 " --apparmor - enable AppArmor confinement.\n" 33 " --apparmor - enable AppArmor confinement.\n"
34 " --apparmor.print=name|pid - print apparmor status.\n" 34 " --apparmor.print=name|pid - print apparmor status.\n"
35 " --appimage - sandbox an AppImage application.\n" 35 " --appimage - sandbox an AppImage application.\n"
36 " --audit[=test-program] - audit the sandbox.\n"
37#ifdef HAVE_NETWORK 36#ifdef HAVE_NETWORK
38 " --bandwidth=name|pid - set bandwidth limits.\n" 37 " --bandwidth=name|pid - set bandwidth limits.\n"
39#endif 38#endif
@@ -56,6 +55,7 @@ static char *usage_str =
56#endif 55#endif
57 " --cpu=cpu-number,cpu-number - set cpu affinity.\n" 56 " --cpu=cpu-number,cpu-number - set cpu affinity.\n"
58 " --cpu.print=name|pid - print the cpus in use.\n" 57 " --cpu.print=name|pid - print the cpus in use.\n"
58#ifdef HAVE_DBUSPROXY
59 " --dbus-log=file - set DBus log file location.\n" 59 " --dbus-log=file - set DBus log file location.\n"
60 " --dbus-system=filter|none - set system DBus access policy.\n" 60 " --dbus-system=filter|none - set system DBus access policy.\n"
61 " --dbus-system.broadcast=rule - allow signals on the system DBus according to rule.\n" 61 " --dbus-system.broadcast=rule - allow signals on the system DBus according to rule.\n"
@@ -71,6 +71,7 @@ static char *usage_str =
71 " --dbus-user.own=name - allow ownership of name on the session DBus.\n" 71 " --dbus-user.own=name - allow ownership of name on the session DBus.\n"
72 " --dbus-user.see=name - allow seeing name on the session DBus.\n" 72 " --dbus-user.see=name - allow seeing name on the session DBus.\n"
73 " --dbus-user.talk=name - allow talking to name on the session DBus.\n" 73 " --dbus-user.talk=name - allow talking to name on the session DBus.\n"
74#endif
74 " --debug - print sandbox debug messages.\n" 75 " --debug - print sandbox debug messages.\n"
75 " --debug-blacklists - debug blacklisting.\n" 76 " --debug-blacklists - debug blacklisting.\n"
76 " --debug-caps - print all recognized capabilities.\n" 77 " --debug-caps - print all recognized capabilities.\n"
@@ -125,6 +126,8 @@ static char *usage_str =
125 " --machine-id - preserve /etc/machine-id\n" 126 " --machine-id - preserve /etc/machine-id\n"
126 " --memory-deny-write-execute - seccomp filter to block attempts to create\n" 127 " --memory-deny-write-execute - seccomp filter to block attempts to create\n"
127 "\tmemory mappings that are both writable and executable.\n" 128 "\tmemory mappings that are both writable and executable.\n"
129 " --mkdir=dirname - create a directory.\n"
130 " --mkfile=filename - create a file.\n"
128#ifdef HAVE_NETWORK 131#ifdef HAVE_NETWORK
129 " --mtu=number - set interface MTU.\n" 132 " --mtu=number - set interface MTU.\n"
130#endif 133#endif
@@ -161,14 +164,18 @@ static char *usage_str =
161 " --novideo - disable video devices.\n" 164 " --novideo - disable video devices.\n"
162 " --nou2f - disable U2F devices.\n" 165 " --nou2f - disable U2F devices.\n"
163 " --nowhitelist=filename - disable whitelist for file or directory.\n" 166 " --nowhitelist=filename - disable whitelist for file or directory.\n"
167#ifdef HAVE_OUTPUT
164 " --output=logfile - stdout logging and log rotation.\n" 168 " --output=logfile - stdout logging and log rotation.\n"
165 " --output-stderr=logfile - stdout and stderr logging and log rotation.\n" 169 " --output-stderr=logfile - stdout and stderr logging and log rotation.\n"
170#endif
171#ifdef HAVE_OVERLAYFS
166 " --overlay - mount a filesystem overlay on top of the current filesystem.\n" 172 " --overlay - mount a filesystem overlay on top of the current filesystem.\n"
167 " --overlay-named=name - mount a filesystem overlay on top of the current\n" 173 " --overlay-named=name - mount a filesystem overlay on top of the current\n"
168 "\tfilesystem, and store it in name directory.\n" 174 "\tfilesystem, and store it in name directory.\n"
169 " --overlay-tmpfs - mount a temporary filesystem overlay on top of the\n" 175 " --overlay-tmpfs - mount a temporary filesystem overlay on top of the\n"
170 "\tcurrent filesystem.\n" 176 "\tcurrent filesystem.\n"
171 " --overlay-clean - clean all overlays stored in $HOME/.firejail directory.\n" 177 " --overlay-clean - clean all overlays stored in $HOME/.firejail directory.\n"
178#endif
172 " --private - temporary home directory.\n" 179 " --private - temporary home directory.\n"
173 " --private=directory - use directory as user home.\n" 180 " --private=directory - use directory as user home.\n"
174 " --private-cache - temporary ~/.cache directory.\n" 181 " --private-cache - temporary ~/.cache directory.\n"
diff --git a/src/firejail/util.c b/src/firejail/util.c
index f3709b5fd..53c671794 100644
--- a/src/firejail/util.c
+++ b/src/firejail/util.c
@@ -400,6 +400,8 @@ void touch_file_as_user(const char *fname, mode_t mode) {
400 SET_PERMS_STREAM(fp, -1, -1, mode); 400 SET_PERMS_STREAM(fp, -1, -1, mode);
401 fclose(fp); 401 fclose(fp);
402 } 402 }
403 else
404 fwarning("cannot create %s\n", fname);
403#ifdef HAVE_GCOV 405#ifdef HAVE_GCOV
404 __gcov_flush(); 406 __gcov_flush();
405#endif 407#endif
diff --git a/src/firemon/Makefile.in b/src/firemon/Makefile.in
index 9ee798fe9..a1b6692aa 100644
--- a/src/firemon/Makefile.in
+++ b/src/firemon/Makefile.in
@@ -1,3 +1,4 @@
1.PHONY: all
1all: firemon 2all: firemon
2 3
3include ../common.mk 4include ../common.mk
@@ -8,7 +9,9 @@ include ../common.mk
8firemon: $(OBJS) ../lib/common.o ../lib/pid.o 9firemon: $(OBJS) ../lib/common.o ../lib/pid.o
9 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o ../lib/pid.o $(LIBS) $(EXTRA_LDFLAGS) 10 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o ../lib/pid.o $(LIBS) $(EXTRA_LDFLAGS)
10 11
12.PHONY: clean
11clean:; rm -fr *.o firemon *.gcov *.gcda *.gcno *.plist 13clean:; rm -fr *.o firemon *.gcov *.gcda *.gcno *.plist
12 14
15.PHONY: distclean
13distclean: clean 16distclean: clean
14 rm -fr Makefile 17 rm -fr Makefile
diff --git a/src/fldd/Makefile.in b/src/fldd/Makefile.in
index 37b139d38..ba87d16cd 100644
--- a/src/fldd/Makefile.in
+++ b/src/fldd/Makefile.in
@@ -1,3 +1,4 @@
1.PHONY: all
1all: fldd 2all: fldd
2 3
3include ../common.mk 4include ../common.mk
@@ -8,7 +9,9 @@ include ../common.mk
8fldd: $(OBJS) ../lib/common.o ../lib/ldd_utils.o 9fldd: $(OBJS) ../lib/common.o ../lib/ldd_utils.o
9 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o ../lib/ldd_utils.o $(LIBS) $(EXTRA_LDFLAGS) 10 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o ../lib/ldd_utils.o $(LIBS) $(EXTRA_LDFLAGS)
10 11
12.PHONY: clean
11clean:; rm -fr *.o fldd *.gcov *.gcda *.gcno *.plist 13clean:; rm -fr *.o fldd *.gcov *.gcda *.gcno *.plist
12 14
15.PHONY: distclean
13distclean: clean 16distclean: clean
14 rm -fr Makefile 17 rm -fr Makefile
diff --git a/src/fnet/Makefile.in b/src/fnet/Makefile.in
index bd5fe9e7a..7447c6d3f 100644
--- a/src/fnet/Makefile.in
+++ b/src/fnet/Makefile.in
@@ -1,3 +1,4 @@
1.PHONY: all
1all: fnet 2all: fnet
2 3
3include ../common.mk 4include ../common.mk
@@ -8,7 +9,9 @@ include ../common.mk
8fnet: $(OBJS) ../lib/common.o ../lib/libnetlink.o 9fnet: $(OBJS) ../lib/common.o ../lib/libnetlink.o
9 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o ../lib/libnetlink.o $(LIBS) $(EXTRA_LDFLAGS) 10 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o ../lib/libnetlink.o $(LIBS) $(EXTRA_LDFLAGS)
10 11
12.PHONY: clean
11clean:; rm -fr *.o fnet *.gcov *.gcda *.gcno *.plist 13clean:; rm -fr *.o fnet *.gcov *.gcda *.gcno *.plist
12 14
15.PHONY: distclean
13distclean: clean 16distclean: clean
14 rm -fr Makefile 17 rm -fr Makefile
diff --git a/src/fnetfilter/Makefile.in b/src/fnetfilter/Makefile.in
index 6fe650a17..825262482 100644
--- a/src/fnetfilter/Makefile.in
+++ b/src/fnetfilter/Makefile.in
@@ -1,3 +1,4 @@
1.PHONY: all
1all: fnetfilter 2all: fnetfilter
2 3
3include ../common.mk 4include ../common.mk
@@ -8,7 +9,9 @@ include ../common.mk
8fnetfilter: $(OBJS) ../lib/common.o 9fnetfilter: $(OBJS) ../lib/common.o
9 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o $(LIBS) $(EXTRA_LDFLAGS) 10 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o $(LIBS) $(EXTRA_LDFLAGS)
10 11
12.PHONY: clean
11clean:; rm -fr *.o fnetfilter *.gcov *.gcda *.gcno *.plist 13clean:; rm -fr *.o fnetfilter *.gcov *.gcda *.gcno *.plist
12 14
15.PHONY: distclean
13distclean: clean 16distclean: clean
14 rm -fr Makefile 17 rm -fr Makefile
diff --git a/src/fsec-optimize/Makefile.in b/src/fsec-optimize/Makefile.in
index cc5ac7e35..a2187e89c 100644
--- a/src/fsec-optimize/Makefile.in
+++ b/src/fsec-optimize/Makefile.in
@@ -1,3 +1,4 @@
1.PHONY: all
1all: fsec-optimize 2all: fsec-optimize
2 3
3include ../common.mk 4include ../common.mk
@@ -8,7 +9,9 @@ include ../common.mk
8fsec-optimize: $(OBJS) ../lib/common.o ../lib/libnetlink.o 9fsec-optimize: $(OBJS) ../lib/common.o ../lib/libnetlink.o
9 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o ../lib/errno.o $(LIBS) $(EXTRA_LDFLAGS) 10 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o ../lib/errno.o $(LIBS) $(EXTRA_LDFLAGS)
10 11
12.PHONY: clean
11clean:; rm -fr *.o fsec-optimize *.gcov *.gcda *.gcno *.plist 13clean:; rm -fr *.o fsec-optimize *.gcov *.gcda *.gcno *.plist
12 14
15.PHONY: distclean
13distclean: clean 16distclean: clean
14 rm -fr Makefile 17 rm -fr Makefile
diff --git a/src/fsec-print/Makefile.in b/src/fsec-print/Makefile.in
index bf39a8c77..824fb5daf 100644
--- a/src/fsec-print/Makefile.in
+++ b/src/fsec-print/Makefile.in
@@ -1,3 +1,4 @@
1.PHONY: all
1all: fsec-print 2all: fsec-print
2 3
3include ../common.mk 4include ../common.mk
@@ -8,7 +9,9 @@ include ../common.mk
8fsec-print: $(OBJS) ../lib/common.o ../lib/libnetlink.o ../lib/errno.o ../lib/syscall.o 9fsec-print: $(OBJS) ../lib/common.o ../lib/libnetlink.o ../lib/errno.o ../lib/syscall.o
9 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o ../lib/errno.o ../lib/syscall.o $(LIBS) $(EXTRA_LDFLAGS) 10 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o ../lib/errno.o ../lib/syscall.o $(LIBS) $(EXTRA_LDFLAGS)
10 11
12.PHONY: clean
11clean:; rm -fr *.o fsec-print *.gcov *.gcda *.gcno *.plist 13clean:; rm -fr *.o fsec-print *.gcov *.gcda *.gcno *.plist
12 14
15.PHONY: distclean
13distclean: clean 16distclean: clean
14 rm -fr Makefile 17 rm -fr Makefile
diff --git a/src/fseccomp/Makefile.in b/src/fseccomp/Makefile.in
index b776a73ce..41abfce17 100644
--- a/src/fseccomp/Makefile.in
+++ b/src/fseccomp/Makefile.in
@@ -1,3 +1,4 @@
1.PHONY: all
1all: fseccomp 2all: fseccomp
2 3
3include ../common.mk 4include ../common.mk
@@ -8,7 +9,9 @@ include ../common.mk
8fseccomp: $(OBJS) ../lib/common.o ../lib/errno.o ../lib/syscall.o 9fseccomp: $(OBJS) ../lib/common.o ../lib/errno.o ../lib/syscall.o
9 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o ../lib/errno.o ../lib/syscall.o $(LIBS) $(EXTRA_LDFLAGS) 10 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o ../lib/errno.o ../lib/syscall.o $(LIBS) $(EXTRA_LDFLAGS)
10 11
12.PHONY: clean
11clean:; rm -fr *.o fseccomp *.gcov *.gcda *.gcno *.plist 13clean:; rm -fr *.o fseccomp *.gcov *.gcda *.gcno *.plist
12 14
15.PHONY: distclean
13distclean: clean 16distclean: clean
14 rm -fr Makefile 17 rm -fr Makefile
diff --git a/src/ftee/Makefile.in b/src/ftee/Makefile.in
index 32cdc63d3..05caf81be 100644
--- a/src/ftee/Makefile.in
+++ b/src/ftee/Makefile.in
@@ -1,3 +1,4 @@
1.PHONY: all
1all: ftee 2all: ftee
2 3
3include ../common.mk 4include ../common.mk
@@ -8,7 +9,9 @@ include ../common.mk
8ftee: $(OBJS) 9ftee: $(OBJS)
9 $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(EXTRA_LDFLAGS) 10 $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(EXTRA_LDFLAGS)
10 11
12.PHONY: clean
11clean:; rm -fr *.o ftee *.gcov *.gcda *.gcno *.plist 13clean:; rm -fr *.o ftee *.gcov *.gcda *.gcno *.plist
12 14
15.PHONY: distclean
13distclean: clean 16distclean: clean
14 rm -fr Makefile 17 rm -fr Makefile
diff --git a/src/jailtest/Makefile.in b/src/jailtest/Makefile.in
index 9c9c0c508..6306d24ec 100644
--- a/src/jailtest/Makefile.in
+++ b/src/jailtest/Makefile.in
@@ -1,3 +1,4 @@
1.PHONY: all
1all: jailtest 2all: jailtest
2 3
3include ../common.mk 4include ../common.mk
@@ -8,7 +9,9 @@ include ../common.mk
8jailtest: $(OBJS) 9jailtest: $(OBJS)
9 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o ../lib/pid.o $(LIBS) $(EXTRA_LDFLAGS) 10 $(CC) $(LDFLAGS) -o $@ $(OBJS) ../lib/common.o ../lib/pid.o $(LIBS) $(EXTRA_LDFLAGS)
10 11
12.PHONY: clean
11clean:; rm -fr *.o jailtest *.gcov *.gcda *.gcno *.plist 13clean:; rm -fr *.o jailtest *.gcov *.gcda *.gcno *.plist
12 14
15.PHONY: distclean
13distclean: clean 16distclean: clean
14 rm -fr Makefile 17 rm -fr Makefile
diff --git a/src/lib/Makefile.in b/src/lib/Makefile.in
index 681252832..49c8057b3 100644
--- a/src/lib/Makefile.in
+++ b/src/lib/Makefile.in
@@ -1,11 +1,14 @@
1include ../common.mk 1include ../common.mk
2 2
3.PHONY: all
3all: $(OBJS) 4all: $(OBJS)
4 5
5%.o : %.c $(H_FILE_LIST) 6%.o : %.c $(H_FILE_LIST)
6 $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(INCLUDE) -c $< -o $@ 7 $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(INCLUDE) -c $< -o $@
7 8
9.PHONY: clean
8clean:; rm -fr $(OBJS) *.gcov *.gcda *.gcno *.plist 10clean:; rm -fr $(OBJS) *.gcov *.gcda *.gcno *.plist
9 11
12.PHONY: distclean
10distclean: clean 13distclean: clean
11 rm -fr Makefile 14 rm -fr Makefile
diff --git a/src/libpostexecseccomp/Makefile.in b/src/libpostexecseccomp/Makefile.in
index edd4534b8..e3e5716ca 100644
--- a/src/libpostexecseccomp/Makefile.in
+++ b/src/libpostexecseccomp/Makefile.in
@@ -11,6 +11,7 @@ BINOBJS = $(foreach file, $(OBJS), $file)
11CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIC -Wformat -Wformat-security 11CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIC -Wformat -Wformat-security
12LDFLAGS += -pie -fPIE -Wl,-z,relro -Wl,-z,now 12LDFLAGS += -pie -fPIE -Wl,-z,relro -Wl,-z,now
13 13
14.PHONY: all
14all: libpostexecseccomp.so 15all: libpostexecseccomp.so
15 16
16%.o : %.c $(H_FILE_LIST) ../include/seccomp.h ../include/rundefs.h 17%.o : %.c $(H_FILE_LIST) ../include/seccomp.h ../include/rundefs.h
@@ -19,7 +20,9 @@ all: libpostexecseccomp.so
19libpostexecseccomp.so: $(OBJS) 20libpostexecseccomp.so: $(OBJS)
20 $(CC) $(LDFLAGS) -shared -fPIC -z relro -o $@ $(OBJS) -ldl 21 $(CC) $(LDFLAGS) -shared -fPIC -z relro -o $@ $(OBJS) -ldl
21 22
23.PHONY: clean
22clean:; rm -fr $(OBJS) libpostexecseccomp.so *.plist 24clean:; rm -fr $(OBJS) libpostexecseccomp.so *.plist
23 25
26.PHONY: distclean
24distclean: clean 27distclean: clean
25 rm -fr Makefile 28 rm -fr Makefile
diff --git a/src/libtrace/Makefile.in b/src/libtrace/Makefile.in
index 5c7d0f885..095037569 100644
--- a/src/libtrace/Makefile.in
+++ b/src/libtrace/Makefile.in
@@ -11,6 +11,7 @@ BINOBJS = $(foreach file, $(OBJS), $file)
11CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIC -Wformat -Wformat-security 11CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIC -Wformat -Wformat-security
12LDFLAGS += -pie -fPIE -Wl,-z,relro -Wl,-z,now 12LDFLAGS += -pie -fPIE -Wl,-z,relro -Wl,-z,now
13 13
14.PHONY: all
14all: libtrace.so 15all: libtrace.so
15 16
16%.o : %.c $(H_FILE_LIST) 17%.o : %.c $(H_FILE_LIST)
@@ -19,8 +20,9 @@ all: libtrace.so
19libtrace.so: $(OBJS) 20libtrace.so: $(OBJS)
20 $(CC) $(LDFLAGS) -shared -fPIC -z relro -o $@ $(OBJS) -ldl 21 $(CC) $(LDFLAGS) -shared -fPIC -z relro -o $@ $(OBJS) -ldl
21 22
22 23.PHONY: clean
23clean:; rm -fr $(OBJS) libtrace.so *.plist 24clean:; rm -fr $(OBJS) libtrace.so *.plist
24 25
26.PHONY: distclean
25distclean: clean 27distclean: clean
26 rm -fr Makefile 28 rm -fr Makefile
diff --git a/src/libtracelog/Makefile.in b/src/libtracelog/Makefile.in
index b1ac9e57c..5bac19c04 100644
--- a/src/libtracelog/Makefile.in
+++ b/src/libtracelog/Makefile.in
@@ -11,6 +11,7 @@ BINOBJS = $(foreach file, $(OBJS), $file)
11CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIC -Wformat -Wformat-security 11CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIC -Wformat -Wformat-security
12LDFLAGS += -pie -fPIE -Wl,-z,relro -Wl,-z,now 12LDFLAGS += -pie -fPIE -Wl,-z,relro -Wl,-z,now
13 13
14.PHONY: all
14all: libtracelog.so 15all: libtracelog.so
15 16
16%.o : %.c $(H_FILE_LIST) ../include/rundefs.h 17%.o : %.c $(H_FILE_LIST) ../include/rundefs.h
@@ -19,8 +20,9 @@ all: libtracelog.so
19libtracelog.so: $(OBJS) 20libtracelog.so: $(OBJS)
20 $(CC) $(LDFLAGS) -shared -fPIC -z relro -o $@ $(OBJS) -ldl 21 $(CC) $(LDFLAGS) -shared -fPIC -z relro -o $@ $(OBJS) -ldl
21 22
22 23.PHONY: clean
23clean:; rm -fr $(OBJS) libtracelog.so *.plist 24clean:; rm -fr $(OBJS) libtracelog.so *.plist
24 25
26.PHONY: distclean
25distclean: clean 27distclean: clean
26 rm -fr Makefile 28 rm -fr Makefile
diff --git a/src/man/Makefile.in b/src/man/Makefile.in
index 1a1f8ba08..3711d5cec 100644
--- a/src/man/Makefile.in
+++ b/src/man/Makefile.in
@@ -1,10 +1,14 @@
1.PHONY: all
1all: firecfg.man firejail.man firejail-login.man firejail-users.man firejail-profile.man firemon.man jailtest.man 2all: firecfg.man firejail.man firejail-login.man firejail-users.man firejail-profile.man firemon.man jailtest.man
3
2include ../common.mk 4include ../common.mk
3 5
4%.man: %.txt 6%.man: %.txt
5 gawk -f ./preproc.awk -- $(MANFLAGS) < $< > $@ 7 gawk -f ./preproc.awk -- $(MANFLAGS) < $< > $@
6 8
9.PHONY: clean
7clean:; rm -fr *.man 10clean:; rm -fr *.man
8 11
12.PHONY: distclean
9distclean: clean 13distclean: clean
10 rm -fr Makefile 14 rm -fr Makefile
diff --git a/src/man/firejail-profile.txt b/src/man/firejail-profile.txt
index c7dc4c434..b0b390507 100644
--- a/src/man/firejail-profile.txt
+++ b/src/man/firejail-profile.txt
@@ -103,7 +103,7 @@ Example: "?HAS_APPIMAGE: whitelist ${HOME}/special/appimage/dir"
103 103
104This example will load the whitelist profile line only if the \-\-appimage option has been specified on the command line. 104This example will load the whitelist profile line only if the \-\-appimage option has been specified on the command line.
105 105
106Currently the only conditionals supported this way are HAS_APPIMAGE, HAS_NET, HAS_NODBUS, HAS_NOSOUND and HAS_X11. The conditionals BROWSER_DISABLE_U2F and BROWSER_ALLOW_DRM 106Currently the only conditionals supported this way are HAS_APPIMAGE, HAS_NET, HAS_NODBUS, HAS_NOSOUND, HAS_PRIVATE and HAS_X11. The conditionals BROWSER_DISABLE_U2F and BROWSER_ALLOW_DRM
107can be enabled or disabled globally in Firejail's configuration file. 107can be enabled or disabled globally in Firejail's configuration file.
108 108
109The profile line may be any profile line that you would normally use in a profile \fBexcept\fR for "quiet" and "include" lines. 109The profile line may be any profile line that you would normally use in a profile \fBexcept\fR for "quiet" and "include" lines.
@@ -266,7 +266,7 @@ Mount new /root and /home/user directories in temporary
266filesystems. All modifications are discarded when the sandbox is 266filesystems. All modifications are discarded when the sandbox is
267closed. 267closed.
268.TP 268.TP
269\fBprivate=directory 269\fBprivate directory
270Use directory as user home. 270Use directory as user home.
271.TP 271.TP
272\fBprivate-bin file,file 272\fBprivate-bin file,file
diff --git a/src/man/firejail.txt b/src/man/firejail.txt
index 9e89d4e79..68deb85ec 100644
--- a/src/man/firejail.txt
+++ b/src/man/firejail.txt
@@ -42,6 +42,15 @@ Miscellaneous:
42firejail {\-? | \-\-debug-caps | \-\-debug-errnos | \-\-debug-syscalls | \-\-debug-syscalls32 | \-\-debug-protocols | \-\-help | \-\-version} 42firejail {\-? | \-\-debug-caps | \-\-debug-errnos | \-\-debug-syscalls | \-\-debug-syscalls32 | \-\-debug-protocols | \-\-help | \-\-version}
43.RE 43.RE
44.SH DESCRIPTION 44.SH DESCRIPTION
45#ifdef HAVE_LTS
46This is Firejail long-term support (LTS), an enterprise focused version of the software,
47LTS is usually supported for two or three years.
48During this time only bugs and the occasional documentation problems are fixed.
49The attack surface of the SUID executable was greatly reduced by removing some of the features.
50.br
51
52.br
53#endif
45Firejail is a SUID sandbox program that reduces the risk of security breaches by 54Firejail is a SUID sandbox program that reduces the risk of security breaches by
46restricting the running environment of untrusted applications using Linux 55restricting the running environment of untrusted applications using Linux
47namespaces, seccomp-bpf and Linux capabilities. 56namespaces, seccomp-bpf and Linux capabilities.
@@ -146,12 +155,6 @@ $ firejail --appimage --private krita-3.0-x86_64.appimage
146$ firejail --appimage --net=none --x11 krita-3.0-x86_64.appimage 155$ firejail --appimage --net=none --x11 krita-3.0-x86_64.appimage
147#endif 156#endif
148.TP 157.TP
149\fB\-\-audit
150Audit the sandbox, see \fBAUDIT\fR section for more details.
151.TP
152\fB\-\-audit=test-program
153Audit the sandbox, see \fBAUDIT\fR section for more details.
154.TP
155\fB\-\-bandwidth=name|pid 158\fB\-\-bandwidth=name|pid
156Set bandwidth limits for the sandbox identified by name or PID, see \fBTRAFFIC SHAPING\fR section for more details. 159Set bandwidth limits for the sandbox identified by name or PID, see \fBTRAFFIC SHAPING\fR section for more details.
157.TP 160.TP
@@ -1105,6 +1108,26 @@ Example:
1105$ firejail \-\-machine-id 1108$ firejail \-\-machine-id
1106 1109
1107.TP 1110.TP
1111\fB\-\-mkdir=dirname
1112Create a directory in user home. Parent directories are created as needed.
1113.br
1114
1115.br
1116Example:
1117.br
1118$ firejail --mkdir=~/work/project
1119
1120.TP
1121\fB\-\-mkfile=filename
1122Create an empty file in user home.
1123.br
1124
1125.br
1126Example:
1127.br
1128$ firejail --mkfile=~/work/project/readme
1129
1130.TP
1108\fB\-\-memory-deny-write-execute 1131\fB\-\-memory-deny-write-execute
1109Install a seccomp filter to block attempts to create memory mappings 1132Install a seccomp filter to block attempts to create memory mappings
1110that are both writable and executable, to change mappings to be 1133that are both writable and executable, to change mappings to be
@@ -1622,6 +1645,7 @@ Disable video devices.
1622\fB\-\-nowhitelist=dirname_or_filename 1645\fB\-\-nowhitelist=dirname_or_filename
1623Disable whitelist for this directory or file. 1646Disable whitelist for this directory or file.
1624 1647
1648#ifdef HAVE_OUTPUT
1625.TP 1649.TP
1626\fB\-\-output=logfile 1650\fB\-\-output=logfile
1627stdout logging and log rotation. Copy stdout to logfile, and keep the size of the file under 500KB using log 1651stdout logging and log rotation. Copy stdout to logfile, and keep the size of the file under 500KB using log
@@ -1652,6 +1676,7 @@ $ ls -l sandboxlog*
1652.TP 1676.TP
1653\fB\-\-output-stderr=logfile 1677\fB\-\-output-stderr=logfile
1654Similar to \-\-output, but stderr is also stored. 1678Similar to \-\-output, but stderr is also stored.
1679#endif
1655 1680
1656#ifdef HAVE_OVERLAYFS 1681#ifdef HAVE_OVERLAYFS
1657.TP 1682.TP
@@ -2451,7 +2476,7 @@ $ firejail --seccomp.print=browser
2451$ 2476$
2452 2477
2453.TP 2478.TP
2454\fB\-\-seccomp-error-action= kill | ERRNO 2479\fB\-\-seccomp-error-action= kill | ERRNO | log
2455By default, if a seccomp filter blocks a system call, the process gets 2480By default, if a seccomp filter blocks a system call, the process gets
2456EPERM as the error. With \-\-seccomp-error-action=error, another error 2481EPERM as the error. With \-\-seccomp-error-action=error, another error
2457number can be returned, for example ENOSYS or EACCES. The process can 2482number can be returned, for example ENOSYS or EACCES. The process can
@@ -2941,30 +2966,6 @@ To enable AppArmor confinement on top of your current Firejail security features
2941$ firejail --apparmor firefox 2966$ firejail --apparmor firefox
2942#endif 2967#endif
2943 2968
2944.SH AUDIT
2945Audit feature allows the user to point out gaps in security profiles. The
2946implementation replaces the program to be sandboxed with a test program. By
2947default, we use faudit program distributed with Firejail. A custom test program
2948can also be supplied by the user. Examples:
2949
2950Running the default audit program:
2951.br
2952 $ firejail --audit transmission-gtk
2953
2954Running a custom audit program:
2955.br
2956 $ firejail --audit=~/sandbox-test transmission-gtk
2957
2958In the examples above, the sandbox configures transmission-gtk profile and
2959starts the test program. The real program, transmission-gtk, will not be
2960started.
2961
2962You can also audit a specific profile without specifying a program.
2963.br
2964 $ firejail --audit --profile=/etc/firejail/zoom.profile
2965
2966Limitations: audit feature is not implemented for --x11 commands.
2967
2968.SH DESKTOP INTEGRATION 2969.SH DESKTOP INTEGRATION
2969A symbolic link to /usr/bin/firejail under the name of a program, will start the program in Firejail sandbox. 2970A symbolic link to /usr/bin/firejail under the name of a program, will start the program in Firejail sandbox.
2970The symbolic link should be placed in the first $PATH position. On most systems, a good place 2971The symbolic link should be placed in the first $PATH position. On most systems, a good place
diff --git a/src/man/jailtest.txt b/src/man/jailtest.txt
index 1b64097ea..b52fc5eed 100644
--- a/src/man/jailtest.txt
+++ b/src/man/jailtest.txt
@@ -14,7 +14,7 @@ These directories are build by firejail at startup using --private* and --whitel
14.TP 14.TP
15\fB2. Noexec test 15\fB2. Noexec test
16jailtest inserts executable programs in /home/username, /tmp, and /var/tmp directories 16jailtest inserts executable programs in /home/username, /tmp, and /var/tmp directories
17and tries to run them form inside the sandbox, thus testing if the directory is executable or not. 17and tries to run them from inside the sandbox, thus testing if the directory is executable or not.
18.TP 18.TP
19\fB3. Read access test 19\fB3. Read access test
20jailtest creates test files in the directories specified by the user and tries to read 20jailtest creates test files in the directories specified by the user and tries to read
@@ -29,10 +29,10 @@ The program is started as root using sudo.
29.SH OPTIONS 29.SH OPTIONS
30.TP 30.TP
31\fB\-\-debug 31\fB\-\-debug
32Print debug messages 32Print debug messages.
33.TP 33.TP
34\fB\-?\fR, \fB\-\-help\fR 34\fB\-?\fR, \fB\-\-help\fR
35Print options end exit. 35Print options and exit.
36.TP 36.TP
37\fB\-\-version 37\fB\-\-version
38Print program version and exit. 38Print program version and exit.
diff --git a/src/profstats/Makefile.in b/src/profstats/Makefile.in
index 2beaa3ed6..e025f5939 100644
--- a/src/profstats/Makefile.in
+++ b/src/profstats/Makefile.in
@@ -1,3 +1,4 @@
1.PHONY: all
1all: profstats 2all: profstats
2 3
3include ../common.mk 4include ../common.mk
@@ -8,7 +9,9 @@ include ../common.mk
8profstats: $(OBJS) 9profstats: $(OBJS)
9 $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(EXTRA_LDFLAGS) 10 $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(EXTRA_LDFLAGS)
10 11
12.PHONY: clean
11clean:; rm -fr *.o profstats *.gcov *.gcda *.gcno *.plist 13clean:; rm -fr *.o profstats *.gcov *.gcda *.gcno *.plist
12 14
15.PHONY: distclean
13distclean: clean 16distclean: clean
14 rm -fr Makefile 17 rm -fr Makefile
diff --git a/src/zsh_completion/Makefile.in b/src/zsh_completion/Makefile.in
index 3f756aa5f..a83cccf6c 100644
--- a/src/zsh_completion/Makefile.in
+++ b/src/zsh_completion/Makefile.in
@@ -1,3 +1,4 @@
1.PHONY: all
1all: _firejail 2all: _firejail
2 3
3include ../common.mk 4include ../common.mk
@@ -7,8 +8,10 @@ _firejail: _firejail.in
7 sed "s|_SYSCONFDIR_|$(sysconfdir)|" < $@.tmp > $@ 8 sed "s|_SYSCONFDIR_|$(sysconfdir)|" < $@.tmp > $@
8 rm $@.tmp 9 rm $@.tmp
9 10
11.PHONY: clean
10clean: 12clean:
11 rm -fr _firejail 13 rm -fr _firejail
12 14
15.PHONY: distclean
13distclean: clean 16distclean: clean
14 rm -fr Makefile 17 rm -fr Makefile
diff --git a/src/zsh_completion/_firejail.in b/src/zsh_completion/_firejail.in
index 7e8df138e..fd27bb35f 100644
--- a/src/zsh_completion/_firejail.in
+++ b/src/zsh_completion/_firejail.in
@@ -1,5 +1,8 @@
1#compdef firejail 1#compdef firejail
2 2
3# Documentation: man 1 zshcompsys
4# HowTo: https://github.com/zsh-users/zsh-completions/blob/master/zsh-completions-howto.org
5
3_all_firejails() { 6_all_firejails() {
4 local -a _all_firejails_list 7 local -a _all_firejails_list
5 for jail in ${(f)"$(_call_program modules_tag "firejail --list 2> /dev/null | cut -d: -f1")"}; do 8 for jail in ${(f)"$(_call_program modules_tag "firejail --list 2> /dev/null | cut -d: -f1")"}; do
@@ -16,7 +19,7 @@ _all_cpus() {
16} 19}
17 20
18_profiles() { 21_profiles() {
19 print $1/*.profile | sed -E "s;^$1/;;g;s;\.profile$;;g;" 22 print $1/*.profile | sed -E "s;$1/;;g;s;\.profile;;g;"
20} 23}
21_profiles_with_ext() { 24_profiles_with_ext() {
22 print $1/*.profile 25 print $1/*.profile
@@ -26,15 +29,40 @@ _all_profiles() {
26 _values 'profiles' $(_profiles _SYSCONFDIR_/firejail) $(_profiles $HOME/.config/firejail) $(_profiles_with_ext .) 29 _values 'profiles' $(_profiles _SYSCONFDIR_/firejail) $(_profiles $HOME/.config/firejail) $(_profiles_with_ext .)
27} 30}
28 31
32_session_bus_names() {
33 _values names $(busctl --user list --no-legend --activatable | cut -d" " -f1)
34 # Alternatives to hack on for non-systemd systems:
35 # dbus-send --session --dest=org.freedesktop.DBus --type=method_call --print-reply=literal /org/freedesktop/DBus org.freedesktop.DBus.ListNames
36 # ls /usr/share/dbus-1/services | xargs -I FILENAME basename FILENAME .service
37}
38
39_system_bus_names() {
40 _values names $(busctl --system list --no-legend --activatable | cut -d" " -f1)
41}
42
43_caps() {
44 _values -s "," caps $(firejail --debug-caps | awk '/[0-9]+\s*- /{print $3}')
45}
46
29_firejail_args=( 47_firejail_args=(
30 '*::arguments:_normal' 48 '*::arguments:_normal'
31 '(--profile)'{--profile=,--profile=}'[use a custom profile]: :_all_profiles' 49
32 '--caps[enable default Linux capabilities filter]' 50 '--appimage[sandbox an AppImage application]'
33 '(--caps.drop)'{--caps.drop=,--caps.drop=}'[drop capabilities: all|cap1,cap2,...]: :->caps_drop' 51 '--build[build a whitelisted profile for the application and print it on stdout]'
34 '(--caps.keep)'{--caps.keep=,--caps.keep=}'[keep capabilities: cap1,cap2,...]: :->caps_keep' 52 '--build=-[build a whitelisted profile for the application and save it]: :_files'
35 '(--caps.print)'{--caps.print=,--caps.print=}'[print the caps filter name|pid]:firejail:_all_firejails' 53 # Ignore that you can do -? too as it's the only short option
36 '--allow-debuggers[allow tools such as strace and gdb inside the sandbox]' 54 '--help[this help screen]'
37 '(--debug)'{--debug,--debug}'[print sandbox debug messages]' 55 '--join=-[join the sandbox name|pid]: :_all_firejails'
56 '--join-filesystem=-[join the mount namespace name|pid]: :_all_firejails'
57 '--list[list all sandboxes]'
58 '(--profile)--noprofile[do not use a security profile]'
59 '(--noprofile)--profile=-[use a custom profile]: :_all_profiles'
60 '--shutdown=-[shutdown the sandbox identified by name|pid]: :_all_firejails'
61 '--top[monitor the most CPU-intensive sandboxes]'
62 '--tree[print a tree of all sandboxed processes]'
63 '--version[print program version and exit]'
64
65 '--debug[print sandbox debug messages]'
38 '--debug-blacklists[debug blacklisting]' 66 '--debug-blacklists[debug blacklisting]'
39 '--debug-caps[print all recognized capabilities]' 67 '--debug-caps[print all recognized capabilities]'
40 '--debug-errnos[print all recognized error numbers]' 68 '--debug-errnos[print all recognized error numbers]'
@@ -43,197 +71,200 @@ _firejail_args=(
43 '--debug-syscalls[print all recognized system calls]' 71 '--debug-syscalls[print all recognized system calls]'
44 '--debug-syscalls32[print all recognized 32 bit system calls]' 72 '--debug-syscalls32[print all recognized 32 bit system calls]'
45 '--debug-whitelists[debug whitelisting]' 73 '--debug-whitelists[debug whitelisting]'
46 # Ignore that you can do -? too as it's the only short option 74
47 '(--help)'{--help,--help}'[this help screen]' 75 '--caps.print=-[print the caps filter name|pid]:firejail:_all_firejails'
76 '--cpu.print=-[print the cpus in use name|pid]: :_all_firejails'
77 '--fs.print=-[print the filesystem log name|pid]: :_all_firejails'
78 '--profile.print=-[print the name of profile file name|pid]: :_all_firejails'
79 '--protocol.print=-[print the protocol filter name|pid]: :_all_firejails'
80 '--seccomp.print=-[print the seccomp filter for the sandbox identified by name|pid]: :_all_firejails'
81
82 '--allow-debuggers[allow tools such as strace and gdb inside the sandbox]'
48 '--allusers[all user home directories are visible inside the sandbox]' 83 '--allusers[all user home directories are visible inside the sandbox]'
49 '--appimage[sandbox an AppImage application]' 84 # Should be _files, a comma and files or files -/
50 '--private[temporary home directory]' 85 '*--bind=-[mount-bind dirname1/filename1 on top of dirname2/filename2]: :(file1,file2 dir1,dir2)'
51 '(--private)'{--private=,--private=}'[use directory as user home]: : _files -/' 86 '*--blacklist=-[blacklist directory or file]: :_files'
52 '--seccomp[enable seccomp filter and apply the default blacklist]' 87 '--caps[enable default Linux capabilities filter]'
53 '(--seccomp=)'{--seccomp=,--seccomp=}'[enable seccomp filter, blacklist the default syscall list and the syscalls specified by the command]:' 88 '--caps.drop=all[drop all capabilities]'
54 '(--seccomp.print)'{--seccomp.print=,--seccomp.print=}'[print the seccomp filter for the sandbox identified by name|pid]: : _all_firejails' 89 '*--caps.drop=-[drop capabilities: all|cap1,cap2,...]: :_caps'
55 '--seccomp.block-secondary[build only the native architecture filters]' 90 '*--caps.keep=-[keep capabilities: cap1,cap2,...]: :_caps'
56 '(--seccomp.drop)'{--seccomp.drop=,--seccomp.drop=}'[enable seccomp filter, and blacklist the syscalls specified by the command]: :' 91 '--cgroup=-[place the sandbox in the specified control group]: :'
57 '(--seccomp.keep)'{--seccomp.keep=,--seccomp.keep=}'[enable seccomp filter, and whitelist the syscalls specified by the command]: :' 92 '--cpu=-[set cpu affinity]: :->cpus'
58 '(--seccomp.32.drop)'{--seccomp.32.drop=,--seccomp.32.drop=}'[enable seccomp filter, and blacklist the 32 bit syscalls specified by the command]: :' 93 "--deterministic-exit-code[always exit with first child's status code]"
59 '(--seccomp.32.keep)'{--seccomp.32.keep=,--seccomp.32.keep=}'[enable seccomp filter, and whitelist the 32 bit syscalls specified by the command]: :' 94 '*--dns=-[set DNS server]: :'
60 '(--seccomp-error-action)'{--seccomp-error-action=,--seccomp-error-action=}'[change error code, kill process or log the attempt]: :(ERRNO kill log)' 95 '*--env=-[set environment variable]: :'
96 '--hostname=-[set sandbox hostname]: :'
97 '--hosts-file=-[use file as /etc/hosts]: :_files'
98 '*--ignore=-[ignore command in profile files]: :'
99 '--ipc-namespace[enable a new IPC namespace]'
100 '--join-or-start=-[join the sandbox or start a new one name|pid]: :_all_firejails'
101 '--keep-dev-shm[/dev/shm directory is untouched (even with --private-dev)]'
102 '--keep-var-tmp[/var/tmp directory is untouched]'
103 '--machine-id[preserve /etc/machine-id]'
61 '--memory-deny-write-execute[seccomp filter to block attempts to create memory mappings that are both writable and executable]' 104 '--memory-deny-write-execute[seccomp filter to block attempts to create memory mappings that are both writable and executable]'
62 '*'{--blacklist=,--blacklist=}'[blacklist directory or file]: : _files' 105 '*--mkdir=-[create a directory]:'
63 '--writable-etc[/etc directory is mounted read-write]' 106 '*--mkfile=-[create a file]:'
64 '--writable-run-user[allow access to /run/user/$UID/systemd and /run/user/$UID/gnupg]' 107 '--name=-[set sandbox name]: :'
65 '--writable-var[/var directory is mounted read-write]' 108 '--net=none[enable a new, unconnected network namespace]'
66 '--writable-var-log[use the real /var/log directory, not a clone]' 109 # Sample values as I don't think
67 '--build[build a whitelisted profile for the application and print it on stdout]' 110 # many would enjoy getting a list from -20..20
68 '(--build)'{--build=,--build=}'[build a whitelisted profile for the application and save it]: : _files' 111 '--nice=-[set nice value]: :(1 10 15 20)'
69 '(--fs.print)'{--fs.print=,--fs.print=}'[print the filesystem log name|pid]: : _all_firejails'
70 '(--join)'{--join=,--join=}'[join the sandbox name|pid]: : _all_firejails'
71 '(--join-filesystem)'{--join-filesystem=,--join-filesystem=}'[join the mount namespace name|pid]: : _all_firejails'
72 '(--profile.print)'{--profile.print=,--profile.print=}'[print the name of profile file name|pid]: : _all_firejails'
73 '(--protocol.print)'{--protocol.print=,--protocol.print=}'[print the protocol filter name|pid]: : _all_firejails'
74 '(--shutdown)'{--shutdown=,--shutdown=}'[shutdown the sandbox identified by name|pid]: : _all_firejails'
75 '(--cat)'{--cat=,--cat=}'[print content of file from sandbox container name|pid]: : _all_firejails'
76 '(--cpu.print)'{--cpu.print=,--cpu.print=}'[print the cpus in use name|pid]: : _all_firejails'
77 '--list[list all sandboxes]'
78 '(--dns)'{--dns=,--dns=}'[set DNS server]: :'
79 '(--protocol)'{--protocol=,--protocol=}'[enable protocol filter]: :'
80 '(--join-or-start)'{--join-or-start=,--join-or-start=}'[join the sandbox or start a new one name|pid]: : _all_firejails'
81 '(--hosts-file)'{--hosts-file=,--hosts-file=}'[use file as /etc/hosts]: : _files'
82 '--shell=none[run the program directly without a user shell]'
83 '(--shell)'{--shell=,--shell=}'[set default user shell]: : _files -g "*(*)"'
84 '(--output)'{--output=,--output=}'[stdout logging and log rotation]: : _files'
85 '(--output-stderr)'{--output-stderr=,--output-stderr=}'[stdout and stderr logging and log rotation]: : _files'
86 '--no3d[disable 3D hardware acceleration]' 112 '--no3d[disable 3D hardware acceleration]'
113 '--noautopulse[disable automatic ~/.config/pulse init]'
114 '--noblacklist=-[disable blacklist for file or directory]: :_files'
115 '--nodbus[disable D-Bus access]'
87 '--nodvd[disable DVD and audio CD devices]' 116 '--nodvd[disable DVD and audio CD devices]'
117 '*--noexec=-[remount the file or directory noexec nosuid and nodev]: :_files'
88 '--nogroups[disable supplementary groups]' 118 '--nogroups[disable supplementary groups]'
89 '--nonewprivs[sets the NO_NEW_PRIVS prctl]' 119 '--nonewprivs[sets the NO_NEW_PRIVS prctl]'
90 '--noprofile[do not use a security profile]' 120 '--nosound[disable sound system]'
91 '(--noexec)'{--noexec=,--noexec=}'[remount the file or directory noexec nosuid and nodev]: : _files' 121 '--nou2f[disable U2F devices]'
92 '--ipc-namespace[enable a new IPC namespace]' 122 '--novideo[disable video devices]'
93 '--keep-dev-shm[/dev/shm directory is untouched (even with --private-dev)]' 123 '--private[temporary home directory]'
94 '--keep-var-tmp[/var/tmp directory is untouched]' 124 '--private=-[use directory as user home]: :_files -/'
95 '--top[monitor the most CPU-intensive sandboxes]' 125 '--private-bin=-[build a new /bin in a temporary filesystem, and copy the programs in the list]: :_files -W /usr/bin'
96 '--trace[trace open, access and connect system calls]' 126 '--private-cwd[do not inherit working directory inside jail]'
97 '--tracelog[add a syslog message for every access to files or directories blacklisted by the security profile]' 127 '--private-cwd=-[set working directory inside jail]: :_files -/'
98 '--tree[print a tree of all sandboxed processes]'
99 '(--cpu)'{--cpu=,--cpu=}'[set cpu affinity]: :->cpus'
100 '--private-dev[create a new /dev directory with a small number of common device files]' 128 '--private-dev[create a new /dev directory with a small number of common device files]'
129 '(--writable-etc)--private-etc=-[build a new /etc in a temporary filesystem, and copy the files and directories in the list]: :_files -W /etc'
130 '--private-opt=-[build a new /opt in a temporary filesystem]: :_files -W /opt'
131 '--private-srv=-[build a new /srv in a temporary filesystem]: :_files -W /srv'
101 '--private-tmp[mount a tmpfs on top of /tmp directory]' 132 '--private-tmp[mount a tmpfs on top of /tmp directory]'
102 '--private-cwd[do not inherit working directory inside jail]' 133 '*--protocol=-[enable protocol filter]: :_values -s , protocols unix inet inet6 netlink packet bluetooth'
103 '(--private-cwd)'{--private-cwd=,--private-cwd=}'[set working directory inside jail]: : _files -/'
104 '*'{--read-only=,--read-only=}'[set directory or file read-only]: : _files'
105 '*'{--read-write=,--read-write=}'[set directory or file read-write]: : _files'
106 '(--tmpfs)'{--tmpfs=,--tmpfs=}'[mount a tmpfs filesystem on directory dirname]: : _files -/'
107 '(--private-etc)'{--private-etc=,--private-etc=}'[build a new /etc in a temporary filesystem, and copy the files and directories in the list]: : _files'
108 "--deterministic-exit-code[always exit with first child's status code]"
109 '--machine-id[preserve /etc/machine-id]'
110 # Sample values as I don't think
111 # many would enjoy getting a list from -20..20
112 '(--nice)'{--nice=,--nice=}'[set nice value]: :(1 10 15 20)'
113 # Should be _files, a comma and files or files -/
114 '*'{--bind=,--bind=}'[mount-bind dirname1/filename1 on top of dirname2/filename2]: :(file1,file2 dir1,dir2)'
115 '--audit[audit the sandbox]'
116 '(--audit)'{--audit=,--audit=}'[audit the sandbox with a test-program]: :'
117 '(--cgroup)'{--cgroup=,--cgroup=}'[place the sandbox in the specified control group]: :'
118 '*'{--env=,--env=}'[set environment variable]: :'
119 '(--hostname)'{--hostname=,--hostname=}'[set sandbox hostname]: :'
120 '(--ignore)'{--ignore=,--ignore=}'[ignore command in profile files]: :'
121 '(--name)'{--name=,--name=}'[set sandbox name]: :'
122 '(--rlimit-as)'{--rlimit-as=,--rlimit-as=}"[set the maximum size of the process's virtual memory (address space) in bytes]: :"
123 '(--rlimit-cpu)'{--rlimit-cpu=,--rlimit-cpu=}'[set the maximum CPU time in seconds]: :'
124 '(--rlimit-fsize)'{--rlimit-fsize=,--rlimit-fsize=}'[set the maximum file size that can be created by a process]: :'
125 '(--rlimit-nofile)'{--rlimit-nofile=,--rlimit-nofile=}'[set the maximum number of files that can be opened by a process]: :'
126 '(--rlimit-nproc)'{--rlimit-nproc=,--rlimit-nproc=}'[set the maximum number of processes that can be created for the real user ID of the calling process]: :'
127 '(--rlimit-sigpending)'{--rlimit-sigpending=,--rlimit-sigpending=}'[set the maximum number of pending signals for a process]: :'
128 '*'{--rmenv=,--rmenv=}'[remove environment variable in the new sandbox]: :'
129 '(--timeout)'{--timeout=,--timeout=}'[kill the sandbox automatically after the time has elapsed]: :(hh\:mm\:ss)'
130 "--quiet[turn off Firejail's output.]" 134 "--quiet[turn off Firejail's output.]"
131 '--version[print program version and exit]' 135 '*--read-only=-[set directory or file read-only]: :_files'
136 '*--read-write=-[set directory or file read-write]: :_files'
137 "--rlimit-as=-[set the maximum size of the process's virtual memory (address space) in bytes]: :"
138 '--rlimit-cpu=-[set the maximum CPU time in seconds]: :'
139 '--rlimit-fsize=-[set the maximum file size that can be created by a process]: :'
140 '--rlimit-nofile=-[set the maximum number of files that can be opened by a process]: :'
141 '--rlimit-nproc=-[set the maximum number of processes that can be created for the real user ID of the calling process]: :'
142 '--rlimit-sigpending=-[set the maximum number of pending signals for a process]: :'
143 '*--rmenv=-[remove environment variable in the new sandbox]: :_values environment-variables $(env | cut -d= -f1)'
144 '--seccomp[enable seccomp filter and apply the default blacklist]: :'
145 '--seccomp=-[enable seccomp filter, blacklist the default syscall list and the syscalls specified by the command]: :->seccomp'
146 '--seccomp.block-secondary[build only the native architecture filters]'
147 '*--seccomp.drop=-[enable seccomp filter, and blacklist the syscalls specified by the command]: :->seccomp'
148 '*--seccomp.keep=-[enable seccomp filter, and whitelist the syscalls specified by the command]: :->seccomp'
149 '*--seccomp.32.drop=-[enable seccomp filter, and blacklist the 32 bit syscalls specified by the command]: :'
150 '*--seccomp.32.keep=-[enable seccomp filter, and whitelist the 32 bit syscalls specified by the command]: :'
151 # FIXME: Add errnos
152 '--seccomp-error-action=-[change error code, kill process or log the attempt]: :(kill log)'
153 '--shell=none[run the program directly without a user shell]'
154 '--shell=-[set default user shell]: :_values $(cat /etc/shells)'
155 '--timeout=-[kill the sandbox automatically after the time has elapsed]: :'
156 #'(--tracelog)--trace[trace open, access and connect system calls]'
157 '(--tracelog)--trace=-[trace open, access and connect system calls]: :_files'
158 '(--trace)--tracelog[add a syslog message for every access to files or directories blacklisted by the security profile]'
159 '(--private-etc)--writable-etc[/etc directory is mounted read-write]'
160 '--writable-run-user[allow access to /run/user/$UID/systemd and /run/user/$UID/gnupg]'
161 '--writable-var[/var directory is mounted read-write]'
162 '--writable-var-log[use the real /var/log directory, not a clone]'
163
132#ifdef HAVE_APPARMOR 164#ifdef HAVE_APPARMOR
133 '--apparmor[enable AppArmor confinement]' 165 '--apparmor[enable AppArmor confinement]'
134 '(--apparmor.print=)'{--apparmor.print=,--apparmor.print=}'[print apparmor status name|pid]:firejail:_all_firejails' 166 '--apparmor.print=-[print apparmor status name|pid]:firejail:_all_firejails'
135#endif 167#endif
168
136#ifdef HAVE_CHROOT 169#ifdef HAVE_CHROOT
137 '(--chroot)'{--chroot=,--chroot=}'[chroot into directory]: : _files -/' 170 '(--noroot --overlay --overlay-named --overlay-tmpfs)--chroot=-[chroot into directory]: :_files -/'
138#endif 171#endif
172
173#ifdef HAVE_DBUSPROXY
174 # FIXME: _xx_bus_names is actually wrong for --dbus-*.{broadcast,call}.
175 # We can steal some function from https://github.com/systemd/systemd/blob/main/shell-completion/zsh/_busctl
176 '--dbus-log=-[set DBus log file location]: :_files'
177 '--dbus-system=-[set system DBus access policy]: :(filter none)'
178 '--dbus-system.broadcast=-[allow signals on the system DBus according to rule]: :_system_bus_names'
179 '--dbus-system.call=-[allow calls on the system DBus according to rule]: :_system_bus_names'
180 '--dbus-system.own=-[allow ownership of name on the system DBus]: :_system_bus_names'
181 '--dbus-system.see=-[allow seeing name on the system DBus]: :_system_bus_names'
182 '--dbus-system.talk=-[allow talking to name on the system DBus]: :_system_bus_names'
183 '--dbus-user=-[set session DBus access policy or none]: :(filter none)'
184 '--dbus-user.broadcast=-[allow signals on the session DBus according to rule]: :_session_bus_names'
185 '--dbus-user.call=-[allow calls on the session DBus according to rule]: :_session_bus_names'
186 '--dbus-user.own=-[allow ownership of name on the session DBus]: :_session_bus_names'
187 '--dbus-user.see=-[allow seeing name on the session DBus]: :_session_bus_names'
188 '--dbus-user.talk=-[allow talking to name on the session DBus]: :_session_bus_names'
189#endif
190
139#ifdef HAVE_FILE_TRANSFER 191#ifdef HAVE_FILE_TRANSFER
140 '(--get)'{--get=,--get=}'[get a file from sandbox container name|pid]: : _all_firejails' 192 '--cat=-[print content of file from sandbox container name|pid]: :_all_firejails'
193 '--get=-[get a file from sandbox container name|pid]: :_all_firejails'
141 # --put=name|pid src-filename dest-filename - put a file in sandbox container. 194 # --put=name|pid src-filename dest-filename - put a file in sandbox container.
142 '(--put)'{--put=,--put=}'[put a file in sandbox container]: :' 195 '--put=-[put a file in sandbox container]: :'
143 '(--ls)'{--ls=,--ls=}'[list files in sandbox container name|pid]: : _all_firejails' 196 '--ls=-[list files in sandbox container name|pid]: :_all_firejails'
197#endif
198
199#ifdef HAVE_FIRETUNNEL
200 '--tunnel=-[connect the sandbox to a tunnel created by firetunnel utility]: :'
144#endif 201#endif
202
145#ifdef HAVE_NETWORK 203#ifdef HAVE_NETWORK
146 # '--net=none[enable a new, unconnected network namespace]' 204 '--bandwidth=-[set bandwidth limits name|pid]: :_all_firejails'
147 '(--net)'{--net=,--net=}'[enable network namespaces and connect to this bridge or Ethernet interface (or none to disable)]: :->net_or_none' 205 '--defaultgw=[configure default gateway]: :'
148 '(--net.print)'{--net.print=,--net.print=}'[print network interface configuration name|pid]: : _all_firejails' 206 '--dns.print=-[print DNS configuration name|pid]: :_all_firejails'
149 '(--netfilter.print)'{--netfilter.print=,--netfilter.print=}'[print the firewall name|pid]: : _all_firejails' 207 '--join-network=-[join the network namespace name|pid]: :_all_firejails'
150 '(--netfilter6.print)'{--netfilter6.print=,--netfilter6.print=}'[print the IPv6 firewall name|pid]: : _all_firejails' 208 '--mac=-[set interface MAC address]: :(xx\:xx\:xx\:xx\:xx\:xx)'
209 '--mtu=-[set interface MTU]: :'
210 '--net=-[enable network namespaces and connect to this bridge or Ethernet interface (or none to disable)]: :->net_or_none'
211 '--net.print=-[print network interface configuration name|pid]: :_all_firejails'
212 '--netfilter=-[enable firewall]: :'
213 '--netfilter.print=-[print the firewall name|pid]: :_all_firejails'
214 '--netfilter6=-[enable IPv6 firewall]: :'
215 '--netfilter6.print=-[print the IPv6 firewall name|pid]: :_all_firejails'
216 '--netmask=-[define a network mask when dealing with unconfigured parrent interfaces]: :'
217 '--netns=-[Run the program in a named, persistent network namespace]: :'
151 '--netstats[monitor network statistics]' 218 '--netstats[monitor network statistics]'
152 '(--netmask)'{--netmask=,--netmask=}'[define a network mask when dealing with unconfigured parrent interfaces]: :' 219 '--interface=-[move interface in sandbox]: :'
153 '(--netns)'{--netns=,--netns=}'[Run the program in a named, persistent network namespace]: :' 220 '--ip=-[set interface IP address none|dhcp|ADDRESS]: :(none dhcp)'
154 '(--netfilter)'{--netfilter=,--netfilter=}'[enable firewall]: :' 221 '--ip6=-[set interface IPv6 address or use dhcp via dhclient]: :(dhcp)'
155 '(--netfilter6)'{--netfilter6=,--netfilter6=}'[enable IPv6 firewall]: :' 222 '--iprange=-[configure an IP address in this range]: :'
156 '(--veth-name)'{--veth-name=,--veth-name=}'[use this name for the interface connected to the bridge]: :'
157 '(--join-network)'{--join-network=,--join-network=}'[join the network namespace name|pid]: : _all_firejails'
158 '(--defaultgw)'{--defaultgw=,--defaultgw=}'[configure default gateway]: :'
159 '(--ip)'{--ip=,--ip=}'[set interface IP address none|dhcp|ADDRESS]: :(none dhcp)'
160 '(--dns.print)'{--dns.print=,--dns.print=}'[print DNS configuration name|pid]: : _all_firejails'
161 '(--interface)'{--interface=,--interface=}'[move interface in sandbox]: :'
162 '(--ip6)'{--ip6=,--ip6=}'[set interface IPv6 address or use dhcp via dhclient]: :(dhcp)'
163 '(--iprange)'{--iprange=,--iprange=}'[configure an IP address in this range]: :'
164 '(--mac)'{--mac=,--mac=}'[set interface MAC address]: :(xx\:xx\:xx\:xx\:xx\:xx)'
165 '(--mtu)'{--mtu=,--mtu=}'[set interface MTU]: :'
166 '--scan[ARP-scan all the networks from inside a network namespace]' 223 '--scan[ARP-scan all the networks from inside a network namespace]'
167 '(--bandwidth)'{--bandwidth=,--bandwidth=}'[set bandwidth limits name|pid]: : _all_firejails' 224 '--veth-name=-[use this name for the interface connected to the bridge]: :'
168#endif
169#ifdef HAVE_X11
170 '--x11[enable X11 sandboxing. The software checks first if Xpra is installed, then it checks if Xephyr is installed. If all fails, it will attempt to use X11 security extension]'
171 '(--x11)'{--x11=,--x11=}'[disable or enable specific X11 server]: :(none xephyr xorg xpra xvfb)'
172 '(--xephyr-screen)'{--xephyr-screen=,--xephyr-screen=}'[set screen size for --x11=xephyr]: :(WIDTHxHEIGHT)'
173#endif 225#endif
174#ifdef HAVE_USERNS 226
175 '--noroot[install a user namespace with only the current user]' 227#ifdef HAVE_OUTPUT
228 '--output=-[stdout logging and log rotation]: :_files'
229 '--output-stderr=-[stdout and stderr logging and log rotation]: :_files'
176#endif 230#endif
177 '--nosound[disable sound system]' 231
178 '--noautopulse[disable automatic ~/.config/pulse init]'
179 '--novideo[disable video devices]'
180 '--nou2f[disable U2F devices]'
181#ifdef HAVE_OVERLAYFS 232#ifdef HAVE_OVERLAYFS
182 '--overlay[mount a filesystem overlay on top of the current filesystem]' 233 '(--chroot --noroot)--overlay[mount a filesystem overlay on top of the current filesystem]'
183 '(--overlay-named)'{--overlay-named=,--overlay-named=}'[mount a filesystem overlay on top of the current filesystem, and store it in name directory]: : _files -/'
184 '--overlay-tmpfs[mount a temporary filesystem overlay on top of the current filesystem]'
185 '--overlay-clean[clean all overlays stored in $HOME/.firejail directory]' 234 '--overlay-clean[clean all overlays stored in $HOME/.firejail directory]'
235 '(--chroot --noroot)--overlay-named=-[mount a filesystem overlay on top of the current filesystem, and store it in name directory]: :_files -/'
236 '(--chroot --noroot)--overlay-tmpfs[mount a temporary filesystem overlay on top of the current filesystem]'
186#endif 237#endif
187#ifdef HAVE_WHITELIST 238
188 '(--nowhitelist)'{--nowhitelist=,--nowhitelist=}'[disable whitelist for file or directory]: : _files'
189 '*'{--whitelist=,--whitelist=}'[whitelist directory or file]: : _files'
190#endif
191 '(--noblacklist)'{--noblacklist=,--noblacklist=}'[disable blacklist for file or directory]: : _files'
192#ifdef HAVE_DBUSPROXY
193 '(--dbus-system)'{--dbus-system=,--dbus-system=}'[set system DBus access policy or none]: :'
194 '(--dbus-system.broadcast)'{--dbus-system.broadcast=,--dbus-system.broadcast=}'[allow signals on the system DBus according to rule]: :'
195 '(--dbus-system.call)'{--dbus-system.call=,--dbus-system.call=}'[allow calls on the system DBus according to rule]: :'
196 '(--dbus-system.own)'{--dbus-system.own=,--dbus-system.own=}'[allow ownership of name on the system DBus]: :'
197 '(--dbus-system.see)'{--dbus-system.see=,--dbus-system.see=}'[allow seeing name on the system DBus]: :'
198 '(--dbus-system.talk)'{--dbus-system.talk=,--dbus-system.talk=}'[allow talking to name on the system DBus]: :'
199 '(--dbus-user)'{--dbus-user=,--dbus-user=}'[set session DBus access policy or none]: :'
200 '(--dbus-user.broadcast)'{--dbus-user.broadcast=,--dbus-user.broadcast=}'[allow signals on the session DBus according to rule]: :'
201 '(--dbus-user.call)'{--dbus-user.call=,--dbus-user.call=}'[allow calls on the session DBus according to rule]: :'
202 '(--dbus-user.see)'{--dbus-user.see=,--dbus-user.see=}'[allow seeing name on the session DBus]: :'
203 '(--dbus-user.talk)'{--dbus-user.talk=,--dbus-user.talk=}'[allow talking to name on the session DBus]: :'
204 '(--dbus-log)'{--dbus-log=,--dbus-log=}'[set DBus log file location]: : _files'
205 '(--dbus-system)'{--dbus-system=,--dbus-system=}'[set system DBus access policy]: :(filter none)'
206 '--dbus-user.log[turn on logging for the user DBus]'
207 '(--dbus-user.own)'{--dbus-user.own=,--dbus-user.own=}'[allow ownership of name on the session DBus]: :'
208 '--dbus-system.log[turn on logging for the system DBus]'
209 '--nodbus[disable D-Bus access]'
210#endif
211#ifdef HAVE_PRIVATE_HOME 239#ifdef HAVE_PRIVATE_HOME
212 '(--private-home)'{--private-home=,--private-home=}'[build a new user home in a temporary filesystem, and copy the files and directories in the list in the new home]: :' 240 '--private-home=-[build a new user home in a temporary filesystem, and copy the files and directories in the list in the new home]: :_files'
241#endif
242
243#ifdef HAVE_USERNS
244 '(--chroot --overlay --overlay-named --overlay-tmpfs)--noroot[install a user namespace with only the current user]'
213#endif 245#endif
214 '(--private-bin)'{--private-bin=,--private-bin=}'[build a new /bin in a temporary filesystem, and copy the programs in the list]: :' 246
215 '(--private-opt)'{--private-opt=,--private-opt=}'[build a new /opt in a temporary filesystem]: :'
216 '(--private-srv)'{--private-srv=,--private-srv=}'[build a new /srv in a temporary filesystem]: :'
217#ifdef HAVE_USERTMPFS 247#ifdef HAVE_USERTMPFS
218 '--private-cache[temporary ~/.cache directory]' 248 '--private-cache[temporary ~/.cache directory]'
249 '*--tmpfs=-[mount a tmpfs filesystem on directory dirname]: :_files -/'
219#endif 250#endif
220#ifdef HAVE_FIRETUNNEL 251
221 '(--tunnel)'{--tunnel=,--tunnel=}'[connect the sandbox to a tunnel created by firetunnel utility]: :' 252#ifdef HAVE_WHITELIST
253 '*--nowhitelist=-[disable whitelist for file or directory]: :_files'
254 '*--whitelist=-[whitelist directory or file]: :_files'
222#endif 255#endif
223 ) 256
257#ifdef HAVE_X11
258 '--x11[enable X11 sandboxing. The software checks first if Xpra is installed, then it checks if Xephyr is installed. If all fails, it will attempt to use X11 security extension]'
259 '--x11=-[disable or enable specific X11 server]: :(none xephyr xorg xpra xvfb)'
260 '--xephyr-screen=-[set screen size for --x11=xephyr]: :(WIDTHxHEIGHT)'
261#endif
262)
224 263
225 264
226_firejail() { 265_firejail() {
227 _arguments -S $_firejail_args 266 _arguments -S $_firejail_args
228 case "$state" in 267 case "$state" in
229 caps_drop)
230 local caps_and_all=(all $(firejail --debug-caps | awk '/[0-9]+\s*- /{print $3}'))
231 _values -s "," 'caps_drop' $caps_and_all
232 ;;
233 caps_keep)
234 local caps=($(firejail --debug-caps | awk '/[0-9]+\s*- /{print $3}'))
235 _values -s "," 'caps_keep' $caps
236 ;;
237 cpus) 268 cpus)
238 _values -s "," 'cpus' $(_all_cpus) 269 _values -s "," 'cpus' $(_all_cpus)
239 ;; 270 ;;
@@ -242,5 +273,11 @@ _firejail() {
242 local net_and_none=(none $netdevs) 273 local net_and_none=(none $netdevs)
243 _values 'net' $net_and_none 274 _values 'net' $net_and_none
244 ;; 275 ;;
276 seccomp)
277 # TODO: syscall groups
278 _values -s "," 'syscalls' $(firejail --debug-syscalls | cut -d" " -f2)
279 ;;
245 esac 280 esac
246} 281}
282
283# vim: ft=zsh sw=4 ts=4 et sts=4 ai