From 94231ecb35b7628fbda2688058189dfe29dcacbb Mon Sep 17 00:00:00 2001 From: netblue30 Date: Fri, 11 Mar 2016 07:47:35 -0500 Subject: --get option --- src/firejail/firejail.h | 6 +- src/firejail/ls.c | 184 +++++++++++++++++++++++++++++++++++------------- src/firejail/main.c | 27 ++++++- 3 files changed, 164 insertions(+), 53 deletions(-) (limited to 'src') diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 9c4dcc9a6..99705f0e6 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h @@ -532,8 +532,10 @@ int x11_display(void); int x11_check_xpra(void); // ls.c -void ls_name(const char *name, const char *path); -void ls(pid_t pid, const char *path); +#define SANDBOX_FS_LS 0 +#define SANDBOX_FS_GET 1 +void sandboxfs_name(int op, const char *name, const char *path); +void sandboxfs(int op, pid_t pid, const char *path); #endif diff --git a/src/firejail/ls.c b/src/firejail/ls.c index fe6348312..6a8d6acbd 100644 --- a/src/firejail/ls.c +++ b/src/firejail/ls.c @@ -184,7 +184,7 @@ static void print_directory(const char *path) { free(namelist); } -void ls_name(const char *name, const char *path) { +void sandboxfs_name(int op, const char *name, const char *path) { EUID_ASSERT(); if (!name || strlen(name) == 0) { @@ -197,10 +197,10 @@ void ls_name(const char *name, const char *path) { exit(1); } - ls(pid, path); + sandboxfs(op, pid, path); } -void ls(pid_t pid, const char *path) { +void sandboxfs(int op, pid_t pid, const char *path) { EUID_ASSERT(); // if the pid is that of a firejail process, use the pid of the first child process @@ -225,16 +225,6 @@ void ls(pid_t pid, const char *path) { } } - EUID_ROOT(); - // chroot - char *rootdir; - if (asprintf(&rootdir, "/proc/%d/root", pid) == -1) - errExit("asprintf"); - if (chroot(rootdir) < 0) - errExit("chroot"); - if (chdir("/") < 0) - errExit("chdir"); - // full path or file in current directory? char *fname; if (*path == '/') { @@ -251,55 +241,151 @@ void ls(pid_t pid, const char *path) { exit(1); } - // access chek is performed with the real UID - if (access(fname, R_OK) == -1) { - fprintf(stderr, "Error: Cannot access file %s\n", fname); - exit(1); - } + // sandbox root directory + char *rootdir; + if (asprintf(&rootdir, "/proc/%d/root", pid) == -1) + errExit("asprintf"); - // list directory contents - struct stat s; - if (stat(fname, &s) == -1) { - fprintf(stderr, "Error: Cannot access file %s\n", fname); - exit(1); + if (op == SANDBOX_FS_LS) { + EUID_ROOT(); + // chroot + if (chroot(rootdir) < 0) + errExit("chroot"); + if (chdir("/") < 0) + errExit("chdir"); + + // access chek is performed with the real UID + if (access(fname, R_OK) == -1) { + fprintf(stderr, "Error: Cannot access file %s\n", fname); + exit(1); + } + + // list directory contents + struct stat s; + if (stat(fname, &s) == -1) { + fprintf(stderr, "Error: Cannot access file %s\n", fname); + exit(1); + } + if (S_ISDIR(s.st_mode)) { + char *rp = realpath(fname, NULL); + if (!rp) { + fprintf(stderr, "Error: Cannot access file %s\n", fname); + exit(1); + } + if (arg_debug) + printf("realpath %s\n", rp); + + char *dir; + if (asprintf(&dir, "%s/", rp) == -1) + errExit("asprintf"); + + print_directory(dir); + free(rp); + free(dir); + } + else { + char *rp = realpath(fname, NULL); + if (!rp) { + fprintf(stderr, "Error: Cannot access file %s\n", fname); + exit(1); + } + if (arg_debug) + printf("realpath %s\n", rp); + char *split = strrchr(rp, '/'); + if (split) { + *split = '\0'; + char *rp2 = split + 1; + if (arg_debug) + printf("path %s, file %s\n", rp, rp2); + print_file_or_dir(rp, rp2, 1); + } + free(rp); + } } - if (S_ISDIR(s.st_mode)) { - char *rp = realpath(fname, NULL); - if (!rp) { + + // get file from sandbox + else if (op == SANDBOX_FS_GET) { + // check source file (sandbox) + char *src_fname; + if (asprintf(&src_fname, "%s%s", rootdir, fname) == -1) + errExit("asprintf"); + EUID_ROOT(); + struct stat s; + if (stat(src_fname, &s) == -1) { fprintf(stderr, "Error: Cannot access file %s\n", fname); exit(1); } - if (arg_debug) - printf("realpath %s\n", rp); + + + // try to open the source file - we need to chroot + pid_t child = fork(); + if (child < 0) + errExit("fork"); + if (child == 0) { + // chroot + if (chroot(rootdir) < 0) + errExit("chroot"); + if (chdir("/") < 0) + errExit("chdir"); + + // drop privileges + drop_privs(0); + + // try to read the file + if (access(fname, R_OK) == -1) { + fprintf(stderr, "Error: Cannot read file %s\n", fname); + exit(1); + } + exit(0); + } - char *dir; - if (asprintf(&dir, "%s/", rp) == -1) - errExit("asprintf"); + // wait for the child to finish + int status = NULL; + waitpid(child, &status, 0); + if (WIFEXITED(status) && WEXITSTATUS(status) == 0); + else + exit(1); + EUID_USER(); - print_directory(dir); - free(rp); - free(dir); - } - else { - char *rp = realpath(fname, NULL); - if (!rp) { - fprintf(stderr, "Error: Cannot access file %s\n", fname); + // check destination file (host) + char *dest_fname = strrchr(fname, '/'); + if (!dest_fname || *(++dest_fname) == '\0') { + fprintf(stderr, "Error: invalid file name %s\n", fname); exit(1); } - if (arg_debug) - printf("realpath %s\n", rp); - char *split = strrchr(rp, '/'); - if (split) { - *split = '\0'; - char *rp2 = split + 1; - if (arg_debug) - printf("path %s, file %s\n", rp, rp2); - print_file_or_dir(rp, rp2, 1); + + if (access(dest_fname, F_OK) == -1) { + // try to create the file + FILE *fp = fopen(dest_fname, "w"); + if (!fp) { + fprintf(stderr, "Error: cannot create %s file\n", dest_fname); + exit(1); + } + fclose(fp); } - free(rp); + else { + if (access(dest_fname, W_OK) == -1) { + fprintf(stderr, "Error: cannot writee %s file\n", dest_fname); + exit(1); + } + } + // copy file + EUID_ROOT(); + copy_file(src_fname, dest_fname); + if (chown(dest_fname, getuid(), getgid()) == -1) + errExit("chown"); + if (chmod(dest_fname, 0644) == -1) + errExit("chmod"); + EUID_USER(); } + + // put file in sandbox + else if (op == SANDBOX_FS_LS) { +printf("todo!\n"); + } free(fname); + free(rootdir); exit(0); } diff --git a/src/firejail/main.c b/src/firejail/main.c index eebb04fcc..2c6b5a5e1 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c @@ -426,6 +426,29 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { exit(0); } #endif + else if (strncmp(argv[i], "--get=", 6) == 0) { + logargs(argc, argv); + + // verify path + if ((i + 2) != argc) { + fprintf(stderr, "Error: invalid --get option, path expected\n"); + exit(1); + } + char *path = argv[i + 1]; + invalid_filename(path); + if (strstr(path, "..")) { + fprintf(stderr, "Error: invalid file name %s\n", path); + exit(1); + } + + // get file + pid_t pid; + if (read_pid(argv[i] + 6, &pid) == 0) + sandboxfs(SANDBOX_FS_GET, pid, path); + else + sandboxfs_name(SANDBOX_FS_GET, argv[i] + 6, path); + exit(0); + } else if (strncmp(argv[i], "--ls=", 5) == 0) { logargs(argc, argv); @@ -444,9 +467,9 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { // list directory contents pid_t pid; if (read_pid(argv[i] + 5, &pid) == 0) - ls(pid, path); + sandboxfs(SANDBOX_FS_LS, pid, path); else - ls_name(argv[i] + 5, path); + sandboxfs_name(SANDBOX_FS_LS, argv[i] + 5, path); exit(0); } else if (strncmp(argv[i], "--join=", 7) == 0) { -- cgit v1.2.3-54-g00ecf