aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.in13
-rwxr-xr-xconfigure3
-rw-r--r--configure.ac5
-rwxr-xr-xgcov.sh5
-rw-r--r--src/fcopy/Makefile.in45
-rw-r--r--src/fcopy/main.c345
-rw-r--r--src/firejail/util.c1
-rw-r--r--src/fnet/main.c6
-rw-r--r--src/fseccomp/main.c4
-rwxr-xr-xtest/fcopy/cmdline.exp56
-rwxr-xr-xtest/fcopy/dircopy.exp86
-rwxr-xr-xtest/fcopy/fcopy.sh23
-rwxr-xr-xtest/fcopy/filecopy.exp54
-rwxr-xr-xtest/fcopy/linkcopy.exp86
-rw-r--r--test/fcopy/src/a/b/file411
-rw-r--r--test/fcopy/src/a/file30
l---------test/fcopy/src/dircopy.exp1
-rwxr-xr-xtest/fcopy/src/file10
-rw-r--r--test/fcopy/src/file20
19 files changed, 733 insertions, 11 deletions
diff --git a/Makefile.in b/Makefile.in
index 86fd4f4b7..6501989a9 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,6 +1,6 @@
1all: apps man 1all: apps man
2MYLIBS = src/lib 2MYLIBS = src/lib
3APPS = src/firejail src/firemon src/firecfg src/libtrace src/libtracelog src/ftee src/faudit src/libconnect src/fnet src/fseccomp 3APPS = src/firejail src/firemon src/firecfg src/libtrace src/libtracelog src/ftee src/faudit src/libconnect src/fnet src/fseccomp src/fcopy
4MANPAGES = firejail.1 firemon.1 firecfg.1 firejail-profile.5 firejail-login.5 4MANPAGES = firejail.1 firemon.1 firecfg.1 firejail-profile.5 firejail-login.5
5 5
6prefix=@prefix@ 6prefix=@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
133uninstall: 135uninstall:
@@ -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
147DISTFILES = "src etc platform configure configure.ac Makefile.in install.sh mkman.sh mketc.sh mkdeb.sh mkuid.sh COPYING README RELNOTES" 149DISTFILES = "src etc platform configure configure.ac Makefile.in install.sh mkman.sh mketc.sh mkdeb.sh mkuid.sh COPYING README RELNOTES"
148DISTFILES_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" 150DISTFILES_TEST = "test/rlimit 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
150dist: 152dist:
151 mv config.status config.status.old 153 mv config.status config.status.old
@@ -226,7 +228,10 @@ test-fs:
226test-rlimit: 228test-rlimit:
227 cd test/rlimit; ./rlimit.sh | grep TESTING 229 cd test/rlimit; ./rlimit.sh | grep TESTING
228 230
229test: test-profiles test-fs test-utils test-environment test-apps test-apps-x11 test-apps-x11-xorg test-filters test-arguments test-rlimit 231test-fcopy:
232 cd test/fcopy; ./fcopy.sh | grep TESTING
233
234test: test-profiles test-fcopy test-fs test-utils test-environment test-apps test-apps-x11 test-apps-x11-xorg test-filters test-arguments test-rlimit
230 echo "TEST COMPLETE" 235 echo "TEST COMPLETE"
231 236
232########################################## 237##########################################
@@ -254,6 +259,6 @@ test-overlay:
254 259
255# For testing hidepid system, the command to set it up is "mount -o remount,rw,hidepid=2 /proc" 260# For testing hidepid system, the command to set it up is "mount -o remount,rw,hidepid=2 /proc"
256 261
257test-all: test-root test-network test-appimage test-overlay test 262test-all: test-root test-network test-appimage test-overlay test-fcopy test
258 echo "TEST COMPLETE" 263 echo "TEST COMPLETE"
259 \ No newline at end of file 264 \ No newline at end of file
diff --git a/configure b/configure
index 0aefb5c62..9efba1b1d 100755
--- a/configure
+++ b/configure
@@ -3777,7 +3777,7 @@ if test "$prefix" = /usr; then
3777 sysconfdir="/etc" 3777 sysconfdir="/etc"
3778fi 3778fi
3779 3779
3780ac_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" 3780ac_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
3782cat >confcache <<\_ACEOF 3782cat >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"
159fi 159fi
160 160
161AC_OUTPUT(Makefile src/lib/Makefile src/fnet/Makefile src/firejail/Makefile src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile \ 161AC_OUTPUT(Makefile src/lib/Makefile src/fcopy/Makefile src/fnet/Makefile src/firejail/Makefile \
162src/firecfg/Makefile src/ftee/Makefile src/faudit/Makefile src/libconnect/Makefile src/fseccomp/Makefile) 162src/firemon/Makefile src/libtrace/Makefile src/libtracelog/Makefile src/firecfg/Makefile \
163src/ftee/Makefile src/faudit/Makefile src/libconnect/Makefile src/fseccomp/Makefile)
163 164
164echo 165echo
165echo "Configuration options:" 166echo "Configuration options:"
diff --git a/gcov.sh b/gcov.sh
index ffacce6b5..6f668d65f 100755
--- a/gcov.sh
+++ b/gcov.sh
@@ -13,6 +13,7 @@ firemon --help
13/usr/lib/firejail/fnet --help 13/usr/lib/firejail/fnet --help
14/usr/lib/firejail/fseccomp --help 14/usr/lib/firejail/fseccomp --help
15/usr/lib/firejail/ftee --help 15/usr/lib/firejail/ftee --help
16/usr/lib/firejail/fcopy --help
16firecfg --help 17firecfg --help
17sudo chown $USER:$USER `find .` 18sudo chown $USER:$USER `find .`
18generate 19generate
@@ -34,6 +35,10 @@ make test-overlay
34generate 35generate
35sleep 2 36sleep 2
36 37
38make test-fcopy
39generate
40sleep 2
41
37make test-profiles 42make test-profiles
38generate 43generate
39sleep 2 44sleep 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 @@
1all: fcopy
2
3prefix=@prefix@
4exec_prefix=@exec_prefix@
5libdir=@libdir@
6sysconfdir=@sysconfdir@
7
8VERSION=@PACKAGE_VERSION@
9NAME=@PACKAGE_NAME@
10HAVE_SECCOMP_H=@HAVE_SECCOMP_H@
11HAVE_SECCOMP=@HAVE_SECCOMP@
12HAVE_CHROOT=@HAVE_CHROOT@
13HAVE_BIND=@HAVE_BIND@
14HAVE_FATAL_WARNINGS=@HAVE_FATAL_WARNINGS@
15HAVE_NETWORK=@HAVE_NETWORK@
16HAVE_USERNS=@HAVE_USERNS@
17HAVE_X11=@HAVE_X11@
18HAVE_FILE_TRANSFER=@HAVE_FILE_TRANSFER@
19HAVE_WHITELIST=@HAVE_WHITELIST@
20HAVE_GLOBALCFG=@HAVE_GLOBALCFG@
21HAVE_APPARMOR=@HAVE_APPARMOR@
22HAVE_OVERLAYFS=@HAVE_OVERLAYFS@
23HAVE_PRIVATE_HOME=@HAVE_PRIVATE_HOME@
24EXTRA_LDFLAGS +=@EXTRA_LDFLAGS@
25HAVE_GCOV=@HAVE_GCOV@
26EXTRA_LDFLAGS +=@EXTRA_LDFLAGS@
27
28H_FILE_LIST = $(sort $(wildcard *.[h]))
29C_FILE_LIST = $(sort $(wildcard *.c))
30OBJS = $(C_FILE_LIST:.c=.o)
31BINOBJS = $(foreach file, $(OBJS), $file)
32CFLAGS += -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
33LDFLAGS += -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
38fcopy: $(OBJS)
39 $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(EXTRA_LDFLAGS)
40
41clean:; rm -f *.o fcopy *.gcov *.gcda *.gcno
42
43distclean: clean
44 rm -fr Makefile
45
diff --git a/src/fcopy/main.c b/src/fcopy/main.c
new file mode 100644
index 000000000..4437b90e5
--- /dev/null
+++ b/src/fcopy/main.c
@@ -0,0 +1,345 @@
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)
27static int size_limit_reached = 0;
28static unsigned file_cnt = 0;
29static unsigned size_cnt = 0;
30
31static char *outpath = NULL;
32static char *inpath = NULL;
33
34
35// modified version of the function from util.c
36static 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
81errexit:
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
91static 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
104void copy_link(const char *target, const char *linkpath, mode_t mode, uid_t uid, gid_t gid) {
105 char *rp = realpath(target, NULL);
106 if (rp) {
107 if (symlink(rp, linkpath) == -1)
108 goto errout;
109 free(rp);
110 }
111 else
112 goto errout;
113
114 return;
115errout:
116 fprintf(stderr, "Warning fcopy: cannot create symbolic link %s\n", target);
117}
118
119static int first = 1;
120static int fs_copydir(const char *infname, const struct stat *st, int ftype, struct FTW *sftw) {
121 (void) st;
122 (void) sftw;
123 assert(infname);
124 assert(*infname != '\0');
125 assert(outpath);
126 assert(*outpath != '\0');
127 assert(inpath);
128
129 // check size limit
130 if (size_limit_reached)
131 return 0;
132
133 char *outfname;
134 if (asprintf(&outfname, "%s%s", outpath, infname + strlen(inpath)) == -1)
135 errExit("asprintf");
136
137 // don't copy it if we already have the file
138 struct stat s;
139 if (stat(outfname, &s) == 0) {
140 if (first)
141 first = 0;
142 else
143 fprintf(stderr, "Warning fcopy: skipping %s, file already present\n", infname);
144 free(outfname);
145 return 0;
146 }
147
148 // extract mode and ownership
149 if (stat(infname, &s) != 0) {
150 fprintf(stderr, "Warning fcopy: skipping %s, cannot find inode\n", infname);
151 free(outfname);
152 return 0;
153 }
154 uid_t uid = s.st_uid;
155 gid_t gid = s.st_gid;
156 mode_t mode = s.st_mode;
157
158 // recalculate size
159 if ((s.st_size + size_cnt) > COPY_LIMIT) {
160 fprintf(stderr, "Error fcopy: size limit of %dMB reached\n", (COPY_LIMIT / 1024) / 1024);
161 size_limit_reached = 1;
162 free(outfname);
163 return 0;
164 }
165
166 file_cnt++;
167 size_cnt += s.st_size;
168
169 if(ftype == FTW_F) {
170 copy_file(infname, outfname, mode, uid, gid);
171 }
172 else if (ftype == FTW_D) {
173 mkdir_attr(outfname, mode, uid, gid);
174 }
175 else if (ftype == FTW_SL) {
176 copy_link(infname, outfname, mode, uid, gid);
177 }
178
179 return(0);
180}
181
182static char *check(const char *src) {
183 struct stat s;
184 char *rsrc = realpath(src, NULL);
185 if (!rsrc || stat(rsrc, &s) == -1) {
186 fprintf(stderr, "Error fcopy: cannot find %s directory\n", src);
187 exit(1);
188 }
189
190 // check uid
191 if (s.st_uid != getuid() || s.st_gid != getgid()) {
192 fprintf(stderr, "Error fcopy: uid/gid mismatch for %s\n", rsrc);
193 exit(1);
194 }
195
196 // dir, link, regular file
197 if (S_ISDIR(s.st_mode) || S_ISREG(s.st_mode) || S_ISLNK(s.st_mode)) {
198 return rsrc; // normal exit from the function
199 }
200 fprintf(stderr, "Error fcopy: invalid directory %s\n", rsrc);
201 exit(1);
202}
203
204static void duplicate_dir(const char *src, const char *dest, struct stat *s) {
205 (void) s;
206 char *rsrc = check(src);
207 char *rdest = check(dest);
208 inpath = rsrc;
209 outpath = rdest;
210
211 // walk
212 if(nftw(rsrc, fs_copydir, 1, FTW_PHYS) != 0) {
213 fprintf(stderr, "Error: unable to copy file\n");
214 exit(1);
215 }
216
217 free(rsrc);
218 free(rdest);
219}
220
221static void duplicate_file(const char *src, const char *dest, struct stat *s) {
222 char *rsrc = check(src);
223 char *rdest = check(dest);
224 uid_t uid = s->st_uid;
225 gid_t gid = s->st_gid;
226 mode_t mode = s->st_mode;
227
228 // build destination file name
229 char *name;
230 char *ptr = strrchr(rsrc, '/');
231 ptr++;
232 if (asprintf(&name, "%s/%s", rdest, ptr) == -1)
233 errExit("asprintf");
234
235 // copy
236 copy_file(rsrc, name, mode, uid, gid);
237
238 free(name);
239 free(rsrc);
240 free(rdest);
241}
242
243static void duplicate_link(const char *src, const char *dest, struct stat *s) {
244 char *rsrc = check(src);
245 char *rdest = check(dest);
246 uid_t uid = s->st_uid;
247 gid_t gid = s->st_gid;
248 mode_t mode = s->st_mode;
249
250 // build destination file name
251 char *name;
252 char *ptr = strrchr(rsrc, '/');
253 ptr++;
254 if (asprintf(&name, "%s/%s", rdest, ptr) == -1)
255 errExit("asprintf");
256
257 // copy
258 copy_link(rsrc, name, mode, uid, gid);
259
260 free(name);
261 free(rsrc);
262 free(rdest);
263}
264
265static void usage(void) {
266 printf("Usage: fcopy src dest\n");
267 printf("Copy src file in dest directory. If src is a directory, copy all the files in\n");
268 printf("src recoursively\n");
269}
270
271int main(int argc, char **argv) {
272#if 0
273{
274//system("cat /proc/self/status");
275int i;
276for (i = 0; i < argc; i++)
277 printf("*%s* ", argv[i]);
278printf("\n");
279}
280#endif
281 if (argc != 3) {
282 fprintf(stderr, "Error fcopy: files missing\n");
283 usage();
284 exit(1);
285 }
286
287 int i;
288 int index = 1;
289 for (i = 1; i < (argc - 2); i++) {
290 if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") ==0) {
291 usage();
292 return 0;
293 }
294 }
295
296 // check the two files; remove ending /
297 char *src = argv[index];
298 int len = strlen(src);
299 if (src[len - 1] == '/')
300 src[len - 1] = '\0';
301 if (strcspn(src, "\\*&!?\"'<>%^(){}[];,") != (size_t)len) {
302 fprintf(stderr, "Error fcopy: invalid file name %s\n", src);
303 exit(1);
304 }
305
306 char *dest = argv[index + 1];
307 len = strlen(dest);
308 if (dest[len - 1] == '/')
309 dest[len - 1] = '\0';
310 if (strcspn(dest, "\\*&!?\"'<>%^(){}[];,~") != (size_t)len) {
311 fprintf(stderr, "Error fcopy: invalid file name %s\n", dest);
312 exit(1);
313 }
314
315
316 // the destination should be a directory; remove ending /
317 struct stat s;
318 if (stat(dest, &s) == -1) {
319 fprintf(stderr, "Error fcopy: cannot find destination directory\n");
320 exit(1);
321 }
322 if (S_ISDIR(s.st_mode) == -1) {
323 fprintf(stderr, "Error fcopy: the destination should be a directory\n");
324 exit(1);
325 }
326
327 // copy files
328 if (lstat(src, &s) == -1) {
329 fprintf(stderr, "Error fcopy: cannot find source file\n");
330 exit(1);
331 }
332
333 if (S_ISDIR(s.st_mode))
334 duplicate_dir(src, dest, &s);
335 else if (S_ISREG(s.st_mode))
336 duplicate_file(src, dest, &s);
337 else if (S_ISLNK(s.st_mode))
338 duplicate_link(src, dest, &s);
339 else {
340 fprintf(stderr, "Error fcopy: source file unsupported\n");
341 exit(1);
342 }
343
344 return 0;
345}
diff --git a/src/firejail/util.c b/src/firejail/util.c
index d928c6b42..027f1cd47 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");
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++)
42printf("\n"); 42printf("\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++)
47printf("\n"); 47printf("\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/test/fcopy/cmdline.exp b/test/fcopy/cmdline.exp
new file mode 100755
index 000000000..95e221321
--- /dev/null
+++ b/test/fcopy/cmdline.exp
@@ -0,0 +1,56 @@
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
6set timeout 10
7spawn $env(SHELL)
8match_max 100000
9
10send -- "/usr/lib/firejail/fcopy\r"
11expect {
12 timeout {puts "TESTING ERROR 0\n";exit}
13 "files missing"
14}
15expect {
16 timeout {puts "TESTING ERROR 1\n";exit}
17 "Usage:"
18}
19after 100
20
21send -- "/usr/lib/firejail/fcopy foo\r"
22expect {
23 timeout {puts "TESTING ERROR 2\n";exit}
24 "files missing"
25}
26expect {
27 timeout {puts "TESTING ERROR 3\n";exit}
28 "Usage:"
29}
30after 100
31
32send -- "/usr/lib/firejail/fcopy f%oo1 foo2\r"
33expect {
34 timeout {puts "TESTING ERROR 4\n";exit}
35 "invalid file name"
36}
37after 100
38
39send -- "/usr/lib/firejail/fcopy foo1 f,oo2\r"
40expect {
41 timeout {puts "TESTING ERROR 5\n";exit}
42 "invalid file name"
43}
44after 100
45
46send -- "/usr/lib/firejail/fcopy foo1 foo2\r"
47expect {
48 timeout {puts "TESTING ERROR 6\n";exit}
49 "cannot find destination directory"
50}
51after 100
52
53
54
55
56puts "\nall done\n"
diff --git a/test/fcopy/dircopy.exp b/test/fcopy/dircopy.exp
new file mode 100755
index 000000000..b87f24a59
--- /dev/null
+++ b/test/fcopy/dircopy.exp
@@ -0,0 +1,86 @@
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#
9set timeout 10
10spawn $env(SHELL)
11match_max 100000
12
13send -- "rm -fr dest/*\r"
14after 100
15
16send -- "/usr/lib/firejail/fcopy src dest\r"
17after 100
18
19send -- "find dest\r"
20expect {
21 timeout {puts "TESTING ERROR 0\n";exit}
22 "dest/"
23}
24expect {
25 timeout {puts "TESTING ERROR 1\n";exit}
26 "dest/a"
27}
28expect {
29 timeout {puts "TESTING ERROR 2\n";exit}
30 "dest/a/b"
31}
32expect {
33 timeout {puts "TESTING ERROR 3\n";exit}
34 "dest/a/b/file4"
35}
36expect {
37 timeout {puts "TESTING ERROR 4\n";exit}
38 "dest/a/file3"
39}
40expect {
41 timeout {puts "TESTING ERROR 5\n";exit}
42 "dest/dircopy.exp"
43}
44expect {
45 timeout {puts "TESTING ERROR 6\n";exit}
46 "dest/file2"
47}
48expect {
49 timeout {puts "TESTING ERROR 7\n";exit}
50 "dest/file1"
51}
52after 100
53
54
55send -- "ls -al dest\r"
56expect {
57 timeout {puts "TESTING ERROR 8\n";exit}
58 "drwx--x--x"
59}
60expect {
61 timeout {puts "TESTING ERROR 9\n";exit}
62 "rwxrwxrwx"
63}
64expect {
65 timeout {puts "TESTING ERROR 10\n";exit}
66 "rw-r--r--"
67}
68after 100
69
70send -- "diff -q src/a/b/file4 dest/a/b/file4; echo done\r"
71expect {
72 timeout {puts "TESTING ERROR 11\n";exit}
73 "differ" {puts "TESTING ERROR 12\n";exit}
74 "done"
75}
76
77send -- "file dest/dircopy.exp\r"
78expect {
79 timeout {puts "TESTING ERROR 13\n";exit}
80 "symbolic link"
81}
82
83send -- "rm -fr dest/*\r"
84after 100
85
86puts "\nall done\n"
diff --git a/test/fcopy/fcopy.sh b/test/fcopy/fcopy.sh
new file mode 100755
index 000000000..9961d6317
--- /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
6export MALLOC_CHECK_=3
7export MALLOC_PERTURB_=$(($RANDOM % 255 + 1))
8
9rm -fr dest/*
10
11echo "TESTING: fcopy cmdline (test/fcopy/cmdline.exp)"
12./cmdline.exp
13
14echo "TESTING: fcopy directory (test/fcopy/dircopy.exp)"
15./dircopy.exp
16
17echo "TESTING: fcopy file (test/fcopy/filecopy.exp)"
18./filecopy.exp
19
20echo "TESTING: fcopy link (test/fcopy/linkcopy.exp)"
21./linkcopy.exp
22
23rm -fr dest/*
diff --git a/test/fcopy/filecopy.exp b/test/fcopy/filecopy.exp
new file mode 100755
index 000000000..9927e18fe
--- /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#
9set timeout 10
10spawn $env(SHELL)
11match_max 100000
12
13send -- "rm -fr dest/*\r"
14after 100
15
16send -- "/usr/lib/firejail/fcopy src/dircopy.exp dest\r"
17after 100
18
19send -- "find dest\r"
20expect {
21 timeout {puts "TESTING ERROR 0\n";exit}
22 "dest/"
23}
24expect {
25 timeout {puts "TESTING ERROR 1\n";exit}
26 "dest/dircopy.exp"
27}
28after 100
29
30
31send -- "ls -al dest\r"
32expect {
33 timeout {puts "TESTING ERROR 2\n";exit}
34 "lrwxrwxrwx"
35}
36after 100
37
38send -- "diff -q dircopy.exp dest/dircopy.exp; echo done\r"
39expect {
40 timeout {puts "TESTING ERROR 3\n";exit}
41 "differ" {puts "TESTING ERROR 4\n";exit}
42 "done"
43}
44
45send -- "file dest/dircopy.exp\r"
46expect {
47 timeout {puts "TESTING ERROR 5\n";exit}
48 "symbolic link"
49}
50
51send -- "rm -fr dest/*\r"
52after 100
53
54puts "\nall done\n"
diff --git a/test/fcopy/linkcopy.exp b/test/fcopy/linkcopy.exp
new file mode 100755
index 000000000..b87f24a59
--- /dev/null
+++ b/test/fcopy/linkcopy.exp
@@ -0,0 +1,86 @@
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#
9set timeout 10
10spawn $env(SHELL)
11match_max 100000
12
13send -- "rm -fr dest/*\r"
14after 100
15
16send -- "/usr/lib/firejail/fcopy src dest\r"
17after 100
18
19send -- "find dest\r"
20expect {
21 timeout {puts "TESTING ERROR 0\n";exit}
22 "dest/"
23}
24expect {
25 timeout {puts "TESTING ERROR 1\n";exit}
26 "dest/a"
27}
28expect {
29 timeout {puts "TESTING ERROR 2\n";exit}
30 "dest/a/b"
31}
32expect {
33 timeout {puts "TESTING ERROR 3\n";exit}
34 "dest/a/b/file4"
35}
36expect {
37 timeout {puts "TESTING ERROR 4\n";exit}
38 "dest/a/file3"
39}
40expect {
41 timeout {puts "TESTING ERROR 5\n";exit}
42 "dest/dircopy.exp"
43}
44expect {
45 timeout {puts "TESTING ERROR 6\n";exit}
46 "dest/file2"
47}
48expect {
49 timeout {puts "TESTING ERROR 7\n";exit}
50 "dest/file1"
51}
52after 100
53
54
55send -- "ls -al dest\r"
56expect {
57 timeout {puts "TESTING ERROR 8\n";exit}
58 "drwx--x--x"
59}
60expect {
61 timeout {puts "TESTING ERROR 9\n";exit}
62 "rwxrwxrwx"
63}
64expect {
65 timeout {puts "TESTING ERROR 10\n";exit}
66 "rw-r--r--"
67}
68after 100
69
70send -- "diff -q src/a/b/file4 dest/a/b/file4; echo done\r"
71expect {
72 timeout {puts "TESTING ERROR 11\n";exit}
73 "differ" {puts "TESTING ERROR 12\n";exit}
74 "done"
75}
76
77send -- "file dest/dircopy.exp\r"
78expect {
79 timeout {puts "TESTING ERROR 13\n";exit}
80 "symbolic link"
81}
82
83send -- "rm -fr dest/*\r"
84after 100
85
86puts "\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
3Lorem 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
5Mauris 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
7Aliquam 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
9Ut 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
11Vestibulum 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