From b05f7f3bd9d0264a6e143e10269e3eca5416b048 Mon Sep 17 00:00:00 2001 From: startx2017 Date: Mon, 10 Apr 2017 09:24:00 -0400 Subject: --quiet fixes --- src/fcopy/main.c | 577 +++++++++++++++++++++++++----------------------- src/firejail/join.c | 5 +- src/firejail/sbox.c | 5 + src/fnet/fnet.h | 3 + src/fnet/interface.c | 6 +- src/fnet/main.c | 5 + src/fseccomp/fseccomp.h | 3 + src/fseccomp/main.c | 5 + src/fseccomp/protocol.c | 6 +- src/fseccomp/syscall.c | 6 +- 10 files changed, 332 insertions(+), 289 deletions(-) diff --git a/src/fcopy/main.c b/src/fcopy/main.c index 9f19b6dd8..88379001c 100644 --- a/src/fcopy/main.c +++ b/src/fcopy/main.c @@ -16,16 +16,16 @@ * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ + */ #include "../include/common.h" #include #include #include +int arg_quiet = 0; static int arg_follow_link = 0; - #define COPY_LIMIT (500 * 1024 *1024) static int size_limit_reached = 0; static unsigned file_cnt = 0; @@ -34,323 +34,338 @@ static unsigned size_cnt = 0; static char *outpath = NULL; static char *inpath = NULL; - // modified version of the function from util.c static void copy_file(const char *srcname, const char *destname, mode_t mode, uid_t uid, gid_t gid) { - assert(srcname); - assert(destname); - mode &= 07777; - - // open source - int src = open(srcname, O_RDONLY); - if (src < 0) { - fprintf(stderr, "Warning fcopy: cannot open %s, file not copied\n", srcname); - return; - } - - // open destination - int dst = open(destname, O_CREAT|O_WRONLY|O_TRUNC, 0755); - if (dst < 0) { - fprintf(stderr, "Warning fcopy: cannot open %s, file not copied\n", destname); - close(src); - return; - } - - // copy - ssize_t len; - static const int BUFLEN = 1024; - unsigned char buf[BUFLEN]; - while ((len = read(src, buf, BUFLEN)) > 0) { - int done = 0; - while (done != len) { - int rv = write(dst, buf + done, len - done); - if (rv == -1) - goto errexit; - done += rv; - } - } - fflush(0); - - if (fchown(dst, uid, gid) == -1) - goto errexit; - if (fchmod(dst, mode) == -1) - goto errexit; - - close(src); - close(dst); - - return; + assert(srcname); + assert(destname); + mode &= 07777; + + // open source + int src = open(srcname, O_RDONLY); + if (src < 0) { + if (!arg_quiet) + fprintf(stderr, "Warning fcopy: cannot open %s, file not copied\n", srcname); + return; + } + + // open destination + int dst = open(destname, O_CREAT|O_WRONLY|O_TRUNC, 0755); + if (dst < 0) { + if (!arg_quiet) + fprintf(stderr, "Warning fcopy: cannot open %s, file not copied\n", destname); + close(src); + return; + } + + // copy + ssize_t len; + static const int BUFLEN = 1024; + unsigned char buf[BUFLEN]; + while ((len = read(src, buf, BUFLEN)) > 0) { + int done = 0; + while (done != len) { + int rv = write(dst, buf + done, len - done); + if (rv == -1) + goto errexit; + done += rv; + } + } + fflush(0); + + if (fchown(dst, uid, gid) == -1) + goto errexit; + if (fchmod(dst, mode) == -1) + goto errexit; + + close(src); + close(dst); + + return; errexit: - close(src); - close(dst); - unlink(destname); - fprintf(stderr, "Warning fcopy: cannot copy %s\n", destname); + close(src); + close(dst); + unlink(destname); + if (!arg_quiet) + fprintf(stderr, "Warning fcopy: cannot copy %s\n", destname); } - // modified version of the function in firejail/util.c static void mkdir_attr(const char *fname, mode_t mode, uid_t uid, gid_t gid) { - assert(fname); - mode &= 07777; - - if (mkdir(fname, mode) == -1 || - chmod(fname, mode) == -1) { - fprintf(stderr, "Error fcopy: failed to create %s directory\n", fname); - errExit("mkdir/chmod"); - } - if (chown(fname, uid, gid)) - fprintf(stderr, "Warning fcopy: failed to change ownership of %s\n", fname); + assert(fname); + mode &= 07777; + + if (mkdir(fname, mode) == -1 || + chmod(fname, mode) == -1) { + fprintf(stderr, "Error fcopy: failed to create %s directory\n", fname); + errExit("mkdir/chmod"); + } + if (chown(fname, uid, gid)) { + if (!arg_quiet) + fprintf(stderr, "Warning fcopy: failed to change ownership of %s\n", fname); + } } + void copy_link(const char *target, const char *linkpath, mode_t mode, uid_t uid, gid_t gid) { - (void) mode; - (void) uid; - (void) gid; - char *rp = realpath(target, NULL); - if (rp) { - if (symlink(rp, linkpath) == -1) - goto errout; - free(rp); - } - else - goto errout; - - return; + (void) mode; + (void) uid; + (void) gid; + char *rp = realpath(target, NULL); + if (rp) { + if (symlink(rp, linkpath) == -1) + goto errout; + free(rp); + } + else + goto errout; + + return; errout: - fprintf(stderr, "Warning fcopy: cannot create symbolic link %s\n", target); + if (!arg_quiet) + fprintf(stderr, "Warning fcopy: cannot create symbolic link %s\n", target); } + static int first = 1; static int fs_copydir(const char *infname, const struct stat *st, int ftype, struct FTW *sftw) { - (void) st; - (void) sftw; - assert(infname); - assert(*infname != '\0'); - assert(outpath); - assert(*outpath != '\0'); - assert(inpath); - - // check size limit - if (size_limit_reached) - return 0; - - - char *outfname; - if (asprintf(&outfname, "%s%s", outpath, infname + strlen(inpath)) == -1) - errExit("asprintf"); - - // don't copy it if we already have the file - struct stat s; - if (stat(outfname, &s) == 0) { - if (first) - first = 0; - else - fprintf(stderr, "Warning fcopy: skipping %s, file already present\n", infname); - free(outfname); - return 0; - } - - // extract mode and ownership - if (stat(infname, &s) != 0) { - fprintf(stderr, "Warning fcopy: skipping %s, cannot find inode\n", infname); - free(outfname); - return 0; - } - uid_t uid = s.st_uid; - gid_t gid = s.st_gid; - mode_t mode = s.st_mode; - - // recalculate size - if ((s.st_size + size_cnt) > COPY_LIMIT) { - fprintf(stderr, "Error fcopy: size limit of %dMB reached\n", (COPY_LIMIT / 1024) / 1024); - size_limit_reached = 1; - free(outfname); - return 0; - } - - file_cnt++; - size_cnt += s.st_size; - - if(ftype == FTW_F) { - copy_file(infname, outfname, mode, uid, gid); - } - else if (ftype == FTW_D) { - mkdir_attr(outfname, mode, uid, gid); - } - else if (ftype == FTW_SL) { - copy_link(infname, outfname, mode, uid, gid); - } - - return(0); + (void) st; + (void) sftw; + assert(infname); + assert(*infname != '\0'); + assert(outpath); + assert(*outpath != '\0'); + assert(inpath); + + // check size limit + if (size_limit_reached) + return 0; + + char *outfname; + if (asprintf(&outfname, "%s%s", outpath, infname + strlen(inpath)) == -1) + errExit("asprintf"); + + // don't copy it if we already have the file + struct stat s; + if (stat(outfname, &s) == 0) { + if (first) + first = 0; + else if (!arg_quiet) + fprintf(stderr, "Warning fcopy: skipping %s, file already present\n", infname); + free(outfname); + return 0; + } + + // extract mode and ownership + if (stat(infname, &s) != 0) { + if (!arg_quiet) + fprintf(stderr, "Warning fcopy: skipping %s, cannot find inode\n", infname); + free(outfname); + return 0; + } + uid_t uid = s.st_uid; + gid_t gid = s.st_gid; + mode_t mode = s.st_mode; + + // recalculate size + if ((s.st_size + size_cnt) > COPY_LIMIT) { + fprintf(stderr, "Error fcopy: size limit of %dMB reached\n", (COPY_LIMIT / 1024) / 1024); + size_limit_reached = 1; + free(outfname); + return 0; + } + + file_cnt++; + size_cnt += s.st_size; + + if(ftype == FTW_F) { + copy_file(infname, outfname, mode, uid, gid); + } + else if (ftype == FTW_D) { + mkdir_attr(outfname, mode, uid, gid); + } + else if (ftype == FTW_SL) { + copy_link(infname, outfname, mode, uid, gid); + } + + return(0); } + static char *check(const char *src) { - struct stat s; - char *rsrc = realpath(src, NULL); - if (!rsrc || stat(rsrc, &s) == -1) - goto errexit; + struct stat s; + char *rsrc = realpath(src, NULL); + if (!rsrc || stat(rsrc, &s) == -1) + goto errexit; - // check uid - if (s.st_uid != getuid() || s.st_gid != getgid()) - goto errexit; + // check uid + if (s.st_uid != getuid() || s.st_gid != getgid()) + goto errexit; - // dir, link, regular file - if (S_ISDIR(s.st_mode) || S_ISREG(s.st_mode) || S_ISLNK(s.st_mode)) - return rsrc; // normal exit from the function + // dir, link, regular file + if (S_ISDIR(s.st_mode) || S_ISREG(s.st_mode) || S_ISLNK(s.st_mode)) + return rsrc; // normal exit from the function errexit: - fprintf(stderr, "Error fcopy: invalid file %s\n", src); - exit(1); + fprintf(stderr, "Error fcopy: invalid file %s\n", src); + exit(1); } + static void duplicate_dir(const char *src, const char *dest, struct stat *s) { - (void) s; - char *rsrc = check(src); - char *rdest = check(dest); - inpath = rsrc; - outpath = rdest; - - // walk - if(nftw(rsrc, fs_copydir, 1, FTW_PHYS) != 0) { - fprintf(stderr, "Error: unable to copy file\n"); - exit(1); - } - - free(rsrc); - free(rdest); + (void) s; + char *rsrc = check(src); + char *rdest = check(dest); + inpath = rsrc; + outpath = rdest; + + // walk + if(nftw(rsrc, fs_copydir, 1, FTW_PHYS) != 0) { + fprintf(stderr, "Error: unable to copy file\n"); + exit(1); + } + + free(rsrc); + free(rdest); } + static void duplicate_file(const char *src, const char *dest, struct stat *s) { - char *rsrc = check(src); - char *rdest = check(dest); - uid_t uid = s->st_uid; - gid_t gid = s->st_gid; - mode_t mode = s->st_mode; - - // build destination file name - char *name; - char *ptr = (arg_follow_link)? strrchr(src, '/'): strrchr(rsrc, '/'); - ptr++; - if (asprintf(&name, "%s/%s", rdest, ptr) == -1) - errExit("asprintf"); - - // copy - copy_file(rsrc, name, mode, uid, gid); - - free(name); - free(rsrc); - free(rdest); + char *rsrc = check(src); + char *rdest = check(dest); + uid_t uid = s->st_uid; + gid_t gid = s->st_gid; + mode_t mode = s->st_mode; + + // build destination file name + char *name; + char *ptr = (arg_follow_link)? strrchr(src, '/'): strrchr(rsrc, '/'); + ptr++; + if (asprintf(&name, "%s/%s", rdest, ptr) == -1) + errExit("asprintf"); + + // copy + copy_file(rsrc, name, mode, uid, gid); + + free(name); + free(rsrc); + free(rdest); } + static void duplicate_link(const char *src, const char *dest, struct stat *s) { - char *rsrc = check(src); // we drop the result and use the original name - char *rdest = check(dest); - uid_t uid = s->st_uid; - gid_t gid = s->st_gid; - mode_t mode = s->st_mode; - - // build destination file name - char *name; -// char *ptr = strrchr(rsrc, '/'); - char *ptr = strrchr(src, '/'); - ptr++; - if (asprintf(&name, "%s/%s", rdest, ptr) == -1) - errExit("asprintf"); - - // copy - copy_link(rsrc, name, mode, uid, gid); - - free(name); - free(rsrc); - free(rdest); + char *rsrc = check(src); // we drop the result and use the original name + char *rdest = check(dest); + uid_t uid = s->st_uid; + gid_t gid = s->st_gid; + mode_t mode = s->st_mode; + + // build destination file name + char *name; + // char *ptr = strrchr(rsrc, '/'); + char *ptr = strrchr(src, '/'); + ptr++; + if (asprintf(&name, "%s/%s", rdest, ptr) == -1) + errExit("asprintf"); + + // copy + copy_link(rsrc, name, mode, uid, gid); + + free(name); + free(rsrc); + free(rdest); } + static void usage(void) { - fputs("Usage: fcopy [--follow-link] src dest\n" - "\n" - "Copy SRC to DEST/SRC. SRC may be a file, directory, or symbolic link.\n" - "If SRC is a directory it is copied recursively. If it is a symlink,\n" - "the link itself is duplicated, unless --follow-link is given,\n" - "in which case the destination of the link is copied.\n" - "DEST must already exist and must be a directory.\n", stderr); + fputs("Usage: fcopy [--follow-link] src dest\n" + "\n" + "Copy SRC to DEST/SRC. SRC may be a file, directory, or symbolic link.\n" + "If SRC is a directory it is copied recursively. If it is a symlink,\n" + "the link itself is duplicated, unless --follow-link is given,\n" + "in which case the destination of the link is copied.\n" + "DEST must already exist and must be a directory.\n", stderr); } + int main(int argc, char **argv) { #if 0 -{ -//system("cat /proc/self/status"); -int i; -for (i = 0; i < argc; i++) - printf("*%s* ", argv[i]); -printf("\n"); -} -#endif - char *src; - char *dest; - - if (argc == 3) { - src = argv[1]; - dest = argv[2]; - arg_follow_link = 0; - } - else if (argc == 4 && !strcmp(argv[1], "--follow-link")) { - src = argv[2]; - dest = argv[3]; - arg_follow_link = 1; - } - else { - fprintf(stderr, "Error: arguments missing\n"); - usage(); - exit(1); - } - - // check the two files; remove ending / - int len = strlen(src); - if (src[len - 1] == '/') - src[len - 1] = '\0'; - if (strcspn(src, "\\*&!?\"'<>%^(){}[];,") != (size_t)len) { - fprintf(stderr, "Error fcopy: invalid source file name %s\n", src); - exit(1); - } - - len = strlen(dest); - if (dest[len - 1] == '/') - dest[len - 1] = '\0'; - if (strcspn(dest, "\\*&!?\"'<>%^(){}[];,~") != (size_t)len) { - fprintf(stderr, "Error fcopy: invalid dest file name %s\n", dest); - exit(1); - } - - - // the destination should be a directory; - struct stat s; - if (stat(dest, &s) == -1) { - fprintf(stderr, "Error fcopy: dest dir %s: %s\n", dest, strerror(errno)); - exit(1); - } - if (!S_ISDIR(s.st_mode)) { - fprintf(stderr, "Error fcopy: dest %s is not a directory\n", dest); - exit(1); - } - - // copy files - if ((arg_follow_link ? stat : lstat)(src, &s) == -1) { - fprintf(stderr, "Error fcopy: src %s: %s\n", src, strerror(errno)); - exit(1); - } - - if (S_ISDIR(s.st_mode)) - duplicate_dir(src, dest, &s); - else if (S_ISREG(s.st_mode)) - duplicate_file(src, dest, &s); - else if (S_ISLNK(s.st_mode)) - duplicate_link(src, dest, &s); - else { - fprintf(stderr, "Error fcopy: src %s is an unsupported type of file\n", src); - exit(1); - } - - return 0; + { + //system("cat /proc/self/status"); + int i; + for (i = 0; i < argc; i++) + printf("*%s* ", argv[i]); + printf("\n"); + } +#endif + char *quiet = getenv("FIREJAIL_QUIET"); + if (quiet && strcmp(quiet, "yes") == 0) + arg_quiet = 1; + + char *src; + char *dest; + + if (argc == 3) { + src = argv[1]; + dest = argv[2]; + arg_follow_link = 0; + } + else if (argc == 4 && !strcmp(argv[1], "--follow-link")) { + src = argv[2]; + dest = argv[3]; + arg_follow_link = 1; + } + else { + fprintf(stderr, "Error: arguments missing\n"); + usage(); + exit(1); + } + + // check the two files; remove ending / + int len = strlen(src); + if (src[len - 1] == '/') + src[len - 1] = '\0'; + if (strcspn(src, "\\*&!?\"'<>%^(){}[];,") != (size_t)len) { + fprintf(stderr, "Error fcopy: invalid source file name %s\n", src); + exit(1); + } + + len = strlen(dest); + if (dest[len - 1] == '/') + dest[len - 1] = '\0'; + if (strcspn(dest, "\\*&!?\"'<>%^(){}[];,~") != (size_t)len) { + fprintf(stderr, "Error fcopy: invalid dest file name %s\n", dest); + exit(1); + } + + // the destination should be a directory; + struct stat s; + if (stat(dest, &s) == -1) { + fprintf(stderr, "Error fcopy: dest dir %s: %s\n", dest, strerror(errno)); + exit(1); + } + if (!S_ISDIR(s.st_mode)) { + fprintf(stderr, "Error fcopy: dest %s is not a directory\n", dest); + exit(1); + } + + // copy files + if ((arg_follow_link ? stat : lstat)(src, &s) == -1) { + fprintf(stderr, "Error fcopy: src %s: %s\n", src, strerror(errno)); + exit(1); + } + + if (S_ISDIR(s.st_mode)) + duplicate_dir(src, dest, &s); + else if (S_ISREG(s.st_mode)) + duplicate_file(src, dest, &s); + else if (S_ISLNK(s.st_mode)) + duplicate_link(src, dest, &s); + else { + fprintf(stderr, "Error fcopy: src %s is an unsupported type of file\n", src); + exit(1); + } + + return 0; } diff --git a/src/firejail/join.c b/src/firejail/join.c index fa19243b8..a4b16ff8d 100644 --- a/src/firejail/join.c +++ b/src/firejail/join.c @@ -176,7 +176,7 @@ static void extract_user_namespace(pid_t pid) { void join(pid_t pid, int argc, char **argv, int index) { EUID_ASSERT(); char *homedir = cfg.homedir; - + extract_command(argc, argv, index); signal (SIGTERM, signal_handler); @@ -189,7 +189,8 @@ void join(pid_t pid, int argc, char **argv, int index) { pid_t child; if (find_child(pid, &child) == 0) { pid = child; - printf("Switching to pid %u, the first child process inside the sandbox\n", (unsigned) pid); + if (!arg_quiet) + printf("Switching to pid %u, the first child process inside the sandbox\n", (unsigned) pid); } } free(comm); diff --git a/src/firejail/sbox.c b/src/firejail/sbox.c index 467745a64..9640ef9ed 100644 --- a/src/firejail/sbox.c +++ b/src/firejail/sbox.c @@ -200,6 +200,11 @@ int sbox_run(unsigned filter, int num, ...) { drop_privs(1); clearenv(); + + // --quiet is passed as an environment variable + if (arg_quiet) + setenv("FIREJAIL_QUIET", "yes", 1); + if (arg[0]) // get rid of scan-build warning execvp(arg[0], arg); else diff --git a/src/fnet/fnet.h b/src/fnet/fnet.h index d6080e283..b4b7e6a37 100644 --- a/src/fnet/fnet.h +++ b/src/fnet/fnet.h @@ -26,6 +26,9 @@ #include #include "../include/common.h" +// main.c +extern int arg_quiet; + // veth.c int net_create_veth(const char *dev, const char *nsdev, unsigned pid); int net_create_macvlan(const char *dev, const char *parent, unsigned pid); diff --git a/src/fnet/interface.c b/src/fnet/interface.c index 5813db337..33ad766ec 100644 --- a/src/fnet/interface.c +++ b/src/fnet/interface.c @@ -156,8 +156,10 @@ void net_set_mtu(const char *ifname, int mtu) { ifr.ifr_addr.sa_family = AF_INET; strncpy(ifr.ifr_name, ifname, IFNAMSIZ); ifr.ifr_mtu = mtu; - if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) != 0) - fprintf(stderr, "Warning fnet: cannot set mtu for interface %s\n", ifname); + if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) != 0) { + if (!arg_quiet) + fprintf(stderr, "Warning fnet: cannot set mtu for interface %s\n", ifname); + } close(s); } diff --git a/src/fnet/main.c b/src/fnet/main.c index 6ec8e5f84..0c55f3141 100644 --- a/src/fnet/main.c +++ b/src/fnet/main.c @@ -18,6 +18,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "fnet.h" +int arg_quiet = 0; static void usage(void) { printf("Usage:\n"); @@ -47,6 +48,10 @@ printf("\n"); return 1; } + char *quiet = getenv("FIREJAIL_QUIET"); + if (quiet && strcmp(quiet, "yes") == 0) + arg_quiet = 1; + if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") ==0) { usage(); return 0; diff --git a/src/fseccomp/fseccomp.h b/src/fseccomp/fseccomp.h index e0d423b4a..1e4881e9c 100644 --- a/src/fseccomp/fseccomp.h +++ b/src/fseccomp/fseccomp.h @@ -25,6 +25,9 @@ #include #include "../include/common.h" +// main.c +extern int arg_quiet; + // syscall.c void syscall_print(void); int syscall_check_list(const char *slist, void (*callback)(int fd, int syscall, int arg), int fd, int arg); diff --git a/src/fseccomp/main.c b/src/fseccomp/main.c index 134b840f2..7e0239a5f 100644 --- a/src/fseccomp/main.c +++ b/src/fseccomp/main.c @@ -18,6 +18,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "fseccomp.h" +int arg_quiet = 0; static void usage(void) { printf("Usage:\n"); @@ -51,6 +52,10 @@ printf("\n"); usage(); return 1; } + + char *quiet = getenv("FIREJAIL_QUIET"); + if (quiet && strcmp(quiet, "yes") == 0) + arg_quiet = 1; if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") ==0) { usage(); diff --git a/src/fseccomp/protocol.c b/src/fseccomp/protocol.c index e9f65e7e8..57ce2f8e0 100644 --- a/src/fseccomp/protocol.c +++ b/src/fseccomp/protocol.c @@ -89,7 +89,8 @@ static struct sock_filter *find_protocol_domain(const char *p) { void protocol_print(void) { #ifndef SYS_socket - fprintf(stderr, "Warning fseccomp: firejail --protocol not supported on this platform\n"); + if (!arg_quiet) + fprintf(stderr, "Warning fseccomp: firejail --protocol not supported on this platform\n"); return; #endif @@ -107,7 +108,8 @@ void protocol_build_filter(const char *prlist, const char *fname) { assert(fname); #ifndef SYS_socket - fprintf(stderr, "Warning fseccomp: --protocol not supported on this platform\n"); + if (!arg_quiet) + fprintf(stderr, "Warning fseccomp: --protocol not supported on this platform\n"); return; #else // build the filter diff --git a/src/fseccomp/syscall.c b/src/fseccomp/syscall.c index 398a49578..b86c1c489 100644 --- a/src/fseccomp/syscall.c +++ b/src/fseccomp/syscall.c @@ -130,8 +130,10 @@ int syscall_check_list(const char *slist, void (*callback)(int fd, int syscall, int syscall_nr; int error_nr; syscall_process_name(ptr, &syscall_nr, &error_nr); - if (syscall_nr == -1) - fprintf(stderr, "Warning fseccomp: syscall %s not found\n", ptr); + if (syscall_nr == -1) { + if (!arg_quiet) + fprintf(stderr, "Warning fseccomp: syscall \"%s\" not available on this platform\n", ptr); + } else if (callback != NULL) { if (error_nr != -1) filter_add_errno(fd, syscall_nr, error_nr); -- cgit v1.2.3-54-g00ecf