diff options
-rw-r--r-- | src/firejail/ls.c | 122 |
1 files changed, 36 insertions, 86 deletions
diff --git a/src/firejail/ls.c b/src/firejail/ls.c index 4d0a001b6..ebd65cdd3 100644 --- a/src/firejail/ls.c +++ b/src/firejail/ls.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <dirent.h> | 26 | #include <dirent.h> |
27 | #include <pwd.h> | 27 | #include <pwd.h> |
28 | #include <grp.h> | 28 | #include <grp.h> |
29 | #include <fcntl.h> | ||
29 | //#include <dirent.h> | 30 | //#include <dirent.h> |
30 | //#include <stdio.h> | 31 | //#include <stdio.h> |
31 | //#include <stdlib.h> | 32 | //#include <stdlib.h> |
@@ -291,6 +292,41 @@ void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) { | |||
291 | printf("file2 %s\n", fname2 ? fname2 : "(null)"); | 292 | printf("file2 %s\n", fname2 ? fname2 : "(null)"); |
292 | } | 293 | } |
293 | 294 | ||
295 | // get file from sandbox and store it in the current directory | ||
296 | // implemented using --cat | ||
297 | if (op == SANDBOX_FS_GET) { | ||
298 | char *dest_fname = strrchr(fname1, '/'); | ||
299 | if (!dest_fname || *(++dest_fname) == '\0') { | ||
300 | fprintf(stderr, "Error: invalid file name %s\n", fname1); | ||
301 | exit(1); | ||
302 | } | ||
303 | // create destination file if necessary | ||
304 | EUID_ASSERT(); | ||
305 | int fd = open(dest_fname, O_WRONLY|O_CREAT|O_CLOEXEC, S_IRUSR | S_IWRITE); | ||
306 | if (fd == -1) { | ||
307 | fprintf(stderr, "Error: cannot open %s for writing\n", dest_fname); | ||
308 | exit(1); | ||
309 | } | ||
310 | struct stat s; | ||
311 | if (fstat(fd, &s) == -1) | ||
312 | errExit("fstat"); | ||
313 | if (!S_ISREG(s.st_mode)) { | ||
314 | fprintf(stderr, "Error: %s is no regular file\n", dest_fname); | ||
315 | exit(1); | ||
316 | } | ||
317 | if (ftruncate(fd, 0) == -1) | ||
318 | errExit("ftruncate"); | ||
319 | // go quiet - messages on stdout will corrupt the file | ||
320 | arg_debug = 0; | ||
321 | arg_quiet = 1; | ||
322 | // redirection | ||
323 | if (dup2(fd, STDOUT_FILENO) == -1) | ||
324 | errExit("dup2"); | ||
325 | assert(fd != STDOUT_FILENO); | ||
326 | close(fd); | ||
327 | op = SANDBOX_FS_CAT; | ||
328 | } | ||
329 | |||
294 | // sandbox root directory | 330 | // sandbox root directory |
295 | char *rootdir; | 331 | char *rootdir; |
296 | if (asprintf(&rootdir, "/proc/%d/root", pid) == -1) | 332 | if (asprintf(&rootdir, "/proc/%d/root", pid) == -1) |
@@ -327,92 +363,6 @@ void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) { | |||
327 | else | 363 | else |
328 | exit(1); | 364 | exit(1); |
329 | } | 365 | } |
330 | |||
331 | // get file from sandbox and store it in the current directory | ||
332 | else if (op == SANDBOX_FS_GET) { | ||
333 | char *src_fname =fname1; | ||
334 | char *dest_fname = strrchr(fname1, '/'); | ||
335 | if (!dest_fname || *(++dest_fname) == '\0') { | ||
336 | fprintf(stderr, "Error: invalid file name %s\n", fname1); | ||
337 | exit(1); | ||
338 | } | ||
339 | |||
340 | EUID_ROOT(); | ||
341 | if (arg_debug) | ||
342 | printf("copy %s to %s\n", src_fname, dest_fname); | ||
343 | |||
344 | // create a user-owned temporary file in /run/firejail directory | ||
345 | char tmp_fname[] = "/run/firejail/tmpget-XXXXXX"; | ||
346 | int fd = mkstemp(tmp_fname); | ||
347 | if (fd == -1) { | ||
348 | fprintf(stderr, "Error: cannot create temporary file %s\n", tmp_fname); | ||
349 | exit(1); | ||
350 | } | ||
351 | SET_PERMS_FD(fd, getuid(), getgid(), 0600); | ||
352 | close(fd); | ||
353 | |||
354 | // copy the source file into the temporary file - we need to chroot | ||
355 | pid_t child = fork(); | ||
356 | if (child < 0) | ||
357 | errExit("fork"); | ||
358 | if (child == 0) { | ||
359 | // chroot | ||
360 | if (chroot(rootdir) < 0) | ||
361 | errExit("chroot"); | ||
362 | if (chdir("/") < 0) | ||
363 | errExit("chdir"); | ||
364 | |||
365 | // drop privileges | ||
366 | drop_privs(0); | ||
367 | |||
368 | // copy the file | ||
369 | if (copy_file(src_fname, tmp_fname, getuid(), getgid(), 0600)) // already a regular user | ||
370 | _exit(1); | ||
371 | #ifdef HAVE_GCOV | ||
372 | __gcov_flush(); | ||
373 | #endif | ||
374 | _exit(0); | ||
375 | } | ||
376 | |||
377 | // wait for the child to finish | ||
378 | int status = 0; | ||
379 | waitpid(child, &status, 0); | ||
380 | if (WIFEXITED(status) && WEXITSTATUS(status) == 0); | ||
381 | else { | ||
382 | unlink(tmp_fname); | ||
383 | exit(1); | ||
384 | } | ||
385 | |||
386 | // copy the temporary file into the destination file | ||
387 | child = fork(); | ||
388 | if (child < 0) | ||
389 | errExit("fork"); | ||
390 | if (child == 0) { | ||
391 | // drop privileges | ||
392 | drop_privs(0); | ||
393 | |||
394 | // copy the file | ||
395 | if (copy_file(tmp_fname, dest_fname, getuid(), getgid(), 0600)) // already a regular user | ||
396 | _exit(1); | ||
397 | #ifdef HAVE_GCOV | ||
398 | __gcov_flush(); | ||
399 | #endif | ||
400 | _exit(0); | ||
401 | } | ||
402 | |||
403 | // wait for the child to finish | ||
404 | status = 0; | ||
405 | waitpid(child, &status, 0); | ||
406 | if (WIFEXITED(status) && WEXITSTATUS(status) == 0); | ||
407 | else { | ||
408 | unlink(tmp_fname); | ||
409 | exit(1); | ||
410 | } | ||
411 | |||
412 | // remove the temporary file | ||
413 | unlink(tmp_fname); | ||
414 | EUID_USER(); | ||
415 | } | ||
416 | // get file from host and store it in the sandbox | 366 | // get file from host and store it in the sandbox |
417 | else if (op == SANDBOX_FS_PUT && path2) { | 367 | else if (op == SANDBOX_FS_PUT && path2) { |
418 | char *src_fname =fname1; | 368 | char *src_fname =fname1; |