diff options
Diffstat (limited to 'src')
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 | ||
1 | all: firejail.bash_completion | 2 | all: firejail.bash_completion |
2 | 3 | ||
3 | include ../common.mk | 4 | include ../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 | ||
10 | clean: | 12 | clean: |
11 | rm -fr firejail.bash_completion | 13 | rm -fr firejail.bash_completion |
12 | 14 | ||
15 | .PHONY: distclean | ||
13 | distclean: clean | 16 | distclean: 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@ | |||
25 | HAVE_SELINUX=@HAVE_SELINUX@ | 25 | HAVE_SELINUX=@HAVE_SELINUX@ |
26 | HAVE_DBUSPROXY=@HAVE_DBUSPROXY@ | 26 | HAVE_DBUSPROXY=@HAVE_DBUSPROXY@ |
27 | HAVE_USERTMPFS=@HAVE_USERTMPFS@ | 27 | HAVE_USERTMPFS=@HAVE_USERTMPFS@ |
28 | HAVE_OUTPUT=@HAVE_OUTPUT@ | ||
29 | HAVE_LTS=@HAVE_LTS@ | ||
30 | HAVE_FORCE_NONEWPRIVS=@HAVE_FORCE_NONEWPRIVS@ | ||
28 | 31 | ||
29 | H_FILE_LIST = $(sort $(wildcard *.[h])) | 32 | H_FILE_LIST = $(sort $(wildcard *.[h])) |
30 | C_FILE_LIST = $(sort $(wildcard *.c)) | 33 | C_FILE_LIST = $(sort $(wildcard *.c)) |
@@ -34,7 +37,7 @@ BINOBJS = $(foreach file, $(OBJS), $file) | |||
34 | CFLAGS = @CFLAGS@ | 37 | CFLAGS = @CFLAGS@ |
35 | CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' $(HAVE_GCOV) | 38 | CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' $(HAVE_GCOV) |
36 | CFLAGS += -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)/firejail"' -DLIBDIR='"$(libdir)"' -DBINDIR='"$(bindir)"' | 39 | CFLAGS += -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)/firejail"' -DLIBDIR='"$(libdir)"' -DBINDIR='"$(bindir)"' |
37 | MANFLAGS = $(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) | 40 | MANFLAGS = $(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) |
38 | CFLAGS += $(MANFLAGS) | 41 | CFLAGS += $(MANFLAGS) |
39 | CFLAGS += -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -Wformat -Wformat-security | 42 | CFLAGS += -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -Wformat -Wformat-security |
40 | LDFLAGS += -pie -fPIE -Wl,-z,relro -Wl,-z,now -lpthread | 43 | LDFLAGS += -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 @@ | |||
1 | all: faudit | ||
2 | |||
3 | include ../common.mk | ||
4 | |||
5 | %.o : %.c $(H_FILE_LIST) | ||
6 | $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(INCLUDE) -c $< -o $@ | ||
7 | |||
8 | faudit: $(OBJS) | ||
9 | $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(EXTRA_LDFLAGS) | ||
10 | |||
11 | clean:; rm -fr *.o faudit *.gcov *.gcda *.gcno *.plist | ||
12 | |||
13 | distclean: 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 | ||
25 | static 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 | ||
47 | static 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 | |||
59 | void 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 | ||
27 | int 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 | |||
51 | static 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 | |||
105 | static 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); | ||
117 | end: | ||
118 | free(sockfile); | ||
119 | } | ||
120 | |||
121 | void 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 | |||
23 | void 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 | ||
37 | extern char *prog; | ||
38 | |||
39 | // pid.c | ||
40 | void pid_test(void); | ||
41 | |||
42 | // caps.c | ||
43 | void caps_test(void); | ||
44 | |||
45 | // seccomp.c | ||
46 | void seccomp_test(void); | ||
47 | |||
48 | // syscall.c | ||
49 | void syscall_helper(int argc, char **argv); | ||
50 | void syscall_run(const char *name); | ||
51 | |||
52 | // files.c | ||
53 | void files_test(void); | ||
54 | |||
55 | // network.c | ||
56 | void network_test(void); | ||
57 | |||
58 | // dbus.c | ||
59 | int check_unix(const char *sockfile); | ||
60 | void dbus_test(void); | ||
61 | |||
62 | // dev.c | ||
63 | void dev_test(void); | ||
64 | |||
65 | // x11.c | ||
66 | void 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 | |||
24 | static char *username = NULL; | ||
25 | static char *homedir = NULL; | ||
26 | |||
27 | static 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 | |||
44 | void 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" | ||
21 | char *prog; | ||
22 | |||
23 | int 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 | |||
26 | static 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 | |||
50 | static 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 | |||
74 | void 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 | |||
97 | void 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 | |||
22 | void 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 | ||
23 | static 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 | |||
44 | void 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> | ||
27 | extern int init_module(void *module_image, unsigned long len, | ||
28 | const char *param_values); | ||
29 | extern int finit_module(int fd, const char *param_values, | ||
30 | int flags); | ||
31 | extern int delete_module(const char *name, int flags); | ||
32 | extern int pivot_root(const char *new_root, const char *put_old); | ||
33 | |||
34 | void 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 | |||
91 | void 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 | |||
25 | void 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 | ||
1 | all: fbuilder | 2 | all: fbuilder |
2 | 3 | ||
3 | include ../common.mk | 4 | include ../common.mk |
@@ -8,7 +9,9 @@ include ../common.mk | |||
8 | fbuilder: $(OBJS) | 9 | fbuilder: $(OBJS) |
9 | $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(EXTRA_LDFLAGS) | 10 | $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(EXTRA_LDFLAGS) |
10 | 11 | ||
12 | .PHONY: clean | ||
11 | clean:; rm -fr *.o fbuilder *.gcov *.gcda *.gcno *.plist | 13 | clean:; rm -fr *.o fbuilder *.gcov *.gcda *.gcno *.plist |
12 | 14 | ||
15 | .PHONY: distclean | ||
13 | distclean: clean | 16 | distclean: 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 | ||
1 | all: fcopy | 2 | all: fcopy |
2 | 3 | ||
3 | include ../common.mk | 4 | include ../common.mk |
@@ -8,7 +9,9 @@ include ../common.mk | |||
8 | fcopy: $(OBJS) ../lib/common.o | 9 | fcopy: $(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 | ||
11 | clean:; rm -fr *.o fcopy *.gcov *.gcda *.gcno *.plist | 13 | clean:; rm -fr *.o fcopy *.gcov *.gcda *.gcno *.plist |
12 | 14 | ||
15 | .PHONY: distclean | ||
13 | distclean: clean | 16 | distclean: 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 |
54 | static void selinux_relabel_path(const char *path, const char *inside_path) | 54 | static 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 | ||
176 | static 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 | |||
216 | done: | ||
217 | if (proc_pid) | ||
218 | free(proc_pid); | ||
219 | return use_target; | ||
220 | } | ||
175 | 221 | ||
176 | void copy_link(const char *target, const char *linkpath, mode_t mode, uid_t uid, gid_t gid) { | 222 | void 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 | 308 | out: | |
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 | ||
297 | errexit: | 341 | errexit: |
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 | ||
1 | all: firecfg | 2 | all: firecfg |
2 | 3 | ||
3 | include ../common.mk | 4 | include ../common.mk |
@@ -8,7 +9,9 @@ include ../common.mk | |||
8 | firecfg: $(OBJS) ../lib/common.o ../lib/firejail_user.o | 9 | firecfg: $(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 | ||
11 | clean:; rm -fr *.o firecfg *.gcov *.gcda *.gcno *.plist | 13 | clean:; rm -fr *.o firecfg *.gcov *.gcda *.gcno *.plist |
12 | 14 | ||
15 | .PHONY: distclean | ||
13 | distclean: clean | 16 | distclean: 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 | |||
464 | lyx | 464 | lyx |
465 | macrofusion | 465 | macrofusion |
466 | magicor | 466 | magicor |
467 | # man | 467 | man |
468 | manaplus | 468 | manaplus |
469 | marker | 469 | marker |
470 | masterpdfeditor | 470 | masterpdfeditor |
@@ -553,6 +553,8 @@ neverputt | |||
553 | newsbeuter | 553 | newsbeuter |
554 | newsboat | 554 | newsboat |
555 | newsflash | 555 | newsflash |
556 | nextcloud | ||
557 | nextcloud-desktop | ||
556 | nheko | 558 | nheko |
557 | nicotine | 559 | nicotine |
558 | nitroshare | 560 | nitroshare |
@@ -809,6 +811,8 @@ vivaldi-snapshot | |||
809 | vivaldi-stable | 811 | vivaldi-stable |
810 | vlc | 812 | vlc |
811 | vmware | 813 | vmware |
814 | vmware-player | ||
815 | vmware-workstation | ||
812 | vscodium | 816 | vscodium |
813 | vulturesclaw | 817 | vulturesclaw |
814 | vultureseye | 818 | vultureseye |
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 | ||
1 | all: firejail | 2 | all: firejail |
2 | 3 | ||
3 | include ../common.mk | 4 | include ../common.mk |
@@ -8,7 +9,9 @@ include ../common.mk | |||
8 | firejail: $(OBJS) ../lib/libnetlink.o ../lib/common.o ../lib/ldd_utils.o ../lib/firejail_user.o ../lib/errno.o ../lib/syscall.o | 9 | firejail: $(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 | ||
11 | clean:; rm -fr *.o firejail *.gcov *.gcda *.gcno *.plist | 13 | clean:; rm -fr *.o firejail *.gcov *.gcda *.gcno *.plist |
12 | 14 | ||
15 | .PHONY: distclean | ||
13 | distclean: clean | 16 | distclean: 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 | ||
270 | void print_compiletime_support(void) { | 270 | void 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 | ||
117 | int dbus_check_name(const char *name) { | 117 | int 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 | |||
328 | extern int arg_writable_run_user; // writable /run/user | 328 | extern int arg_writable_run_user; // writable /run/user |
329 | extern int arg_writable_var_log; // writable /var/log | 329 | extern int arg_writable_var_log; // writable /var/log |
330 | extern int arg_appimage; // appimage | 330 | extern int arg_appimage; // appimage |
331 | extern int arg_audit; // audit | ||
332 | extern char *arg_audit_prog; // audit | ||
333 | extern int arg_apparmor; // apparmor | 331 | extern int arg_apparmor; // apparmor |
334 | extern int arg_allow_debuggers; // allow debuggers | 332 | extern int arg_allow_debuggers; // allow debuggers |
335 | extern int arg_x11_block; // block X11 | 333 | extern 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 |
452 | void profile_add(char *str); | 450 | void profile_add(char *str); |
453 | void profile_add_ignore(const char *str); | 451 | void profile_add_ignore(const char *str); |
452 | char *profile_list_normalize(char *list); | ||
453 | char *profile_list_compress(char *list); | ||
454 | void profile_list_augment(char **list, const char *items); | ||
454 | 455 | ||
455 | // list.c | 456 | // list.c |
456 | void list(void); | 457 | void list(void); |
@@ -649,6 +650,8 @@ void network_set_run_file(pid_t pid); | |||
649 | 650 | ||
650 | // fs_etc.c | 651 | // fs_etc.c |
651 | void fs_machineid(void); | 652 | void fs_machineid(void); |
653 | void fs_private_dir_copy(const char *private_dir, const char *private_run_dir, const char *private_list); | ||
654 | void fs_private_dir_mount(const char *private_dir, const char *private_run_dir); | ||
652 | void fs_private_dir_list(const char *private_dir, const char *private_run_dir, const char *private_list); | 655 | void 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 | ||
141 | void fs_private_dir_list(const char *private_dir, const char *private_run_dir, const char *private_list) { | 142 | void 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 | |||
189 | void 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 | ||
214 | void 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 | ||
30 | extern void fslib_install_stdc(void); | 30 | extern void fslib_install_stdc(void); |
31 | extern void fslib_install_firejail(void); | ||
31 | extern void fslib_install_system(void); | 32 | extern void fslib_install_system(void); |
32 | 33 | ||
33 | static int lib_cnt = 0; | 34 | static 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 |
170 | void fslib_copy_libs(const char *full_path) { | 170 | static 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 | ||
201 | void 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. | ||
217 | void 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 | ||
212 | void fslib_copy_dir(const char *full_path) { | 230 | void 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 | ||
24 | extern void fslib_duplicate(const char *full_path); | 24 | extern void fslib_duplicate(const char *full_path); |
25 | extern void fslib_copy_libs(const char *full_path); | 25 | extern void fslib_copy_libs_parse_as_user(const char *full_path); |
26 | extern void fslib_copy_libs_parse_as_root(const char *full_path); | ||
26 | extern void fslib_copy_dir(const char *full_path); | 27 | extern 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 | |||
131 | static 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 | |||
152 | void 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 | |||
130 | int arg_writable_run_user = 0; // writable /run/user | 130 | int arg_writable_run_user = 0; // writable /run/user |
131 | int arg_writable_var_log = 0; // writable /var/log | 131 | int arg_writable_var_log = 0; // writable /var/log |
132 | int arg_appimage = 0; // appimage | 132 | int arg_appimage = 0; // appimage |
133 | int arg_audit = 0; // audit | ||
134 | char *arg_audit_prog = NULL; // audit | ||
135 | int arg_apparmor = 0; // apparmor | 133 | int arg_apparmor = 0; // apparmor |
136 | int arg_allow_debuggers = 0; // allow debuggers | 134 | int arg_allow_debuggers = 0; // allow debuggers |
137 | int arg_x11_block = 0; // block X11 | 135 | int 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 | ||
25 | void check_output(int argc, char **argv) { | 26 | void 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 | ||
160 | static int check_private(void) { | ||
161 | return arg_private; | ||
162 | } | ||
163 | |||
160 | static int check_x11(void) { | 164 | static 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 | |||
1777 | char *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 | |||
1802 | char *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 | |||
1908 | void 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 | ||
591 | static void enforce_filters(void) { | 577 | static 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 | ||
1 | all: firemon | 2 | all: firemon |
2 | 3 | ||
3 | include ../common.mk | 4 | include ../common.mk |
@@ -8,7 +9,9 @@ include ../common.mk | |||
8 | firemon: $(OBJS) ../lib/common.o ../lib/pid.o | 9 | firemon: $(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 | ||
11 | clean:; rm -fr *.o firemon *.gcov *.gcda *.gcno *.plist | 13 | clean:; rm -fr *.o firemon *.gcov *.gcda *.gcno *.plist |
12 | 14 | ||
15 | .PHONY: distclean | ||
13 | distclean: clean | 16 | distclean: 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 | ||
1 | all: fldd | 2 | all: fldd |
2 | 3 | ||
3 | include ../common.mk | 4 | include ../common.mk |
@@ -8,7 +9,9 @@ include ../common.mk | |||
8 | fldd: $(OBJS) ../lib/common.o ../lib/ldd_utils.o | 9 | fldd: $(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 | ||
11 | clean:; rm -fr *.o fldd *.gcov *.gcda *.gcno *.plist | 13 | clean:; rm -fr *.o fldd *.gcov *.gcda *.gcno *.plist |
12 | 14 | ||
15 | .PHONY: distclean | ||
13 | distclean: clean | 16 | distclean: 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 | ||
1 | all: fnet | 2 | all: fnet |
2 | 3 | ||
3 | include ../common.mk | 4 | include ../common.mk |
@@ -8,7 +9,9 @@ include ../common.mk | |||
8 | fnet: $(OBJS) ../lib/common.o ../lib/libnetlink.o | 9 | fnet: $(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 | ||
11 | clean:; rm -fr *.o fnet *.gcov *.gcda *.gcno *.plist | 13 | clean:; rm -fr *.o fnet *.gcov *.gcda *.gcno *.plist |
12 | 14 | ||
15 | .PHONY: distclean | ||
13 | distclean: clean | 16 | distclean: 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 | ||
1 | all: fnetfilter | 2 | all: fnetfilter |
2 | 3 | ||
3 | include ../common.mk | 4 | include ../common.mk |
@@ -8,7 +9,9 @@ include ../common.mk | |||
8 | fnetfilter: $(OBJS) ../lib/common.o | 9 | fnetfilter: $(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 | ||
11 | clean:; rm -fr *.o fnetfilter *.gcov *.gcda *.gcno *.plist | 13 | clean:; rm -fr *.o fnetfilter *.gcov *.gcda *.gcno *.plist |
12 | 14 | ||
15 | .PHONY: distclean | ||
13 | distclean: clean | 16 | distclean: 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 | ||
1 | all: fsec-optimize | 2 | all: fsec-optimize |
2 | 3 | ||
3 | include ../common.mk | 4 | include ../common.mk |
@@ -8,7 +9,9 @@ include ../common.mk | |||
8 | fsec-optimize: $(OBJS) ../lib/common.o ../lib/libnetlink.o | 9 | fsec-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 | ||
11 | clean:; rm -fr *.o fsec-optimize *.gcov *.gcda *.gcno *.plist | 13 | clean:; rm -fr *.o fsec-optimize *.gcov *.gcda *.gcno *.plist |
12 | 14 | ||
15 | .PHONY: distclean | ||
13 | distclean: clean | 16 | distclean: 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 | ||
1 | all: fsec-print | 2 | all: fsec-print |
2 | 3 | ||
3 | include ../common.mk | 4 | include ../common.mk |
@@ -8,7 +9,9 @@ include ../common.mk | |||
8 | fsec-print: $(OBJS) ../lib/common.o ../lib/libnetlink.o ../lib/errno.o ../lib/syscall.o | 9 | fsec-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 | ||
11 | clean:; rm -fr *.o fsec-print *.gcov *.gcda *.gcno *.plist | 13 | clean:; rm -fr *.o fsec-print *.gcov *.gcda *.gcno *.plist |
12 | 14 | ||
15 | .PHONY: distclean | ||
13 | distclean: clean | 16 | distclean: 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 | ||
1 | all: fseccomp | 2 | all: fseccomp |
2 | 3 | ||
3 | include ../common.mk | 4 | include ../common.mk |
@@ -8,7 +9,9 @@ include ../common.mk | |||
8 | fseccomp: $(OBJS) ../lib/common.o ../lib/errno.o ../lib/syscall.o | 9 | fseccomp: $(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 | ||
11 | clean:; rm -fr *.o fseccomp *.gcov *.gcda *.gcno *.plist | 13 | clean:; rm -fr *.o fseccomp *.gcov *.gcda *.gcno *.plist |
12 | 14 | ||
15 | .PHONY: distclean | ||
13 | distclean: clean | 16 | distclean: 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 | ||
1 | all: ftee | 2 | all: ftee |
2 | 3 | ||
3 | include ../common.mk | 4 | include ../common.mk |
@@ -8,7 +9,9 @@ include ../common.mk | |||
8 | ftee: $(OBJS) | 9 | ftee: $(OBJS) |
9 | $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(EXTRA_LDFLAGS) | 10 | $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(EXTRA_LDFLAGS) |
10 | 11 | ||
12 | .PHONY: clean | ||
11 | clean:; rm -fr *.o ftee *.gcov *.gcda *.gcno *.plist | 13 | clean:; rm -fr *.o ftee *.gcov *.gcda *.gcno *.plist |
12 | 14 | ||
15 | .PHONY: distclean | ||
13 | distclean: clean | 16 | distclean: 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 | ||
1 | all: jailtest | 2 | all: jailtest |
2 | 3 | ||
3 | include ../common.mk | 4 | include ../common.mk |
@@ -8,7 +9,9 @@ include ../common.mk | |||
8 | jailtest: $(OBJS) | 9 | jailtest: $(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 | ||
11 | clean:; rm -fr *.o jailtest *.gcov *.gcda *.gcno *.plist | 13 | clean:; rm -fr *.o jailtest *.gcov *.gcda *.gcno *.plist |
12 | 14 | ||
15 | .PHONY: distclean | ||
13 | distclean: clean | 16 | distclean: 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 @@ | |||
1 | include ../common.mk | 1 | include ../common.mk |
2 | 2 | ||
3 | .PHONY: all | ||
3 | all: $(OBJS) | 4 | all: $(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 | ||
8 | clean:; rm -fr $(OBJS) *.gcov *.gcda *.gcno *.plist | 10 | clean:; rm -fr $(OBJS) *.gcov *.gcda *.gcno *.plist |
9 | 11 | ||
12 | .PHONY: distclean | ||
10 | distclean: clean | 13 | distclean: 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) | |||
11 | CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIC -Wformat -Wformat-security | 11 | CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIC -Wformat -Wformat-security |
12 | LDFLAGS += -pie -fPIE -Wl,-z,relro -Wl,-z,now | 12 | LDFLAGS += -pie -fPIE -Wl,-z,relro -Wl,-z,now |
13 | 13 | ||
14 | .PHONY: all | ||
14 | all: libpostexecseccomp.so | 15 | all: 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 | |||
19 | libpostexecseccomp.so: $(OBJS) | 20 | libpostexecseccomp.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 | ||
22 | clean:; rm -fr $(OBJS) libpostexecseccomp.so *.plist | 24 | clean:; rm -fr $(OBJS) libpostexecseccomp.so *.plist |
23 | 25 | ||
26 | .PHONY: distclean | ||
24 | distclean: clean | 27 | distclean: 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) | |||
11 | CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIC -Wformat -Wformat-security | 11 | CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIC -Wformat -Wformat-security |
12 | LDFLAGS += -pie -fPIE -Wl,-z,relro -Wl,-z,now | 12 | LDFLAGS += -pie -fPIE -Wl,-z,relro -Wl,-z,now |
13 | 13 | ||
14 | .PHONY: all | ||
14 | all: libtrace.so | 15 | all: libtrace.so |
15 | 16 | ||
16 | %.o : %.c $(H_FILE_LIST) | 17 | %.o : %.c $(H_FILE_LIST) |
@@ -19,8 +20,9 @@ all: libtrace.so | |||
19 | libtrace.so: $(OBJS) | 20 | libtrace.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 | |
23 | clean:; rm -fr $(OBJS) libtrace.so *.plist | 24 | clean:; rm -fr $(OBJS) libtrace.so *.plist |
24 | 25 | ||
26 | .PHONY: distclean | ||
25 | distclean: clean | 27 | distclean: 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) | |||
11 | CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIC -Wformat -Wformat-security | 11 | CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIC -Wformat -Wformat-security |
12 | LDFLAGS += -pie -fPIE -Wl,-z,relro -Wl,-z,now | 12 | LDFLAGS += -pie -fPIE -Wl,-z,relro -Wl,-z,now |
13 | 13 | ||
14 | .PHONY: all | ||
14 | all: libtracelog.so | 15 | all: 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 | |||
19 | libtracelog.so: $(OBJS) | 20 | libtracelog.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 | |
23 | clean:; rm -fr $(OBJS) libtracelog.so *.plist | 24 | clean:; rm -fr $(OBJS) libtracelog.so *.plist |
24 | 25 | ||
26 | .PHONY: distclean | ||
25 | distclean: clean | 27 | distclean: 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 | ||
1 | all: firecfg.man firejail.man firejail-login.man firejail-users.man firejail-profile.man firemon.man jailtest.man | 2 | all: firecfg.man firejail.man firejail-login.man firejail-users.man firejail-profile.man firemon.man jailtest.man |
3 | |||
2 | include ../common.mk | 4 | include ../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 | ||
7 | clean:; rm -fr *.man | 10 | clean:; rm -fr *.man |
8 | 11 | ||
12 | .PHONY: distclean | ||
9 | distclean: clean | 13 | distclean: 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 | ||
104 | This example will load the whitelist profile line only if the \-\-appimage option has been specified on the command line. | 104 | This example will load the whitelist profile line only if the \-\-appimage option has been specified on the command line. |
105 | 105 | ||
106 | Currently 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 | 106 | Currently 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 |
107 | can be enabled or disabled globally in Firejail's configuration file. | 107 | can be enabled or disabled globally in Firejail's configuration file. |
108 | 108 | ||
109 | The profile line may be any profile line that you would normally use in a profile \fBexcept\fR for "quiet" and "include" lines. | 109 | The 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 | |||
266 | filesystems. All modifications are discarded when the sandbox is | 266 | filesystems. All modifications are discarded when the sandbox is |
267 | closed. | 267 | closed. |
268 | .TP | 268 | .TP |
269 | \fBprivate=directory | 269 | \fBprivate directory |
270 | Use directory as user home. | 270 | Use 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: | |||
42 | firejail {\-? | \-\-debug-caps | \-\-debug-errnos | \-\-debug-syscalls | \-\-debug-syscalls32 | \-\-debug-protocols | \-\-help | \-\-version} | 42 | firejail {\-? | \-\-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 | ||
46 | This is Firejail long-term support (LTS), an enterprise focused version of the software, | ||
47 | LTS is usually supported for two or three years. | ||
48 | During this time only bugs and the occasional documentation problems are fixed. | ||
49 | The attack surface of the SUID executable was greatly reduced by removing some of the features. | ||
50 | .br | ||
51 | |||
52 | .br | ||
53 | #endif | ||
45 | Firejail is a SUID sandbox program that reduces the risk of security breaches by | 54 | Firejail is a SUID sandbox program that reduces the risk of security breaches by |
46 | restricting the running environment of untrusted applications using Linux | 55 | restricting the running environment of untrusted applications using Linux |
47 | namespaces, seccomp-bpf and Linux capabilities. | 56 | namespaces, 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 | ||
150 | Audit the sandbox, see \fBAUDIT\fR section for more details. | ||
151 | .TP | ||
152 | \fB\-\-audit=test-program | ||
153 | Audit the sandbox, see \fBAUDIT\fR section for more details. | ||
154 | .TP | ||
155 | \fB\-\-bandwidth=name|pid | 158 | \fB\-\-bandwidth=name|pid |
156 | Set bandwidth limits for the sandbox identified by name or PID, see \fBTRAFFIC SHAPING\fR section for more details. | 159 | Set 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 | ||
1112 | Create a directory in user home. Parent directories are created as needed. | ||
1113 | .br | ||
1114 | |||
1115 | .br | ||
1116 | Example: | ||
1117 | .br | ||
1118 | $ firejail --mkdir=~/work/project | ||
1119 | |||
1120 | .TP | ||
1121 | \fB\-\-mkfile=filename | ||
1122 | Create an empty file in user home. | ||
1123 | .br | ||
1124 | |||
1125 | .br | ||
1126 | Example: | ||
1127 | .br | ||
1128 | $ firejail --mkfile=~/work/project/readme | ||
1129 | |||
1130 | .TP | ||
1108 | \fB\-\-memory-deny-write-execute | 1131 | \fB\-\-memory-deny-write-execute |
1109 | Install a seccomp filter to block attempts to create memory mappings | 1132 | Install a seccomp filter to block attempts to create memory mappings |
1110 | that are both writable and executable, to change mappings to be | 1133 | that 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 |
1623 | Disable whitelist for this directory or file. | 1646 | Disable whitelist for this directory or file. |
1624 | 1647 | ||
1648 | #ifdef HAVE_OUTPUT | ||
1625 | .TP | 1649 | .TP |
1626 | \fB\-\-output=logfile | 1650 | \fB\-\-output=logfile |
1627 | stdout logging and log rotation. Copy stdout to logfile, and keep the size of the file under 500KB using log | 1651 | stdout 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 |
1654 | Similar to \-\-output, but stderr is also stored. | 1678 | Similar 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 |
2455 | By default, if a seccomp filter blocks a system call, the process gets | 2480 | By default, if a seccomp filter blocks a system call, the process gets |
2456 | EPERM as the error. With \-\-seccomp-error-action=error, another error | 2481 | EPERM as the error. With \-\-seccomp-error-action=error, another error |
2457 | number can be returned, for example ENOSYS or EACCES. The process can | 2482 | number 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 | ||
2945 | Audit feature allows the user to point out gaps in security profiles. The | ||
2946 | implementation replaces the program to be sandboxed with a test program. By | ||
2947 | default, we use faudit program distributed with Firejail. A custom test program | ||
2948 | can also be supplied by the user. Examples: | ||
2949 | |||
2950 | Running the default audit program: | ||
2951 | .br | ||
2952 | $ firejail --audit transmission-gtk | ||
2953 | |||
2954 | Running a custom audit program: | ||
2955 | .br | ||
2956 | $ firejail --audit=~/sandbox-test transmission-gtk | ||
2957 | |||
2958 | In the examples above, the sandbox configures transmission-gtk profile and | ||
2959 | starts the test program. The real program, transmission-gtk, will not be | ||
2960 | started. | ||
2961 | |||
2962 | You can also audit a specific profile without specifying a program. | ||
2963 | .br | ||
2964 | $ firejail --audit --profile=/etc/firejail/zoom.profile | ||
2965 | |||
2966 | Limitations: audit feature is not implemented for --x11 commands. | ||
2967 | |||
2968 | .SH DESKTOP INTEGRATION | 2969 | .SH DESKTOP INTEGRATION |
2969 | A symbolic link to /usr/bin/firejail under the name of a program, will start the program in Firejail sandbox. | 2970 | A symbolic link to /usr/bin/firejail under the name of a program, will start the program in Firejail sandbox. |
2970 | The symbolic link should be placed in the first $PATH position. On most systems, a good place | 2971 | The 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 |
16 | jailtest inserts executable programs in /home/username, /tmp, and /var/tmp directories | 16 | jailtest inserts executable programs in /home/username, /tmp, and /var/tmp directories |
17 | and tries to run them form inside the sandbox, thus testing if the directory is executable or not. | 17 | and 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 |
20 | jailtest creates test files in the directories specified by the user and tries to read | 20 | jailtest 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 |
32 | Print debug messages | 32 | Print debug messages. |
33 | .TP | 33 | .TP |
34 | \fB\-?\fR, \fB\-\-help\fR | 34 | \fB\-?\fR, \fB\-\-help\fR |
35 | Print options end exit. | 35 | Print options and exit. |
36 | .TP | 36 | .TP |
37 | \fB\-\-version | 37 | \fB\-\-version |
38 | Print program version and exit. | 38 | Print 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 | ||
1 | all: profstats | 2 | all: profstats |
2 | 3 | ||
3 | include ../common.mk | 4 | include ../common.mk |
@@ -8,7 +9,9 @@ include ../common.mk | |||
8 | profstats: $(OBJS) | 9 | profstats: $(OBJS) |
9 | $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(EXTRA_LDFLAGS) | 10 | $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(EXTRA_LDFLAGS) |
10 | 11 | ||
12 | .PHONY: clean | ||
11 | clean:; rm -fr *.o profstats *.gcov *.gcda *.gcno *.plist | 13 | clean:; rm -fr *.o profstats *.gcov *.gcda *.gcno *.plist |
12 | 14 | ||
15 | .PHONY: distclean | ||
13 | distclean: clean | 16 | distclean: 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 | ||
1 | all: _firejail | 2 | all: _firejail |
2 | 3 | ||
3 | include ../common.mk | 4 | include ../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 | ||
10 | clean: | 12 | clean: |
11 | rm -fr _firejail | 13 | rm -fr _firejail |
12 | 14 | ||
15 | .PHONY: distclean | ||
13 | distclean: clean | 16 | distclean: 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 | ||