From 825ac9cdc38c4285584e69d6f29102b149914dfe Mon Sep 17 00:00:00 2001 From: smitsohu Date: Sun, 16 May 2021 15:48:14 +0200 Subject: open files O_CLOEXEC|O_EXCL Dumb patch that adds O_CLOEXEC to all open/fopen calls, even where it is obviously pointless. While at it, also add O_EXCL where it might be considered useful, for example to clear Coverity warnings, or on files that subsequently are used to configure a join sandbox. Pure defense in depth, this patch should have no observable effects. --- src/firejail/appimage.c | 6 +++--- src/firejail/bandwidth.c | 32 +++++++++++++------------------- src/firejail/caps.c | 2 +- src/firejail/cgroup.c | 20 ++++++++++---------- src/firejail/checkcfg.c | 2 +- src/firejail/cpu.c | 6 +++--- src/firejail/dhcp.c | 2 +- src/firejail/env.c | 7 +------ src/firejail/fs_dev.c | 6 +++--- src/firejail/fs_etc.c | 2 +- src/firejail/fs_home.c | 4 ++-- src/firejail/fs_hostname.c | 6 +++--- src/firejail/fs_lib.c | 2 +- src/firejail/fs_logger.c | 25 +++++-------------------- src/firejail/fs_trace.c | 9 ++++----- src/firejail/fs_var.c | 9 ++++----- src/firejail/join.c | 6 +++--- src/firejail/ls.c | 2 +- src/firejail/macros.c | 2 +- src/firejail/main.c | 16 ++++++++-------- src/firejail/network.c | 2 +- src/firejail/network_main.c | 2 +- src/firejail/no_sandbox.c | 14 +++++--------- src/firejail/preproc.c | 2 +- src/firejail/profile.c | 2 +- src/firejail/protocol.c | 4 ++-- src/firejail/pulseaudio.c | 2 +- src/firejail/restrict_users.c | 8 ++++---- src/firejail/restricted_shell.c | 4 ++-- src/firejail/run_files.c | 6 +++--- src/firejail/sandbox.c | 4 ++-- src/firejail/seccomp.c | 8 ++++---- src/firejail/shutdown.c | 2 +- src/firejail/util.c | 25 ++++++++++++------------- src/firejail/x11.c | 4 ++-- 35 files changed, 111 insertions(+), 144 deletions(-) (limited to 'src') diff --git a/src/firejail/appimage.c b/src/firejail/appimage.c index 59758bf2d..6b9fed765 100644 --- a/src/firejail/appimage.c +++ b/src/firejail/appimage.c @@ -67,7 +67,7 @@ void appimage_set(const char *appimage) { // find or allocate a free loop device to use EUID_ROOT(); - int cfd = open("/dev/loop-control", O_RDWR); + int cfd = open("/dev/loop-control", O_RDWR|O_CLOEXEC); if (cfd == -1) err_loop(); int devnr = ioctl(cfd, LOOP_CTL_GET_FREE); @@ -78,7 +78,7 @@ void appimage_set(const char *appimage) { errExit("asprintf"); // associate loop device with appimage - int lfd = open(devloop, O_RDONLY); + int lfd = open(devloop, O_RDONLY|O_CLOEXEC); if (lfd == -1) err_loop(); if (ioctl(lfd, LOOP_SET_FD, ffd) == -1) @@ -146,7 +146,7 @@ void appimage_mount(void) { void appimage_clear(void) { EUID_ROOT(); if (devloop) { - int lfd = open(devloop, O_RDONLY); + int lfd = open(devloop, O_RDONLY|O_CLOEXEC); if (lfd != -1) { if (ioctl(lfd, LOOP_CLR_FD, 0) != -1) fmessage("AppImage detached\n"); diff --git a/src/firejail/bandwidth.c b/src/firejail/bandwidth.c index 1c952c0bc..a085f2c27 100644 --- a/src/firejail/bandwidth.c +++ b/src/firejail/bandwidth.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "firejail.h" @@ -119,26 +120,19 @@ static void bandwidth_create_run_file(pid_t pid) { if (asprintf(&fname, "%s/%d-bandwidth", RUN_FIREJAIL_BANDWIDTH_DIR, (int) pid) == -1) errExit("asprintf"); - // if the file already exists, do nothing - struct stat s; - if (stat(fname, &s) == 0) { - free(fname); - return; - } - // create an empty file and set mod and ownership - /* coverity[toctou] */ - FILE *fp = fopen(fname, "w"); - if (fp) { - SET_PERMS_STREAM(fp, 0, 0, 0644); - fclose(fp); - } - else { + // if the file already exists, do nothing + FILE *fp = fopen(fname, "wxe"); + free(fname); + if (!fp) { + if (errno == EEXIST) + return; fprintf(stderr, "Error: cannot create bandwidth file\n"); exit(1); } - free(fname); + SET_PERMS_STREAM(fp, 0, 0, 0644); + fclose(fp); } @@ -148,7 +142,7 @@ void network_set_run_file(pid_t pid) { errExit("asprintf"); // create an empty file and set mod and ownership - FILE *fp = fopen(fname, "w"); + FILE *fp = fopen(fname, "we"); if (fp) { if (cfg.bridge0.configured) fprintf(fp, "%s:%s\n", cfg.bridge0.dev, cfg.bridge0.devsandbox); @@ -178,7 +172,7 @@ static void read_bandwidth_file(pid_t pid) { if (asprintf(&fname, "%s/%d-bandwidth", RUN_FIREJAIL_BANDWIDTH_DIR, (int) pid) == -1) errExit("asprintf"); - FILE *fp = fopen(fname, "r"); + FILE *fp = fopen(fname, "re"); if (fp) { char buf[1024]; while (fgets(buf, 1024,fp)) { @@ -214,7 +208,7 @@ static void write_bandwidth_file(pid_t pid) { if (asprintf(&fname, "%s/%d-bandwidth", RUN_FIREJAIL_BANDWIDTH_DIR, (int) pid) == -1) errExit("asprintf"); - FILE *fp = fopen(fname, "w"); + FILE *fp = fopen(fname, "we"); if (fp) { IFBW *ptr = ifbw; while (ptr) { @@ -307,7 +301,7 @@ void bandwidth_pid(pid_t pid, const char *command, const char *dev, int down, in char *fname; if (asprintf(&fname, "%s/%d-netmap", RUN_FIREJAIL_NETWORK_DIR, (int) pid) == -1) errExit("asprintf"); - FILE *fp = fopen(fname, "r"); + FILE *fp = fopen(fname, "re"); if (!fp) { fprintf(stderr, "Error: cannot read network map file %s\n", fname); exit(1); diff --git a/src/firejail/caps.c b/src/firejail/caps.c index 597f9915b..5e02b99c2 100644 --- a/src/firejail/caps.c +++ b/src/firejail/caps.c @@ -389,7 +389,7 @@ static uint64_t extract_caps(int pid) { errExit("asprintf"); EUID_ROOT(); // grsecurity - FILE *fp = fopen(file, "r"); + FILE *fp = fopen(file, "re"); EUID_USER(); // grsecurity if (!fp) goto errexit; diff --git a/src/firejail/cgroup.c b/src/firejail/cgroup.c index 986b1157d..e7ffbca36 100644 --- a/src/firejail/cgroup.c +++ b/src/firejail/cgroup.c @@ -26,7 +26,7 @@ void save_cgroup(void) { if (cfg.cgroup == NULL) return; - FILE *fp = fopen(RUN_CGROUP_CFG, "w"); + FILE *fp = fopen(RUN_CGROUP_CFG, "wxe"); if (fp) { fprintf(fp, "%s", cfg.cgroup); fflush(0); @@ -48,7 +48,7 @@ void load_cgroup(const char *fname) { if (!fname) return; - FILE *fp = fopen(fname, "r"); + FILE *fp = fopen(fname, "re"); if (fp) { char buf[MAXBUF]; if (fgets(buf, MAXBUF, fp)) { @@ -91,19 +91,19 @@ void set_cgroup(const char *path) { goto errout; // tasks file exists - struct stat s; - if (stat(path, &s) == -1) + FILE *fp = fopen(path, "ae"); + if (!fp) goto errout; - // task file belongs to the user running the sandbox + int fd = fileno(fp); + if (fd == -1) + errExit("fileno"); + struct stat s; + if (fstat(fd, &s) == -1) + errExit("fstat"); if (s.st_uid != getuid() && s.st_gid != getgid()) goto errout2; - // add the task to cgroup - /* coverity[toctou] */ - FILE *fp = fopen(path, "a"); - if (!fp) - goto errout; pid_t pid = getpid(); int rv = fprintf(fp, "%d\n", pid); (void) rv; diff --git a/src/firejail/checkcfg.c b/src/firejail/checkcfg.c index e1613b325..d6643cf3a 100644 --- a/src/firejail/checkcfg.c +++ b/src/firejail/checkcfg.c @@ -59,7 +59,7 @@ int checkcfg(int val) { // open configuration file const char *fname = SYSCONFDIR "/firejail.config"; - fp = fopen(fname, "r"); + fp = fopen(fname, "re"); if (!fp) { #ifdef HAVE_GLOBALCFG fprintf(stderr, "Error: Firejail configuration file %s not found\n", fname); diff --git a/src/firejail/cpu.c b/src/firejail/cpu.c index 3427e8ade..fe7258fb0 100644 --- a/src/firejail/cpu.c +++ b/src/firejail/cpu.c @@ -75,7 +75,7 @@ void save_cpu(void) { if (cfg.cpus == 0) return; - FILE *fp = fopen(RUN_CPU_CFG, "w"); + FILE *fp = fopen(RUN_CPU_CFG, "wxe"); if (fp) { fprintf(fp, "%x\n", cfg.cpus); SET_PERMS_STREAM(fp, 0, 0, 0600); @@ -91,7 +91,7 @@ void load_cpu(const char *fname) { if (!fname) return; - FILE *fp = fopen(fname, "r"); + FILE *fp = fopen(fname, "re"); if (fp) { unsigned tmp; int rv = fscanf(fp, "%x", &tmp); @@ -139,7 +139,7 @@ static void print_cpu(int pid) { } EUID_ROOT(); // grsecurity - FILE *fp = fopen(file, "r"); + FILE *fp = fopen(file, "re"); EUID_USER(); // grsecurity if (!fp) { printf(" Error: cannot open %s\n", file); diff --git a/src/firejail/dhcp.c b/src/firejail/dhcp.c index bdbb338d5..5bcdcad37 100644 --- a/src/firejail/dhcp.c +++ b/src/firejail/dhcp.c @@ -93,7 +93,7 @@ static pid_t dhcp_read_pidfile(const Dhclient *client) { while (found == 0 && tries < 10) { if (tries >= 1) usleep(100000); - FILE *pidfile = fopen(client->pid_file, "r"); + FILE *pidfile = fopen(client->pid_file, "re"); if (pidfile) { long pid; if (fscanf(pidfile, "%ld", &pid) == 1) diff --git a/src/firejail/env.c b/src/firejail/env.c index 03818df0b..f5e9dd980 100644 --- a/src/firejail/env.c +++ b/src/firejail/env.c @@ -59,12 +59,7 @@ void env_ibus_load(void) { if (asprintf(&dirname, "%s/.config/ibus/bus", cfg.homedir) == -1) errExit("asprintf"); - struct stat s; - if (stat(dirname, &s) == -1) - return; - // find the file - /* coverity[toctou] */ DIR *dir = opendir(dirname); if (!dir) { free(dirname); @@ -84,7 +79,7 @@ void env_ibus_load(void) { char *fname; if (asprintf(&fname, "%s/%s", dirname, entry->d_name) == -1) errExit("asprintf"); - FILE *fp = fopen(fname, "r"); + FILE *fp = fopen(fname, "re"); free(fname); if (!fp) continue; diff --git a/src/firejail/fs_dev.c b/src/firejail/fs_dev.c index 2f0067c93..8c2870a4d 100644 --- a/src/firejail/fs_dev.c +++ b/src/firejail/fs_dev.c @@ -122,7 +122,7 @@ static void deventry_mount(void) { i++; continue; } - FILE *fp = fopen(dev[i].dev_fname, "w"); + FILE *fp = fopen(dev[i].dev_fname, "we"); if (fp) { fprintf(fp, "\n"); SET_PERMS_STREAM(fp, s.st_uid, s.st_gid, s.st_mode); @@ -218,7 +218,7 @@ void fs_private_dev(void){ struct stat s; if (stat("/dev/log", &s) == 0) { have_devlog = 1; - FILE *fp = fopen(RUN_DEVLOG_FILE, "w"); + FILE *fp = fopen(RUN_DEVLOG_FILE, "we"); if (!fp) have_devlog = 0; else { @@ -239,7 +239,7 @@ void fs_private_dev(void){ // bring back /dev/log if (have_devlog) { - FILE *fp = fopen("/dev/log", "w"); + FILE *fp = fopen("/dev/log", "we"); if (fp) { fprintf(fp, "\n"); fclose(fp); diff --git a/src/firejail/fs_etc.c b/src/firejail/fs_etc.c index 8cb25a1ff..b0e1e1bf1 100644 --- a/src/firejail/fs_etc.c +++ b/src/firejail/fs_etc.c @@ -52,7 +52,7 @@ void fs_machineid(void) { mid.u8[8] = (mid.u8[8] & 0x3F) | 0x80; // write it in a file - FILE *fp = fopen(RUN_MACHINEID, "w"); + FILE *fp = fopen(RUN_MACHINEID, "we"); if (!fp) errExit("fopen"); fprintf(fp, "%08x%08x%08x%08x\n", mid.u32[0], mid.u32[1], mid.u32[2], mid.u32[3]); diff --git a/src/firejail/fs_home.c b/src/firejail/fs_home.c index 46f32d7ad..c7b87235a 100644 --- a/src/firejail/fs_home.c +++ b/src/firejail/fs_home.c @@ -130,7 +130,7 @@ static int store_xauthority(void) { } // create an empty file as root, and change ownership to user - FILE *fp = fopen(dest, "w"); + FILE *fp = fopen(dest, "we"); if (fp) { fprintf(fp, "\n"); SET_PERMS_STREAM(fp, getuid(), getgid(), 0600); @@ -178,7 +178,7 @@ static int store_asoundrc(void) { } // create an empty file as root, and change ownership to user - FILE *fp = fopen(dest, "w"); + FILE *fp = fopen(dest, "we"); if (fp) { fprintf(fp, "\n"); SET_PERMS_STREAM(fp, getuid(), getgid(), 0644); diff --git a/src/firejail/fs_hostname.c b/src/firejail/fs_hostname.c index 8a3bb71ea..80046f7ae 100644 --- a/src/firejail/fs_hostname.c +++ b/src/firejail/fs_hostname.c @@ -47,11 +47,11 @@ void fs_hostname(const char *hostname) { printf("Creating a new /etc/hosts file\n"); // copy /etc/host into our new file, and modify it on the fly /* coverity[toctou] */ - FILE *fp1 = fopen("/etc/hosts", "r"); + FILE *fp1 = fopen("/etc/hosts", "re"); if (!fp1) goto errexit; - FILE *fp2 = fopen(RUN_HOSTS_FILE, "w"); + FILE *fp2 = fopen(RUN_HOSTS_FILE, "we"); if (!fp2) { fclose(fp1); goto errexit; @@ -165,7 +165,7 @@ void fs_resolvconf(void) { if (arg_debug) printf("Creating a new /etc/resolv.conf file\n"); - FILE *fp = fopen("/etc/resolv.conf", "w"); + FILE *fp = fopen("/etc/resolv.conf", "wxe"); if (!fp) { fprintf(stderr, "Error: cannot create /etc/resolv.conf file\n"); exit(1); diff --git a/src/firejail/fs_lib.c b/src/firejail/fs_lib.c index 85fb70854..5df356d04 100644 --- a/src/firejail/fs_lib.c +++ b/src/firejail/fs_lib.c @@ -221,7 +221,7 @@ void fslib_mount_libs(const char *full_path, unsigned user) { sbox_run(mask | SBOX_SECCOMP | SBOX_CAPS_NONE, 3, PATH_FLDD, full_path, RUN_LIB_FILE); // open the list of libraries and install them on by one - FILE *fp = fopen(RUN_LIB_FILE, "r"); + FILE *fp = fopen(RUN_LIB_FILE, "re"); if (!fp) errExit("fopen"); diff --git a/src/firejail/fs_logger.c b/src/firejail/fs_logger.c index 67ad4b52e..604e297b1 100644 --- a/src/firejail/fs_logger.c +++ b/src/firejail/fs_logger.c @@ -92,7 +92,7 @@ void fs_logger_print(void) { if (!head) return; - FILE *fp = fopen(RUN_FSLOGGER_FILE, "a"); + FILE *fp = fopen(RUN_FSLOGGER_FILE, "ae"); if (!fp) { perror("fopen"); return; @@ -123,15 +123,8 @@ void fs_logger_print_log(pid_t pid) { // in case the pid is that of a firejail process, use the pid of the first child process pid = switch_to_child(pid); - // check privileges for non-root users - uid_t uid = getuid(); - if (uid != 0) { - uid_t sandbox_uid = pid_get_uid(pid); - if (uid != sandbox_uid) { - fprintf(stderr, "Error: permission denied\n"); - exit(1); - } - } + // exit if no permission to join the sandbox + check_join_permission(pid); // print RUN_FSLOGGER_FILE char *fname; @@ -139,24 +132,16 @@ void fs_logger_print_log(pid_t pid) { errExit("asprintf"); EUID_ROOT(); - struct stat s; - if (stat(fname, &s) == -1 || s.st_uid != 0) { - fprintf(stderr, "Error: Cannot access filesystem log\n"); - exit(1); - } - - /* coverity[toctou] */ - FILE *fp = fopen(fname, "r"); + FILE *fp = fopen(fname, "re"); + free(fname); if (!fp) { fprintf(stderr, "Error: Cannot open filesystem log\n"); exit(1); } - char buf[MAXBUF]; while (fgets(buf, MAXBUF, fp)) printf("%s", buf); fclose(fp); - free(fname); exit(0); } diff --git a/src/firejail/fs_trace.c b/src/firejail/fs_trace.c index 8f939b5f5..1fc38361e 100644 --- a/src/firejail/fs_trace.c +++ b/src/firejail/fs_trace.c @@ -33,8 +33,7 @@ void fs_trace_preload(void) { if (stat("/etc/ld.so.preload", &s)) { if (arg_debug) printf("Creating an empty /etc/ld.so.preload file\n"); - /* coverity[toctou] */ - FILE *fp = fopen("/etc/ld.so.preload", "w"); + FILE *fp = fopen("/etc/ld.so.preload", "wxe"); if (!fp) errExit("fopen"); SET_PERMS_STREAM(fp, 0, 0, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH); @@ -64,11 +63,11 @@ void fs_tracefile(void) { if (ftruncate(fd, 0) == -1) errExit("ftruncate"); EUID_ROOT(); - FILE *fp = fopen(RUN_TRACE_FILE, "w"); + FILE *fp = fopen(RUN_TRACE_FILE, "we"); if (!fp) errExit("fopen " RUN_TRACE_FILE); fclose(fp); - fs_logger2("touch ", arg_tracefile); + fs_logger2("touch", arg_tracefile); // mount using the symbolic link in /proc/self/fd if (arg_debug) printf("Bind mount %s to %s\n", arg_tracefile, RUN_TRACE_FILE); @@ -88,7 +87,7 @@ void fs_trace(void) { if (arg_debug) printf("Create the new ld.so.preload file\n"); - FILE *fp = fopen(RUN_LDPRELOAD_FILE, "w"); + FILE *fp = fopen(RUN_LDPRELOAD_FILE, "we"); if (!fp) errExit("fopen"); const char *prefix = RUN_FIREJAIL_LIB_DIR; diff --git a/src/firejail/fs_var.c b/src/firejail/fs_var.c index f07581cd8..64238e070 100644 --- a/src/firejail/fs_var.c +++ b/src/firejail/fs_var.c @@ -127,7 +127,7 @@ void fs_var_log(void) { // create an empty /var/log/wtmp file /* coverity[toctou] */ - FILE *fp = fopen("/var/log/wtmp", "w"); + FILE *fp = fopen("/var/log/wtmp", "wxe"); if (fp) { SET_PERMS_STREAM(fp, 0, wtmp_group, S_IRUSR | S_IWRITE | S_IRGRP | S_IWGRP | S_IROTH); fclose(fp); @@ -135,7 +135,7 @@ void fs_var_log(void) { fs_logger("touch /var/log/wtmp"); // create an empty /var/log/btmp file - fp = fopen("/var/log/btmp", "w"); + fp = fopen("/var/log/btmp", "wxe"); if (fp) { SET_PERMS_STREAM(fp, 0, wtmp_group, S_IRUSR | S_IWRITE | S_IRGRP | S_IWGRP); fclose(fp); @@ -158,8 +158,7 @@ void fs_var_lib(void) { fs_logger("tmpfs /var/lib/dhcp"); // isc dhcp server requires a /var/lib/dhcp/dhcpd.leases file - FILE *fp = fopen("/var/lib/dhcp/dhcpd.leases", "w"); - + FILE *fp = fopen("/var/lib/dhcp/dhcpd.leases", "wxe"); if (fp) { fprintf(fp, "\n"); SET_PERMS_STREAM(fp, 0, 0, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); @@ -296,7 +295,7 @@ void fs_var_utmp(void) { printf("Create the new utmp file\n"); /* coverity[toctou] */ - FILE *fp = fopen(RUN_UTMP_FILE, "w"); + FILE *fp = fopen(RUN_UTMP_FILE, "wxe"); if (!fp) errExit("fopen"); diff --git a/src/firejail/join.c b/src/firejail/join.c index 1575a7469..bab4b830f 100644 --- a/src/firejail/join.c +++ b/src/firejail/join.c @@ -103,7 +103,7 @@ static void extract_x11_display(pid_t pid) { if (asprintf(&fname, "%s/%d", RUN_FIREJAIL_X11_DIR, pid) == -1) errExit("asprintf"); - FILE *fp = fopen(fname, "r"); + FILE *fp = fopen(fname, "re"); free(fname); if (!fp) return; @@ -219,7 +219,7 @@ static void extract_caps(pid_t pid) { perror("asprintf"); exit(1); } - FILE *fp = fopen(file, "r"); + FILE *fp = fopen(file, "re"); if (!fp) goto errexit; @@ -266,7 +266,7 @@ static void extract_user_namespace(pid_t pid) { char *uidmap; if (asprintf(&uidmap, "/proc/%u/uid_map", pid) == -1) errExit("asprintf"); - FILE *fp = fopen(uidmap, "r"); + FILE *fp = fopen(uidmap, "re"); if (!fp) { free(uidmap); return; diff --git a/src/firejail/ls.c b/src/firejail/ls.c index 63ef2309b..796c42290 100644 --- a/src/firejail/ls.c +++ b/src/firejail/ls.c @@ -221,7 +221,7 @@ void cat(const char *path) { if (arg_debug) printf("cat %s\n", path); - FILE *fp = fopen(path, "r"); + FILE *fp = fopen(path, "re"); if (!fp) { fprintf(stderr, "Error: cannot read %s\n", path); exit(1); diff --git a/src/firejail/macros.c b/src/firejail/macros.c index 7f2f6dbf3..bcac1feb4 100644 --- a/src/firejail/macros.c +++ b/src/firejail/macros.c @@ -99,7 +99,7 @@ static char *resolve_xdg(const char *var) { if (asprintf(&fname, "%s/.config/user-dirs.dirs", cfg.homedir) == -1) errExit("asprintf"); - FILE *fp = fopen(fname, "r"); + FILE *fp = fopen(fname, "re"); if (!fp) { free(fname); return NULL; diff --git a/src/firejail/main.c b/src/firejail/main.c index a0ee1e433..cf14c077a 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c @@ -535,7 +535,7 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { char *fname; if (asprintf(&fname, RUN_FIREJAIL_PROFILE_DIR "/%d", pid) == -1) errExit("asprintf"); - FILE *fp = fopen(fname, "r"); + FILE *fp = fopen(fname, "re"); if (!fp) { fprintf(stderr, "Error: sandbox %s not found\n", argv[i] + 16); exit(1); @@ -1043,7 +1043,7 @@ int main(int argc, char **argv, char **envp) { preproc_build_firejail_dir(); const char *container_name = env_get("container"); if (!container_name || strcmp(container_name, "firejail")) { - lockfd_directory = open(RUN_DIRECTORY_LOCK_FILE, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); + lockfd_directory = open(RUN_DIRECTORY_LOCK_FILE, O_WRONLY | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR); if (lockfd_directory != -1) { int rv = fchown(lockfd_directory, 0, 0); (void) rv; @@ -1145,7 +1145,7 @@ int main(int argc, char **argv, char **envp) { #ifdef DEBUG_RESTRICTED_SHELL {EUID_ROOT(); - FILE *fp = fopen("/firelog", "w"); + FILE *fp = fopen("/firelog", "we"); if (fp) { int i; fprintf(fp, "argc %d: ", argc); @@ -1164,7 +1164,7 @@ int main(int argc, char **argv, char **envp) { strncmp(argv[2], "scp ", 4) == 0) { #ifdef DEBUG_RESTRICTED_SHELL {EUID_ROOT(); - FILE *fp = fopen("/firelog", "a"); + FILE *fp = fopen("/firelog", "ae"); if (fp) { fprintf(fp, "run without a sandbox\n"); fclose(fp); @@ -1197,7 +1197,7 @@ int main(int argc, char **argv, char **envp) { #ifdef DEBUG_RESTRICTED_SHELL {EUID_ROOT(); - FILE *fp = fopen("/firelog", "a"); + FILE *fp = fopen("/firelog", "ae"); if (fp) { fprintf(fp, "fullargc %d: ", fullargc); int i; @@ -1219,7 +1219,7 @@ int main(int argc, char **argv, char **envp) { #ifdef DEBUG_RESTRICTED_SHELL {EUID_ROOT(); - FILE *fp = fopen("/firelog", "a"); + FILE *fp = fopen("/firelog", "ae"); if (fp) { fprintf(fp, "argc %d: ", argc); int i; @@ -2852,7 +2852,7 @@ int main(int argc, char **argv, char **envp) { // check and assign an IP address - for macvlan it will be done again in the sandbox! if (any_bridge_configured()) { EUID_ROOT(); - lockfd_network = open(RUN_NETWORK_LOCK_FILE, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); + lockfd_network = open(RUN_NETWORK_LOCK_FILE, O_WRONLY | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR); if (lockfd_network != -1) { int rv = fchown(lockfd_network, 0, 0); (void) rv; @@ -2892,7 +2892,7 @@ int main(int argc, char **argv, char **envp) { // set name and x11 run files EUID_ROOT(); - lockfd_directory = open(RUN_DIRECTORY_LOCK_FILE, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); + lockfd_directory = open(RUN_DIRECTORY_LOCK_FILE, O_WRONLY | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR); if (lockfd_directory != -1) { int rv = fchown(lockfd_directory, 0, 0); (void) rv; diff --git a/src/firejail/network.c b/src/firejail/network.c index f7142cefd..289e164c6 100644 --- a/src/firejail/network.c +++ b/src/firejail/network.c @@ -217,7 +217,7 @@ int net_add_route(uint32_t ip, uint32_t mask, uint32_t gw) { #define BUFSIZE 1024 uint32_t network_get_defaultgw(void) { - FILE *fp = fopen("/proc/self/net/route", "r"); + FILE *fp = fopen("/proc/self/net/route", "re"); if (!fp) errExit("fopen"); diff --git a/src/firejail/network_main.c b/src/firejail/network_main.c index ee3c00872..d3e75bbed 100644 --- a/src/firejail/network_main.c +++ b/src/firejail/network_main.c @@ -292,7 +292,7 @@ void net_dns_print(pid_t pid) { errExit("chdir"); // access /etc/resolv.conf - FILE *fp = fopen("/etc/resolv.conf", "r"); + FILE *fp = fopen("/etc/resolv.conf", "re"); if (!fp) { fprintf(stderr, "Error: cannot access /etc/resolv.conf\n"); exit(1); diff --git a/src/firejail/no_sandbox.c b/src/firejail/no_sandbox.c index 60a82821e..0e153c47b 100644 --- a/src/firejail/no_sandbox.c +++ b/src/firejail/no_sandbox.c @@ -20,6 +20,7 @@ #include "firejail.h" #include #include +#include #include #include @@ -47,7 +48,7 @@ int check_namespace_virt(void) { // check PID 1 container environment variable EUID_ROOT(); - FILE *fp = fopen("/proc/1/environ", "r"); + FILE *fp = fopen("/proc/1/environ", "re"); if (fp) { int c = 0; while (c != EOF) { @@ -105,20 +106,15 @@ int check_kernel_procs(void) { // look at the first 10 processes // if a kernel process is found, return 1 for (i = 1; i <= 10; i++) { - struct stat s; char *fname; if (asprintf(&fname, "/proc/%d/comm", i) == -1) errExit("asprintf"); - if (stat(fname, &s) == -1) { - free(fname); - continue; - } // open file - /* coverity[toctou] */ - FILE *fp = fopen(fname, "r"); + FILE *fp = fopen(fname, "re"); if (!fp) { - fwarning("cannot open %s\n", fname); + if (errno != ENOENT) + fwarning("cannot open %s\n", fname); free(fname); continue; } diff --git a/src/firejail/preproc.c b/src/firejail/preproc.c index 7f602545d..1aafd1ca2 100644 --- a/src/firejail/preproc.c +++ b/src/firejail/preproc.c @@ -164,7 +164,7 @@ void preproc_clean_run(void) { int max_pids=32769; int start_pid = 100; // extract real max_pids - FILE *fp = fopen("/proc/sys/kernel/pid_max", "r"); + FILE *fp = fopen("/proc/sys/kernel/pid_max", "re"); if (fp) { int val; if (fscanf(fp, "%d", &val) == 1) { diff --git a/src/firejail/profile.c b/src/firejail/profile.c index 2ea32b665..d94e24ef6 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c @@ -1691,7 +1691,7 @@ void profile_read(const char *fname) { } // open profile file: - FILE *fp = fopen(fname, "r"); + FILE *fp = fopen(fname, "re"); if (fp == NULL) { fprintf(stderr, "Error: cannot open profile file %s\n", fname); exit(1); diff --git a/src/firejail/protocol.c b/src/firejail/protocol.c index 926af7967..f21f8c96e 100644 --- a/src/firejail/protocol.c +++ b/src/firejail/protocol.c @@ -23,7 +23,7 @@ void protocol_filter_save(void) { // save protocol filter configuration in PROTOCOL_CFG - FILE *fp = fopen(RUN_PROTOCOL_CFG, "w"); + FILE *fp = fopen(RUN_PROTOCOL_CFG, "wxe"); if (!fp) errExit("fopen"); fprintf(fp, "%s\n", cfg.protocol); @@ -35,7 +35,7 @@ void protocol_filter_load(const char *fname) { assert(fname); // read protocol filter configuration from PROTOCOL_CFG - FILE *fp = fopen(fname, "r"); + FILE *fp = fopen(fname, "re"); if (!fp) return; diff --git a/src/firejail/pulseaudio.c b/src/firejail/pulseaudio.c index 4b9203c36..97c022bad 100644 --- a/src/firejail/pulseaudio.c +++ b/src/firejail/pulseaudio.c @@ -106,7 +106,7 @@ void pulseaudio_init(void) { errExit("asprintf"); if (copy_file(PULSE_CLIENT_SYSCONF, pulsecfg, -1, -1, 0644)) // root needed errExit("copy_file"); - FILE *fp = fopen(pulsecfg, "a"); + FILE *fp = fopen(pulsecfg, "ae"); if (!fp) errExit("fopen"); fprintf(fp, "%s", "\nenable-shm = no\n"); diff --git a/src/firejail/restrict_users.c b/src/firejail/restrict_users.c index a0ca4c02c..e173c9888 100644 --- a/src/firejail/restrict_users.c +++ b/src/firejail/restrict_users.c @@ -183,10 +183,10 @@ static void sanitize_passwd(void) { // open files /* coverity[toctou] */ - fpin = fopen("/etc/passwd", "r"); + fpin = fopen("/etc/passwd", "re"); if (!fpin) goto errout; - fpout = fopen(RUN_PASSWD_FILE, "w"); + fpout = fopen(RUN_PASSWD_FILE, "we"); if (!fpout) goto errout; @@ -318,10 +318,10 @@ static void sanitize_group(void) { // open files /* coverity[toctou] */ - fpin = fopen("/etc/group", "r"); + fpin = fopen("/etc/group", "re"); if (!fpin) goto errout; - fpout = fopen(RUN_GROUP_FILE, "w"); + fpout = fopen(RUN_GROUP_FILE, "we"); if (!fpout) goto errout; diff --git a/src/firejail/restricted_shell.c b/src/firejail/restricted_shell.c index ae453f4f1..ed66903b5 100644 --- a/src/firejail/restricted_shell.c +++ b/src/firejail/restricted_shell.c @@ -32,7 +32,7 @@ int restricted_shell(const char *user) { char *fname; if (asprintf(&fname, "%s/login.users", SYSCONFDIR) == -1) errExit("asprintf"); - FILE *fp = fopen(fname, "r"); + FILE *fp = fopen(fname, "re"); free(fname); if (fp == NULL) return 0; @@ -96,7 +96,7 @@ int restricted_shell(const char *user) { fullargv[i] = ptr; #ifdef DEBUG_RESTRICTED_SHELL {EUID_ROOT(); - FILE *fp = fopen("/firelog", "a"); + FILE *fp = fopen("/firelog", "ae"); if (fp) { fprintf(fp, "i %d ptr #%s#\n", i, fullargv[i]); fclose(fp); diff --git a/src/firejail/run_files.c b/src/firejail/run_files.c index cd44f745f..c28c3e01b 100644 --- a/src/firejail/run_files.c +++ b/src/firejail/run_files.c @@ -101,7 +101,7 @@ void set_name_run_file(pid_t pid) { errExit("asprintf"); // the file is deleted first - FILE *fp = fopen(fname, "w"); + FILE *fp = fopen(fname, "we"); if (!fp) { fprintf(stderr, "Error: cannot create %s\n", fname); exit(1); @@ -120,7 +120,7 @@ void set_x11_run_file(pid_t pid, int display) { errExit("asprintf"); // the file is deleted first - FILE *fp = fopen(fname, "w"); + FILE *fp = fopen(fname, "we"); if (!fp) { fprintf(stderr, "Error: cannot create %s\n", fname); exit(1); @@ -139,7 +139,7 @@ void set_profile_run_file(pid_t pid, const char *fname) { EUID_ROOT(); // the file is deleted first - FILE *fp = fopen(runfile, "w"); + FILE *fp = fopen(runfile, "we"); if (!fp) { fprintf(stderr, "Error: cannot create %s\n", runfile); exit(1); diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index 3af828ede..2c751809e 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c @@ -67,7 +67,7 @@ static void sandbox_handler(int sig){ if (asprintf(&monfile, "/proc/%d/cmdline", monitored_pid) == -1) errExit("asprintf"); while (monsec) { - FILE *fp = fopen(monfile, "r"); + FILE *fp = fopen(monfile, "re"); if (!fp) break; @@ -162,7 +162,7 @@ static void save_nogroups(void) { if (arg_nogroups == 0) return; - FILE *fp = fopen(RUN_GROUPS_CFG, "w"); + FILE *fp = fopen(RUN_GROUPS_CFG, "wxe"); if (fp) { fprintf(fp, "\n"); SET_PERMS_STREAM(fp, 0, 0, 0644); // assume mode 0644 diff --git a/src/firejail/seccomp.c b/src/firejail/seccomp.c index 785c29517..9670fe816 100644 --- a/src/firejail/seccomp.c +++ b/src/firejail/seccomp.c @@ -86,7 +86,7 @@ int seccomp_install_filters(void) { static void seccomp_save_file_list(const char *fname) { assert(fname); - FILE *fp = fopen(RUN_SECCOMP_LIST, "a+"); + FILE *fp = fopen(RUN_SECCOMP_LIST, "ae"); if (!fp) errExit("fopen"); @@ -99,7 +99,7 @@ static void seccomp_save_file_list(const char *fname) { #define MAXBUF 4096 static int load_file_list_flag = 0; void seccomp_load_file_list(void) { - FILE *fp = fopen(RUN_SECCOMP_LIST, "r"); + FILE *fp = fopen(RUN_SECCOMP_LIST, "re"); if (!fp) return; // no seccomp configuration whatsoever @@ -122,7 +122,7 @@ int seccomp_load(const char *fname) { assert(fname); // open filter file - int fd = open(fname, O_RDONLY); + int fd = open(fname, O_RDONLY|O_CLOEXEC); if (fd == -1) goto errexit; @@ -438,7 +438,7 @@ void seccomp_print_filter(pid_t pid) { if (stat(fname, &s) == -1) goto errexit; - FILE *fp = fopen(fname, "r"); + FILE *fp = fopen(fname, "re"); if (!fp) goto errexit; free(fname); diff --git a/src/firejail/shutdown.c b/src/firejail/shutdown.c index 8fb03d0a6..fbfe1765b 100644 --- a/src/firejail/shutdown.c +++ b/src/firejail/shutdown.c @@ -64,7 +64,7 @@ void shut(pid_t pid) { monsec--; EUID_ROOT(); - FILE *fp = fopen(monfile, "r"); + FILE *fp = fopen(monfile, "re"); EUID_USER(); if (!fp) { killdone = 1; diff --git a/src/firejail/util.c b/src/firejail/util.c index 2ad85acd6..2c985c0d6 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c @@ -298,14 +298,14 @@ int copy_file(const char *srcname, const char *destname, uid_t uid, gid_t gid, m assert(destname); // open source - int src = open(srcname, O_RDONLY); + int src = open(srcname, O_RDONLY|O_CLOEXEC); if (src < 0) { fwarning("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); + int dst = open(destname, O_CREAT|O_WRONLY|O_TRUNC|O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (dst < 0) { fwarning("cannot open destination file %s, file not copied\n", destname); close(src); @@ -348,7 +348,7 @@ void copy_file_as_user(const char *srcname, const char *destname, uid_t uid, gid void copy_file_from_user_to_root(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode) { // open destination - int dst = open(destname, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + int dst = open(destname, O_CREAT|O_WRONLY|O_TRUNC|O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (dst < 0) { fwarning("cannot open destination file %s, file not copied\n", destname); return; @@ -361,7 +361,7 @@ void copy_file_from_user_to_root(const char *srcname, const char *destname, uid_ // drop privileges drop_privs(0); - int src = open(srcname, O_RDONLY); + int src = open(srcname, O_RDONLY|O_CLOEXEC); if (src < 0) { fwarning("cannot open source file %s, file not copied\n", srcname); } else { @@ -616,7 +616,7 @@ int find_child(pid_t parent, pid_t *child) { perror("asprintf"); exit(1); } - FILE *fp = fopen(file, "r"); + FILE *fp = fopen(file, "re"); if (!fp) { free(file); continue; @@ -722,7 +722,7 @@ void update_map(char *mapping, char *map_file) { if (mapping[j] == ',') mapping[j] = '\n'; - fd = open(map_file, O_RDWR); + fd = open(map_file, O_RDWR|O_CLOEXEC); if (fd == -1) { fprintf(stderr, "Error: cannot open %s: %s\n", map_file, strerror(errno)); exit(EXIT_FAILURE); @@ -742,9 +742,9 @@ void wait_for_other(int fd) { // wait for the parent to be initialized //**************************** char childstr[BUFLEN + 1]; - int newfd = dup(fd); + int newfd = fcntl(fd, F_DUPFD_CLOEXEC, 0); if (newfd == -1) - errExit("dup"); + errExit("fcntl"); FILE* stream; stream = fdopen(newfd, "r"); *childstr = '\0'; @@ -791,9 +791,9 @@ void wait_for_other(int fd) { void notify_other(int fd) { FILE* stream; - int newfd = dup(fd); + int newfd = fcntl(fd, F_DUPFD_CLOEXEC, 0); if (newfd == -1) - errExit("dup"); + errExit("fcntl"); stream = fdopen(newfd, "w"); fprintf(stream, "arg_noroot=%d\n", arg_noroot); fflush(stream); @@ -811,7 +811,7 @@ uid_t pid_get_uid(pid_t pid) { exit(1); } EUID_ROOT(); // grsecurity fix - FILE *fp = fopen(file, "r"); + FILE *fp = fopen(file, "re"); if (!fp) { free(file); fprintf(stderr, "Error: cannot open /proc file\n"); @@ -1021,8 +1021,7 @@ void create_empty_file_as_root(const char *fname, mode_t mode) { if (arg_debug) printf("Creating empty %s file\n", fname); - /* coverity[toctou] */ - FILE *fp = fopen(fname, "w"); + FILE *fp = fopen(fname, "wxe"); if (!fp) errExit("fopen"); SET_PERMS_STREAM(fp, 0, 0, mode); diff --git a/src/firejail/x11.c b/src/firejail/x11.c index 1dabf272e..c0587ffc1 100644 --- a/src/firejail/x11.c +++ b/src/firejail/x11.c @@ -84,7 +84,7 @@ int x11_display(void) { static int x11_abstract_sockets_present(void) { EUID_ROOT(); // grsecurity fix - FILE *fp = fopen("/proc/net/unix", "r"); + FILE *fp = fopen("/proc/net/unix", "re"); if (!fp) errExit("fopen"); EUID_USER(); @@ -1363,7 +1363,7 @@ void fs_x11(void) { fs_logger("tmpfs /tmp/.X11-unix"); // create an empty root-owned file which will have the desired socket bind-mounted over it - int fd = open(x11file, O_RDONLY|O_CREAT|O_EXCL, S_IRUSR | S_IWUSR); + int fd = open(x11file, O_RDONLY|O_CREAT|O_EXCL|O_CLOEXEC, S_IRUSR | S_IWUSR); if (fd < 0) errExit(x11file); close(fd); -- cgit v1.2.3-70-g09d2