diff options
-rw-r--r-- | Makefile.in | 5 | ||||
-rwxr-xr-x | configure | 3 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | src/faudit/Makefile.in | 25 | ||||
-rw-r--r-- | src/faudit/caps.c | 79 | ||||
-rw-r--r-- | src/faudit/dbus.c | 74 | ||||
-rw-r--r-- | src/faudit/faudit.h | 60 | ||||
-rw-r--r-- | src/faudit/files.c | 75 | ||||
-rw-r--r-- | src/faudit/main.c | 68 | ||||
-rw-r--r-- | src/faudit/network.c | 77 | ||||
-rw-r--r-- | src/faudit/pid.c | 90 | ||||
-rw-r--r-- | src/faudit/seccomp.c | 103 | ||||
-rw-r--r-- | src/faudit/syscall.c | 91 | ||||
-rw-r--r-- | todo | 41 |
14 files changed, 784 insertions, 9 deletions
diff --git a/Makefile.in b/Makefile.in index 9cf00562e..9ee65c975 100644 --- a/Makefile.in +++ b/Makefile.in | |||
@@ -1,6 +1,6 @@ | |||
1 | all: apps firejail.1 firemon.1 firecfg.1 firejail-profile.5 firejail-login.5 firejail-config.5 | 1 | all: apps firejail.1 firemon.1 firecfg.1 firejail-profile.5 firejail-login.5 firejail-config.5 |
2 | MYLIBS = src/lib | 2 | MYLIBS = src/lib |
3 | APPS = src/firejail src/firemon src/firecfg src/libtrace src/libtracelog src/ftee | 3 | APPS = src/firejail src/firemon src/firecfg src/libtrace src/libtracelog src/ftee src/libtracelog src/faudit |
4 | 4 | ||
5 | prefix=@prefix@ | 5 | prefix=@prefix@ |
6 | exec_prefix=@exec_prefix@ | 6 | exec_prefix=@exec_prefix@ |
@@ -84,6 +84,7 @@ realinstall: | |||
84 | install -c -m 0755 src/ftee/ftee $(DESTDIR)/$(libdir)/firejail/. | 84 | install -c -m 0755 src/ftee/ftee $(DESTDIR)/$(libdir)/firejail/. |
85 | install -c -m 0755 src/fshaper/fshaper.sh $(DESTDIR)/$(libdir)/firejail/. | 85 | install -c -m 0755 src/fshaper/fshaper.sh $(DESTDIR)/$(libdir)/firejail/. |
86 | install -c -m 0644 src/firecfg/firecfg.config $(DESTDIR)/$(libdir)/firejail/. | 86 | install -c -m 0644 src/firecfg/firecfg.config $(DESTDIR)/$(libdir)/firejail/. |
87 | install -c -m 0755 src/faudit/faudit $(DESTDIR)/$(libdir)/firejail/. | ||
87 | # documents | 88 | # documents |
88 | install -m 0755 -d $(DESTDIR)/$(DOCDIR) | 89 | install -m 0755 -d $(DESTDIR)/$(DOCDIR) |
89 | install -c -m 0644 COPYING $(DESTDIR)/$(DOCDIR)/. | 90 | install -c -m 0644 COPYING $(DESTDIR)/$(DOCDIR)/. |
@@ -250,7 +251,6 @@ realinstall: | |||
250 | install -c -m 0644 src/bash_completion/firemon.bash_completion $(DESTDIR)/$(datarootdir)/bash-completion/completions/firemon | 251 | install -c -m 0644 src/bash_completion/firemon.bash_completion $(DESTDIR)/$(datarootdir)/bash-completion/completions/firemon |
251 | install -c -m 0644 src/bash_completion/firecfg.bash_completion $(DESTDIR)/$(datarootdir)/bash-completion/completions/firecfg | 252 | install -c -m 0644 src/bash_completion/firecfg.bash_completion $(DESTDIR)/$(datarootdir)/bash-completion/completions/firecfg |
252 | 253 | ||
253 | |||
254 | install: all | 254 | install: all |
255 | $(MAKE) realinstall | 255 | $(MAKE) realinstall |
256 | 256 | ||
@@ -261,6 +261,7 @@ install-strip: all | |||
261 | strip src/libtrace/libtrace.so | 261 | strip src/libtrace/libtrace.so |
262 | strip src/libtracelog/libtracelog.so | 262 | strip src/libtracelog/libtracelog.so |
263 | strip src/ftee/ftee | 263 | strip src/ftee/ftee |
264 | strip src/faudit/faudit | ||
264 | $(MAKE) realinstall | 265 | $(MAKE) realinstall |
265 | 266 | ||
266 | uninstall: | 267 | uninstall: |
@@ -3673,7 +3673,7 @@ if test "$prefix" = /usr; then | |||
3673 | sysconfdir="/etc" | 3673 | sysconfdir="/etc" |
3674 | fi | 3674 | fi |
3675 | 3675 | ||
3676 | ac_config_files="$ac_config_files Makefile src/lib/Makefile src/firejail/Makefile src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/ftee/Makefile" | 3676 | ac_config_files="$ac_config_files Makefile src/lib/Makefile src/firejail/Makefile src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/ftee/Makefile src/faudit/Makefile" |
3677 | 3677 | ||
3678 | cat >confcache <<\_ACEOF | 3678 | cat >confcache <<\_ACEOF |
3679 | # This file is a shell script that caches the results of configure | 3679 | # This file is a shell script that caches the results of configure |
@@ -4390,6 +4390,7 @@ do | |||
4390 | "src/libtracelog/Makefile") CONFIG_FILES="$CONFIG_FILES src/libtracelog/Makefile" ;; | 4390 | "src/libtracelog/Makefile") CONFIG_FILES="$CONFIG_FILES src/libtracelog/Makefile" ;; |
4391 | "src/firecfg/Makefile") CONFIG_FILES="$CONFIG_FILES src/firecfg/Makefile" ;; | 4391 | "src/firecfg/Makefile") CONFIG_FILES="$CONFIG_FILES src/firecfg/Makefile" ;; |
4392 | "src/ftee/Makefile") CONFIG_FILES="$CONFIG_FILES src/ftee/Makefile" ;; | 4392 | "src/ftee/Makefile") CONFIG_FILES="$CONFIG_FILES src/ftee/Makefile" ;; |
4393 | "src/faudit/Makefile") CONFIG_FILES="$CONFIG_FILES src/faudit/Makefile" ;; | ||
4393 | 4394 | ||
4394 | *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; | 4395 | *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; |
4395 | esac | 4396 | esac |
diff --git a/configure.ac b/configure.ac index 93e062518..470c55d37 100644 --- a/configure.ac +++ b/configure.ac | |||
@@ -106,7 +106,7 @@ if test "$prefix" = /usr; then | |||
106 | sysconfdir="/etc" | 106 | sysconfdir="/etc" |
107 | fi | 107 | fi |
108 | 108 | ||
109 | AC_OUTPUT(Makefile src/lib/Makefile src/firejail/Makefile src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/ftee/Makefile) | 109 | AC_OUTPUT(Makefile src/lib/Makefile src/firejail/Makefile src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/ftee/Makefile src/faudit/Makefile) |
110 | 110 | ||
111 | echo | 111 | echo |
112 | echo "Configuration options:" | 112 | echo "Configuration options:" |
diff --git a/src/faudit/Makefile.in b/src/faudit/Makefile.in new file mode 100644 index 000000000..995a0bf49 --- /dev/null +++ b/src/faudit/Makefile.in | |||
@@ -0,0 +1,25 @@ | |||
1 | all: faudit | ||
2 | |||
3 | PREFIX=@prefix@ | ||
4 | VERSION=@PACKAGE_VERSION@ | ||
5 | NAME=@PACKAGE_NAME@ | ||
6 | HAVE_FATAL_WARNINGS=@HAVE_FATAL_WARNINGS@ | ||
7 | |||
8 | H_FILE_LIST = $(sort $(wildcard *.[h])) | ||
9 | C_FILE_LIST = $(sort $(wildcard *.c)) | ||
10 | OBJS = $(C_FILE_LIST:.c=.o) | ||
11 | BINOBJS = $(foreach file, $(OBJS), $file) | ||
12 | CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' -DPREFIX='"$(PREFIX)"' -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -pie -Wformat -Wformat-security | ||
13 | LDFLAGS += -pie -Wl,-z,relro -Wl,-z,now -lpthread | ||
14 | |||
15 | %.o : %.c $(H_FILE_LIST) | ||
16 | $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@ | ||
17 | |||
18 | faudit: $(OBJS) | ||
19 | $(CC) $(LDFLAGS) -o $@ $(OBJS) | ||
20 | |||
21 | clean:; rm -f *.o faudit | ||
22 | |||
23 | distclean: clean | ||
24 | rm -fr Makefile | ||
25 | |||
diff --git a/src/faudit/caps.c b/src/faudit/caps.c new file mode 100644 index 000000000..d4a62b34f --- /dev/null +++ b/src/faudit/caps.c | |||
@@ -0,0 +1,79 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014-2016 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 tbe 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 | } | ||
79 | |||
diff --git a/src/faudit/dbus.c b/src/faudit/dbus.c new file mode 100644 index 000000000..5f25e7312 --- /dev/null +++ b/src/faudit/dbus.c | |||
@@ -0,0 +1,74 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014-2016 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 <sys/un.h> | ||
23 | |||
24 | void check_session_bus(const char *sockfile) { | ||
25 | assert(sockfile); | ||
26 | |||
27 | // open socket | ||
28 | int sock = socket(AF_UNIX, SOCK_STREAM, 0); | ||
29 | if (sock == -1) { | ||
30 | printf("GOOD: I cannot connect to session bus. If the application misbehaves, please log a bug with the application developer.\n"); | ||
31 | return; | ||
32 | } | ||
33 | |||
34 | // connect | ||
35 | struct sockaddr_un remote; | ||
36 | memset(&remote, 0, sizeof(struct sockaddr_un)); | ||
37 | remote.sun_family = AF_UNIX; | ||
38 | strcpy(remote.sun_path, sockfile); | ||
39 | int len = strlen(remote.sun_path) + sizeof(remote.sun_family); | ||
40 | remote.sun_path[0] = '\0'; | ||
41 | if (connect(sock, (struct sockaddr *)&remote, len) == -1) { | ||
42 | printf("GOOD: I cannot connect to session bus. If the application misbehaves, please log a bug with the application developer.\n"); | ||
43 | } | ||
44 | else { | ||
45 | printf("MAYBE: I can connect to session bus. If this is undesirable, use \"--private-tmp\" or blacklist the socket file.\n"); | ||
46 | } | ||
47 | |||
48 | close(sock); | ||
49 | } | ||
50 | |||
51 | void dbus_test(void) { | ||
52 | // check the session bus | ||
53 | char *str = getenv("DBUS_SESSION_BUS_ADDRESS"); | ||
54 | if (str) { | ||
55 | char *bus = strdup(str); | ||
56 | if (!bus) | ||
57 | errExit("strdup"); | ||
58 | char *sockfile = strstr(bus, "unix:abstract="); | ||
59 | if (sockfile) { | ||
60 | sockfile += 13; | ||
61 | *sockfile = '@'; | ||
62 | char *ptr = strchr(sockfile, ','); | ||
63 | if (ptr) { | ||
64 | *ptr = '\0'; | ||
65 | check_session_bus(sockfile); | ||
66 | } | ||
67 | sockfile -= 13; | ||
68 | free(sockfile); | ||
69 | } | ||
70 | } | ||
71 | } | ||
72 | |||
73 | |||
74 | |||
diff --git a/src/faudit/faudit.h b/src/faudit/faudit.h new file mode 100644 index 000000000..f54f95f98 --- /dev/null +++ b/src/faudit/faudit.h | |||
@@ -0,0 +1,60 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014-2016 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 | #include <stdio.h> | ||
24 | #include <stdlib.h> | ||
25 | #include <stdint.h> | ||
26 | #include <string.h> | ||
27 | #include <unistd.h> | ||
28 | #include <sys/types.h> | ||
29 | #include <sys/stat.h> | ||
30 | #include <sys/mount.h> | ||
31 | #include <assert.h> | ||
32 | |||
33 | #define errExit(msg) do { char msgout[500]; sprintf(msgout, "Error %s:%s(%d)", msg, __FUNCTION__, __LINE__); perror(msgout); exit(1);} while (0) | ||
34 | |||
35 | // main.c | ||
36 | extern char *prog; | ||
37 | |||
38 | // pid.c | ||
39 | void pid_test(void); | ||
40 | |||
41 | // caps.c | ||
42 | void caps_test(void); | ||
43 | |||
44 | // seccomp.c | ||
45 | void seccomp_test(void); | ||
46 | |||
47 | // syscall.c | ||
48 | void syscall_helper(int argc, char **argv); | ||
49 | void syscall_run(const char *name); | ||
50 | |||
51 | // files.c | ||
52 | void files_test(void); | ||
53 | |||
54 | // network.c | ||
55 | void network_test(void); | ||
56 | |||
57 | // dbus.c | ||
58 | void dbus_test(void); | ||
59 | |||
60 | #endif \ No newline at end of file | ||
diff --git a/src/faudit/files.c b/src/faudit/files.c new file mode 100644 index 000000000..c27973358 --- /dev/null +++ b/src/faudit/files.c | |||
@@ -0,0 +1,75 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014-2016 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 retrive 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 new file mode 100644 index 000000000..df549ac3e --- /dev/null +++ b/src/faudit/main.c | |||
@@ -0,0 +1,68 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014-2016 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 | if (argc != 1) { | ||
25 | int i; | ||
26 | |||
27 | for (i = 1; i < argc; i++) { | ||
28 | if (strcmp(argv[i], "syscall")) { | ||
29 | syscall_helper(argc, argv); | ||
30 | return 0; | ||
31 | } | ||
32 | } | ||
33 | return 1; | ||
34 | } | ||
35 | |||
36 | printf("\n---------------- Firejail Audit: the GOOD, the BAD and the UGLY ----------------\n"); | ||
37 | |||
38 | // extract program name | ||
39 | prog = realpath(argv[0], NULL); | ||
40 | if (prog == NULL) { | ||
41 | fprintf(stderr, "Error: cannot extract the path of the audit program\n"); | ||
42 | return 1; | ||
43 | } | ||
44 | printf("INFO: Starting %s.\n", prog); | ||
45 | |||
46 | |||
47 | // check pid namespace | ||
48 | pid_test(); | ||
49 | |||
50 | // check capabilities | ||
51 | caps_test(); | ||
52 | |||
53 | // check seccomp | ||
54 | seccomp_test(); | ||
55 | |||
56 | // check some well-known problematic files and directories | ||
57 | files_test(); | ||
58 | |||
59 | // network | ||
60 | network_test(); | ||
61 | |||
62 | // dbus | ||
63 | dbus_test(); | ||
64 | |||
65 | free(prog); | ||
66 | printf("--------------------------------------------------------------------------------\n"); | ||
67 | return 0; | ||
68 | } | ||
diff --git a/src/faudit/network.c b/src/faudit/network.c new file mode 100644 index 000000000..bb3116c3b --- /dev/null +++ b/src/faudit/network.c | |||
@@ -0,0 +1,77 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014-2016 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 | 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 | void check_netlink(void) { | ||
51 | socklen_t addr_len; | ||
52 | int sock = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, 0); | ||
53 | if (sock == -1) { | ||
54 | printf("GOOD: I cannot connect to netlink socket. Network utilities such as iproute2 will not work in the sandbox.\n"); | ||
55 | return; | ||
56 | } | ||
57 | |||
58 | struct sockaddr_nl local; | ||
59 | memset(&local, 0, sizeof(local)); | ||
60 | local.nl_family = AF_NETLINK; | ||
61 | local.nl_groups = 0; //subscriptions; | ||
62 | |||
63 | if (bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0) { | ||
64 | printf("GOOD: I cannot connect to netlink socket. Network utilities such as iproute2 will not work in the sandbox.\n"); | ||
65 | close(sock); | ||
66 | return; | ||
67 | } | ||
68 | |||
69 | close(sock); | ||
70 | printf("MAYBE: I can connect to netlink socket. Network utilities such as iproute2 will work fine in the sandbox. "); | ||
71 | printf("You can use \"--protocol\" to disable the socket.\n"); | ||
72 | } | ||
73 | |||
74 | void network_test(void) { | ||
75 | check_ssh(); | ||
76 | check_netlink(); | ||
77 | } | ||
diff --git a/src/faudit/pid.c b/src/faudit/pid.c new file mode 100644 index 000000000..2770daece --- /dev/null +++ b/src/faudit/pid.c | |||
@@ -0,0 +1,90 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014-2016 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 | 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 | for (i = 1; i <= 10; i++) { | ||
35 | struct stat s; | ||
36 | char *fname; | ||
37 | if (asprintf(&fname, "/proc/%d/comm", i) == -1) | ||
38 | errExit("asprintf"); | ||
39 | if (stat(fname, &s) == -1) { | ||
40 | free(fname); | ||
41 | continue; | ||
42 | } | ||
43 | |||
44 | // open file | ||
45 | /* coverity[toctou] */ | ||
46 | FILE *fp = fopen(fname, "r"); | ||
47 | if (!fp) { | ||
48 | fprintf(stderr, "Warning: cannot open %s\n", fname); | ||
49 | free(fname); | ||
50 | continue; | ||
51 | } | ||
52 | |||
53 | // read file | ||
54 | char buf[100]; | ||
55 | if (fgets(buf, 10, fp) == NULL) { | ||
56 | fprintf(stderr, "Warning: cannot read %s\n", fname); | ||
57 | fclose(fp); | ||
58 | free(fname); | ||
59 | continue; | ||
60 | } | ||
61 | // clean /n | ||
62 | char *ptr; | ||
63 | if ((ptr = strchr(buf, '\n')) != NULL) | ||
64 | *ptr = '\0'; | ||
65 | |||
66 | // check process name against the kernel list | ||
67 | int j = 0; | ||
68 | while (kern_proc[j] != NULL) { | ||
69 | if (strncmp(buf, kern_proc[j], strlen(kern_proc[j])) == 0) { | ||
70 | fclose(fp); | ||
71 | free(fname); | ||
72 | printf("BAD: Process %d, not running in a PID namespace. ", getpid()); | ||
73 | printf("Are you sure you're running in a sandbox?\n"); | ||
74 | return; | ||
75 | } | ||
76 | j++; | ||
77 | } | ||
78 | |||
79 | fclose(fp); | ||
80 | free(fname); | ||
81 | } | ||
82 | |||
83 | |||
84 | printf("GOOD: process %d running in a PID namespace.\n", getpid()); | ||
85 | |||
86 | // try to guess the type of container/sandbox | ||
87 | char *str = getenv("container"); | ||
88 | if (str) | ||
89 | printf("INFO: container/sandbox %s.\n", str); | ||
90 | } | ||
diff --git a/src/faudit/seccomp.c b/src/faudit/seccomp.c new file mode 100644 index 000000000..099e0e420 --- /dev/null +++ b/src/faudit/seccomp.c | |||
@@ -0,0 +1,103 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014-2016 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", 8) == 0) { | ||
31 | char *ptr = buf + 8; | ||
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 allowd.\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("finit_module... "); fflush(0); | ||
81 | syscall_run("finit_module"); | ||
82 | |||
83 | printf("delete_module... "); fflush(0); | ||
84 | syscall_run("delete_module"); | ||
85 | |||
86 | printf("chroot... "); fflush(0); | ||
87 | syscall_run("chroot"); | ||
88 | |||
89 | printf("pivot_root... "); fflush(0); | ||
90 | syscall_run("pivot_root"); | ||
91 | |||
92 | printf("iopl... "); fflush(0); | ||
93 | syscall_run("iopl"); | ||
94 | |||
95 | printf("ioperm... "); fflush(0); | ||
96 | syscall_run("ioperm"); | ||
97 | |||
98 | printf("\n"); | ||
99 | } | ||
100 | else | ||
101 | fprintf(stderr, "Error: unrecognized seccomp mode\n"); | ||
102 | |||
103 | } \ No newline at end of file | ||
diff --git a/src/faudit/syscall.c b/src/faudit/syscall.c new file mode 100644 index 000000000..84d73a03f --- /dev/null +++ b/src/faudit/syscall.c | |||
@@ -0,0 +1,91 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014-2016 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 syscall_helper(int argc, char **argv) { | ||
23 | if (strcmp(argv[2], "mount") == 0) { | ||
24 | mount(NULL, NULL, NULL, 0, NULL); | ||
25 | printf("\nUGLY: mount syscall permitted.\n"); | ||
26 | } | ||
27 | else if (strcmp(argv[2], "umount2") == 0) { | ||
28 | umount2(NULL, 0); | ||
29 | printf("\nUGLY: umount2 syscall permitted.\n"); | ||
30 | } | ||
31 | else if (strcmp(argv[2], "ptrace") == 0) { | ||
32 | ptrace(0, 0, NULL, NULL); | ||
33 | printf("\nUGLY: ptrace syscall permitted.\n"); | ||
34 | } | ||
35 | else if (strcmp(argv[2], "swapon") == 0) { | ||
36 | swapon(NULL, 0); | ||
37 | printf("\nUGLY: swapon syscall permitted.\n"); | ||
38 | } | ||
39 | else if (strcmp(argv[2], "swapoff") == 0) { | ||
40 | swapoff(NULL); | ||
41 | printf("\nUGLY: swapoff syscall permitted.\n"); | ||
42 | } | ||
43 | else if (strcmp(argv[2], "init_module") == 0) { | ||
44 | init_module(NULL, 0, NULL); | ||
45 | printf("\nUGLY: init_module syscall permitted.\n"); | ||
46 | } | ||
47 | else if (strcmp(argv[2], "finit_module") == 0) { | ||
48 | swapoff(0, NULL, 0); | ||
49 | printf("\nUGLY: finit_module syscall permitted.\n"); | ||
50 | } | ||
51 | else if (strcmp(argv[2], "delete_module") == 0) { | ||
52 | delete_module(NULL, 0); | ||
53 | printf("\nUGLY: delete_module syscall permitted.\n"); | ||
54 | } | ||
55 | else if (strcmp(argv[2], "chroot") == 0) { | ||
56 | int rv = chroot(NULL); | ||
57 | (void) rv; | ||
58 | printf("\nUGLY: chroot syscall permitted.\n"); | ||
59 | } | ||
60 | else if (strcmp(argv[2], "pivot_root") == 0) { | ||
61 | pivot_root(NULL, NULL); | ||
62 | printf("\nUGLY: pivot_root syscall permitted.\n"); | ||
63 | } | ||
64 | else if (strcmp(argv[2], "iopl") == 0) { | ||
65 | iopl(0L); | ||
66 | printf("\nUGLY: iopl syscall permitted.\n"); | ||
67 | } | ||
68 | else if (strcmp(argv[2], "ioperm") == 0) { | ||
69 | ioperm(0, 0, 0); | ||
70 | printf("\nUGLY: ioperm syscall permitted.\n"); | ||
71 | } | ||
72 | exit(0); | ||
73 | } | ||
74 | |||
75 | void syscall_run(const char *name) { | ||
76 | assert(prog); | ||
77 | |||
78 | pid_t child = fork(); | ||
79 | if (child < 0) | ||
80 | errExit("fork"); | ||
81 | if (child == 0) { | ||
82 | char *cmd; | ||
83 | if (asprintf(&cmd, "%s syscall %s", prog, name) == -1) | ||
84 | errExit("asprintf"); | ||
85 | execl(prog, prog, "syscall", name, NULL); | ||
86 | exit(0); | ||
87 | } | ||
88 | |||
89 | // wait for the child to finish | ||
90 | waitpid(child, NULL, 0); | ||
91 | } \ No newline at end of file | ||
@@ -101,10 +101,41 @@ firejail.src: E: no-changelogname-tag | |||
101 | firejail.src: W: invalid-url Source0: https://github.com/netblue30/firejail/archive/0.9.40.tar.gz#/firejail-0.9.40.tar.gz HTTP Error 404: Not Found | 101 | firejail.src: W: invalid-url Source0: https://github.com/netblue30/firejail/archive/0.9.40.tar.gz#/firejail-0.9.40.tar.gz HTTP Error 404: Not Found |
102 | 1 packages and 0 specfiles checked; 1 errors, 1 warnings. | 102 | 1 packages and 0 specfiles checked; 1 errors, 1 warnings. |
103 | 103 | ||
104 | 15. Testing: | 104 | 15. bug: capabiliteis declared on the command line take precedence over caps declared in profiles |
105 | find /usr/share/doc/firejail | cpio -ov > t1 | 105 | |
106 | strings /usr/bin/firejail > t1 | 106 | $ firejail --caps.keep=chown,net_bind_service src/faudit/faudit |
107 | gzip -c /usr/bin/firejail > t1 | 107 | Reading profile /etc/firejail/default.profile |
108 | Reading profile /etc/firejail/disable-common.inc | ||
109 | Reading profile /etc/firejail/disable-programs.inc | ||
110 | Reading profile /etc/firejail/disable-passwdmgr.inc | ||
111 | |||
112 | ** Note: you can use --noprofile to disable default.profile ** | ||
113 | |||
114 | Parent pid 6872, child pid 6873 | ||
115 | |||
116 | Child process initialized | ||
117 | |||
118 | ----- Firejail Audit: the Good, the Bad and the Ugly ----- | ||
119 | |||
120 | GOOD: Process PID 2, running in a PID namespace | ||
121 | Container/sandbox: firejail | ||
122 | GOOD: all capabilities are disabled | ||
123 | |||
124 | |||
125 | Parent is shutting down, bye... | ||
126 | |||
127 | 16. Sound devices: | ||
128 | /dev/snd | ||
129 | |||
130 | |||
131 | /dev/snd/pcmC0D0 -> /dev/audio0 (/dev/audio) -> minor 4 | ||
132 | /dev/snd/pcmC0D0 -> /dev/dsp0 (/dev/dsp) -> minor 3 | ||
133 | /dev/snd/pcmC0D1 -> /dev/adsp0 (/dev/adsp) -> minor 12 | ||
134 | /dev/snd/pcmC1D0 -> /dev/audio1 -> minor 4+16 = 20 | ||
135 | /dev/snd/pcmC1D0 -> /dev/dsp1 -> minor 3+16 = 19 | ||
136 | /dev/snd/pcmC1D1 -> /dev/adsp1 -> minor 12+16 = 28 | ||
137 | /dev/snd/pcmC2D0 -> /dev/audio2 -> minor 4+32 = 36 | ||
138 | /dev/snd/pcmC2D0 -> /dev/dsp2 -> minor 3+32 = 35 | ||
139 | /dev/snd/pcmC2D1 -> /dev/adsp2 -> minor 12+32 = 44 | ||
108 | 140 | ||
109 | use diff -s to compare the files | ||
110 | 141 | ||