From e74fdab5d2125ce8f058c1630ce7cce19cbdac16 Mon Sep 17 00:00:00 2001 From: netblue30 Date: Wed, 4 Jan 2017 18:13:45 -0500 Subject: security fixes --- src/fcopy/main.c | 2 +- src/firejail/fs_home.c | 118 +++++++++++++++++++++++++++++++++++++--------- src/firejail/pulseaudio.c | 45 ++++++++++++++---- src/firejail/util.c | 4 +- 4 files changed, 136 insertions(+), 33 deletions(-) diff --git a/src/fcopy/main.c b/src/fcopy/main.c index b1e2813db..a4f5ace11 100644 --- a/src/fcopy/main.c +++ b/src/fcopy/main.c @@ -41,7 +41,7 @@ static void copy_file(const char *srcname, const char *destname, mode_t mode, ui // open source int src = open(srcname, O_RDONLY); if (src < 0) { - fprintf(stderr, "Warning: cannot open %s, file not copied\n", srcname); + fprintf(stderr, "Warning fcopy: cannot open %s, file not copied\n", srcname); return; } diff --git a/src/firejail/fs_home.c b/src/firejail/fs_home.c index f5e545bf3..4de082b06 100644 --- a/src/firejail/fs_home.c +++ b/src/firejail/fs_home.c @@ -106,6 +106,14 @@ static int store_xauthority(void) { // put a copy of .Xauthority in XAUTHORITY_FILE char *src; char *dest = RUN_XAUTHORITY_FILE; + // create an empty file + FILE *fp = fopen(dest, "w"); + if (fp) { + fprintf(fp, "\n"); + SET_PERMS_STREAM(fp, getuid(), getgid(), 0600); + fclose(fp); + } + if (asprintf(&src, "%s/.Xauthority", cfg.homedir) == -1) errExit("asprintf"); @@ -115,12 +123,28 @@ static int store_xauthority(void) { fprintf(stderr, "Warning: invalid .Xauthority file\n"); return 0; } - - int rv = copy_file(src, dest, -1, -1, 0600); - if (rv) { - fprintf(stderr, "Warning: cannot transfer .Xauthority in private home directory\n"); - return 0; + + pid_t child = fork(); + if (child < 0) + errExit("fork"); + if (child == 0) { + // drop privileges + drop_privs(0); + + // copy, set permissions and ownership + int rv = copy_file(src, dest, getuid(), getgid(), 0600); + if (rv) + fprintf(stderr, "Warning: cannot transfer .Xauthority in private home directory\n"); + else { + fs_logger2("clone", dest); + } +#ifdef HAVE_GCOV + __gcov_flush(); +#endif + _exit(0); } + // wait for the child to finish + waitpid(child, NULL, 0); return 1; // file copied } @@ -130,6 +154,14 @@ static int store_xauthority(void) { static int store_asoundrc(void) { char *src; char *dest = RUN_ASOUNDRC_FILE; + // create an empty file + FILE *fp = fopen(dest, "w"); + if (fp) { + fprintf(fp, "\n"); + SET_PERMS_STREAM(fp, getuid(), getgid(), 0644); + fclose(fp); + } + if (asprintf(&src, "%s/.asoundrc", cfg.homedir) == -1) errExit("asprintf"); @@ -150,11 +182,27 @@ static int store_asoundrc(void) { free(rp); } - int rv = copy_file(src, dest, -1, -1, -0644); - if (rv) { - fprintf(stderr, "Warning: cannot transfer .asoundrc in private home directory\n"); - return 0; + pid_t child = fork(); + if (child < 0) + errExit("fork"); + if (child == 0) { + // drop privileges + drop_privs(0); + + // copy, set permissions and ownership + int rv = copy_file(src, dest, getuid(), getgid(), 0644); + if (rv) + fprintf(stderr, "Warning: cannot transfer .asoundrc in private home directory\n"); + else { + fs_logger2("clone", dest); + } +#ifdef HAVE_GCOV + __gcov_flush(); +#endif + _exit(0); } + // wait for the child to finish + waitpid(child, NULL, 0); return 1; // file copied } @@ -174,13 +222,27 @@ static void copy_xauthority(void) { exit(1); } - // copy, set permissions and ownership - int rv = copy_file(src, dest, getuid(), getgid(), S_IRUSR | S_IWUSR); - if (rv) - fprintf(stderr, "Warning: cannot transfer .Xauthority in private home directory\n"); - else { - fs_logger2("clone", dest); + pid_t child = fork(); + if (child < 0) + errExit("fork"); + if (child == 0) { + // drop privileges + drop_privs(0); + + // copy, set permissions and ownership + int rv = copy_file(src, dest, getuid(), getgid(), S_IRUSR | S_IWUSR); + if (rv) + fprintf(stderr, "Warning: cannot transfer .Xauthority in private home directory\n"); + else { + fs_logger2("clone", dest); + } +#ifdef HAVE_GCOV + __gcov_flush(); +#endif + _exit(0); } + // wait for the child to finish + waitpid(child, NULL, 0); // delete the temporary file unlink(src); @@ -199,13 +261,27 @@ static void copy_asoundrc(void) { exit(1); } - // copy, set permissions and ownership - int rv = copy_file(src, dest, getuid(), getgid(), S_IRUSR | S_IWUSR); - if (rv) - fprintf(stderr, "Warning: cannot transfer .asoundrc in private home directory\n"); - else { - fs_logger2("clone", dest); + pid_t child = fork(); + if (child < 0) + errExit("fork"); + if (child == 0) { + // drop privileges + drop_privs(0); + + // copy, set permissions and ownership + int rv = copy_file(src, dest, getuid(), getgid(), S_IRUSR | S_IWUSR); + if (rv) + fprintf(stderr, "Warning: cannot transfer .asoundrc in private home directory\n"); + else { + fs_logger2("clone", dest); + } +#ifdef HAVE_GCOV + __gcov_flush(); +#endif + _exit(0); } + // wait for the child to finish + waitpid(child, NULL, 0); // delete the temporary file unlink(src); diff --git a/src/firejail/pulseaudio.c b/src/firejail/pulseaudio.c index b3a22bad9..14a7f03dd 100644 --- a/src/firejail/pulseaudio.c +++ b/src/firejail/pulseaudio.c @@ -127,11 +127,25 @@ void pulseaudio_init(void) { if (asprintf(&dir1, "%s/.config", cfg.homedir) == -1) errExit("asprintf"); if (stat(dir1, &s) == -1) { - int rv = mkdir(dir1, 0755); - if (rv == 0) { - if (set_perms(dir1, getuid(), getgid(), 0755)) - {;} // do nothing + pid_t child = fork(); + if (child < 0) + errExit("fork"); + if (child == 0) { + // drop privileges + drop_privs(0); + + int rv = mkdir(dir1, 0755); + if (rv == 0) { + if (set_perms(dir1, getuid(), getgid(), 0755)) + {;} // do nothing + } +#ifdef HAVE_GCOV + __gcov_flush(); +#endif + _exit(0); } + // wait for the child to finish + waitpid(child, NULL, 0); } else { // make sure the directory is owned by the user @@ -145,12 +159,25 @@ void pulseaudio_init(void) { if (asprintf(&dir1, "%s/.config/pulse", cfg.homedir) == -1) errExit("asprintf"); if (stat(dir1, &s) == -1) { - /* coverity[toctou] */ - int rv = mkdir(dir1, 0700); - if (rv == 0) { - if (set_perms(dir1, getuid(), getgid(), 0700)) - {;} // do nothing + pid_t child = fork(); + if (child < 0) + errExit("fork"); + if (child == 0) { + // drop privileges + drop_privs(0); + + int rv = mkdir(dir1, 0700); + if (rv == 0) { + if (set_perms(dir1, getuid(), getgid(), 0700)) + {;} // do nothing + } +#ifdef HAVE_GCOV + __gcov_flush(); +#endif + _exit(0); } + // wait for the child to finish + waitpid(child, NULL, 0); } else { // make sure the directory is owned by the user diff --git a/src/firejail/util.c b/src/firejail/util.c index 75f2acdb9..5b94aa288 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c @@ -177,14 +177,14 @@ int copy_file(const char *srcname, const char *destname, uid_t uid, gid_t gid, m // open source int src = open(srcname, O_RDONLY); if (src < 0) { - fprintf(stderr, "Warning: cannot open %s, file not copied\n", srcname); + fprintf(stderr, "Warning: cannot open source file %s, file not copied\n", srcname); return -1; } // open destination int dst = open(destname, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (dst < 0) { - fprintf(stderr, "Warning: cannot open %s, file not copied\n", destname); + fprintf(stderr, "Warning: cannot open destination file %s, file not copied\n", destname); close(src); return -1; } -- cgit v1.2.3-70-g09d2