diff options
74 files changed, 1390 insertions, 712 deletions
diff --git a/.gitignore b/.gitignore index 459119b14..9b9935b93 100644 --- a/.gitignore +++ b/.gitignore | |||
@@ -22,4 +22,5 @@ src/tags | |||
22 | src/faudit/faudit | 22 | src/faudit/faudit |
23 | src/fnet/fnet | 23 | src/fnet/fnet |
24 | src/fseccomp/fseccomp | 24 | src/fseccomp/fseccomp |
25 | src/fcopy/fcopy | ||
25 | uids.h | 26 | uids.h |
diff --git a/Makefile.in b/Makefile.in index 86fd4f4b7..772dc8c06 100644 --- a/Makefile.in +++ b/Makefile.in | |||
@@ -1,6 +1,6 @@ | |||
1 | all: apps man | 1 | all: apps man |
2 | MYLIBS = src/lib | 2 | MYLIBS = src/lib |
3 | APPS = src/firejail src/firemon src/firecfg src/libtrace src/libtracelog src/ftee src/faudit src/libconnect src/fnet src/fseccomp | 3 | APPS = src/firejail src/firemon src/firecfg src/libtrace src/libtracelog src/ftee src/faudit src/libconnect src/fnet src/fseccomp src/fcopy |
4 | MANPAGES = firejail.1 firemon.1 firecfg.1 firejail-profile.5 firejail-login.5 | 4 | MANPAGES = firejail.1 firemon.1 firecfg.1 firejail-profile.5 firejail-login.5 |
5 | 5 | ||
6 | prefix=@prefix@ | 6 | prefix=@prefix@ |
@@ -78,6 +78,7 @@ realinstall: | |||
78 | install -c -m 0755 src/faudit/faudit $(DESTDIR)/$(libdir)/firejail/. | 78 | install -c -m 0755 src/faudit/faudit $(DESTDIR)/$(libdir)/firejail/. |
79 | install -c -m 0755 src/fnet/fnet $(DESTDIR)/$(libdir)/firejail/. | 79 | install -c -m 0755 src/fnet/fnet $(DESTDIR)/$(libdir)/firejail/. |
80 | install -c -m 0755 src/fseccomp/fseccomp $(DESTDIR)/$(libdir)/firejail/. | 80 | install -c -m 0755 src/fseccomp/fseccomp $(DESTDIR)/$(libdir)/firejail/. |
81 | install -c -m 0755 src/fcopy/fcopy $(DESTDIR)/$(libdir)/firejail/. | ||
81 | # documents | 82 | # documents |
82 | install -m 0755 -d $(DESTDIR)/$(DOCDIR) | 83 | install -m 0755 -d $(DESTDIR)/$(DOCDIR) |
83 | install -c -m 0644 COPYING $(DESTDIR)/$(DOCDIR)/. | 84 | install -c -m 0644 COPYING $(DESTDIR)/$(DOCDIR)/. |
@@ -128,6 +129,7 @@ install-strip: all | |||
128 | strip src/faudit/faudit | 129 | strip src/faudit/faudit |
129 | strip src/fnet/fnet | 130 | strip src/fnet/fnet |
130 | strip src/fseccomp/fseccomp | 131 | strip src/fseccomp/fseccomp |
132 | strip src/fcopy/fcopy | ||
131 | $(MAKE) realinstall | 133 | $(MAKE) realinstall |
132 | 134 | ||
133 | uninstall: | 135 | uninstall: |
@@ -145,7 +147,7 @@ uninstall: | |||
145 | rm -f $(DESTDIR)/$(datarootdir)/bash-completion/completions/firecfg | 147 | rm -f $(DESTDIR)/$(datarootdir)/bash-completion/completions/firecfg |
146 | 148 | ||
147 | DISTFILES = "src etc platform configure configure.ac Makefile.in install.sh mkman.sh mketc.sh mkdeb.sh mkuid.sh COPYING README RELNOTES" | 149 | DISTFILES = "src etc platform configure configure.ac Makefile.in install.sh mkman.sh mketc.sh mkdeb.sh mkuid.sh COPYING README RELNOTES" |
148 | DISTFILES_TEST = "test/rlimit test/apps test/apps-x11 test/apps-x11-xorg test/root test/environment test/profiles test/utils test/compile test/filters test/network test/arguments test/fs test/sysutils" | 150 | DISTFILES_TEST = "test/apps test/apps-x11 test/apps-x11-xorg test/root test/fcopy test/environment test/profiles test/utils test/compile test/filters test/network test/arguments test/fs test/sysutils" |
149 | 151 | ||
150 | dist: | 152 | dist: |
151 | mv config.status config.status.old | 153 | mv config.status config.status.old |
@@ -223,10 +225,10 @@ test-arguments: | |||
223 | test-fs: | 225 | test-fs: |
224 | cd test/fs; ./fs.sh | grep TESTING | 226 | cd test/fs; ./fs.sh | grep TESTING |
225 | 227 | ||
226 | test-rlimit: | 228 | test-fcopy: |
227 | cd test/rlimit; ./rlimit.sh | grep TESTING | 229 | cd test/fcopy; ./fcopy.sh | grep TESTING |
228 | 230 | ||
229 | test: test-profiles test-fs test-utils test-environment test-apps test-apps-x11 test-apps-x11-xorg test-filters test-arguments test-rlimit | 231 | test: test-profiles test-fcopy test-fs test-utils test-environment test-apps test-apps-x11 test-apps-x11-xorg test-filters test-arguments |
230 | echo "TEST COMPLETE" | 232 | echo "TEST COMPLETE" |
231 | 233 | ||
232 | ########################################## | 234 | ########################################## |
@@ -254,6 +256,6 @@ test-overlay: | |||
254 | 256 | ||
255 | # For testing hidepid system, the command to set it up is "mount -o remount,rw,hidepid=2 /proc" | 257 | # For testing hidepid system, the command to set it up is "mount -o remount,rw,hidepid=2 /proc" |
256 | 258 | ||
257 | test-all: test-root test-network test-appimage test-overlay test | 259 | test-all: test-root test-network test-appimage test-overlay test-fcopy test |
258 | echo "TEST COMPLETE" | 260 | echo "TEST COMPLETE" |
259 | \ No newline at end of file | 261 | \ No newline at end of file |
@@ -103,6 +103,7 @@ valoq (https://github.com/valoq) | |||
103 | - blacklist suid binaries in disable-common.inc | 103 | - blacklist suid binaries in disable-common.inc |
104 | - fix man pages | 104 | - fix man pages |
105 | - various profile improvements | 105 | - various profile improvements |
106 | - added keypass2, qemu profiles | ||
106 | Vadim A. Misbakh-Soloviov (https://github.com/msva) | 107 | Vadim A. Misbakh-Soloviov (https://github.com/msva) |
107 | - profile fixes | 108 | - profile fixes |
108 | Rafael Cavalcanti (https://github.com/rccavalcanti) | 109 | Rafael Cavalcanti (https://github.com/rccavalcanti) |
@@ -51,10 +51,15 @@ Use this issue to request new profiles: https://github.com/netblue30/firejail/is | |||
51 | ````` | 51 | ````` |
52 | 52 | ||
53 | ````` | 53 | ````` |
54 | ## AppImage type 2 support | ||
55 | ````` | ||
56 | |||
57 | ````` | ||
54 | ## New Profiles | 58 | ## New Profiles |
55 | xiphos, Tor Browser Bundle, display (imagemagik), Wire, mumble, zoom,Guayadeque | 59 | xiphos, Tor Browser Bundle, display (imagemagik), Wire, mumble, zoom,Guayadeque, qemu, keypass2 |
56 | amarok, ark, atool, bleachbit, brasero, dolphin, dragon, elinks, enchant, exiftool, file-roller, gedit | 60 | amarok, ark, atool, bleachbit, brasero, dolphin, dragon, elinks, enchant, exiftool, file-roller, gedit |
57 | gjs, gnome-books, gnome-clocks, gnome-documents, gnome-maps, gnome-music, gnome-photos, gnome-weather | 61 | gjs, gnome-books, gnome-clocks, gnome-documents, gnome-maps, gnome-music, gnome-photos, gnome-weather |
58 | goobox, gpa, gpg, gpg-agent, highlight, img2txt, k3b, kate, lynx, mediainfo, nautilus, odt2txt, pdftotext | 62 | goobox, gpa, gpg, gpg-agent, highlight, img2txt, k3b, kate, lynx, mediainfo, nautilus, odt2txt, pdftotext |
59 | simple-scan, skanlite, ssh-agent, tracker, transmission-cli, transmission-show, w3m, xfburn, xpra | 63 | simple-scan, skanlite, ssh-agent, tracker, transmission-cli, transmission-show, w3m, xfburn, xpra |
60 | 64 | ||
65 | |||
@@ -5,9 +5,12 @@ firejail (0.9.45) baseline; urgency=low | |||
5 | * security: invalid environment exploit found by Martin Carpenter | 5 | * security: invalid environment exploit found by Martin Carpenter |
6 | * security: split most of networking code in a separate executable | 6 | * security: split most of networking code in a separate executable |
7 | * security: split seccomp filter code configuration in a separate executable | 7 | * security: split seccomp filter code configuration in a separate executable |
8 | * security: split file copying in private option in a separate executable | ||
8 | * feature: allow root user access to /dev/shm (--noblacklist=/dev/shm) | 9 | * feature: allow root user access to /dev/shm (--noblacklist=/dev/shm) |
10 | * feature: AppImage type 2 support | ||
11 | * feature: test coverage (gcov) support | ||
9 | * new profiles: xiphos, Tor Browser Bundle, display (imagemagik), Wire, | 12 | * new profiles: xiphos, Tor Browser Bundle, display (imagemagik), Wire, |
10 | * new profiles: mumble, zoom, Guayadeque | 13 | * new profiles: mumble, zoom, Guayadeque, qemu, keypass2 |
11 | * bugfixes | 14 | * bugfixes |
12 | -- netblue30 <netblue30@yahoo.com> Sun, 23 Oct 2016 08:00:00 -0500 | 15 | -- netblue30 <netblue30@yahoo.com> Sun, 23 Oct 2016 08:00:00 -0500 |
13 | 16 | ||
@@ -3777,7 +3777,7 @@ if test "$prefix" = /usr; then | |||
3777 | sysconfdir="/etc" | 3777 | sysconfdir="/etc" |
3778 | fi | 3778 | fi |
3779 | 3779 | ||
3780 | ac_config_files="$ac_config_files Makefile src/lib/Makefile src/fnet/Makefile src/firejail/Makefile src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/ftee/Makefile src/faudit/Makefile src/libconnect/Makefile src/fseccomp/Makefile" | 3780 | ac_config_files="$ac_config_files Makefile src/lib/Makefile src/fcopy/Makefile src/fnet/Makefile src/firejail/Makefile src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile src/ftee/Makefile src/faudit/Makefile src/libconnect/Makefile src/fseccomp/Makefile" |
3781 | 3781 | ||
3782 | cat >confcache <<\_ACEOF | 3782 | cat >confcache <<\_ACEOF |
3783 | # This file is a shell script that caches the results of configure | 3783 | # This file is a shell script that caches the results of configure |
@@ -4488,6 +4488,7 @@ do | |||
4488 | case $ac_config_target in | 4488 | case $ac_config_target in |
4489 | "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; | 4489 | "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; |
4490 | "src/lib/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib/Makefile" ;; | 4490 | "src/lib/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib/Makefile" ;; |
4491 | "src/fcopy/Makefile") CONFIG_FILES="$CONFIG_FILES src/fcopy/Makefile" ;; | ||
4491 | "src/fnet/Makefile") CONFIG_FILES="$CONFIG_FILES src/fnet/Makefile" ;; | 4492 | "src/fnet/Makefile") CONFIG_FILES="$CONFIG_FILES src/fnet/Makefile" ;; |
4492 | "src/firejail/Makefile") CONFIG_FILES="$CONFIG_FILES src/firejail/Makefile" ;; | 4493 | "src/firejail/Makefile") CONFIG_FILES="$CONFIG_FILES src/firejail/Makefile" ;; |
4493 | "src/firemon/Makefile") CONFIG_FILES="$CONFIG_FILES src/firemon/Makefile" ;; | 4494 | "src/firemon/Makefile") CONFIG_FILES="$CONFIG_FILES src/firemon/Makefile" ;; |
diff --git a/configure.ac b/configure.ac index 74ba09f43..f3076f2f8 100644 --- a/configure.ac +++ b/configure.ac | |||
@@ -158,8 +158,9 @@ if test "$prefix" = /usr; then | |||
158 | sysconfdir="/etc" | 158 | sysconfdir="/etc" |
159 | fi | 159 | fi |
160 | 160 | ||
161 | AC_OUTPUT(Makefile src/lib/Makefile src/fnet/Makefile src/firejail/Makefile src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile \ | 161 | AC_OUTPUT(Makefile src/lib/Makefile src/fcopy/Makefile src/fnet/Makefile src/firejail/Makefile \ |
162 | src/firecfg/Makefile src/ftee/Makefile src/faudit/Makefile src/libconnect/Makefile src/fseccomp/Makefile) | 162 | src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile \ |
163 | src/ftee/Makefile src/faudit/Makefile src/libconnect/Makefile src/fseccomp/Makefile) | ||
163 | 164 | ||
164 | echo | 165 | echo |
165 | echo "Configuration options:" | 166 | echo "Configuration options:" |
diff --git a/etc/vivaldi.profile b/etc/vivaldi.profile index 3c608dccb..08b046847 100644 --- a/etc/vivaldi.profile +++ b/etc/vivaldi.profile | |||
@@ -6,7 +6,6 @@ include /etc/firejail/disable-programs.inc | |||
6 | include /etc/firejail/disable-devel.inc | 6 | include /etc/firejail/disable-devel.inc |
7 | 7 | ||
8 | netfilter | 8 | netfilter |
9 | nonewprivs | ||
10 | 9 | ||
11 | whitelist ${DOWNLOADS} | 10 | whitelist ${DOWNLOADS} |
12 | mkdir ~/.config/vivaldi | 11 | mkdir ~/.config/vivaldi |
@@ -1,21 +1,28 @@ | |||
1 | #!/bin/bash | 1 | #!/bin/bash |
2 | 2 | ||
3 | gcov_init() { | ||
4 | USER=`whoami` | ||
5 | firejail --help | ||
6 | firemon --help | ||
7 | /usr/lib/firejail/fnet --help | ||
8 | /usr/lib/firejail/fseccomp --help | ||
9 | /usr/lib/firejail/ftee --help | ||
10 | /usr/lib/firejail/fcopy --help | ||
11 | firecfg --help | ||
12 | sudo chown $USER:$USER `find .` | ||
13 | } | ||
14 | |||
3 | generate() { | 15 | generate() { |
4 | lcov --capture -d src/firejail -d src/firemon -d src/fseccomp -d src/fnet -d src/ftee -d src/lib -d src/firecfg --output-file gcov-file | 16 | lcov --capture -d src/firejail -d src/firemon -d src/fcopy -d src/fseccomp -d src/fnet -d src/ftee -d src/lib -d src/firecfg --output-file gcov-file |
5 | rm -fr gcov-dir | 17 | rm -fr gcov-dir |
6 | genhtml gcov-file --output-directory gcov-dir | 18 | genhtml gcov-file --output-directory gcov-dir |
7 | } | 19 | } |
8 | 20 | ||
9 | # init | 21 | gcov_init |
10 | USER=`whoami` | ||
11 | firejail --help | ||
12 | firemon --help | ||
13 | /usr/lib/firejail/fnet --help | ||
14 | /usr/lib/firejail/fseccomp --help | ||
15 | /usr/lib/firejail/ftee --help | ||
16 | firecfg --help | ||
17 | sudo chown $USER:$USER `find .` | ||
18 | generate | 22 | generate |
23 | echo "press any key to continue, or Ctrl-C to exit" | ||
24 | read text | ||
25 | |||
19 | 26 | ||
20 | # running tests | 27 | # running tests |
21 | make test-root | 28 | make test-root |
@@ -34,6 +41,10 @@ make test-overlay | |||
34 | generate | 41 | generate |
35 | sleep 2 | 42 | sleep 2 |
36 | 43 | ||
44 | make test-fcopy | ||
45 | generate | ||
46 | sleep 2 | ||
47 | |||
37 | make test-profiles | 48 | make test-profiles |
38 | generate | 49 | generate |
39 | sleep 2 | 50 | sleep 2 |
diff --git a/src/fcopy/Makefile.in b/src/fcopy/Makefile.in new file mode 100644 index 000000000..278957a4f --- /dev/null +++ b/src/fcopy/Makefile.in | |||
@@ -0,0 +1,45 @@ | |||
1 | all: fcopy | ||
2 | |||
3 | prefix=@prefix@ | ||
4 | exec_prefix=@exec_prefix@ | ||
5 | libdir=@libdir@ | ||
6 | sysconfdir=@sysconfdir@ | ||
7 | |||
8 | VERSION=@PACKAGE_VERSION@ | ||
9 | NAME=@PACKAGE_NAME@ | ||
10 | HAVE_SECCOMP_H=@HAVE_SECCOMP_H@ | ||
11 | HAVE_SECCOMP=@HAVE_SECCOMP@ | ||
12 | HAVE_CHROOT=@HAVE_CHROOT@ | ||
13 | HAVE_BIND=@HAVE_BIND@ | ||
14 | HAVE_FATAL_WARNINGS=@HAVE_FATAL_WARNINGS@ | ||
15 | HAVE_NETWORK=@HAVE_NETWORK@ | ||
16 | HAVE_USERNS=@HAVE_USERNS@ | ||
17 | HAVE_X11=@HAVE_X11@ | ||
18 | HAVE_FILE_TRANSFER=@HAVE_FILE_TRANSFER@ | ||
19 | HAVE_WHITELIST=@HAVE_WHITELIST@ | ||
20 | HAVE_GLOBALCFG=@HAVE_GLOBALCFG@ | ||
21 | HAVE_APPARMOR=@HAVE_APPARMOR@ | ||
22 | HAVE_OVERLAYFS=@HAVE_OVERLAYFS@ | ||
23 | HAVE_PRIVATE_HOME=@HAVE_PRIVATE_HOME@ | ||
24 | EXTRA_LDFLAGS +=@EXTRA_LDFLAGS@ | ||
25 | HAVE_GCOV=@HAVE_GCOV@ | ||
26 | EXTRA_LDFLAGS +=@EXTRA_LDFLAGS@ | ||
27 | |||
28 | H_FILE_LIST = $(sort $(wildcard *.[h])) | ||
29 | C_FILE_LIST = $(sort $(wildcard *.c)) | ||
30 | OBJS = $(C_FILE_LIST:.c=.o) | ||
31 | BINOBJS = $(foreach file, $(OBJS), $file) | ||
32 | CFLAGS += -ggdb $(HAVE_FATAL_WARNINGS) -O2 -DVERSION='"$(VERSION)"' $(HAVE_GCOV) -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)/firejail"' -DLIBDIR='"$(libdir)"' $(HAVE_X11) $(HAVE_PRIVATE_HOME) $(HAVE_APPARMOR) $(HAVE_OVERLAYFS) $(HAVE_SECCOMP) $(HAVE_GLOBALCFG) $(HAVE_SECCOMP_H) $(HAVE_CHROOT) $(HAVE_NETWORK) $(HAVE_USERNS) $(HAVE_BIND) $(HAVE_FILE_TRANSFER) $(HAVE_WHITELIST) -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -pie -Wformat -Wformat-security | ||
33 | LDFLAGS += -pie -Wl,-z,relro -Wl,-z,now -lpthread | ||
34 | |||
35 | %.o : %.c $(H_FILE_LIST) ../include/common.h ../include/syscall.h | ||
36 | $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@ | ||
37 | |||
38 | fcopy: $(OBJS) | ||
39 | $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(EXTRA_LDFLAGS) | ||
40 | |||
41 | clean:; rm -f *.o fcopy *.gcov *.gcda *.gcno | ||
42 | |||
43 | distclean: clean | ||
44 | rm -fr Makefile | ||
45 | |||
diff --git a/src/fcopy/main.c b/src/fcopy/main.c new file mode 100644 index 000000000..b1e2813db --- /dev/null +++ b/src/fcopy/main.c | |||
@@ -0,0 +1,340 @@ | |||
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 "../include/common.h" | ||
22 | #include <fcntl.h> | ||
23 | #include <ftw.h> | ||
24 | |||
25 | |||
26 | #define COPY_LIMIT (500 * 1024 *1024) | ||
27 | static int size_limit_reached = 0; | ||
28 | static unsigned file_cnt = 0; | ||
29 | static unsigned size_cnt = 0; | ||
30 | |||
31 | static char *outpath = NULL; | ||
32 | static char *inpath = NULL; | ||
33 | |||
34 | |||
35 | // modified version of the function from util.c | ||
36 | static void copy_file(const char *srcname, const char *destname, mode_t mode, uid_t uid, gid_t gid) { | ||
37 | assert(srcname); | ||
38 | assert(destname); | ||
39 | mode &= 07777; | ||
40 | |||
41 | // open source | ||
42 | int src = open(srcname, O_RDONLY); | ||
43 | if (src < 0) { | ||
44 | fprintf(stderr, "Warning: cannot open %s, file not copied\n", srcname); | ||
45 | return; | ||
46 | } | ||
47 | |||
48 | // open destination | ||
49 | int dst = open(destname, O_CREAT|O_WRONLY|O_TRUNC, 0755); | ||
50 | if (dst < 0) { | ||
51 | fprintf(stderr, "Warning fcopy: cannot open %s, file not copied\n", destname); | ||
52 | close(src); | ||
53 | return; | ||
54 | } | ||
55 | |||
56 | // copy | ||
57 | ssize_t len; | ||
58 | static const int BUFLEN = 1024; | ||
59 | unsigned char buf[BUFLEN]; | ||
60 | while ((len = read(src, buf, BUFLEN)) > 0) { | ||
61 | int done = 0; | ||
62 | while (done != len) { | ||
63 | int rv = write(dst, buf + done, len - done); | ||
64 | if (rv == -1) | ||
65 | goto errexit; | ||
66 | done += rv; | ||
67 | } | ||
68 | } | ||
69 | fflush(0); | ||
70 | |||
71 | if (fchown(dst, uid, gid) == -1) | ||
72 | goto errexit; | ||
73 | if (fchmod(dst, mode) == -1) | ||
74 | goto errexit; | ||
75 | |||
76 | close(src); | ||
77 | close(dst); | ||
78 | |||
79 | return; | ||
80 | |||
81 | errexit: | ||
82 | close(src); | ||
83 | close(dst); | ||
84 | unlink(destname); | ||
85 | fprintf(stderr, "Warning fcopy: cannot copy %s\n", destname); | ||
86 | } | ||
87 | |||
88 | |||
89 | |||
90 | // modified version of the function in firejail/util.c | ||
91 | static void mkdir_attr(const char *fname, mode_t mode, uid_t uid, gid_t gid) { | ||
92 | assert(fname); | ||
93 | mode &= 07777; | ||
94 | |||
95 | if (mkdir(fname, mode) == -1 || | ||
96 | chmod(fname, mode) == -1) { | ||
97 | fprintf(stderr, "Error fcopy: failed to create %s directory\n", fname); | ||
98 | errExit("mkdir/chmod"); | ||
99 | } | ||
100 | if (chown(fname, uid, gid)) | ||
101 | fprintf(stderr, "Warning fcopy: failed to change ownership of %s\n", fname); | ||
102 | } | ||
103 | |||
104 | void copy_link(const char *target, const char *linkpath, mode_t mode, uid_t uid, gid_t gid) { | ||
105 | (void) mode; | ||
106 | (void) uid; | ||
107 | (void) gid; | ||
108 | char *rp = realpath(target, NULL); | ||
109 | if (rp) { | ||
110 | if (symlink(rp, linkpath) == -1) | ||
111 | goto errout; | ||
112 | free(rp); | ||
113 | } | ||
114 | else | ||
115 | goto errout; | ||
116 | |||
117 | return; | ||
118 | errout: | ||
119 | fprintf(stderr, "Warning fcopy: cannot create symbolic link %s\n", target); | ||
120 | } | ||
121 | |||
122 | static int first = 1; | ||
123 | static int fs_copydir(const char *infname, const struct stat *st, int ftype, struct FTW *sftw) { | ||
124 | (void) st; | ||
125 | (void) sftw; | ||
126 | assert(infname); | ||
127 | assert(*infname != '\0'); | ||
128 | assert(outpath); | ||
129 | assert(*outpath != '\0'); | ||
130 | assert(inpath); | ||
131 | |||
132 | // check size limit | ||
133 | if (size_limit_reached) | ||
134 | return 0; | ||
135 | |||
136 | |||
137 | char *outfname; | ||
138 | if (asprintf(&outfname, "%s%s", outpath, infname + strlen(inpath)) == -1) | ||
139 | errExit("asprintf"); | ||
140 | |||
141 | //printf("outpaht %s\n", outpath); | ||
142 | //printf("inpath %s\n", inpath); | ||
143 | //printf("infname %s\n", infname); | ||
144 | //printf("outfname %s\n\n", outfname); | ||
145 | |||
146 | // don't copy it if we already have the file | ||
147 | struct stat s; | ||
148 | if (stat(outfname, &s) == 0) { | ||
149 | if (first) | ||
150 | first = 0; | ||
151 | else | ||
152 | fprintf(stderr, "Warning fcopy: skipping %s, file already present\n", infname); | ||
153 | free(outfname); | ||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | // extract mode and ownership | ||
158 | if (stat(infname, &s) != 0) { | ||
159 | fprintf(stderr, "Warning fcopy: skipping %s, cannot find inode\n", infname); | ||
160 | free(outfname); | ||
161 | return 0; | ||
162 | } | ||
163 | uid_t uid = s.st_uid; | ||
164 | gid_t gid = s.st_gid; | ||
165 | mode_t mode = s.st_mode; | ||
166 | |||
167 | // recalculate size | ||
168 | if ((s.st_size + size_cnt) > COPY_LIMIT) { | ||
169 | fprintf(stderr, "Error fcopy: size limit of %dMB reached\n", (COPY_LIMIT / 1024) / 1024); | ||
170 | size_limit_reached = 1; | ||
171 | free(outfname); | ||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | file_cnt++; | ||
176 | size_cnt += s.st_size; | ||
177 | |||
178 | if(ftype == FTW_F) { | ||
179 | copy_file(infname, outfname, mode, uid, gid); | ||
180 | } | ||
181 | else if (ftype == FTW_D) { | ||
182 | mkdir_attr(outfname, mode, uid, gid); | ||
183 | } | ||
184 | else if (ftype == FTW_SL) { | ||
185 | copy_link(infname, outfname, mode, uid, gid); | ||
186 | } | ||
187 | |||
188 | return(0); | ||
189 | } | ||
190 | |||
191 | static char *check(const char *src) { | ||
192 | struct stat s; | ||
193 | char *rsrc = realpath(src, NULL); | ||
194 | if (!rsrc || stat(rsrc, &s) == -1) | ||
195 | goto errexit; | ||
196 | |||
197 | // check uid | ||
198 | if (s.st_uid != getuid() || s.st_gid != getgid()) | ||
199 | goto errexit; | ||
200 | |||
201 | // dir, link, regular file | ||
202 | if (S_ISDIR(s.st_mode) || S_ISREG(s.st_mode) || S_ISLNK(s.st_mode)) | ||
203 | return rsrc; // normal exit from the function | ||
204 | |||
205 | errexit: | ||
206 | fprintf(stderr, "Error fcopy: invalid file %s\n", src); | ||
207 | exit(1); | ||
208 | } | ||
209 | |||
210 | static void duplicate_dir(const char *src, const char *dest, struct stat *s) { | ||
211 | (void) s; | ||
212 | char *rsrc = check(src); | ||
213 | char *rdest = check(dest); | ||
214 | inpath = rsrc; | ||
215 | outpath = rdest; | ||
216 | |||
217 | // walk | ||
218 | if(nftw(rsrc, fs_copydir, 1, FTW_PHYS) != 0) { | ||
219 | fprintf(stderr, "Error: unable to copy file\n"); | ||
220 | exit(1); | ||
221 | } | ||
222 | |||
223 | free(rsrc); | ||
224 | free(rdest); | ||
225 | } | ||
226 | |||
227 | static void duplicate_file(const char *src, const char *dest, struct stat *s) { | ||
228 | char *rsrc = check(src); | ||
229 | char *rdest = check(dest); | ||
230 | uid_t uid = s->st_uid; | ||
231 | gid_t gid = s->st_gid; | ||
232 | mode_t mode = s->st_mode; | ||
233 | |||
234 | // build destination file name | ||
235 | char *name; | ||
236 | char *ptr = strrchr(rsrc, '/'); | ||
237 | ptr++; | ||
238 | if (asprintf(&name, "%s/%s", rdest, ptr) == -1) | ||
239 | errExit("asprintf"); | ||
240 | |||
241 | // copy | ||
242 | copy_file(rsrc, name, mode, uid, gid); | ||
243 | |||
244 | free(name); | ||
245 | free(rsrc); | ||
246 | free(rdest); | ||
247 | } | ||
248 | |||
249 | static void duplicate_link(const char *src, const char *dest, struct stat *s) { | ||
250 | char *rsrc = check(src); // we drop the result and use the original name | ||
251 | char *rdest = check(dest); | ||
252 | uid_t uid = s->st_uid; | ||
253 | gid_t gid = s->st_gid; | ||
254 | mode_t mode = s->st_mode; | ||
255 | |||
256 | // build destination file name | ||
257 | char *name; | ||
258 | // char *ptr = strrchr(rsrc, '/'); | ||
259 | char *ptr = strrchr(src, '/'); | ||
260 | ptr++; | ||
261 | if (asprintf(&name, "%s/%s", rdest, ptr) == -1) | ||
262 | errExit("asprintf"); | ||
263 | |||
264 | // copy | ||
265 | copy_link(rsrc, name, mode, uid, gid); | ||
266 | |||
267 | free(name); | ||
268 | free(rsrc); | ||
269 | free(rdest); | ||
270 | } | ||
271 | |||
272 | static void usage(void) { | ||
273 | printf("Usage: fcopy src dest\n"); | ||
274 | printf("Copy src file in dest directory. If src is a directory, copy all the files in\n"); | ||
275 | printf("src recoursively. If the destination directory does not exist, it will be created.\n"); | ||
276 | } | ||
277 | |||
278 | int main(int argc, char **argv) { | ||
279 | #if 0 | ||
280 | { | ||
281 | //system("cat /proc/self/status"); | ||
282 | int i; | ||
283 | for (i = 0; i < argc; i++) | ||
284 | printf("*%s* ", argv[i]); | ||
285 | printf("\n"); | ||
286 | } | ||
287 | #endif | ||
288 | if (argc != 3) { | ||
289 | fprintf(stderr, "Error fcopy: files missing\n"); | ||
290 | usage(); | ||
291 | exit(1); | ||
292 | } | ||
293 | |||
294 | // check the two files; remove ending / | ||
295 | char *src = argv[1]; | ||
296 | int len = strlen(src); | ||
297 | if (src[len - 1] == '/') | ||
298 | src[len - 1] = '\0'; | ||
299 | if (strcspn(src, "\\*&!?\"'<>%^(){}[];,") != (size_t)len) { | ||
300 | fprintf(stderr, "Error fcopy: invalid file name %s\n", src); | ||
301 | exit(1); | ||
302 | } | ||
303 | |||
304 | char *dest = argv[2]; | ||
305 | len = strlen(dest); | ||
306 | if (dest[len - 1] == '/') | ||
307 | dest[len - 1] = '\0'; | ||
308 | if (strcspn(dest, "\\*&!?\"'<>%^(){}[];,~") != (size_t)len) { | ||
309 | fprintf(stderr, "Error fcopy: invalid file name %s\n", dest); | ||
310 | exit(1); | ||
311 | } | ||
312 | |||
313 | |||
314 | // the destination should be a directory; | ||
315 | struct stat s; | ||
316 | if (stat(dest, &s) == -1 || | ||
317 | !S_ISDIR(s.st_mode)) { | ||
318 | fprintf(stderr, "Error fcopy: invalid destination directory\n"); | ||
319 | exit(1); | ||
320 | } | ||
321 | |||
322 | // copy files | ||
323 | if (lstat(src, &s) == -1) { | ||
324 | fprintf(stderr, "Error fcopy: cannot find source file\n"); | ||
325 | exit(1); | ||
326 | } | ||
327 | |||
328 | if (S_ISDIR(s.st_mode)) | ||
329 | duplicate_dir(src, dest, &s); | ||
330 | else if (S_ISREG(s.st_mode)) | ||
331 | duplicate_file(src, dest, &s); | ||
332 | else if (S_ISLNK(s.st_mode)) | ||
333 | duplicate_link(src, dest, &s); | ||
334 | else { | ||
335 | fprintf(stderr, "Error fcopy: source file unsupported\n"); | ||
336 | exit(1); | ||
337 | } | ||
338 | |||
339 | return 0; | ||
340 | } | ||
diff --git a/src/firejail/appimage.c b/src/firejail/appimage.c index a658173eb..6a9ca1679 100644 --- a/src/firejail/appimage.c +++ b/src/firejail/appimage.c | |||
@@ -31,38 +31,39 @@ | |||
31 | static char *devloop = NULL; // device file | 31 | static char *devloop = NULL; // device file |
32 | static char *mntdir = NULL; // mount point in /tmp directory | 32 | static char *mntdir = NULL; // mount point in /tmp directory |
33 | 33 | ||
34 | const char *appimage_getdir(void) { | 34 | void appimage_set(const char *appimage) { |
35 | return mntdir; | 35 | assert(appimage); |
36 | } | ||
37 | |||
38 | void appimage_set(const char *appimage_path) { | ||
39 | assert(appimage_path); | ||
40 | assert(devloop == NULL); // don't call this twice! | 36 | assert(devloop == NULL); // don't call this twice! |
41 | EUID_ASSERT(); | 37 | EUID_ASSERT(); |
42 | 38 | ||
43 | #ifdef LOOP_CTL_GET_FREE // test for older kernels; this definition is found in /usr/include/linux/loop.h | 39 | #ifdef LOOP_CTL_GET_FREE // test for older kernels; this definition is found in /usr/include/linux/loop.h |
44 | // check appimage_path | 40 | // check appimage file |
45 | if (access(appimage_path, R_OK) == -1) { | 41 | invalid_filename(appimage); |
42 | if (access(appimage, R_OK) == -1) { | ||
46 | fprintf(stderr, "Error: cannot access AppImage file\n"); | 43 | fprintf(stderr, "Error: cannot access AppImage file\n"); |
47 | exit(1); | 44 | exit(1); |
48 | } | 45 | } |
49 | 46 | ||
50 | // get appimage type and ELF size | 47 | // get appimage type and ELF size |
51 | // a value of 0 means we are dealing with a type1 appimage | 48 | // a value of 0 means we are dealing with a type1 appimage |
52 | long unsigned int size = appimage2_size(appimage_path); | 49 | long unsigned int size = appimage2_size(appimage); |
53 | if (arg_debug) | 50 | if (arg_debug) |
54 | printf("AppImage ELF size %lu\n", size); | 51 | printf("AppImage ELF size %lu\n", size); |
55 | 52 | ||
56 | // open as user to prevent race condition | 53 | // open appimage file |
57 | int ffd = open(appimage_path, O_RDONLY|O_CLOEXEC); | 54 | int ffd = open(appimage, O_RDONLY|O_CLOEXEC); |
58 | if (ffd == -1) { | 55 | if (ffd == -1) { |
59 | fprintf(stderr, "Error: /dev/loop-control interface is not supported by your kernel\n"); | 56 | fprintf(stderr, "Error: cannot open AppImage file\n"); |
60 | exit(1); | 57 | exit(1); |
61 | } | 58 | } |
62 | 59 | ||
63 | // find or allocate a free loop device to use | 60 | // find or allocate a free loop device to use |
64 | EUID_ROOT(); | 61 | EUID_ROOT(); |
65 | int cfd = open("/dev/loop-control", O_RDWR); | 62 | int cfd = open("/dev/loop-control", O_RDWR); |
63 | if (cfd == -1) { | ||
64 | fprintf(stderr, "Error: /dev/loop-control interface is not supported by your kernel\n"); | ||
65 | exit(1); | ||
66 | } | ||
66 | int devnr = ioctl(cfd, LOOP_CTL_GET_FREE); | 67 | int devnr = ioctl(cfd, LOOP_CTL_GET_FREE); |
67 | if (devnr == -1) { | 68 | if (devnr == -1) { |
68 | fprintf(stderr, "Error: cannot allocate a new loopback device\n"); | 69 | fprintf(stderr, "Error: cannot allocate a new loopback device\n"); |
@@ -117,7 +118,7 @@ void appimage_set(const char *appimage_path) { | |||
117 | EUID_USER(); | 118 | EUID_USER(); |
118 | 119 | ||
119 | // set environment | 120 | // set environment |
120 | if (appimage_path && setenv("APPIMAGE", appimage_path, 1) < 0) | 121 | if (appimage && setenv("APPIMAGE", appimage, 1) < 0) |
121 | errExit("setenv"); | 122 | errExit("setenv"); |
122 | if (mntdir && setenv("APPDIR", mntdir, 1) < 0) | 123 | if (mntdir && setenv("APPDIR", mntdir, 1) < 0) |
123 | errExit("setenv"); | 124 | errExit("setenv"); |
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index d7ba539e6..2562094d3 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -490,8 +490,6 @@ void fs_private_template(void); | |||
490 | void fs_check_private_dir(void); | 490 | void fs_check_private_dir(void); |
491 | // check new private template home directory (--private-template= option) exit if it fails | 491 | // check new private template home directory (--private-template= option) exit if it fails |
492 | void fs_check_private_template(void); | 492 | void fs_check_private_template(void); |
493 | // check directory list specified by user (--private-home option) - exit if it fails | ||
494 | void fs_check_home_list(void); | ||
495 | void fs_private_home_list(void); | 493 | void fs_private_home_list(void); |
496 | 494 | ||
497 | 495 | ||
@@ -557,7 +555,6 @@ void network_del_run_file(pid_t pid); | |||
557 | void network_set_run_file(pid_t pid); | 555 | void network_set_run_file(pid_t pid); |
558 | 556 | ||
559 | // fs_etc.c | 557 | // fs_etc.c |
560 | void fs_check_etc_list(void); | ||
561 | void fs_private_etc_list(void); | 558 | void fs_private_etc_list(void); |
562 | 559 | ||
563 | // no_sandbox.c | 560 | // no_sandbox.c |
@@ -590,7 +587,6 @@ void pulseaudio_init(void); | |||
590 | void pulseaudio_disable(void); | 587 | void pulseaudio_disable(void); |
591 | 588 | ||
592 | // fs_bin.c | 589 | // fs_bin.c |
593 | void fs_check_bin_list(void); | ||
594 | void fs_private_bin_list(void); | 590 | void fs_private_bin_list(void); |
595 | 591 | ||
596 | // protocol.c | 592 | // protocol.c |
@@ -681,6 +677,7 @@ void build_cmdline(char **command_line, char **window_title, int argc, char **ar | |||
681 | #define PATH_FNET (LIBDIR "/firejail/fnet") | 677 | #define PATH_FNET (LIBDIR "/firejail/fnet") |
682 | #define PATH_FIREMON (PREFIX "/bin/firemon") | 678 | #define PATH_FIREMON (PREFIX "/bin/firemon") |
683 | #define PATH_FSECCOMP (LIBDIR "/firejail/fseccomp") | 679 | #define PATH_FSECCOMP (LIBDIR "/firejail/fseccomp") |
680 | #define PATH_FCOPY (LIBDIR "/firejail/fcopy") | ||
684 | // bitmapped filters for sbox_run | 681 | // bitmapped filters for sbox_run |
685 | #define SBOX_ROOT (1 << 0) // run the sandbox as root | 682 | #define SBOX_ROOT (1 << 0) // run the sandbox as root |
686 | #define SBOX_USER (1 << 1) // run the sandbox as a regular user | 683 | #define SBOX_USER (1 << 1) // run the sandbox as a regular user |
diff --git a/src/firejail/fs_bin.c b/src/firejail/fs_bin.c index 6cc1bf3ab..421df717d 100644 --- a/src/firejail/fs_bin.c +++ b/src/firejail/fs_bin.c | |||
@@ -39,7 +39,6 @@ static char *paths[] = { | |||
39 | // return 1 if found, 0 if not found | 39 | // return 1 if found, 0 if not found |
40 | static char *check_dir_or_file(const char *name) { | 40 | static char *check_dir_or_file(const char *name) { |
41 | assert(name); | 41 | assert(name); |
42 | invalid_filename(name); | ||
43 | 42 | ||
44 | struct stat s; | 43 | struct stat s; |
45 | char *fname = NULL; | 44 | char *fname = NULL; |
@@ -94,68 +93,13 @@ static char *check_dir_or_file(const char *name) { | |||
94 | return paths[i]; | 93 | return paths[i]; |
95 | } | 94 | } |
96 | 95 | ||
97 | void fs_check_bin_list(void) { | 96 | static void duplicate(char *fname) { |
98 | EUID_ASSERT(); | 97 | if (*fname == '~' || *fname == '/' || strstr(fname, "..")) { |
99 | if (strstr(cfg.bin_private_keep, "..")) { | 98 | fprintf(stderr, "Error: \"%s\" is an invalid filename\n", fname); |
100 | fprintf(stderr, "Error: invalid private bin list\n"); | ||
101 | exit(1); | 99 | exit(1); |
102 | } | 100 | } |
103 | 101 | invalid_filename(fname); | |
104 | char *dlist = strdup(cfg.bin_private_keep); | ||
105 | if (!dlist) | ||
106 | errExit("strdup"); | ||
107 | |||
108 | // create a new list removing files not found | ||
109 | char *newlist = malloc(strlen(dlist) + 1 + 1); // +',' + '\0' | ||
110 | if (!newlist) | ||
111 | errExit("malloc"); | ||
112 | *newlist = '\0'; | ||
113 | char *newlistptr = newlist; | ||
114 | |||
115 | // check the first file | ||
116 | char *ptr = strtok(dlist, ","); | ||
117 | int notfound = 0; | ||
118 | if (check_dir_or_file(ptr)) { | ||
119 | // file found, copy the name in the new list | ||
120 | strcpy(newlistptr, ptr); | ||
121 | strcat(newlistptr, ","); | ||
122 | newlistptr += strlen(newlistptr); | ||
123 | } | ||
124 | else | ||
125 | notfound = 1; | ||
126 | |||
127 | // check the rest of the list | ||
128 | while ((ptr = strtok(NULL, ",")) != NULL) { | ||
129 | if (check_dir_or_file(ptr)) { | ||
130 | // file found, copy the name in the new list | ||
131 | strcpy(newlistptr, ptr); | ||
132 | strcat(newlistptr, ","); | ||
133 | newlistptr += strlen(newlistptr); | ||
134 | } | ||
135 | else | ||
136 | notfound = 1; | ||
137 | } | ||
138 | |||
139 | if (*newlist == '\0') { | ||
140 | // fprintf(stderr, "Warning: no --private-bin list executable found, option disabled\n"); | ||
141 | // cfg.bin_private_keep = NULL; | ||
142 | // arg_private_bin = 0; | ||
143 | free(newlist); | ||
144 | } | ||
145 | else { | ||
146 | ptr = strrchr(newlist, ','); | ||
147 | assert(ptr); | ||
148 | *ptr = '\0'; | ||
149 | if (notfound && !arg_quiet) | ||
150 | fprintf(stderr, "Warning: not all executables from --private-bin list were found. The current list is %s\n", newlist); | ||
151 | |||
152 | cfg.bin_private_keep = newlist; | ||
153 | } | ||
154 | |||
155 | free(dlist); | ||
156 | } | ||
157 | 102 | ||
158 | static void duplicate(char *fname) { | ||
159 | char *path = check_dir_or_file(fname); | 103 | char *path = check_dir_or_file(fname); |
160 | if (!path) | 104 | if (!path) |
161 | return; | 105 | return; |
@@ -165,44 +109,9 @@ static void duplicate(char *fname) { | |||
165 | if (asprintf(&full_path, "%s/%s", path, fname) == -1) | 109 | if (asprintf(&full_path, "%s/%s", path, fname) == -1) |
166 | errExit("asprintf"); | 110 | errExit("asprintf"); |
167 | 111 | ||
168 | char *actual_path = realpath(full_path, NULL); | 112 | // copy the file |
169 | if (actual_path) { | 113 | sbox_run(SBOX_ROOT| SBOX_SECCOMP, 3, PATH_FCOPY, full_path, RUN_BIN_DIR); |
170 | // if the file is a symbolic link not under path, make a symbolic link | 114 | fs_logger2("clone", fname); |
171 | if (is_link(full_path) && strncmp(actual_path, path, strlen(path))) { | ||
172 | char *lnkname; | ||
173 | if (asprintf(&lnkname, "%s/%s", RUN_BIN_DIR, fname) == -1) | ||
174 | errExit("asprintf"); | ||
175 | int rv = symlink(actual_path, lnkname); | ||
176 | if (rv) | ||
177 | fprintf(stderr, "Warning cannot create symbolic link %s\n", lnkname); | ||
178 | else if (arg_debug) | ||
179 | printf("Created symbolic link %s -> %s\n", lnkname, actual_path); | ||
180 | free(lnkname); | ||
181 | } | ||
182 | else { | ||
183 | // copy the file | ||
184 | if (arg_debug) | ||
185 | printf("running: %s -a %s %s/%s", RUN_CP_COMMAND, actual_path, RUN_BIN_DIR, fname); | ||
186 | |||
187 | pid_t child = fork(); | ||
188 | if (child < 0) | ||
189 | errExit("fork"); | ||
190 | if (child == 0) { | ||
191 | char *f; | ||
192 | if (asprintf(&f, "%s/%s", RUN_BIN_DIR, fname) == -1) | ||
193 | errExit("asprintf"); | ||
194 | clearenv(); | ||
195 | execlp(RUN_CP_COMMAND, RUN_CP_COMMAND, "-a", actual_path, f, NULL); | ||
196 | perror("execlp"); | ||
197 | _exit(1); | ||
198 | } | ||
199 | // wait for the child to finish | ||
200 | waitpid(child, NULL, 0); | ||
201 | |||
202 | } | ||
203 | free(actual_path); | ||
204 | } | ||
205 | |||
206 | free(full_path); | 115 | free(full_path); |
207 | } | 116 | } |
208 | 117 | ||
@@ -214,42 +123,20 @@ void fs_private_bin_list(void) { | |||
214 | // create /run/firejail/mnt/bin directory | 123 | // create /run/firejail/mnt/bin directory |
215 | mkdir_attr(RUN_BIN_DIR, 0755, 0, 0); | 124 | mkdir_attr(RUN_BIN_DIR, 0755, 0, 0); |
216 | 125 | ||
217 | // copy the list of files in the new etc directory | 126 | if (arg_debug) |
218 | // using a new child process without root privileges | 127 | printf("Copying files in the new bin directory\n"); |
219 | fs_logger_print(); // save the current log | ||
220 | pid_t child = fork(); | ||
221 | if (child < 0) | ||
222 | errExit("fork"); | ||
223 | if (child == 0) { | ||
224 | if (arg_debug) | ||
225 | printf("Copying files in the new home:\n"); | ||
226 | 128 | ||
227 | // elevate privileges - files in the new /bin directory belong to root | 129 | // copy the list of files in the new home directory |
228 | if (setreuid(0, 0) < 0) | 130 | char *dlist = strdup(private_list); |
229 | errExit("setreuid"); | 131 | if (!dlist) |
230 | if (setregid(0, 0) < 0) | 132 | errExit("strdup"); |
231 | errExit("setregid"); | ||
232 | |||
233 | // copy the list of files in the new home directory | ||
234 | char *dlist = strdup(private_list); | ||
235 | if (!dlist) | ||
236 | errExit("strdup"); | ||
237 | |||
238 | 133 | ||
239 | char *ptr = strtok(dlist, ","); | 134 | char *ptr = strtok(dlist, ","); |
135 | duplicate(ptr); | ||
136 | while ((ptr = strtok(NULL, ",")) != NULL) | ||
240 | duplicate(ptr); | 137 | duplicate(ptr); |
241 | 138 | free(dlist); | |
242 | while ((ptr = strtok(NULL, ",")) != NULL) | ||
243 | duplicate(ptr); | ||
244 | free(dlist); | ||
245 | fs_logger_print(); | 139 | fs_logger_print(); |
246 | #ifdef HAVE_GCOV | ||
247 | __gcov_flush(); | ||
248 | #endif | ||
249 | _exit(0); | ||
250 | } | ||
251 | // wait for the child to finish | ||
252 | waitpid(child, NULL, 0); | ||
253 | 140 | ||
254 | // mount-bind | 141 | // mount-bind |
255 | int i = 0; | 142 | int i = 0; |
@@ -265,29 +152,5 @@ void fs_private_bin_list(void) { | |||
265 | } | 152 | } |
266 | i++; | 153 | i++; |
267 | } | 154 | } |
268 | |||
269 | // log cloned files | ||
270 | char *dlist = strdup(private_list); | ||
271 | if (!dlist) | ||
272 | errExit("strdup"); | ||
273 | |||
274 | |||
275 | char *ptr = strtok(dlist, ","); | ||
276 | while (ptr) { | ||
277 | i = 0; | ||
278 | while (paths[i]) { | ||
279 | struct stat s; | ||
280 | if (stat(paths[i], &s) == 0) { | ||
281 | char *fname; | ||
282 | if (asprintf(&fname, "%s/%s", paths[i], ptr) == -1) | ||
283 | errExit("asprintf"); | ||
284 | fs_logger2("clone", fname); | ||
285 | free(fname); | ||
286 | } | ||
287 | i++; | ||
288 | } | ||
289 | ptr = strtok(NULL, ","); | ||
290 | } | ||
291 | free(dlist); | ||
292 | } | 155 | } |
293 | 156 | ||
diff --git a/src/firejail/fs_etc.c b/src/firejail/fs_etc.c index 7e18840fd..80329d5ba 100644 --- a/src/firejail/fs_etc.c +++ b/src/firejail/fs_etc.c | |||
@@ -21,20 +21,13 @@ | |||
21 | #include <sys/mount.h> | 21 | #include <sys/mount.h> |
22 | #include <sys/stat.h> | 22 | #include <sys/stat.h> |
23 | #include <sys/types.h> | 23 | #include <sys/types.h> |
24 | #include <sys/wait.h> | ||
25 | #include <unistd.h> | 24 | #include <unistd.h> |
26 | 25 | ||
27 | // return 0 if file not found, 1 if found | 26 | // return 0 if file not found, 1 if found |
28 | static int check_dir_or_file(const char *name) { | 27 | static int check_dir_or_file(const char *fname) { |
29 | assert(name); | 28 | assert(fname); |
30 | invalid_filename(name); | ||
31 | 29 | ||
32 | struct stat s; | 30 | struct stat s; |
33 | char *fname; | ||
34 | if (asprintf(&fname, "/etc/%s", name) == -1) | ||
35 | errExit("asprintf"); | ||
36 | if (arg_debug) | ||
37 | printf("Checking %s\n", fname); | ||
38 | if (stat(fname, &s) == -1) { | 31 | if (stat(fname, &s) == -1) { |
39 | if (arg_debug) | 32 | if (arg_debug) |
40 | printf("Warning: file %s not found.\n", fname); | 33 | printf("Warning: file %s not found.\n", fname); |
@@ -46,78 +39,46 @@ static int check_dir_or_file(const char *name) { | |||
46 | goto errexit; | 39 | goto errexit; |
47 | 40 | ||
48 | // dir or regular file | 41 | // dir or regular file |
49 | if (S_ISDIR(s.st_mode) || S_ISREG(s.st_mode)) { | 42 | if (S_ISDIR(s.st_mode) || S_ISREG(s.st_mode) || !is_link(fname)) |
50 | free(fname); | 43 | return 1; // normal exit |
51 | return 1; | ||
52 | } | ||
53 | |||
54 | if (!is_link(fname)) { | ||
55 | free(fname); | ||
56 | return 1; | ||
57 | } | ||
58 | |||
59 | 44 | ||
60 | errexit: | 45 | errexit: |
61 | fprintf(stderr, "Error: invalid file type, %s.\n", fname); | 46 | fprintf(stderr, "Error: invalid file type, %s.\n", fname); |
62 | exit(1); | 47 | exit(1); |
63 | } | 48 | } |
64 | 49 | ||
65 | void fs_check_etc_list(void) { | 50 | static void duplicate(char *fname) { |
66 | EUID_ASSERT(); | 51 | if (*fname == '~' || *fname == '/' || strstr(fname, "..")) { |
67 | if (strstr(cfg.etc_private_keep, "..")) { | 52 | fprintf(stderr, "Error: \"%s\" is an invalid filename\n", fname); |
68 | fprintf(stderr, "Error: invalid private etc list\n"); | ||
69 | exit(1); | 53 | exit(1); |
70 | } | 54 | } |
71 | 55 | invalid_filename(fname); | |
72 | char *dlist = strdup(cfg.etc_private_keep); | 56 | |
73 | if (!dlist) | 57 | char *src; |
74 | errExit("strdup"); | 58 | if (asprintf(&src, "/etc/%s", fname) == -1) |
75 | 59 | errExit("asprintf"); | |
76 | // build a new list only with the files found | 60 | if (check_dir_or_file(src) == 0) { |
77 | char *newlist = malloc(strlen(cfg.etc_private_keep) + 1); | 61 | if (!arg_quiet) |
78 | if (!newlist) | 62 | fprintf(stderr, "Warning: skipping %s for private bin\n", fname); |
79 | errExit("malloc"); | 63 | free(src); |
80 | *newlist = '\0'; | 64 | return; |
81 | |||
82 | char *ptr = strtok(dlist, ","); | ||
83 | if (check_dir_or_file(ptr)) | ||
84 | strcat(newlist, ptr); | ||
85 | while ((ptr = strtok(NULL, ",")) != NULL) { | ||
86 | if (check_dir_or_file(ptr)) { | ||
87 | strcat(newlist, ","); | ||
88 | strcat(newlist, ptr); | ||
89 | } | ||
90 | } | 65 | } |
91 | cfg.etc_private_keep = newlist; | ||
92 | |||
93 | free(dlist); | ||
94 | } | ||
95 | 66 | ||
96 | static void duplicate(char *fname) { | 67 | struct stat s; |
97 | // copy the file | 68 | if (stat(src, &s) == 0 && S_ISDIR(s.st_mode)) { |
98 | if (arg_debug) | 69 | // create the directory in RUN_ETC_DIR |
99 | printf("running: %s -a --parents /etc/%s %s\n", RUN_CP_COMMAND, fname, RUN_MNT_DIR); | 70 | char *dirname; |
100 | 71 | if (asprintf(&dirname, "%s/%s", RUN_ETC_DIR, fname) == -1) | |
101 | pid_t child = fork(); | ||
102 | if (child < 0) | ||
103 | errExit("fork"); | ||
104 | if (child == 0) { | ||
105 | char *f; | ||
106 | if (asprintf(&f, "/etc/%s", fname) == -1) | ||
107 | errExit("asprintf"); | 72 | errExit("asprintf"); |
108 | clearenv(); | 73 | create_empty_dir_as_root(dirname, s.st_mode); |
109 | execlp(RUN_CP_COMMAND, RUN_CP_COMMAND, "-a", "--parents", f, RUN_MNT_DIR, NULL); | 74 | sbox_run(SBOX_ROOT| SBOX_SECCOMP, 3, PATH_FCOPY, src, dirname); |
110 | perror("execlp"); | 75 | free(dirname); |
111 | _exit(1); | ||
112 | } | 76 | } |
113 | // wait for the child to finish | 77 | else |
114 | waitpid(child, NULL, 0); | 78 | sbox_run(SBOX_ROOT| SBOX_SECCOMP, 3, PATH_FCOPY, src, RUN_ETC_DIR); |
115 | 79 | ||
116 | char *name; | 80 | fs_logger2("clone", src); |
117 | if (asprintf(&name, "/etc/%s", fname) == -1) | 81 | free(src); |
118 | errExit("asprintf"); | ||
119 | fs_logger2("clone", name); | ||
120 | free(name); | ||
121 | } | 82 | } |
122 | 83 | ||
123 | 84 | ||
@@ -125,12 +86,6 @@ void fs_private_etc_list(void) { | |||
125 | char *private_list = cfg.etc_private_keep; | 86 | char *private_list = cfg.etc_private_keep; |
126 | assert(private_list); | 87 | assert(private_list); |
127 | 88 | ||
128 | struct stat s; | ||
129 | if (stat("/etc", &s) == -1) { | ||
130 | fprintf(stderr, "Error: cannot find user /etc directory\n"); | ||
131 | exit(1); | ||
132 | } | ||
133 | |||
134 | // create /run/firejail/mnt/etc directory | 89 | // create /run/firejail/mnt/etc directory |
135 | mkdir_attr(RUN_ETC_DIR, 0755, 0, 0); | 90 | mkdir_attr(RUN_ETC_DIR, 0755, 0, 0); |
136 | fs_logger("tmpfs /etc"); | 91 | fs_logger("tmpfs /etc"); |
@@ -141,39 +96,22 @@ void fs_private_etc_list(void) { | |||
141 | // copy the list of files in the new etc directory | 96 | // copy the list of files in the new etc directory |
142 | // using a new child process with root privileges | 97 | // using a new child process with root privileges |
143 | if (*private_list != '\0') { | 98 | if (*private_list != '\0') { |
144 | pid_t child = fork(); | 99 | if (arg_debug) |
145 | if (child < 0) | 100 | printf("Copying files in the new etc directory:\n"); |
146 | errExit("fork"); | 101 | |
147 | if (child == 0) { | 102 | // copy the list of files in the new home directory |
148 | if (arg_debug) | 103 | char *dlist = strdup(private_list); |
149 | printf("Copying files in the new etc directory:\n"); | 104 | if (!dlist) |
105 | errExit("strdup"); | ||
150 | 106 | ||
151 | // elevate privileges - files in the new /etc directory belong to root | 107 | |
152 | if (setreuid(0, 0) < 0) | 108 | char *ptr = strtok(dlist, ","); |
153 | errExit("setreuid"); | 109 | duplicate(ptr); |
154 | if (setregid(0, 0) < 0) | ||
155 | errExit("setregid"); | ||
156 | |||
157 | // copy the list of files in the new home directory | ||
158 | char *dlist = strdup(private_list); | ||
159 | if (!dlist) | ||
160 | errExit("strdup"); | ||
161 | |||
162 | 110 | ||
163 | char *ptr = strtok(dlist, ","); | 111 | while ((ptr = strtok(NULL, ",")) != NULL) |
164 | duplicate(ptr); | 112 | duplicate(ptr); |
165 | 113 | free(dlist); | |
166 | while ((ptr = strtok(NULL, ",")) != NULL) | 114 | fs_logger_print(); |
167 | duplicate(ptr); | ||
168 | free(dlist); | ||
169 | fs_logger_print(); | ||
170 | #ifdef HAVE_GCOV | ||
171 | __gcov_flush(); | ||
172 | #endif | ||
173 | _exit(0); | ||
174 | } | ||
175 | // wait for the child to finish | ||
176 | waitpid(child, NULL, 0); | ||
177 | } | 115 | } |
178 | 116 | ||
179 | if (arg_debug) | 117 | if (arg_debug) |
diff --git a/src/firejail/fs_home.c b/src/firejail/fs_home.c index 242482d26..1f8da398e 100644 --- a/src/firejail/fs_home.c +++ b/src/firejail/fs_home.c | |||
@@ -28,7 +28,7 @@ | |||
28 | #include <sys/wait.h> | 28 | #include <sys/wait.h> |
29 | #include <unistd.h> | 29 | #include <unistd.h> |
30 | #include <grp.h> | 30 | #include <grp.h> |
31 | #include <ftw.h> | 31 | //#include <ftw.h> |
32 | 32 | ||
33 | static void skel(const char *homedir, uid_t u, gid_t g) { | 33 | static void skel(const char *homedir, uid_t u, gid_t g) { |
34 | char *fname; | 34 | char *fname; |
@@ -212,12 +212,6 @@ void fs_private_homedir(void) { | |||
212 | 212 | ||
213 | uid_t u = getuid(); | 213 | uid_t u = getuid(); |
214 | gid_t g = getgid(); | 214 | gid_t g = getgid(); |
215 | struct stat s; | ||
216 | if (stat(homedir, &s) == -1) { | ||
217 | fprintf(stderr, "Error: cannot find user home directory\n"); | ||
218 | exit(1); | ||
219 | } | ||
220 | |||
221 | 215 | ||
222 | // mount bind private_homedir on top of homedir | 216 | // mount bind private_homedir on top of homedir |
223 | if (arg_debug) | 217 | if (arg_debug) |
@@ -349,122 +343,17 @@ void fs_check_private_dir(void) { | |||
349 | //*********************************************************************************** | 343 | //*********************************************************************************** |
350 | // --private-home | 344 | // --private-home |
351 | //*********************************************************************************** | 345 | //*********************************************************************************** |
352 | #define PRIVATE_COPY_LIMIT (500 * 1024 *1024) | ||
353 | static int size_limit_reached = 0; | ||
354 | static unsigned file_cnt = 0; | ||
355 | static unsigned size_cnt = 0; | ||
356 | static char *check_dir_or_file(const char *name); | ||
357 | |||
358 | int fs_copydir(const char *path, const struct stat *st, int ftype, struct FTW *sftw) { | ||
359 | (void) st; | ||
360 | (void) sftw; | ||
361 | if (size_limit_reached) | ||
362 | return 0; | ||
363 | |||
364 | struct stat s; | ||
365 | char *dest; | ||
366 | if (asprintf(&dest, "%s%s", RUN_HOME_DIR, path + strlen(cfg.homedir)) == -1) | ||
367 | errExit("asprintf"); | ||
368 | |||
369 | // don't copy it if we already have the file | ||
370 | if (stat(dest, &s) == 0) { | ||
371 | free(dest); | ||
372 | return 0; | ||
373 | } | ||
374 | |||
375 | // extract mode and ownership | ||
376 | if (stat(path, &s) != 0) { | ||
377 | free(dest); | ||
378 | return 0; | ||
379 | } | ||
380 | |||
381 | // check uid | ||
382 | if (s.st_uid != firejail_uid || s.st_gid != firejail_gid) { | ||
383 | free(dest); | ||
384 | return 0; | ||
385 | } | ||
386 | |||
387 | if ((s.st_size + size_cnt) > PRIVATE_COPY_LIMIT) { | ||
388 | size_limit_reached = 1; | ||
389 | free(dest); | ||
390 | return 0; | ||
391 | } | ||
392 | |||
393 | file_cnt++; | ||
394 | size_cnt += s.st_size; | ||
395 | |||
396 | if(ftype == FTW_F) | ||
397 | copy_file(path, dest, firejail_uid, firejail_gid, s.st_mode); | ||
398 | else if (ftype == FTW_D) { | ||
399 | if (mkdir(dest, s.st_mode) == -1) | ||
400 | errExit("mkdir"); | ||
401 | if (set_perms(dest, firejail_uid, firejail_gid, s.st_mode)) | ||
402 | errExit("set_perms"); | ||
403 | #if 0 | ||
404 | struct stat s2; | ||
405 | if (stat(dest, &s2) == 0) { | ||
406 | printf("%s\t", dest); | ||
407 | printf((S_ISDIR(s.st_mode)) ? "d" : "-"); | ||
408 | printf((s.st_mode & S_IRUSR) ? "r" : "-"); | ||
409 | printf((s.st_mode & S_IWUSR) ? "w" : "-"); | ||
410 | printf((s.st_mode & S_IXUSR) ? "x" : "-"); | ||
411 | printf((s.st_mode & S_IRGRP) ? "r" : "-"); | ||
412 | printf((s.st_mode & S_IWGRP) ? "w" : "-"); | ||
413 | printf((s.st_mode & S_IXGRP) ? "x" : "-"); | ||
414 | printf((s.st_mode & S_IROTH) ? "r" : "-"); | ||
415 | printf((s.st_mode & S_IWOTH) ? "w" : "-"); | ||
416 | printf((s.st_mode & S_IXOTH) ? "x" : "-"); | ||
417 | printf("\n"); | ||
418 | } | ||
419 | #endif | ||
420 | |||
421 | fs_logger2("clone", path); | ||
422 | } | ||
423 | |||
424 | free(dest); | ||
425 | return(0); | ||
426 | } | ||
427 | |||
428 | static void duplicate(char *name) { | ||
429 | char *fname = check_dir_or_file(name); | ||
430 | |||
431 | if (arg_debug) | ||
432 | printf("Private home: duplicating %s\n", fname); | ||
433 | assert(strncmp(fname, cfg.homedir, strlen(cfg.homedir)) == 0); | ||
434 | |||
435 | struct stat s; | ||
436 | if (stat(fname, &s) == -1) { | ||
437 | free(fname); | ||
438 | return; | ||
439 | } | ||
440 | |||
441 | if(nftw(fname, fs_copydir, 1, FTW_PHYS) != 0) { | ||
442 | fprintf(stderr, "Error: unable to copy template dir\n"); | ||
443 | exit(1); | ||
444 | } | ||
445 | fs_logger_print(); // save the current log | ||
446 | |||
447 | free(fname); | ||
448 | } | ||
449 | |||
450 | |||
451 | |||
452 | static char *check_dir_or_file(const char *name) { | 346 | static char *check_dir_or_file(const char *name) { |
453 | assert(name); | 347 | assert(name); |
454 | struct stat s; | ||
455 | 348 | ||
456 | // basic checks | 349 | // basic checks |
457 | invalid_filename(name); | 350 | invalid_filename(name); |
458 | |||
459 | if (arg_debug) | 351 | if (arg_debug) |
460 | printf("Private home: checking %s\n", name); | 352 | printf("Private home: checking %s\n", name); |
461 | 353 | ||
462 | // expand home directory | 354 | // expand home directory |
463 | char *fname = expand_home(name, cfg.homedir); | 355 | char *fname = expand_home(name, cfg.homedir); |
464 | if (!fname) { | 356 | assert(fname); |
465 | fprintf(stderr, "Error: file %s not found.\n", name); | ||
466 | exit(1); | ||
467 | } | ||
468 | 357 | ||
469 | // If it doesn't start with '/', it must be relative to homedir | 358 | // If it doesn't start with '/', it must be relative to homedir |
470 | if (fname[0] != '/') { | 359 | if (fname[0] != '/') { |
@@ -475,87 +364,77 @@ static char *check_dir_or_file(const char *name) { | |||
475 | fname = tmp; | 364 | fname = tmp; |
476 | } | 365 | } |
477 | 366 | ||
478 | // check the file is in user home directory | 367 | // we allow only files in user home directory or symbolic links to files or directories owned by the user |
479 | char *rname = realpath(fname, NULL); | 368 | struct stat s; |
480 | if (!rname) { | 369 | if (lstat(fname, &s) == 0 && S_ISLNK(s.st_mode)) { |
481 | fprintf(stderr, "Error: invalid file %s\n", name); | 370 | if (stat(fname, &s) == 0) { |
482 | exit(1); | 371 | if (s.st_uid != getuid()) { |
483 | } | 372 | fprintf(stderr, "Error: symbolic link %s to file or directory not owned by the user\n", fname); |
484 | if (strncmp(rname, cfg.homedir, strlen(cfg.homedir)) != 0) { | 373 | exit(1); |
485 | fprintf(stderr, "Error: file %s is not in user home directory\n", name); | 374 | } |
486 | exit(1); | 375 | return fname; |
487 | } | 376 | } |
488 | 377 | else { | |
489 | // a full home directory is not allowed | 378 | fprintf(stderr, "Error: invalid file %s\n", name); |
490 | if (strcmp(rname, cfg.homedir) == 0) { | ||
491 | fprintf(stderr, "Error: invalid directory %s\n", rname); | ||
492 | exit(1); | ||
493 | } | ||
494 | |||
495 | // only top files and directories in user home are allowed | ||
496 | char *ptr = rname + strlen(cfg.homedir); | ||
497 | if (*ptr == '\0') { | ||
498 | fprintf(stderr, "Error: invalid file %s\n", name); | ||
499 | exit(1); | ||
500 | } | ||
501 | ptr++; | ||
502 | ptr = strchr(ptr, '/'); | ||
503 | if (ptr) { | ||
504 | if (*ptr != '\0') { | ||
505 | fprintf(stderr, "Error: only top files and directories in user home are allowed\n"); | ||
506 | exit(1); | 379 | exit(1); |
507 | } | 380 | } |
508 | } | 381 | } |
509 | 382 | else { | |
510 | if (stat(fname, &s) == -1) { | 383 | // check the file is in user home directory, a full home directory is not allowed |
511 | fprintf(stderr, "Error: file %s not found.\n", fname); | 384 | char *rname = realpath(fname, NULL); |
512 | exit(1); | 385 | if (!rname || |
513 | } | 386 | strncmp(rname, cfg.homedir, strlen(cfg.homedir)) != 0 || |
514 | 387 | strcmp(rname, cfg.homedir) == 0) { | |
515 | // check uid | 388 | fprintf(stderr, "Error: invalid file %s\n", name); |
516 | uid_t uid = getuid(); | 389 | exit(1); |
517 | gid_t gid = getgid(); | 390 | } |
518 | if (s.st_uid != uid || s.st_gid != gid) { | 391 | |
519 | fprintf(stderr, "Error: only files or directories created by the current user are allowed.\n"); | 392 | // only top files and directories in user home are allowed |
520 | exit(1); | 393 | char *ptr = rname + strlen(cfg.homedir); |
521 | } | 394 | assert(*ptr != '\0'); |
522 | 395 | ptr = strchr(++ptr, '/'); | |
523 | // dir or regular file | 396 | if (ptr) { |
524 | if (S_ISDIR(s.st_mode) || S_ISREG(s.st_mode)) { | 397 | if (*ptr != '\0') { |
398 | fprintf(stderr, "Error: only top files and directories in user home are allowed\n"); | ||
399 | exit(1); | ||
400 | } | ||
401 | } | ||
525 | free(fname); | 402 | free(fname); |
526 | return rname; // regular exit from the function | 403 | return rname; |
527 | } | 404 | } |
528 | |||
529 | fprintf(stderr, "Error: invalid file type, %s.\n", fname); | ||
530 | exit(1); | ||
531 | } | 405 | } |
532 | 406 | ||
407 | static void duplicate(char *name) { | ||
408 | char *fname = check_dir_or_file(name); | ||
533 | 409 | ||
534 | // check directory list specified by user (--private-home option) - exit if it fails | 410 | if (arg_debug) |
535 | void fs_check_home_list(void) { | 411 | printf("Private home: duplicating %s\n", fname); |
536 | if (strstr(cfg.home_private_keep, "..")) { | 412 | assert(strncmp(fname, cfg.homedir, strlen(cfg.homedir)) == 0); |
537 | fprintf(stderr, "Error: invalid private-home list\n"); | ||
538 | exit(1); | ||
539 | } | ||
540 | |||
541 | char *dlist = strdup(cfg.home_private_keep); | ||
542 | if (!dlist) | ||
543 | errExit("strdup"); | ||
544 | |||
545 | char *ptr = strtok(dlist, ","); | ||
546 | char *tmp = check_dir_or_file(ptr); | ||
547 | free(tmp); | ||
548 | 413 | ||
549 | while ((ptr = strtok(NULL, ",")) != NULL) { | 414 | struct stat s; |
550 | tmp = check_dir_or_file(ptr); | 415 | if (lstat(fname, &s) == -1) { |
551 | free(tmp); | 416 | free(fname); |
417 | return; | ||
418 | } | ||
419 | else if (S_ISDIR(s.st_mode)) { | ||
420 | // create the directory in RUN_HOME_DIR | ||
421 | char *name; | ||
422 | char *ptr = strrchr(fname, '/'); | ||
423 | ptr++; | ||
424 | if (asprintf(&name, "%s/%s", RUN_HOME_DIR, ptr) == -1) | ||
425 | errExit("asprintf"); | ||
426 | mkdir_attr(name, 0755, getuid(), getgid()); | ||
427 | sbox_run(SBOX_USER| SBOX_CAPS_NONE | SBOX_SECCOMP, 3, PATH_FCOPY, fname, name); | ||
428 | free(name); | ||
552 | } | 429 | } |
430 | else | ||
431 | sbox_run(SBOX_USER| SBOX_CAPS_NONE | SBOX_SECCOMP, 3, PATH_FCOPY, fname, RUN_HOME_DIR); | ||
432 | fs_logger2("clone", fname); | ||
433 | fs_logger_print(); // save the current log | ||
553 | 434 | ||
554 | free(dlist); | 435 | free(fname); |
555 | } | 436 | } |
556 | 437 | ||
557 | |||
558 | |||
559 | // private mode (--private-home=list): | 438 | // private mode (--private-home=list): |
560 | // mount homedir on top of /home/user, | 439 | // mount homedir on top of /home/user, |
561 | // tmpfs on top of /root in nonroot mode, | 440 | // tmpfs on top of /root in nonroot mode, |
@@ -571,68 +450,28 @@ void fs_private_home_list(void) { | |||
571 | int xflag = store_xauthority(); | 450 | int xflag = store_xauthority(); |
572 | int aflag = store_asoundrc(); | 451 | int aflag = store_asoundrc(); |
573 | 452 | ||
574 | uid_t u = firejail_uid; | 453 | uid_t uid = getuid(); |
575 | gid_t g = firejail_gid; | 454 | gid_t gid = getgid(); |
576 | struct stat s; | ||
577 | if (stat(homedir, &s) == -1) { | ||
578 | fprintf(stderr, "Error: cannot find user home directory\n"); | ||
579 | exit(1); | ||
580 | } | ||
581 | 455 | ||
582 | // create /run/firejail/mnt/home directory | 456 | // create /run/firejail/mnt/home directory |
583 | int rv = mkdir(RUN_HOME_DIR, 0755); | 457 | mkdir_attr(RUN_HOME_DIR, 0755, uid, gid); |
584 | if (rv == -1) | ||
585 | errExit("mkdir"); | ||
586 | if (set_perms(RUN_HOME_DIR, u, g, 0755)) | ||
587 | errExit("set_perms"); | ||
588 | ASSERT_PERMS(RUN_HOME_DIR, u, g, 0755); | ||
589 | |||
590 | fs_logger_print(); // save the current log | 458 | fs_logger_print(); // save the current log |
591 | 459 | ||
460 | if (arg_debug) | ||
461 | printf("Copying files in the new home:\n"); | ||
462 | |||
592 | // copy the list of files in the new home directory | 463 | // copy the list of files in the new home directory |
593 | // using a new child process without root privileges | 464 | char *dlist = strdup(cfg.home_private_keep); |
594 | pid_t child = fork(); | 465 | if (!dlist) |
595 | if (child < 0) | 466 | errExit("strdup"); |
596 | errExit("fork"); | 467 | |
597 | if (child == 0) { | 468 | char *ptr = strtok(dlist, ","); |
598 | if (arg_debug) | 469 | duplicate(ptr); |
599 | printf("Copying files in the new home:\n"); | 470 | while ((ptr = strtok(NULL, ",")) != NULL) |
600 | |||
601 | // drop privileges | ||
602 | if (setgroups(0, NULL) < 0) | ||
603 | errExit("setgroups"); | ||
604 | if (setgid(getgid()) < 0) | ||
605 | errExit("setgid/getgid"); | ||
606 | if (setuid(getuid()) < 0) | ||
607 | errExit("setuid/getuid"); | ||
608 | |||
609 | // copy the list of files in the new home directory | ||
610 | char *dlist = strdup(cfg.home_private_keep); | ||
611 | if (!dlist) | ||
612 | errExit("strdup"); | ||
613 | |||
614 | char *ptr = strtok(dlist, ","); | ||
615 | duplicate(ptr); | 471 | duplicate(ptr); |
616 | while ((ptr = strtok(NULL, ",")) != NULL) | ||
617 | duplicate(ptr); | ||
618 | |||
619 | if (!arg_quiet) { | ||
620 | if (size_limit_reached) | ||
621 | fprintf(stderr, "Warning: private-home copy limit of %u MB reached, not all the files were copied\n", | ||
622 | PRIVATE_COPY_LIMIT / (1024 *1024)); | ||
623 | else | ||
624 | printf("Private home: %u files, total size %u bytes\n", file_cnt, size_cnt); | ||
625 | } | ||
626 | 472 | ||
627 | fs_logger_print(); // save the current log | 473 | fs_logger_print(); // save the current log |
628 | free(dlist); | 474 | free(dlist); |
629 | #ifdef HAVE_GCOV | ||
630 | __gcov_flush(); | ||
631 | #endif | ||
632 | _exit(0); | ||
633 | } | ||
634 | // wait for the child to finish | ||
635 | waitpid(child, NULL, 0); | ||
636 | 475 | ||
637 | if (arg_debug) | 476 | if (arg_debug) |
638 | printf("Mount-bind %s on top of %s\n", RUN_HOME_DIR, homedir); | 477 | printf("Mount-bind %s on top of %s\n", RUN_HOME_DIR, homedir); |
@@ -640,7 +479,7 @@ void fs_private_home_list(void) { | |||
640 | if (mount(RUN_HOME_DIR, homedir, NULL, MS_BIND|MS_REC, NULL) < 0) | 479 | if (mount(RUN_HOME_DIR, homedir, NULL, MS_BIND|MS_REC, NULL) < 0) |
641 | errExit("mount bind"); | 480 | errExit("mount bind"); |
642 | 481 | ||
643 | if (u != 0) { | 482 | if (uid != 0) { |
644 | // mask /root | 483 | // mask /root |
645 | if (arg_debug) | 484 | if (arg_debug) |
646 | printf("Mounting a new /root directory\n"); | 485 | printf("Mounting a new /root directory\n"); |
@@ -655,7 +494,7 @@ void fs_private_home_list(void) { | |||
655 | errExit("mounting home directory"); | 494 | errExit("mounting home directory"); |
656 | } | 495 | } |
657 | 496 | ||
658 | skel(homedir, u, g); | 497 | skel(homedir, uid, gid); |
659 | if (xflag) | 498 | if (xflag) |
660 | copy_xauthority(); | 499 | copy_xauthority(); |
661 | if (aflag) | 500 | if (aflag) |
diff --git a/src/firejail/fs_hostname.c b/src/firejail/fs_hostname.c index 04197eb8f..dcf06fc6f 100644 --- a/src/firejail/fs_hostname.c +++ b/src/firejail/fs_hostname.c | |||
@@ -33,15 +33,7 @@ void fs_hostname(const char *hostname) { | |||
33 | if (arg_debug) | 33 | if (arg_debug) |
34 | printf("Creating a new /etc/hostname file\n"); | 34 | printf("Creating a new /etc/hostname file\n"); |
35 | 35 | ||
36 | FILE *fp = fopen(RUN_HOSTNAME_FILE, "w"); | 36 | create_empty_file_as_root(RUN_HOSTNAME_FILE, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH); |
37 | if (!fp) { | ||
38 | fprintf(stderr, "Error: cannot create %s\n", RUN_HOSTNAME_FILE); | ||
39 | exit(1); | ||
40 | } | ||
41 | fprintf(fp, "%s\n", hostname); | ||
42 | // mode and owner | ||
43 | SET_PERMS_STREAM(fp, 0, 0, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH); | ||
44 | fclose(fp); | ||
45 | 37 | ||
46 | // bind-mount the file on top of /etc/hostname | 38 | // bind-mount the file on top of /etc/hostname |
47 | if (mount(RUN_HOSTNAME_FILE, "/etc/hostname", NULL, MS_BIND|MS_REC, NULL) < 0) | 39 | if (mount(RUN_HOSTNAME_FILE, "/etc/hostname", NULL, MS_BIND|MS_REC, NULL) < 0) |
@@ -56,15 +48,12 @@ void fs_hostname(const char *hostname) { | |||
56 | // copy /etc/host into our new file, and modify it on the fly | 48 | // copy /etc/host into our new file, and modify it on the fly |
57 | /* coverity[toctou] */ | 49 | /* coverity[toctou] */ |
58 | FILE *fp1 = fopen("/etc/hosts", "r"); | 50 | FILE *fp1 = fopen("/etc/hosts", "r"); |
59 | if (!fp1) { | 51 | if (!fp1) |
60 | fprintf(stderr, "Error: cannot open /etc/hosts\n"); | 52 | goto errexit; |
61 | exit(1); | 53 | |
62 | } | ||
63 | FILE *fp2 = fopen(RUN_HOSTS_FILE, "w"); | 54 | FILE *fp2 = fopen(RUN_HOSTS_FILE, "w"); |
64 | if (!fp2) { | 55 | if (!fp2) |
65 | fprintf(stderr, "Error: cannot create %s\n", RUN_HOSTS_FILE); | 56 | goto errexit; |
66 | exit(1); | ||
67 | } | ||
68 | 57 | ||
69 | char buf[4096]; | 58 | char buf[4096]; |
70 | int done = 0; | 59 | int done = 0; |
@@ -92,6 +81,11 @@ void fs_hostname(const char *hostname) { | |||
92 | errExit("mount bind /etc/hosts"); | 81 | errExit("mount bind /etc/hosts"); |
93 | fs_logger("create /etc/hosts"); | 82 | fs_logger("create /etc/hosts"); |
94 | } | 83 | } |
84 | return; | ||
85 | |||
86 | errexit: | ||
87 | fprintf(stderr, "Error: cannot create hostname file\n"); | ||
88 | exit(1); | ||
95 | } | 89 | } |
96 | 90 | ||
97 | void fs_resolvconf(void) { | 91 | void fs_resolvconf(void) { |
diff --git a/src/firejail/main.c b/src/firejail/main.c index ec0c31285..ff7b762cd 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c | |||
@@ -1601,7 +1601,6 @@ int main(int argc, char **argv) { | |||
1601 | 1601 | ||
1602 | // extract private home dirname | 1602 | // extract private home dirname |
1603 | cfg.home_private_keep = argv[i] + 15; | 1603 | cfg.home_private_keep = argv[i] + 15; |
1604 | fs_check_home_list(); | ||
1605 | arg_private = 1; | 1604 | arg_private = 1; |
1606 | } | 1605 | } |
1607 | else { | 1606 | else { |
@@ -1625,7 +1624,6 @@ int main(int argc, char **argv) { | |||
1625 | fprintf(stderr, "Error: invalid private-etc option\n"); | 1624 | fprintf(stderr, "Error: invalid private-etc option\n"); |
1626 | exit(1); | 1625 | exit(1); |
1627 | } | 1626 | } |
1628 | fs_check_etc_list(); | ||
1629 | arg_private_etc = 1; | 1627 | arg_private_etc = 1; |
1630 | } | 1628 | } |
1631 | else if (strncmp(argv[i], "--private-bin=", 14) == 0) { | 1629 | else if (strncmp(argv[i], "--private-bin=", 14) == 0) { |
@@ -1636,7 +1634,6 @@ int main(int argc, char **argv) { | |||
1636 | exit(1); | 1634 | exit(1); |
1637 | } | 1635 | } |
1638 | arg_private_bin = 1; | 1636 | arg_private_bin = 1; |
1639 | fs_check_bin_list(); | ||
1640 | } | 1637 | } |
1641 | else if (strcmp(argv[i], "--private-tmp") == 0) { | 1638 | else if (strcmp(argv[i], "--private-tmp") == 0) { |
1642 | arg_private_tmp = 1; | 1639 | arg_private_tmp = 1; |
diff --git a/src/firejail/profile.c b/src/firejail/profile.c index 0fd45d1ef..688fa9609 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c | |||
@@ -173,7 +173,6 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
173 | #ifdef HAVE_PRIVATE_HOME | 173 | #ifdef HAVE_PRIVATE_HOME |
174 | if (checkcfg(CFG_PRIVATE_HOME)) { | 174 | if (checkcfg(CFG_PRIVATE_HOME)) { |
175 | cfg.home_private_keep = ptr + 13; | 175 | cfg.home_private_keep = ptr + 13; |
176 | fs_check_home_list(); | ||
177 | arg_private = 1; | 176 | arg_private = 1; |
178 | } | 177 | } |
179 | else | 178 | else |
@@ -737,7 +736,6 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
737 | exit(1); | 736 | exit(1); |
738 | } | 737 | } |
739 | cfg.etc_private_keep = ptr + 12; | 738 | cfg.etc_private_keep = ptr + 12; |
740 | fs_check_etc_list(); | ||
741 | arg_private_etc = 1; | 739 | arg_private_etc = 1; |
742 | 740 | ||
743 | return 0; | 741 | return 0; |
@@ -747,7 +745,6 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
747 | if (strncmp(ptr, "private-bin ", 12) == 0) { | 745 | if (strncmp(ptr, "private-bin ", 12) == 0) { |
748 | cfg.bin_private_keep = ptr + 12; | 746 | cfg.bin_private_keep = ptr + 12; |
749 | arg_private_bin = 1; | 747 | arg_private_bin = 1; |
750 | fs_check_bin_list(); | ||
751 | return 0; | 748 | return 0; |
752 | } | 749 | } |
753 | 750 | ||
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index 109daf552..c2e053b0c 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c | |||
@@ -696,7 +696,6 @@ int sandbox(void* sandbox_arg) { | |||
696 | if (asprintf(&tmp, "%s,xauth", cfg.bin_private_keep) == -1) | 696 | if (asprintf(&tmp, "%s,xauth", cfg.bin_private_keep) == -1) |
697 | errExit("asprintf"); | 697 | errExit("asprintf"); |
698 | cfg.bin_private_keep = tmp; | 698 | cfg.bin_private_keep = tmp; |
699 | fs_check_bin_list(); | ||
700 | EUID_ROOT(); | 699 | EUID_ROOT(); |
701 | } | 700 | } |
702 | fs_private_bin_list(); | 701 | fs_private_bin_list(); |
diff --git a/src/firejail/util.c b/src/firejail/util.c index d928c6b42..03f52fabb 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c | |||
@@ -206,6 +206,7 @@ int copy_file(const char *srcname, const char *destname, uid_t uid, gid_t gid, m | |||
206 | done += rv; | 206 | done += rv; |
207 | } | 207 | } |
208 | } | 208 | } |
209 | fflush(0); | ||
209 | 210 | ||
210 | if (fchown(dst, uid, gid) == -1) | 211 | if (fchown(dst, uid, gid) == -1) |
211 | errExit("fchown"); | 212 | errExit("fchown"); |
@@ -561,7 +562,10 @@ char *expand_home(const char *path, const char* homedir) { | |||
561 | return new_name; | 562 | return new_name; |
562 | } | 563 | } |
563 | 564 | ||
564 | return strdup(path); | 565 | char *rv = strdup(path); |
566 | if (!rv) | ||
567 | errExit("strdup"); | ||
568 | return rv; | ||
565 | } | 569 | } |
566 | 570 | ||
567 | 571 | ||
@@ -624,7 +628,7 @@ uid_t pid_get_uid(pid_t pid) { | |||
624 | 628 | ||
625 | 629 | ||
626 | void invalid_filename(const char *fname) { | 630 | void invalid_filename(const char *fname) { |
627 | EUID_ASSERT(); | 631 | // EUID_ASSERT(); |
628 | assert(fname); | 632 | assert(fname); |
629 | const char *ptr = fname; | 633 | const char *ptr = fname; |
630 | 634 | ||
@@ -690,6 +694,7 @@ void flush_stdin(void) { | |||
690 | 694 | ||
691 | void create_empty_dir_as_root(const char *dir, mode_t mode) { | 695 | void create_empty_dir_as_root(const char *dir, mode_t mode) { |
692 | assert(dir); | 696 | assert(dir); |
697 | mode &= 07777; | ||
693 | struct stat s; | 698 | struct stat s; |
694 | 699 | ||
695 | if (stat(dir, &s)) { | 700 | if (stat(dir, &s)) { |
@@ -705,6 +710,7 @@ void create_empty_dir_as_root(const char *dir, mode_t mode) { | |||
705 | 710 | ||
706 | void create_empty_file_as_root(const char *fname, mode_t mode) { | 711 | void create_empty_file_as_root(const char *fname, mode_t mode) { |
707 | assert(fname); | 712 | assert(fname); |
713 | mode &= 07777; | ||
708 | struct stat s; | 714 | struct stat s; |
709 | 715 | ||
710 | if (stat(fname, &s)) { | 716 | if (stat(fname, &s)) { |
diff --git a/src/firemon/caps.c b/src/firemon/caps.c index 81877ab87..3f8a139ae 100644 --- a/src/firemon/caps.c +++ b/src/firemon/caps.c | |||
@@ -24,7 +24,6 @@ static void print_caps(int pid) { | |||
24 | char *file; | 24 | char *file; |
25 | if (asprintf(&file, "/proc/%d/status", pid) == -1) { | 25 | if (asprintf(&file, "/proc/%d/status", pid) == -1) { |
26 | errExit("asprintf"); | 26 | errExit("asprintf"); |
27 | exit(1); | ||
28 | } | 27 | } |
29 | 28 | ||
30 | FILE *fp = fopen(file, "r"); | 29 | FILE *fp = fopen(file, "r"); |
diff --git a/src/firemon/netstats.c b/src/firemon/netstats.c index 3c020d630..534d783cb 100644 --- a/src/firemon/netstats.c +++ b/src/firemon/netstats.c | |||
@@ -216,6 +216,9 @@ void netstats(void) { | |||
216 | print_proc(i, itv, col); | 216 | print_proc(i, itv, col); |
217 | } | 217 | } |
218 | } | 218 | } |
219 | #ifdef HAVE_GCOV | ||
220 | __gcov_flush(); | ||
221 | #endif | ||
219 | } | 222 | } |
220 | } | 223 | } |
221 | 224 | ||
diff --git a/src/firemon/procevent.c b/src/firemon/procevent.c index 1940f4a34..edae21951 100644 --- a/src/firemon/procevent.c +++ b/src/firemon/procevent.c | |||
@@ -43,10 +43,8 @@ static int pid_is_firejail(pid_t pid) { | |||
43 | 43 | ||
44 | // open /proc/self/comm | 44 | // open /proc/self/comm |
45 | char *file; | 45 | char *file; |
46 | if (asprintf(&file, "/proc/%u/comm", pid) == -1) { | 46 | if (asprintf(&file, "/proc/%u/comm", pid) == -1) |
47 | perror("asprintf"); | 47 | errExit("asprintf"); |
48 | exit(1); | ||
49 | } | ||
50 | 48 | ||
51 | FILE *fp = fopen(file, "r"); | 49 | FILE *fp = fopen(file, "r"); |
52 | if (!fp) { | 50 | if (!fp) { |
diff --git a/src/firemon/seccomp.c b/src/firemon/seccomp.c index abc698bb8..f11c624ea 100644 --- a/src/firemon/seccomp.c +++ b/src/firemon/seccomp.c | |||
@@ -22,10 +22,8 @@ | |||
22 | #define MAXBUF 4098 | 22 | #define MAXBUF 4098 |
23 | static void print_seccomp(int pid) { | 23 | static void print_seccomp(int pid) { |
24 | char *file; | 24 | char *file; |
25 | if (asprintf(&file, "/proc/%d/status", pid) == -1) { | 25 | if (asprintf(&file, "/proc/%d/status", pid) == -1) |
26 | errExit("asprintf"); | 26 | errExit("asprintf"); |
27 | exit(1); | ||
28 | } | ||
29 | 27 | ||
30 | FILE *fp = fopen(file, "r"); | 28 | FILE *fp = fopen(file, "r"); |
31 | if (!fp) { | 29 | if (!fp) { |
diff --git a/src/firemon/top.c b/src/firemon/top.c index b804761dd..94271523c 100644 --- a/src/firemon/top.c +++ b/src/firemon/top.c | |||
@@ -292,6 +292,9 @@ void top(void) { | |||
292 | } | 292 | } |
293 | } | 293 | } |
294 | head_print(col, row); | 294 | head_print(col, row); |
295 | #ifdef HAVE_GCOV | ||
296 | __gcov_flush(); | ||
297 | #endif | ||
295 | } | 298 | } |
296 | } | 299 | } |
297 | 300 | ||
diff --git a/src/fnet/main.c b/src/fnet/main.c index 4ae9eb6e3..4e7807d07 100644 --- a/src/fnet/main.c +++ b/src/fnet/main.c | |||
@@ -42,10 +42,10 @@ for (i = 0; i < argc; i++) | |||
42 | printf("\n"); | 42 | printf("\n"); |
43 | } | 43 | } |
44 | #endif | 44 | #endif |
45 | if (argc < 2) | 45 | if (argc < 2) { |
46 | usage(); | ||
46 | return 1; | 47 | return 1; |
47 | 48 | } | |
48 | |||
49 | 49 | ||
50 | if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") ==0) { | 50 | if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") ==0) { |
51 | usage(); | 51 | usage(); |
diff --git a/src/fseccomp/main.c b/src/fseccomp/main.c index 39e72fdf9..2f85a786b 100644 --- a/src/fseccomp/main.c +++ b/src/fseccomp/main.c | |||
@@ -47,8 +47,10 @@ for (i = 0; i < argc; i++) | |||
47 | printf("\n"); | 47 | printf("\n"); |
48 | } | 48 | } |
49 | #endif | 49 | #endif |
50 | if (argc < 2) | 50 | if (argc < 2) { |
51 | usage(); | ||
51 | return 1; | 52 | return 1; |
53 | } | ||
52 | 54 | ||
53 | if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") ==0) { | 55 | if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") ==0) { |
54 | usage(); | 56 | usage(); |
diff --git a/src/ftee/main.c b/src/ftee/main.c index e6aa5f567..2b27baa5a 100644 --- a/src/ftee/main.c +++ b/src/ftee/main.c | |||
@@ -179,10 +179,6 @@ static int is_link(const char *fname) { | |||
179 | return 0; | 179 | return 0; |
180 | } | 180 | } |
181 | 181 | ||
182 | |||
183 | |||
184 | |||
185 | |||
186 | static void usage(void) { | 182 | static void usage(void) { |
187 | printf("Usage: ftee filename\n"); | 183 | printf("Usage: ftee filename\n"); |
188 | } | 184 | } |
@@ -201,33 +197,25 @@ int main(int argc, char **argv) { | |||
201 | 197 | ||
202 | 198 | ||
203 | // do not accept directories, links, and files with ".." | 199 | // do not accept directories, links, and files with ".." |
204 | if (strstr(fname, "..") || is_link(fname) || is_dir(fname)) { | 200 | if (strstr(fname, "..") || is_link(fname) || is_dir(fname)) |
205 | fprintf(stderr, "Error: invalid output file. Links, directories and files with \"..\" are not allowed.\n"); | 201 | goto errexit; |
206 | exit(1); | ||
207 | } | ||
208 | 202 | ||
209 | struct stat s; | 203 | struct stat s; |
210 | if (stat(fname, &s) == 0) { | 204 | if (stat(fname, &s) == 0) { |
211 | // check permissions | 205 | // check permissions |
212 | if (s.st_uid != getuid() || s.st_gid != getgid()) { | 206 | if (s.st_uid != getuid() || s.st_gid != getgid()) |
213 | fprintf(stderr, "Error: the output file needs to be owned by the current user.\n"); | 207 | goto errexit; |
214 | exit(1); | ||
215 | } | ||
216 | 208 | ||
217 | // check hard links | 209 | // check hard links |
218 | if (s.st_nlink != 1) { | 210 | if (s.st_nlink != 1) |
219 | fprintf(stderr, "Error: no hard links allowed.\n"); | 211 | goto errexit; |
220 | exit(1); | ||
221 | } | ||
222 | } | 212 | } |
223 | 213 | ||
224 | // check if we can append to this file | 214 | // check if we can append to this file |
225 | /* coverity[toctou] */ | 215 | /* coverity[toctou] */ |
226 | FILE *fp = fopen(fname, "a"); | 216 | FILE *fp = fopen(fname, "a"); |
227 | if (!fp) { | 217 | if (!fp) |
228 | fprintf(stderr, "Error: cannot open output file %s\n", fname); | 218 | goto errexit; |
229 | exit(1); | ||
230 | } | ||
231 | fclose(fp); | 219 | fclose(fp); |
232 | 220 | ||
233 | 221 | ||
@@ -248,4 +236,8 @@ int main(int argc, char **argv) { | |||
248 | 236 | ||
249 | log_close(); | 237 | log_close(); |
250 | return 0; | 238 | return 0; |
239 | |||
240 | errexit: | ||
241 | fprintf(stderr, "Error ftee: invalid output file.\n"); | ||
242 | return 1; | ||
251 | } | 243 | } |
diff --git a/test/appimage/appimage-v1.exp b/test/appimage/appimage-v1.exp index 503da2b9b..f1c1c10f5 100755 --- a/test/appimage/appimage-v1.exp +++ b/test/appimage/appimage-v1.exp | |||
@@ -7,7 +7,7 @@ set timeout 10 | |||
7 | spawn $env(SHELL) | 7 | spawn $env(SHELL) |
8 | match_max 100000 | 8 | match_max 100000 |
9 | 9 | ||
10 | send -- "firejail --name=appimage-test --appimage Leafpad-0.8.17-x86_64.AppImage\r" | 10 | send -- "firejail --name=appimage-test --debug --appimage Leafpad-0.8.17-x86_64.AppImage\r" |
11 | expect { | 11 | expect { |
12 | timeout {puts "TESTING ERROR 1\n";exit} | 12 | timeout {puts "TESTING ERROR 1\n";exit} |
13 | "Child process initialized" | 13 | "Child process initialized" |
diff --git a/test/appimage/appimage.sh b/test/appimage/appimage.sh index 6a73d0a7e..db221ec8a 100755 --- a/test/appimage/appimage.sh +++ b/test/appimage/appimage.sh | |||
@@ -10,5 +10,7 @@ echo "TESTING: AppImage v1 (test/appimage/appimage-v1.exp)" | |||
10 | ./appimage-v1.exp | 10 | ./appimage-v1.exp |
11 | 11 | ||
12 | echo "TESTING: AppImage v2 (test/appimage/appimage-v2.exp)" | 12 | echo "TESTING: AppImage v2 (test/appimage/appimage-v2.exp)" |
13 | ./appimage-v1.exp | 13 | ./appimage-v2.exp |
14 | 14 | ||
15 | echo "TESTING: AppImage file name (test/appimage/filename.exp)"; | ||
16 | ./filename.exp \ No newline at end of file | ||
diff --git a/test/appimage/filename.exp b/test/appimage/filename.exp new file mode 100755 index 000000000..ce8d70464 --- /dev/null +++ b/test/appimage/filename.exp | |||
@@ -0,0 +1,35 @@ | |||
1 | #!/usr/bin/expect -f | ||
2 | # This file is part of Firejail project | ||
3 | # Copyright (C) 2014-2016 Firejail Authors | ||
4 | # License GPL v2 | ||
5 | |||
6 | set timeout 10 | ||
7 | spawn $env(SHELL) | ||
8 | match_max 100000 | ||
9 | |||
10 | send -- "firejail --appimage \"bla;bla\"\r" | ||
11 | expect { | ||
12 | timeout {puts "TESTING ERROR 1\n";exit} | ||
13 | "is an invalid filename" | ||
14 | } | ||
15 | after 100 | ||
16 | |||
17 | send -- "firejail --appimage /etc/shadow\r" | ||
18 | expect { | ||
19 | timeout {puts "TESTING ERROR 2\n";exit} | ||
20 | "cannot access" | ||
21 | } | ||
22 | after 100 | ||
23 | |||
24 | send -- "firejail --appimage appimage.sh\r" | ||
25 | expect { | ||
26 | timeout {puts "TESTING ERROR 2\n";exit} | ||
27 | "Error mounting appimage" | ||
28 | } | ||
29 | after 100 | ||
30 | |||
31 | |||
32 | |||
33 | |||
34 | puts "\nall done\n" | ||
35 | |||
diff --git a/test/chroot-resolvconf.exp b/test/chroot/chroot-resolvconf.exp index 2d0da2fb0..2d0da2fb0 100755 --- a/test/chroot-resolvconf.exp +++ b/test/chroot/chroot-resolvconf.exp | |||
diff --git a/test/fs_chroot.exp b/test/chroot/fs_chroot.exp index aeb5669e1..aeb5669e1 100755 --- a/test/fs_chroot.exp +++ b/test/chroot/fs_chroot.exp | |||
diff --git a/test/environment/dns.exp b/test/environment/dns.exp index 6ffb124cf..a6a7171eb 100755 --- a/test/environment/dns.exp +++ b/test/environment/dns.exp | |||
@@ -22,9 +22,33 @@ expect { | |||
22 | timeout {puts "TESTING ERROR 1.2\n";exit} | 22 | timeout {puts "TESTING ERROR 1.2\n";exit} |
23 | "53" | 23 | "53" |
24 | } | 24 | } |
25 | |||
26 | after 100 | 25 | after 100 |
27 | 26 | ||
28 | send -- "rm index.html\r" | 27 | send -- "rm index.html\r" |
29 | after 100 | 28 | after 100 |
29 | send -- "exit\r" | ||
30 | sleep 1 | ||
31 | |||
32 | send -- "firejail --dns=8.8.4.4 --dns=8.8.8.8 --dns=4.2.2.1\r" | ||
33 | expect { | ||
34 | timeout {puts "TESTING ERROR 2.1\n";exit} | ||
35 | "Child process initialized" | ||
36 | } | ||
37 | sleep 1 | ||
38 | |||
39 | send -- "cat /etc/resolv.conf\r" | ||
40 | expect { | ||
41 | timeout {puts "TESTING ERROR 2.2\n";exit} | ||
42 | "nameserver 8.8.4.4" | ||
43 | } | ||
44 | expect { | ||
45 | timeout {puts "TESTING ERROR 2.3\n";exit} | ||
46 | "nameserver 8.8.8.8" | ||
47 | } | ||
48 | expect { | ||
49 | timeout {puts "TESTING ERROR 2.4\n";exit} | ||
50 | "nameserver 4.2.2.1" | ||
51 | } | ||
52 | after 100 | ||
53 | |||
30 | puts "\nall done\n" | 54 | puts "\nall done\n" |
diff --git a/test/environment/environment.sh b/test/environment/environment.sh index 5c4d49331..2bb5a249e 100755 --- a/test/environment/environment.sh +++ b/test/environment/environment.sh | |||
@@ -6,6 +6,7 @@ | |||
6 | export MALLOC_CHECK_=3 | 6 | export MALLOC_CHECK_=3 |
7 | export MALLOC_PERTURB_=$(($RANDOM % 255 + 1)) | 7 | export MALLOC_PERTURB_=$(($RANDOM % 255 + 1)) |
8 | 8 | ||
9 | |||
9 | echo "TESTING: DNS (test/environment/dns.exp)" | 10 | echo "TESTING: DNS (test/environment/dns.exp)" |
10 | ./dns.exp | 11 | ./dns.exp |
11 | 12 | ||
@@ -85,3 +86,28 @@ else | |||
85 | echo "TESTING SKIP: strace not found" | 86 | echo "TESTING SKIP: strace not found" |
86 | fi | 87 | fi |
87 | 88 | ||
89 | # to install ibus: | ||
90 | # $ sudo apt-get install ibus-table-array30 | ||
91 | # $ ibus-setup | ||
92 | |||
93 | find ~/.config/ibus/bus | grep unix-0 | ||
94 | if [ "$?" -eq 0 ]; | ||
95 | then | ||
96 | echo "TESTING: ibus (test/environment/ibus.exp)" | ||
97 | ./ibus.exp | ||
98 | else | ||
99 | echo "TESTING SKIP: ibus not configured" | ||
100 | fi | ||
101 | |||
102 | echo "TESTING: rlimit (test/rlimit/rlimit.exp)" | ||
103 | ./rlimit.exp | ||
104 | |||
105 | echo "TESTING: rlimit profile (test/rlimit/rlimit-profile.exp)" | ||
106 | ./rlimit-profile.exp | ||
107 | |||
108 | echo "TESTING: rlimit errors (test/rlimit/rlimit-bad.exp)" | ||
109 | ./rlimit-bad.exp | ||
110 | |||
111 | echo "TESTING: rlimit errors profile (test/rlimit/rlimit-bad-profile.exp)" | ||
112 | ./rlimit-bad-profile.exp | ||
113 | |||
diff --git a/test/environment/ibus.exp b/test/environment/ibus.exp new file mode 100755 index 000000000..4344011a6 --- /dev/null +++ b/test/environment/ibus.exp | |||
@@ -0,0 +1,28 @@ | |||
1 | #!/usr/bin/expect -f | ||
2 | |||
3 | set timeout 10 | ||
4 | cd /home | ||
5 | spawn $env(SHELL) | ||
6 | match_max 100000 | ||
7 | |||
8 | send -- "firejail\r" | ||
9 | expect { | ||
10 | timeout {puts "TESTING ERROR 0\n";exit} | ||
11 | "Child process initialized" | ||
12 | } | ||
13 | after 100 | ||
14 | |||
15 | send -- "env | grep IBUS\r" | ||
16 | expect { | ||
17 | timeout {puts "TESTING ERROR 1\n";exit} | ||
18 | "IBUS_ADDRESS" | ||
19 | } | ||
20 | expect { | ||
21 | timeout {puts "TESTING ERROR 2\n";exit} | ||
22 | "IBUS_DAEMON_PID" | ||
23 | } | ||
24 | after 100 | ||
25 | |||
26 | |||
27 | puts "\nall done\n" | ||
28 | |||
diff --git a/test/environment/rlimit-bad-profile.exp b/test/environment/rlimit-bad-profile.exp new file mode 100755 index 000000000..80693a4a0 --- /dev/null +++ b/test/environment/rlimit-bad-profile.exp | |||
@@ -0,0 +1,35 @@ | |||
1 | #!/usr/bin/expect -f | ||
2 | |||
3 | set timeout 10 | ||
4 | spawn $env(SHELL) | ||
5 | match_max 100000 | ||
6 | |||
7 | |||
8 | send -- "firejail --profile=rlimit-bad1.profile\r" | ||
9 | expect { | ||
10 | timeout {puts "TESTING ERROR 4\n";exit} | ||
11 | "Invalid rlimit option" | ||
12 | } | ||
13 | after 100 | ||
14 | |||
15 | send -- "firejail --profile=rlimit-bad2.profile\r" | ||
16 | expect { | ||
17 | timeout {puts "TESTING ERROR 5\n";exit} | ||
18 | "Invalid rlimit option" | ||
19 | } | ||
20 | after 100 | ||
21 | |||
22 | send -- "firejail --profile=rlimit-bad3.profile\r" | ||
23 | expect { | ||
24 | timeout {puts "TESTING ERROR 6\n";exit} | ||
25 | "Invalid rlimit option" | ||
26 | } | ||
27 | after 100 | ||
28 | send -- "firejail --profile=rlimit-bad4.profile\r" | ||
29 | expect { | ||
30 | timeout {puts "TESTING ERROR 7\n";exit} | ||
31 | "Invalid rlimit option" | ||
32 | } | ||
33 | after 100 | ||
34 | |||
35 | puts "\nall done\n" | ||
diff --git a/test/environment/rlimit-bad.exp b/test/environment/rlimit-bad.exp new file mode 100755 index 000000000..574e7e174 --- /dev/null +++ b/test/environment/rlimit-bad.exp | |||
@@ -0,0 +1,34 @@ | |||
1 | #!/usr/bin/expect -f | ||
2 | |||
3 | set timeout 10 | ||
4 | spawn $env(SHELL) | ||
5 | match_max 100000 | ||
6 | |||
7 | send -- "firejail --rlimit-fsize=-1024\r" | ||
8 | expect { | ||
9 | timeout {puts "TESTING ERROR 0\n";exit} | ||
10 | "invalid rlimt fsize" | ||
11 | } | ||
12 | after 100 | ||
13 | |||
14 | send -- "firejail --rlimit-nofile=asdf\r" | ||
15 | expect { | ||
16 | timeout {puts "TESTING ERROR 1\n";exit} | ||
17 | "invalid rlimt nofile" | ||
18 | } | ||
19 | after 100 | ||
20 | |||
21 | send -- "firejail --rlimit-nproc=100.23\r" | ||
22 | expect { | ||
23 | timeout {puts "TESTING ERROR 2\n";exit} | ||
24 | "invalid rlimt nproc" | ||
25 | } | ||
26 | after 100 | ||
27 | send -- "firejail --rlimit-sigpending=2345-78\r" | ||
28 | expect { | ||
29 | timeout {puts "TESTING ERROR 3\n";exit} | ||
30 | "invalid rlimt sigpending" | ||
31 | } | ||
32 | after 100 | ||
33 | |||
34 | puts "\nall done\n" | ||
diff --git a/test/environment/rlimit-bad1.profile b/test/environment/rlimit-bad1.profile new file mode 100644 index 000000000..b6d3340d8 --- /dev/null +++ b/test/environment/rlimit-bad1.profile | |||
@@ -0,0 +1 @@ | |||
rlimit-fsize -1024 | |||
diff --git a/test/environment/rlimit-bad2.profile b/test/environment/rlimit-bad2.profile new file mode 100644 index 000000000..ef3f243c6 --- /dev/null +++ b/test/environment/rlimit-bad2.profile | |||
@@ -0,0 +1 @@ | |||
rlimit-nofile asdf | |||
diff --git a/test/environment/rlimit-bad3.profile b/test/environment/rlimit-bad3.profile new file mode 100644 index 000000000..af016a29f --- /dev/null +++ b/test/environment/rlimit-bad3.profile | |||
@@ -0,0 +1 @@ | |||
rlimit-nproc 100.23 | |||
diff --git a/test/environment/rlimit-bad4.profile b/test/environment/rlimit-bad4.profile new file mode 100644 index 000000000..aabe3d008 --- /dev/null +++ b/test/environment/rlimit-bad4.profile | |||
@@ -0,0 +1 @@ | |||
rlimit-sigpending 67asd56 \ No newline at end of file | |||
diff --git a/test/rlimit/rlimit-profile.exp b/test/environment/rlimit-profile.exp index a9e54a405..a9e54a405 100755 --- a/test/rlimit/rlimit-profile.exp +++ b/test/environment/rlimit-profile.exp | |||
diff --git a/test/rlimit/rlimit.exp b/test/environment/rlimit.exp index 611f69821..611f69821 100755 --- a/test/rlimit/rlimit.exp +++ b/test/environment/rlimit.exp | |||
diff --git a/test/rlimit/rlimit.profile b/test/environment/rlimit.profile index 271891c03..271891c03 100644 --- a/test/rlimit/rlimit.profile +++ b/test/environment/rlimit.profile | |||
diff --git a/test/fcopy/cmdline.exp b/test/fcopy/cmdline.exp new file mode 100755 index 000000000..24bb19351 --- /dev/null +++ b/test/fcopy/cmdline.exp | |||
@@ -0,0 +1,46 @@ | |||
1 | #!/usr/bin/expect -f | ||
2 | # This file is part of Firejail project | ||
3 | # Copyright (C) 2014-2016 Firejail Authors | ||
4 | # License GPL v2 | ||
5 | |||
6 | set timeout 10 | ||
7 | spawn $env(SHELL) | ||
8 | match_max 100000 | ||
9 | |||
10 | send -- "/usr/lib/firejail/fcopy\r" | ||
11 | expect { | ||
12 | timeout {puts "TESTING ERROR 0\n";exit} | ||
13 | "files missing" | ||
14 | } | ||
15 | expect { | ||
16 | timeout {puts "TESTING ERROR 1\n";exit} | ||
17 | "Usage:" | ||
18 | } | ||
19 | after 100 | ||
20 | |||
21 | send -- "/usr/lib/firejail/fcopy foo\r" | ||
22 | expect { | ||
23 | timeout {puts "TESTING ERROR 2\n";exit} | ||
24 | "files missing" | ||
25 | } | ||
26 | expect { | ||
27 | timeout {puts "TESTING ERROR 3\n";exit} | ||
28 | "Usage:" | ||
29 | } | ||
30 | after 100 | ||
31 | |||
32 | send -- "/usr/lib/firejail/fcopy f%oo1 foo2\r" | ||
33 | expect { | ||
34 | timeout {puts "TESTING ERROR 4\n";exit} | ||
35 | "invalid file name" | ||
36 | } | ||
37 | after 100 | ||
38 | |||
39 | send -- "/usr/lib/firejail/fcopy foo1 f,oo2\r" | ||
40 | expect { | ||
41 | timeout {puts "TESTING ERROR 5\n";exit} | ||
42 | "invalid file name" | ||
43 | } | ||
44 | after 100 | ||
45 | |||
46 | puts "\nall done\n" | ||
diff --git a/test/fcopy/dircopy.exp b/test/fcopy/dircopy.exp new file mode 100755 index 000000000..00b0204ae --- /dev/null +++ b/test/fcopy/dircopy.exp | |||
@@ -0,0 +1,106 @@ | |||
1 | #!/usr/bin/expect -f | ||
2 | # This file is part of Firejail project | ||
3 | # Copyright (C) 2014-2016 Firejail Authors | ||
4 | # License GPL v2 | ||
5 | |||
6 | # | ||
7 | # copy directory src to dest | ||
8 | # | ||
9 | set timeout 10 | ||
10 | spawn $env(SHELL) | ||
11 | match_max 100000 | ||
12 | |||
13 | send -- "rm -fr dest/*\r" | ||
14 | after 100 | ||
15 | |||
16 | send -- "/usr/lib/firejail/fcopy src dest\r" | ||
17 | after 100 | ||
18 | |||
19 | send -- "find dest\r" | ||
20 | expect { | ||
21 | timeout {puts "TESTING ERROR 0\n";exit} | ||
22 | "dest/" | ||
23 | } | ||
24 | expect { | ||
25 | timeout {puts "TESTING ERROR 1\n";exit} | ||
26 | "dest/a" | ||
27 | } | ||
28 | expect { | ||
29 | timeout {puts "TESTING ERROR 2\n";exit} | ||
30 | "dest/a/b" | ||
31 | } | ||
32 | expect { | ||
33 | timeout {puts "TESTING ERROR 3\n";exit} | ||
34 | "dest/a/b/file4" | ||
35 | } | ||
36 | expect { | ||
37 | timeout {puts "TESTING ERROR 4\n";exit} | ||
38 | "dest/a/file3" | ||
39 | } | ||
40 | expect { | ||
41 | timeout {puts "TESTING ERROR 5\n";exit} | ||
42 | "dest/dircopy.exp" | ||
43 | } | ||
44 | expect { | ||
45 | timeout {puts "TESTING ERROR 6\n";exit} | ||
46 | "dest/file2" | ||
47 | } | ||
48 | expect { | ||
49 | timeout {puts "TESTING ERROR 7\n";exit} | ||
50 | "dest/file1" | ||
51 | } | ||
52 | after 100 | ||
53 | |||
54 | |||
55 | send -- "ls -al dest\r" | ||
56 | expect { | ||
57 | timeout {puts "TESTING ERROR 8\n";exit} | ||
58 | "drwxr-xr-x" | ||
59 | } | ||
60 | expect { | ||
61 | timeout {puts "TESTING ERROR 9\n";exit} | ||
62 | "a" | ||
63 | } | ||
64 | expect { | ||
65 | timeout {puts "TESTING ERROR 10\n";exit} | ||
66 | "lrwxrwxrwx" | ||
67 | } | ||
68 | expect { | ||
69 | timeout {puts "TESTING ERROR 11\n";exit} | ||
70 | "dircopy.exp" | ||
71 | } | ||
72 | expect { | ||
73 | timeout {puts "TESTING ERROR 12\n";exit} | ||
74 | "rwxr-xr-x" | ||
75 | } | ||
76 | expect { | ||
77 | timeout {puts "TESTING ERROR 13\n";exit} | ||
78 | "file1" | ||
79 | } | ||
80 | expect { | ||
81 | timeout {puts "TESTING ERROR 14\n";exit} | ||
82 | "rw-r--r--" | ||
83 | } | ||
84 | expect { | ||
85 | timeout {puts "TESTING ERROR 15\n";exit} | ||
86 | "file2" | ||
87 | } | ||
88 | after 100 | ||
89 | |||
90 | send -- "diff -q src/a/b/file4 dest/a/b/file4; echo done\r" | ||
91 | expect { | ||
92 | timeout {puts "TESTING ERROR 16\n";exit} | ||
93 | "differ" {puts "TESTING ERROR 17\n";exit} | ||
94 | "done" | ||
95 | } | ||
96 | |||
97 | send -- "file dest/dircopy.exp\r" | ||
98 | expect { | ||
99 | timeout {puts "TESTING ERROR 18\n";exit} | ||
100 | "symbolic link" | ||
101 | } | ||
102 | |||
103 | send -- "rm -fr dest/*\r" | ||
104 | after 100 | ||
105 | |||
106 | puts "\nall done\n" | ||
diff --git a/test/fcopy/fcopy.sh b/test/fcopy/fcopy.sh new file mode 100755 index 000000000..dcda5ca31 --- /dev/null +++ b/test/fcopy/fcopy.sh | |||
@@ -0,0 +1,23 @@ | |||
1 | #!/bin/bash | ||
2 | # This file is part of Firejail project | ||
3 | # Copyright (C) 2014-2016 Firejail Authors | ||
4 | # License GPL v2 | ||
5 | |||
6 | export MALLOC_CHECK_=3 | ||
7 | export MALLOC_PERTURB_=$(($RANDOM % 255 + 1)) | ||
8 | |||
9 | mkdir dest | ||
10 | |||
11 | echo "TESTING: fcopy cmdline (test/fcopy/cmdline.exp)" | ||
12 | ./cmdline.exp | ||
13 | |||
14 | echo "TESTING: fcopy directory (test/fcopy/dircopy.exp)" | ||
15 | ./dircopy.exp | ||
16 | |||
17 | echo "TESTING: fcopy file (test/fcopy/filecopy.exp)" | ||
18 | ./filecopy.exp | ||
19 | |||
20 | echo "TESTING: fcopy link (test/fcopy/linkcopy.exp)" | ||
21 | ./linkcopy.exp | ||
22 | |||
23 | rm -fr dest/* | ||
diff --git a/test/fcopy/filecopy.exp b/test/fcopy/filecopy.exp new file mode 100755 index 000000000..d1f0a4424 --- /dev/null +++ b/test/fcopy/filecopy.exp | |||
@@ -0,0 +1,54 @@ | |||
1 | #!/usr/bin/expect -f | ||
2 | # This file is part of Firejail project | ||
3 | # Copyright (C) 2014-2016 Firejail Authors | ||
4 | # License GPL v2 | ||
5 | |||
6 | # | ||
7 | # copy directory src to dest | ||
8 | # | ||
9 | set timeout 10 | ||
10 | spawn $env(SHELL) | ||
11 | match_max 100000 | ||
12 | |||
13 | send -- "rm -fr dest/*\r" | ||
14 | after 100 | ||
15 | |||
16 | send -- "/usr/lib/firejail/fcopy dircopy.exp dest\r" | ||
17 | after 100 | ||
18 | |||
19 | send -- "find dest\r" | ||
20 | expect { | ||
21 | timeout {puts "TESTING ERROR 0\n";exit} | ||
22 | "dest/" | ||
23 | } | ||
24 | expect { | ||
25 | timeout {puts "TESTING ERROR 1\n";exit} | ||
26 | "dest/dircopy.exp" | ||
27 | } | ||
28 | after 100 | ||
29 | |||
30 | |||
31 | send -- "ls -al dest\r" | ||
32 | expect { | ||
33 | timeout {puts "TESTING ERROR 2\n";exit} | ||
34 | "rwxr-xr-x" | ||
35 | } | ||
36 | after 100 | ||
37 | |||
38 | send -- "diff -q dircopy.exp dest/dircopy.exp; echo done\r" | ||
39 | expect { | ||
40 | timeout {puts "TESTING ERROR 3\n";exit} | ||
41 | "differ" {puts "TESTING ERROR 4\n";exit} | ||
42 | "done" | ||
43 | } | ||
44 | |||
45 | send -- "file dest/dircopy.exp\r" | ||
46 | expect { | ||
47 | timeout {puts "TESTING ERROR 5\n";exit} | ||
48 | "ASCII text" | ||
49 | } | ||
50 | |||
51 | send -- "rm -fr dest/*\r" | ||
52 | after 100 | ||
53 | |||
54 | puts "\nall done\n" | ||
diff --git a/test/fcopy/linkcopy.exp b/test/fcopy/linkcopy.exp new file mode 100755 index 000000000..9927e18fe --- /dev/null +++ b/test/fcopy/linkcopy.exp | |||
@@ -0,0 +1,54 @@ | |||
1 | #!/usr/bin/expect -f | ||
2 | # This file is part of Firejail project | ||
3 | # Copyright (C) 2014-2016 Firejail Authors | ||
4 | # License GPL v2 | ||
5 | |||
6 | # | ||
7 | # copy directory src to dest | ||
8 | # | ||
9 | set timeout 10 | ||
10 | spawn $env(SHELL) | ||
11 | match_max 100000 | ||
12 | |||
13 | send -- "rm -fr dest/*\r" | ||
14 | after 100 | ||
15 | |||
16 | send -- "/usr/lib/firejail/fcopy src/dircopy.exp dest\r" | ||
17 | after 100 | ||
18 | |||
19 | send -- "find dest\r" | ||
20 | expect { | ||
21 | timeout {puts "TESTING ERROR 0\n";exit} | ||
22 | "dest/" | ||
23 | } | ||
24 | expect { | ||
25 | timeout {puts "TESTING ERROR 1\n";exit} | ||
26 | "dest/dircopy.exp" | ||
27 | } | ||
28 | after 100 | ||
29 | |||
30 | |||
31 | send -- "ls -al dest\r" | ||
32 | expect { | ||
33 | timeout {puts "TESTING ERROR 2\n";exit} | ||
34 | "lrwxrwxrwx" | ||
35 | } | ||
36 | after 100 | ||
37 | |||
38 | send -- "diff -q dircopy.exp dest/dircopy.exp; echo done\r" | ||
39 | expect { | ||
40 | timeout {puts "TESTING ERROR 3\n";exit} | ||
41 | "differ" {puts "TESTING ERROR 4\n";exit} | ||
42 | "done" | ||
43 | } | ||
44 | |||
45 | send -- "file dest/dircopy.exp\r" | ||
46 | expect { | ||
47 | timeout {puts "TESTING ERROR 5\n";exit} | ||
48 | "symbolic link" | ||
49 | } | ||
50 | |||
51 | send -- "rm -fr dest/*\r" | ||
52 | after 100 | ||
53 | |||
54 | puts "\nall done\n" | ||
diff --git a/test/fcopy/src/a/b/file4 b/test/fcopy/src/a/b/file4 new file mode 100644 index 000000000..ac318d7ab --- /dev/null +++ b/test/fcopy/src/a/b/file4 | |||
@@ -0,0 +1,11 @@ | |||
1 | |||
2 | |||
3 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam interdum at massa non aliquam. Maecenas molestie id orci volutpat porta. Praesent aliquam nunc quis mi tristique, ac feugiat enim rutrum. Nulla vitae metus sodales, pellentesque risus sit amet, volutpat nisl. Curabitur accumsan arcu congue lacus porta laoreet. Nulla facilisi. Integer nec augue id magna gravida tincidunt id vitae lorem. Curabitur facilisis, tellus vel pellentesque pretium, odio dolor efficitur lorem, et tincidunt dui enim cursus lacus. Cras a orci ac magna semper dapibus nec et velit. Nullam aliquam sollicitudin auctor. | ||
4 | |||
5 | Mauris ac quam vel purus volutpat semper eget a ante. Curabitur arcu nisl, dapibus ac lectus ac, porttitor fermentum metus. Aliquam et sem aliquam magna interdum ultricies at eu orci. Aenean tortor augue, volutpat nec magna nec, rutrum bibendum justo. Vivamus ex quam, auctor ut pellentesque mattis, aliquet a eros. Etiam ac lacus ac ante ullamcorper sollicitudin a quis orci. Suspendisse quis justo ac mauris cursus finibus quis at elit. Vestibulum elementum finibus diam, eget convallis purus aliquet et. Fusce fermentum ornare urna, non ornare nisl tincidunt consectetur. Donec et lacus vitae ex eleifend porttitor id ut odio. Quisque luctus eget lorem et sollicitudin. | ||
6 | |||
7 | Aliquam libero elit, finibus a nisl a, commodo viverra turpis. Nam pulvinar in est sit amet fermentum. Praesent scelerisque tempus lectus, ac porta elit sodales rutrum. Duis faucibus faucibus urna eget accumsan. Vivamus in turpis ut massa rhoncus pretium nec et lorem. Aenean at tellus eget metus porta ornare. Aliquam erat volutpat. Donec hendrerit a massa vel malesuada. Integer varius sapien et orci viverra pretium. In at velit aliquet, vulputate nisi lobortis, aliquam augue. | ||
8 | |||
9 | Ut aliquam turpis ut lorem aliquam, in faucibus elit pulvinar. Vivamus viverra tortor ornare, lacinia leo sit amet, auctor arcu. Sed erat leo, pellentesque vel nibh a, malesuada vehicula purus. Vivamus est dolor, aliquet quis facilisis fermentum, varius in dolor. Nunc quis libero feugiat, imperdiet est vitae, mollis risus. Vestibulum elementum mattis lorem vitae gravida. Nullam id tellus interdum, aliquam erat eu, laoreet nunc. Aliquam ut felis vel mauris maximus pellentesque. | ||
10 | |||
11 | Vestibulum tempus mauris eget ex interdum, vitae vehicula tortor sollicitudin. Pellentesque et dolor cursus dui vulputate laoreet. Morbi eu bibendum quam, at ultrices elit. Vestibulum dictum enim sit amet ultricies imperdiet. Praesent congue magna ac mauris mattis, a iaculis ante aliquet. Vivamus at egestas ex. Suspendisse orci dolor, pharetra at aliquam a, faucibus facilisis leo. Quisque semper lorem eget elit commodo pretium. Aenean posuere augue quis arcu finibus, sit amet fringilla risus congue. Pellentesque rutrum nunc leo, aliquam lobortis lacus molestie nec. Donec convallis congue diam, ullamcorper vestibulum dui varius nec. Praesent pellentesque nisi risus. In aliquam molestie malesuada. Nulla facilisis a risus eu tristique. Morbi molestie et arcu quis efficitur. Curabitur cursus vestibulum luctus. | ||
diff --git a/test/fcopy/src/a/file3 b/test/fcopy/src/a/file3 new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/test/fcopy/src/a/file3 | |||
diff --git a/test/fcopy/src/dircopy.exp b/test/fcopy/src/dircopy.exp new file mode 120000 index 000000000..2acf88f7b --- /dev/null +++ b/test/fcopy/src/dircopy.exp | |||
@@ -0,0 +1 @@ | |||
../dircopy.exp \ No newline at end of file | |||
diff --git a/test/fcopy/src/file1 b/test/fcopy/src/file1 new file mode 100755 index 000000000..e69de29bb --- /dev/null +++ b/test/fcopy/src/file1 | |||
diff --git a/test/fcopy/src/file2 b/test/fcopy/src/file2 new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/test/fcopy/src/file2 | |||
diff --git a/test/fs/fs.sh b/test/fs/fs.sh index efbf505ee..1c5473f79 100755 --- a/test/fs/fs.sh +++ b/test/fs/fs.sh | |||
@@ -82,10 +82,21 @@ echo "TESTING: recursive mkdir (test/fs/mkdir.exp)" | |||
82 | echo "TESTING: double whitelist (test/fs/whitelist-double.exp)" | 82 | echo "TESTING: double whitelist (test/fs/whitelist-double.exp)" |
83 | ./whitelist-double.exp | 83 | ./whitelist-double.exp |
84 | 84 | ||
85 | |||
86 | echo "TESTING: whitelist (test/fs/whitelist.exp)" | 85 | echo "TESTING: whitelist (test/fs/whitelist.exp)" |
87 | ./whitelist.exp | 86 | ./whitelist.exp |
88 | 87 | ||
88 | echo "TESTING: fscheck --bind non root (test/fs/fscheck-bindnoroot.exp)" | ||
89 | ./fscheck-bindnoroot.exp | ||
90 | |||
91 | echo "TESTING: fscheck --tmpfs non root (test/fs/fscheck-tmpfs.exp)" | ||
92 | ./fscheck-tmpfs.exp | ||
93 | |||
94 | echo "TESTING: fscheck --private= (test/fs/fscheck-private.exp)" | ||
95 | ./fscheck-private.exp | ||
96 | |||
97 | echo "TESTING: fscheck --read-only= (test/fs/fscheck-readonly.exp)" | ||
98 | ./fscheck-readonly.exp | ||
99 | |||
89 | #cleanup | 100 | #cleanup |
90 | rm -fr ~/fjtest-dir | 101 | rm -fr ~/fjtest-dir |
91 | rm -fr ~/fjtest-dir-lnk | 102 | rm -fr ~/fjtest-dir-lnk |
diff --git a/test/fscheck-bindnoroot.exp b/test/fs/fscheck-bindnoroot.exp index 796a7d975..8cbe2b8af 100755 --- a/test/fscheck-bindnoroot.exp +++ b/test/fs/fscheck-bindnoroot.exp | |||
@@ -5,10 +5,13 @@ spawn $env(SHELL) | |||
5 | match_max 100000 | 5 | match_max 100000 |
6 | 6 | ||
7 | # dir | 7 | # dir |
8 | send -- "firejail --net=br0 --bind=fscheck-dir,/etc\r" | 8 | send -- "firejail --net=br0 --bind=testdir1,/etc\r" |
9 | expect { | 9 | expect { |
10 | timeout {puts "TESTING ERROR 0\n";exit} | 10 | timeout {puts "TESTING ERROR 0\n";exit} |
11 | "Error" | 11 | "Error" |
12 | } | 12 | } |
13 | after 100 | 13 | after 100 |
14 | 14 | ||
15 | puts "\nall done\n" | ||
16 | |||
17 | |||
diff --git a/test/fs/fscheck-private.exp b/test/fs/fscheck-private.exp new file mode 100755 index 000000000..28c921538 --- /dev/null +++ b/test/fs/fscheck-private.exp | |||
@@ -0,0 +1,50 @@ | |||
1 | #!/usr/bin/expect -f | ||
2 | |||
3 | set timeout 10 | ||
4 | spawn $env(SHELL) | ||
5 | match_max 100000 | ||
6 | |||
7 | |||
8 | |||
9 | # file link | ||
10 | #send -- "firejail --private=fscheck-file-link\r" | ||
11 | #expect { | ||
12 | # timeout {puts "TESTING ERROR 2\n";exit} | ||
13 | # "Error" | ||
14 | #} | ||
15 | #after 100 | ||
16 | |||
17 | # file | ||
18 | send -- "firejail --private=testfile1\r" | ||
19 | expect { | ||
20 | timeout {puts "TESTING ERROR 2.1\n";exit} | ||
21 | "Error" | ||
22 | } | ||
23 | after 100 | ||
24 | |||
25 | # .. | ||
26 | send -- "firejail --private=../fs/testfile1\r" | ||
27 | expect { | ||
28 | timeout {puts "TESTING ERROR 2.2\n";exit} | ||
29 | "Error" | ||
30 | } | ||
31 | after 100 | ||
32 | |||
33 | # no file | ||
34 | send -- "firejail --private=../test/nodir\r" | ||
35 | expect { | ||
36 | timeout {puts "TESTING ERROR 3\n";exit} | ||
37 | "Error" | ||
38 | } | ||
39 | after 100 | ||
40 | |||
41 | # same owner | ||
42 | send -- "firejail --private=/etc\r" | ||
43 | expect { | ||
44 | timeout {puts "TESTING ERROR 4\n";exit} | ||
45 | "Error" | ||
46 | } | ||
47 | after 100 | ||
48 | |||
49 | puts "\nall done\n" | ||
50 | |||
diff --git a/test/fscheck-readonly.exp b/test/fs/fscheck-readonly.exp index e0f0a8a1d..4d7528e50 100755 --- a/test/fscheck-readonly.exp +++ b/test/fs/fscheck-readonly.exp | |||
@@ -5,10 +5,11 @@ spawn $env(SHELL) | |||
5 | match_max 100000 | 5 | match_max 100000 |
6 | 6 | ||
7 | # dir | 7 | # dir |
8 | send -- "firejail --net=br0 --read-only=../test/fscheck-dir\r" | 8 | send -- "firejail --read-only=../test/testdir1\r" |
9 | expect { | 9 | expect { |
10 | timeout {puts "TESTING ERROR 0\n";exit} | 10 | timeout {puts "TESTING ERROR 0\n";exit} |
11 | "Error" | 11 | "Error" |
12 | } | 12 | } |
13 | after 100 | 13 | after 100 |
14 | 14 | ||
15 | puts "\nall done\n" | ||
diff --git a/test/fscheck-tmpfs.exp b/test/fs/fscheck-tmpfs.exp index d5bbccd96..deac5a631 100755 --- a/test/fscheck-tmpfs.exp +++ b/test/fs/fscheck-tmpfs.exp | |||
@@ -5,7 +5,7 @@ spawn $env(SHELL) | |||
5 | match_max 100000 | 5 | match_max 100000 |
6 | 6 | ||
7 | # .. | 7 | # .. |
8 | send -- "firejail --net=br0 --tmpfs=../test/fscheck-dir\r" | 8 | send -- "firejail --tmpfs=fscheck-dir\r" |
9 | expect { | 9 | expect { |
10 | timeout {puts "TESTING ERROR 0.1\n";exit} | 10 | timeout {puts "TESTING ERROR 0.1\n";exit} |
11 | "Error" | 11 | "Error" |
diff --git a/test/fs/invalid_filename.exp b/test/fs/invalid_filename.exp index 1acc85491..a6efc24b6 100755 --- a/test/fs/invalid_filename.exp +++ b/test/fs/invalid_filename.exp | |||
@@ -109,6 +109,21 @@ expect { | |||
109 | } | 109 | } |
110 | after 100 | 110 | after 100 |
111 | 111 | ||
112 | send -- "firejail --debug-check-filename --noprofile --private-home=\"bla&&bla\"\r" | ||
113 | expect { | ||
114 | timeout {puts "TESTING ERROR 8.1\n";exit} | ||
115 | "Checking filename bla&&bla" | ||
116 | } | ||
117 | expect { | ||
118 | timeout {puts "TESTING ERROR 8.2\n";exit} | ||
119 | "Error:" | ||
120 | } | ||
121 | expect { | ||
122 | timeout {puts "TESTING ERROR 8.3\n";exit} | ||
123 | "is an invalid filename" | ||
124 | } | ||
125 | after 100 | ||
126 | |||
112 | send -- "firejail --debug-check-filename --noprofile --private-etc=\"bla&&bla\"\r" | 127 | send -- "firejail --debug-check-filename --noprofile --private-etc=\"bla&&bla\"\r" |
113 | expect { | 128 | expect { |
114 | timeout {puts "TESTING ERROR 9.1\n";exit} | 129 | timeout {puts "TESTING ERROR 9.1\n";exit} |
diff --git a/test/fs/private-bin.exp b/test/fs/private-bin.exp index fe9468be9..f7181d218 100755 --- a/test/fs/private-bin.exp +++ b/test/fs/private-bin.exp | |||
@@ -65,6 +65,28 @@ expect { | |||
65 | "sh" | 65 | "sh" |
66 | } | 66 | } |
67 | send -- "exit\r" | 67 | send -- "exit\r" |
68 | after 100 | ||
69 | |||
70 | |||
71 | send -- "firejail --private-bin=/etc/shadow\r" | ||
72 | expect { | ||
73 | timeout {puts "TESTING ERROR 8\n";exit} | ||
74 | "invalid filename" | ||
75 | } | ||
76 | after 100 | ||
77 | |||
78 | send -- "firejail --private-bin=\"bla;bla\"\r" | ||
79 | expect { | ||
80 | timeout {puts "TESTING ERROR 9\n";exit} | ||
81 | "is an invalid filename" | ||
82 | } | ||
83 | after 100 | ||
84 | |||
85 | send -- "firejail --private-etc=../bin/ls\r" | ||
86 | expect { | ||
87 | timeout {puts "TESTING ERROR 10\n";exit} | ||
88 | "is an invalid filename" | ||
89 | } | ||
68 | 90 | ||
69 | after 100 | 91 | after 100 |
70 | puts "\nall done\n" | 92 | puts "\nall done\n" |
diff --git a/test/fs/private-etc.exp b/test/fs/private-etc.exp index e692f7382..36b5d247c 100755 --- a/test/fs/private-etc.exp +++ b/test/fs/private-etc.exp | |||
@@ -33,12 +33,40 @@ expect { | |||
33 | "resolv.conf" | 33 | "resolv.conf" |
34 | } | 34 | } |
35 | 35 | ||
36 | send -- "ls -al /etc; echo done\r" | 36 | |
37 | send -- "file /etc/shadow\r" | ||
37 | expect { | 38 | expect { |
38 | timeout {puts "TESTING ERROR 7\n";exit} | 39 | timeout {puts "TESTING ERROR 7\n";exit} |
39 | "shadow" {puts "TESTING ERROR 8\n";exit} | 40 | "No such file or directory" |
40 | "done" | 41 | } |
42 | after 100 | ||
43 | send -- "exit\r" | ||
44 | sleep 1 | ||
45 | |||
46 | send -- "firejail --private-etc=shadow\r" | ||
47 | expect { | ||
48 | timeout {puts "TESTING ERROR 8\n";exit} | ||
49 | "invalid file type" | ||
50 | } | ||
51 | after 100 | ||
52 | |||
53 | send -- "firejail --private-etc=\"bla;bla\"\r" | ||
54 | expect { | ||
55 | timeout {puts "TESTING ERROR 9\n";exit} | ||
56 | "is an invalid filename" | ||
41 | } | 57 | } |
58 | after 100 | ||
59 | |||
60 | send -- "firejail --private-etc=../bin/ls\r" | ||
61 | expect { | ||
62 | timeout {puts "TESTING ERROR 10\n";exit} | ||
63 | "is an invalid filename" | ||
64 | } | ||
65 | after 100 | ||
66 | |||
67 | |||
68 | |||
69 | |||
42 | 70 | ||
43 | after 100 | 71 | after 100 |
44 | puts "\nall done\n" | 72 | puts "\nall done\n" |
diff --git a/test/fs/private-home.exp b/test/fs/private-home.exp index de5a88dea..3840d1cb8 100755 --- a/test/fs/private-home.exp +++ b/test/fs/private-home.exp | |||
@@ -9,11 +9,19 @@ match_max 100000 | |||
9 | 9 | ||
10 | # create some test files in user home directory | 10 | # create some test files in user home directory |
11 | send -- "touch ~/_firejail_test_file1\r" | 11 | send -- "touch ~/_firejail_test_file1\r" |
12 | after 100 | ||
12 | send -- "touch ~/_firejail_test_file2\r" | 13 | send -- "touch ~/_firejail_test_file2\r" |
14 | after 100 | ||
13 | send -- "mkdir ~/_firejail_test_dir1\r" | 15 | send -- "mkdir ~/_firejail_test_dir1\r" |
16 | after 100 | ||
14 | send -- "mkdir ~/_firejail_test_dir1/_firejail_test_dir2\r" | 17 | send -- "mkdir ~/_firejail_test_dir1/_firejail_test_dir2\r" |
18 | after 100 | ||
15 | send -- "touch ~/_firejail_test_dir1/_firejail_test_dir2/_firejail_test_file3\r" | 19 | send -- "touch ~/_firejail_test_dir1/_firejail_test_dir2/_firejail_test_file3\r" |
16 | after 100 | 20 | after 100 |
21 | send -- "ln -s /etc ~/_firejail_test_link1\r" | ||
22 | after 100 | ||
23 | send -- "ln -s ~/_firejail_test_dir1 ~/_firejail_test_link2\r" | ||
24 | after 100 | ||
17 | 25 | ||
18 | send -- "firejail --private-home=_firejail_test_file1,_firejail_test_file2,_firejail_test_dir1\r" | 26 | send -- "firejail --private-home=_firejail_test_file1,_firejail_test_file2,_firejail_test_dir1\r" |
19 | expect { | 27 | expect { |
@@ -37,8 +45,58 @@ expect { | |||
37 | } | 45 | } |
38 | after 100 | 46 | after 100 |
39 | 47 | ||
40 | send -- "rm -f ~/_firejail_test_file*\r" | 48 | send -- "exit\r" |
41 | send -- "rm -fr ~/_firejail_test_dir*\r" | 49 | sleep 1 |
50 | |||
51 | send -- "firejail --private-home=\"bla;bla\"\r" | ||
52 | expect { | ||
53 | timeout {puts "TESTING ERROR 5\n";exit} | ||
54 | "is an invalid filename" | ||
55 | } | ||
56 | after 100 | ||
57 | |||
58 | send -- "firejail --private-home=/etc/shadow\r" | ||
59 | expect { | ||
60 | timeout {puts "TESTING ERROR 6\n";exit} | ||
61 | "invalid file" | ||
62 | } | ||
63 | after 100 | ||
64 | |||
65 | send -- "firejail --private-home=/etc/passwd\r" | ||
66 | expect { | ||
67 | timeout {puts "TESTING ERROR 7\n";exit} | ||
68 | "invalid file" | ||
69 | } | ||
70 | after 100 | ||
71 | |||
72 | send -- "firejail --private-home=../../etc/passwd\r" | ||
73 | expect { | ||
74 | timeout {puts "TESTING ERROR 8\n";exit} | ||
75 | "invalid file" | ||
76 | } | ||
77 | after 100 | ||
78 | |||
79 | send -- "firejail --private-home=_firejail_test_link1\r" | ||
80 | expect { | ||
81 | timeout {puts "TESTING ERROR 9\n";exit} | ||
82 | "to file or directory not owned by the user" | ||
83 | } | ||
84 | after 100 | ||
85 | |||
86 | send -- "firejail --private-home=_firejail_test_link2\r" | ||
87 | expect { | ||
88 | timeout {puts "TESTING ERROR 10\n";exit} | ||
89 | "Child process initialized" | ||
90 | } | ||
91 | after 100 | ||
92 | send -- "file file ~/_firejail_test_link2\r" | ||
93 | expect { | ||
94 | timeout {puts "TESTING ERROR 11\n";exit} | ||
95 | "broken symbolic link" | ||
96 | } | ||
97 | send -- "exit\r" | ||
98 | |||
99 | send -- "rm -f ~/_firejail_test*\r" | ||
42 | after 100 | 100 | after 100 |
43 | 101 | ||
44 | puts "\nall done\n" | 102 | puts "\nall done\n" |
diff --git a/test/fs/read-write.exp b/test/fs/read-write.exp index 57986488e..19a915f66 100755 --- a/test/fs/read-write.exp +++ b/test/fs/read-write.exp | |||
@@ -15,37 +15,21 @@ expect { | |||
15 | } | 15 | } |
16 | sleep 1 | 16 | sleep 1 |
17 | 17 | ||
18 | send -- "echo mytest >~/_firejail_test_dir/a;echo done\r" | 18 | send -- "echo mytest > ~/_firejail_test_dir/a\r" |
19 | expect { | 19 | expect { |
20 | timeout {puts "TESTING ERROR 1\n";exit} | 20 | timeout {puts "TESTING ERROR 5\n";exit} |
21 | "done" | 21 | "Read-only file system" |
22 | } | ||
23 | after 100 | ||
24 | |||
25 | send -- "echo mytest >~/_firejail_test_dir/test1/b;echo done\r" | ||
26 | expect { | ||
27 | timeout {puts "TESTING ERROR 2\n";exit} | ||
28 | "done" | ||
29 | } | 22 | } |
30 | after 100 | 23 | after 100 |
31 | 24 | ||
32 | send -- "cat ~/_firejail_test_dir/a;echo done\r" | 25 | send -- "echo mytest > ~/_firejail_test_dir/test1/b\r" |
33 | expect { | 26 | sleep 1 |
34 | timeout {puts "TESTING ERROR 3\n";exit} | ||
35 | "mytest" {puts "TESTING ERROR 4\n";exit} | ||
36 | "done" | ||
37 | } | ||
38 | after 100 | ||
39 | 27 | ||
40 | send -- "cat ~/_firejail_test_dir/test1/b;echo done\r" | 28 | send -- "cat ~/_firejail_test_dir/test1/b\r" |
41 | expect { | 29 | expect { |
42 | timeout {puts "TESTING ERROR 5\n";exit} | 30 | timeout {puts "TESTING ERROR 5\n";exit} |
43 | "mytest" | 31 | "mytest" |
44 | } | 32 | } |
45 | expect { | ||
46 | timeout {puts "TESTING ERROR 6\n";exit} | ||
47 | "done" | ||
48 | } | ||
49 | 33 | ||
50 | after 100 | 34 | after 100 |
51 | puts "\nall done\n" | 35 | puts "\nall done\n" |
diff --git a/test/fs/testfile1 b/test/fs/testfile1 new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/test/fs/testfile1 | |||
diff --git a/test/fscheck-private.exp b/test/fscheck-private.exp deleted file mode 100755 index 8e485cc03..000000000 --- a/test/fscheck-private.exp +++ /dev/null | |||
@@ -1,70 +0,0 @@ | |||
1 | #!/usr/bin/expect -f | ||
2 | |||
3 | set timeout 10 | ||
4 | spawn $env(SHELL) | ||
5 | match_max 100000 | ||
6 | |||
7 | |||
8 | # .. | ||
9 | #send -- "firejail --net=br0 --private=../test/fscheck-dir\r" | ||
10 | #expect { | ||
11 | # timeout {puts "TESTING ERROR 0.1\n";exit} | ||
12 | # "Error" | ||
13 | #} | ||
14 | #after 100 | ||
15 | |||
16 | # dir link | ||
17 | #send -- "firejail --net=br0 --private=fscheck-dir-link\r" | ||
18 | #expect { | ||
19 | # timeout {puts "TESTING ERROR 1\n";exit} | ||
20 | # "Error" | ||
21 | #} | ||
22 | #after 100 | ||
23 | |||
24 | # .. | ||
25 | #send -- "firejail --net=br0 --private=../test/fscheck-dir-link\r" | ||
26 | #expect { | ||
27 | # timeout {puts "TESTING ERROR 1.1\n";exit} | ||
28 | # "Error" | ||
29 | #} | ||
30 | #after 100 | ||
31 | |||
32 | # file link | ||
33 | send -- "firejail --net=br0 --private=fscheck-file-link\r" | ||
34 | expect { | ||
35 | timeout {puts "TESTING ERROR 2\n";exit} | ||
36 | "Error" | ||
37 | } | ||
38 | after 100 | ||
39 | |||
40 | # file | ||
41 | send -- "firejail --net=br0 --private=fscheck-file\r" | ||
42 | expect { | ||
43 | timeout {puts "TESTING ERROR 2.1\n";exit} | ||
44 | "Error" | ||
45 | } | ||
46 | after 100 | ||
47 | |||
48 | # .. | ||
49 | send -- "firejail --net=br0 --private=../test/fscheck-file\r" | ||
50 | expect { | ||
51 | timeout {puts "TESTING ERROR 2.2\n";exit} | ||
52 | "Error" | ||
53 | } | ||
54 | after 100 | ||
55 | |||
56 | # no file | ||
57 | send -- "firejail --net=br0 --private=../test/nodir\r" | ||
58 | expect { | ||
59 | timeout {puts "TESTING ERROR 3\n";exit} | ||
60 | "Error" | ||
61 | } | ||
62 | after 100 | ||
63 | |||
64 | # same owner | ||
65 | send -- "firejail --net=br0 --private=/etc\r" | ||
66 | expect { | ||
67 | timeout {puts "TESTING ERROR 4\n";exit} | ||
68 | "Error" | ||
69 | } | ||
70 | after 100 | ||
diff --git a/test/rlimit/rlimit.sh b/test/rlimit/rlimit.sh deleted file mode 100755 index d85497176..000000000 --- a/test/rlimit/rlimit.sh +++ /dev/null | |||
@@ -1,14 +0,0 @@ | |||
1 | #!/bin/bash | ||
2 | # This file is part of Firejail project | ||
3 | # Copyright (C) 2014-2016 Firejail Authors | ||
4 | # License GPL v2 | ||
5 | |||
6 | export MALLOC_CHECK_=3 | ||
7 | export MALLOC_PERTURB_=$(($RANDOM % 255 + 1)) | ||
8 | |||
9 | echo "TESTING: rlimit (test/rlimit/rlimit.exp)" | ||
10 | ./rlimit.exp | ||
11 | |||
12 | echo "TESTING: rlimit profile (test/rlimit/rlimit-profile.exp)" | ||
13 | ./rlimit-profile.exp | ||
14 | |||
diff --git a/test/utils/firemon-cpu.exp b/test/utils/firemon-cpu.exp index f2ecd4a5c..00156c909 100755 --- a/test/utils/firemon-cpu.exp +++ b/test/utils/firemon-cpu.exp | |||
@@ -24,7 +24,6 @@ sleep 1 | |||
24 | 24 | ||
25 | spawn $env(SHELL) | 25 | spawn $env(SHELL) |
26 | send -- "firemon --cpu\r" | 26 | send -- "firemon --cpu\r" |
27 | sleep 4 | ||
28 | expect { | 27 | expect { |
29 | timeout {puts "TESTING ERROR 2\n";exit} | 28 | timeout {puts "TESTING ERROR 2\n";exit} |
30 | "need to be root" {puts "TESTING SKIP: /proc mounted as hidepid\n"; exit} | 29 | "need to be root" {puts "TESTING SKIP: /proc mounted as hidepid\n"; exit} |
diff --git a/test/utils/firemon-interface.exp b/test/utils/firemon-interface.exp new file mode 100755 index 000000000..edafd1639 --- /dev/null +++ b/test/utils/firemon-interface.exp | |||
@@ -0,0 +1,18 @@ | |||
1 | #!/usr/bin/expect -f | ||
2 | # This file is part of Firejail project | ||
3 | # Copyright (C) 2014-2016 Firejail Authors | ||
4 | # License GPL v2 | ||
5 | |||
6 | set timeout 10 | ||
7 | spawn $env(SHELL) | ||
8 | match_max 100000 | ||
9 | |||
10 | send -- "firemon --interface\r" | ||
11 | expect { | ||
12 | timeout {puts "TESTING ERROR 0\n";exit} | ||
13 | "you need to be root" | ||
14 | } | ||
15 | after 100 | ||
16 | |||
17 | puts "\nall done\n" | ||
18 | |||
diff --git a/test/utils/firemon-name.exp b/test/utils/firemon-name.exp new file mode 100755 index 000000000..c5dbfabab --- /dev/null +++ b/test/utils/firemon-name.exp | |||
@@ -0,0 +1,28 @@ | |||
1 | #!/usr/bin/expect -f | ||
2 | # This file is part of Firejail project | ||
3 | # Copyright (C) 2014-2016 Firejail Authors | ||
4 | # License GPL v2 | ||
5 | |||
6 | set timeout 10 | ||
7 | spawn $env(SHELL) | ||
8 | match_max 100000 | ||
9 | |||
10 | send -- "firejail --name=test\r" | ||
11 | expect { | ||
12 | timeout {puts "TESTING ERROR 0\n";exit} | ||
13 | "Child process initialized" | ||
14 | } | ||
15 | sleep 1 | ||
16 | |||
17 | spawn $env(SHELL) | ||
18 | send -- "firemon --cpu --name=test\r" | ||
19 | expect { | ||
20 | timeout {puts "TESTING ERROR 2\n";exit} | ||
21 | "need to be root" {puts "TESTING SKIP: /proc mounted as hidepid\n"; exit} | ||
22 | "Cpus_allowed_list" | ||
23 | } | ||
24 | |||
25 | after 100 | ||
26 | |||
27 | puts "\nall done\n" | ||
28 | |||
diff --git a/test/utils/firemon-version.exp b/test/utils/firemon-version.exp new file mode 100755 index 000000000..639c15c29 --- /dev/null +++ b/test/utils/firemon-version.exp | |||
@@ -0,0 +1,18 @@ | |||
1 | #!/usr/bin/expect -f | ||
2 | # This file is part of Firejail project | ||
3 | # Copyright (C) 2014-2016 Firejail Authors | ||
4 | # License GPL v2 | ||
5 | |||
6 | set timeout 10 | ||
7 | spawn $env(SHELL) | ||
8 | match_max 100000 | ||
9 | |||
10 | send -- "firemon --version\r" | ||
11 | expect { | ||
12 | timeout {puts "TESTING ERROR 0\n";exit} | ||
13 | "firemon version" | ||
14 | } | ||
15 | after 100 | ||
16 | |||
17 | puts "\nall done\n" | ||
18 | |||
diff --git a/test/utils/utils.sh b/test/utils/utils.sh index bd91110f7..804e5ae0f 100755 --- a/test/utils/utils.sh +++ b/test/utils/utils.sh | |||
@@ -100,3 +100,12 @@ echo "TESTING: firemon cpu (test/utils/firemon-cpu.exp)" | |||
100 | echo "TESTING: firemon cgroup (test/utils/firemon-cgroup.exp)" | 100 | echo "TESTING: firemon cgroup (test/utils/firemon-cgroup.exp)" |
101 | ./firemon-cgroup.exp | 101 | ./firemon-cgroup.exp |
102 | 102 | ||
103 | echo "TESTING: firemon version (test/utils/firemon-version.exp)" | ||
104 | ./firemon-version.exp | ||
105 | |||
106 | echo "TESTING: firemon interface (test/utils/firemon-interface.exp)" | ||
107 | ./firemon-interface.exp | ||
108 | |||
109 | echo "TESTING: firemon name (test/utils/firemon-name.exp)" | ||
110 | ./firemon-name.exp | ||
111 | |||