diff options
35 files changed, 111 insertions, 144 deletions
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) { | |||
67 | 67 | ||
68 | // find or allocate a free loop device to use | 68 | // find or allocate a free loop device to use |
69 | EUID_ROOT(); | 69 | EUID_ROOT(); |
70 | int cfd = open("/dev/loop-control", O_RDWR); | 70 | int cfd = open("/dev/loop-control", O_RDWR|O_CLOEXEC); |
71 | if (cfd == -1) | 71 | if (cfd == -1) |
72 | err_loop(); | 72 | err_loop(); |
73 | int devnr = ioctl(cfd, LOOP_CTL_GET_FREE); | 73 | int devnr = ioctl(cfd, LOOP_CTL_GET_FREE); |
@@ -78,7 +78,7 @@ void appimage_set(const char *appimage) { | |||
78 | errExit("asprintf"); | 78 | errExit("asprintf"); |
79 | 79 | ||
80 | // associate loop device with appimage | 80 | // associate loop device with appimage |
81 | int lfd = open(devloop, O_RDONLY); | 81 | int lfd = open(devloop, O_RDONLY|O_CLOEXEC); |
82 | if (lfd == -1) | 82 | if (lfd == -1) |
83 | err_loop(); | 83 | err_loop(); |
84 | if (ioctl(lfd, LOOP_SET_FD, ffd) == -1) | 84 | if (ioctl(lfd, LOOP_SET_FD, ffd) == -1) |
@@ -146,7 +146,7 @@ void appimage_mount(void) { | |||
146 | void appimage_clear(void) { | 146 | void appimage_clear(void) { |
147 | EUID_ROOT(); | 147 | EUID_ROOT(); |
148 | if (devloop) { | 148 | if (devloop) { |
149 | int lfd = open(devloop, O_RDONLY); | 149 | int lfd = open(devloop, O_RDONLY|O_CLOEXEC); |
150 | if (lfd != -1) { | 150 | if (lfd != -1) { |
151 | if (ioctl(lfd, LOOP_CLR_FD, 0) != -1) | 151 | if (ioctl(lfd, LOOP_CLR_FD, 0) != -1) |
152 | fmessage("AppImage detached\n"); | 152 | 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 @@ | |||
22 | #include <sys/types.h> | 22 | #include <sys/types.h> |
23 | #include <sys/stat.h> | 23 | #include <sys/stat.h> |
24 | #include <unistd.h> | 24 | #include <unistd.h> |
25 | #include <errno.h> | ||
25 | #include <net/if.h> | 26 | #include <net/if.h> |
26 | #include "firejail.h" | 27 | #include "firejail.h" |
27 | 28 | ||
@@ -119,26 +120,19 @@ static void bandwidth_create_run_file(pid_t pid) { | |||
119 | if (asprintf(&fname, "%s/%d-bandwidth", RUN_FIREJAIL_BANDWIDTH_DIR, (int) pid) == -1) | 120 | if (asprintf(&fname, "%s/%d-bandwidth", RUN_FIREJAIL_BANDWIDTH_DIR, (int) pid) == -1) |
120 | errExit("asprintf"); | 121 | errExit("asprintf"); |
121 | 122 | ||
122 | // if the file already exists, do nothing | ||
123 | struct stat s; | ||
124 | if (stat(fname, &s) == 0) { | ||
125 | free(fname); | ||
126 | return; | ||
127 | } | ||
128 | |||
129 | // create an empty file and set mod and ownership | 123 | // create an empty file and set mod and ownership |
130 | /* coverity[toctou] */ | 124 | // if the file already exists, do nothing |
131 | FILE *fp = fopen(fname, "w"); | 125 | FILE *fp = fopen(fname, "wxe"); |
132 | if (fp) { | 126 | free(fname); |
133 | SET_PERMS_STREAM(fp, 0, 0, 0644); | 127 | if (!fp) { |
134 | fclose(fp); | 128 | if (errno == EEXIST) |
135 | } | 129 | return; |
136 | else { | ||
137 | fprintf(stderr, "Error: cannot create bandwidth file\n"); | 130 | fprintf(stderr, "Error: cannot create bandwidth file\n"); |
138 | exit(1); | 131 | exit(1); |
139 | } | 132 | } |
140 | 133 | ||
141 | free(fname); | 134 | SET_PERMS_STREAM(fp, 0, 0, 0644); |
135 | fclose(fp); | ||
142 | } | 136 | } |
143 | 137 | ||
144 | 138 | ||
@@ -148,7 +142,7 @@ void network_set_run_file(pid_t pid) { | |||
148 | errExit("asprintf"); | 142 | errExit("asprintf"); |
149 | 143 | ||
150 | // create an empty file and set mod and ownership | 144 | // create an empty file and set mod and ownership |
151 | FILE *fp = fopen(fname, "w"); | 145 | FILE *fp = fopen(fname, "we"); |
152 | if (fp) { | 146 | if (fp) { |
153 | if (cfg.bridge0.configured) | 147 | if (cfg.bridge0.configured) |
154 | fprintf(fp, "%s:%s\n", cfg.bridge0.dev, cfg.bridge0.devsandbox); | 148 | fprintf(fp, "%s:%s\n", cfg.bridge0.dev, cfg.bridge0.devsandbox); |
@@ -178,7 +172,7 @@ static void read_bandwidth_file(pid_t pid) { | |||
178 | if (asprintf(&fname, "%s/%d-bandwidth", RUN_FIREJAIL_BANDWIDTH_DIR, (int) pid) == -1) | 172 | if (asprintf(&fname, "%s/%d-bandwidth", RUN_FIREJAIL_BANDWIDTH_DIR, (int) pid) == -1) |
179 | errExit("asprintf"); | 173 | errExit("asprintf"); |
180 | 174 | ||
181 | FILE *fp = fopen(fname, "r"); | 175 | FILE *fp = fopen(fname, "re"); |
182 | if (fp) { | 176 | if (fp) { |
183 | char buf[1024]; | 177 | char buf[1024]; |
184 | while (fgets(buf, 1024,fp)) { | 178 | while (fgets(buf, 1024,fp)) { |
@@ -214,7 +208,7 @@ static void write_bandwidth_file(pid_t pid) { | |||
214 | if (asprintf(&fname, "%s/%d-bandwidth", RUN_FIREJAIL_BANDWIDTH_DIR, (int) pid) == -1) | 208 | if (asprintf(&fname, "%s/%d-bandwidth", RUN_FIREJAIL_BANDWIDTH_DIR, (int) pid) == -1) |
215 | errExit("asprintf"); | 209 | errExit("asprintf"); |
216 | 210 | ||
217 | FILE *fp = fopen(fname, "w"); | 211 | FILE *fp = fopen(fname, "we"); |
218 | if (fp) { | 212 | if (fp) { |
219 | IFBW *ptr = ifbw; | 213 | IFBW *ptr = ifbw; |
220 | while (ptr) { | 214 | while (ptr) { |
@@ -307,7 +301,7 @@ void bandwidth_pid(pid_t pid, const char *command, const char *dev, int down, in | |||
307 | char *fname; | 301 | char *fname; |
308 | if (asprintf(&fname, "%s/%d-netmap", RUN_FIREJAIL_NETWORK_DIR, (int) pid) == -1) | 302 | if (asprintf(&fname, "%s/%d-netmap", RUN_FIREJAIL_NETWORK_DIR, (int) pid) == -1) |
309 | errExit("asprintf"); | 303 | errExit("asprintf"); |
310 | FILE *fp = fopen(fname, "r"); | 304 | FILE *fp = fopen(fname, "re"); |
311 | if (!fp) { | 305 | if (!fp) { |
312 | fprintf(stderr, "Error: cannot read network map file %s\n", fname); | 306 | fprintf(stderr, "Error: cannot read network map file %s\n", fname); |
313 | exit(1); | 307 | 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) { | |||
389 | errExit("asprintf"); | 389 | errExit("asprintf"); |
390 | 390 | ||
391 | EUID_ROOT(); // grsecurity | 391 | EUID_ROOT(); // grsecurity |
392 | FILE *fp = fopen(file, "r"); | 392 | FILE *fp = fopen(file, "re"); |
393 | EUID_USER(); // grsecurity | 393 | EUID_USER(); // grsecurity |
394 | if (!fp) | 394 | if (!fp) |
395 | goto errexit; | 395 | 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) { | |||
26 | if (cfg.cgroup == NULL) | 26 | if (cfg.cgroup == NULL) |
27 | return; | 27 | return; |
28 | 28 | ||
29 | FILE *fp = fopen(RUN_CGROUP_CFG, "w"); | 29 | FILE *fp = fopen(RUN_CGROUP_CFG, "wxe"); |
30 | if (fp) { | 30 | if (fp) { |
31 | fprintf(fp, "%s", cfg.cgroup); | 31 | fprintf(fp, "%s", cfg.cgroup); |
32 | fflush(0); | 32 | fflush(0); |
@@ -48,7 +48,7 @@ void load_cgroup(const char *fname) { | |||
48 | if (!fname) | 48 | if (!fname) |
49 | return; | 49 | return; |
50 | 50 | ||
51 | FILE *fp = fopen(fname, "r"); | 51 | FILE *fp = fopen(fname, "re"); |
52 | if (fp) { | 52 | if (fp) { |
53 | char buf[MAXBUF]; | 53 | char buf[MAXBUF]; |
54 | if (fgets(buf, MAXBUF, fp)) { | 54 | if (fgets(buf, MAXBUF, fp)) { |
@@ -91,19 +91,19 @@ void set_cgroup(const char *path) { | |||
91 | goto errout; | 91 | goto errout; |
92 | 92 | ||
93 | // tasks file exists | 93 | // tasks file exists |
94 | struct stat s; | 94 | FILE *fp = fopen(path, "ae"); |
95 | if (stat(path, &s) == -1) | 95 | if (!fp) |
96 | goto errout; | 96 | goto errout; |
97 | |||
98 | // task file belongs to the user running the sandbox | 97 | // task file belongs to the user running the sandbox |
98 | int fd = fileno(fp); | ||
99 | if (fd == -1) | ||
100 | errExit("fileno"); | ||
101 | struct stat s; | ||
102 | if (fstat(fd, &s) == -1) | ||
103 | errExit("fstat"); | ||
99 | if (s.st_uid != getuid() && s.st_gid != getgid()) | 104 | if (s.st_uid != getuid() && s.st_gid != getgid()) |
100 | goto errout2; | 105 | goto errout2; |
101 | |||
102 | // add the task to cgroup | 106 | // add the task to cgroup |
103 | /* coverity[toctou] */ | ||
104 | FILE *fp = fopen(path, "a"); | ||
105 | if (!fp) | ||
106 | goto errout; | ||
107 | pid_t pid = getpid(); | 107 | pid_t pid = getpid(); |
108 | int rv = fprintf(fp, "%d\n", pid); | 108 | int rv = fprintf(fp, "%d\n", pid); |
109 | (void) rv; | 109 | (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) { | |||
59 | 59 | ||
60 | // open configuration file | 60 | // open configuration file |
61 | const char *fname = SYSCONFDIR "/firejail.config"; | 61 | const char *fname = SYSCONFDIR "/firejail.config"; |
62 | fp = fopen(fname, "r"); | 62 | fp = fopen(fname, "re"); |
63 | if (!fp) { | 63 | if (!fp) { |
64 | #ifdef HAVE_GLOBALCFG | 64 | #ifdef HAVE_GLOBALCFG |
65 | fprintf(stderr, "Error: Firejail configuration file %s not found\n", fname); | 65 | 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) { | |||
75 | if (cfg.cpus == 0) | 75 | if (cfg.cpus == 0) |
76 | return; | 76 | return; |
77 | 77 | ||
78 | FILE *fp = fopen(RUN_CPU_CFG, "w"); | 78 | FILE *fp = fopen(RUN_CPU_CFG, "wxe"); |
79 | if (fp) { | 79 | if (fp) { |
80 | fprintf(fp, "%x\n", cfg.cpus); | 80 | fprintf(fp, "%x\n", cfg.cpus); |
81 | SET_PERMS_STREAM(fp, 0, 0, 0600); | 81 | SET_PERMS_STREAM(fp, 0, 0, 0600); |
@@ -91,7 +91,7 @@ void load_cpu(const char *fname) { | |||
91 | if (!fname) | 91 | if (!fname) |
92 | return; | 92 | return; |
93 | 93 | ||
94 | FILE *fp = fopen(fname, "r"); | 94 | FILE *fp = fopen(fname, "re"); |
95 | if (fp) { | 95 | if (fp) { |
96 | unsigned tmp; | 96 | unsigned tmp; |
97 | int rv = fscanf(fp, "%x", &tmp); | 97 | int rv = fscanf(fp, "%x", &tmp); |
@@ -139,7 +139,7 @@ static void print_cpu(int pid) { | |||
139 | } | 139 | } |
140 | 140 | ||
141 | EUID_ROOT(); // grsecurity | 141 | EUID_ROOT(); // grsecurity |
142 | FILE *fp = fopen(file, "r"); | 142 | FILE *fp = fopen(file, "re"); |
143 | EUID_USER(); // grsecurity | 143 | EUID_USER(); // grsecurity |
144 | if (!fp) { | 144 | if (!fp) { |
145 | printf(" Error: cannot open %s\n", file); | 145 | 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) { | |||
93 | while (found == 0 && tries < 10) { | 93 | while (found == 0 && tries < 10) { |
94 | if (tries >= 1) | 94 | if (tries >= 1) |
95 | usleep(100000); | 95 | usleep(100000); |
96 | FILE *pidfile = fopen(client->pid_file, "r"); | 96 | FILE *pidfile = fopen(client->pid_file, "re"); |
97 | if (pidfile) { | 97 | if (pidfile) { |
98 | long pid; | 98 | long pid; |
99 | if (fscanf(pidfile, "%ld", &pid) == 1) | 99 | 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) { | |||
59 | if (asprintf(&dirname, "%s/.config/ibus/bus", cfg.homedir) == -1) | 59 | if (asprintf(&dirname, "%s/.config/ibus/bus", cfg.homedir) == -1) |
60 | errExit("asprintf"); | 60 | errExit("asprintf"); |
61 | 61 | ||
62 | struct stat s; | ||
63 | if (stat(dirname, &s) == -1) | ||
64 | return; | ||
65 | |||
66 | // find the file | 62 | // find the file |
67 | /* coverity[toctou] */ | ||
68 | DIR *dir = opendir(dirname); | 63 | DIR *dir = opendir(dirname); |
69 | if (!dir) { | 64 | if (!dir) { |
70 | free(dirname); | 65 | free(dirname); |
@@ -84,7 +79,7 @@ void env_ibus_load(void) { | |||
84 | char *fname; | 79 | char *fname; |
85 | if (asprintf(&fname, "%s/%s", dirname, entry->d_name) == -1) | 80 | if (asprintf(&fname, "%s/%s", dirname, entry->d_name) == -1) |
86 | errExit("asprintf"); | 81 | errExit("asprintf"); |
87 | FILE *fp = fopen(fname, "r"); | 82 | FILE *fp = fopen(fname, "re"); |
88 | free(fname); | 83 | free(fname); |
89 | if (!fp) | 84 | if (!fp) |
90 | continue; | 85 | 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) { | |||
122 | i++; | 122 | i++; |
123 | continue; | 123 | continue; |
124 | } | 124 | } |
125 | FILE *fp = fopen(dev[i].dev_fname, "w"); | 125 | FILE *fp = fopen(dev[i].dev_fname, "we"); |
126 | if (fp) { | 126 | if (fp) { |
127 | fprintf(fp, "\n"); | 127 | fprintf(fp, "\n"); |
128 | SET_PERMS_STREAM(fp, s.st_uid, s.st_gid, s.st_mode); | 128 | SET_PERMS_STREAM(fp, s.st_uid, s.st_gid, s.st_mode); |
@@ -218,7 +218,7 @@ void fs_private_dev(void){ | |||
218 | struct stat s; | 218 | struct stat s; |
219 | if (stat("/dev/log", &s) == 0) { | 219 | if (stat("/dev/log", &s) == 0) { |
220 | have_devlog = 1; | 220 | have_devlog = 1; |
221 | FILE *fp = fopen(RUN_DEVLOG_FILE, "w"); | 221 | FILE *fp = fopen(RUN_DEVLOG_FILE, "we"); |
222 | if (!fp) | 222 | if (!fp) |
223 | have_devlog = 0; | 223 | have_devlog = 0; |
224 | else { | 224 | else { |
@@ -239,7 +239,7 @@ void fs_private_dev(void){ | |||
239 | 239 | ||
240 | // bring back /dev/log | 240 | // bring back /dev/log |
241 | if (have_devlog) { | 241 | if (have_devlog) { |
242 | FILE *fp = fopen("/dev/log", "w"); | 242 | FILE *fp = fopen("/dev/log", "we"); |
243 | if (fp) { | 243 | if (fp) { |
244 | fprintf(fp, "\n"); | 244 | fprintf(fp, "\n"); |
245 | fclose(fp); | 245 | 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) { | |||
52 | mid.u8[8] = (mid.u8[8] & 0x3F) | 0x80; | 52 | mid.u8[8] = (mid.u8[8] & 0x3F) | 0x80; |
53 | 53 | ||
54 | // write it in a file | 54 | // write it in a file |
55 | FILE *fp = fopen(RUN_MACHINEID, "w"); | 55 | FILE *fp = fopen(RUN_MACHINEID, "we"); |
56 | if (!fp) | 56 | if (!fp) |
57 | errExit("fopen"); | 57 | errExit("fopen"); |
58 | fprintf(fp, "%08x%08x%08x%08x\n", mid.u32[0], mid.u32[1], mid.u32[2], mid.u32[3]); | 58 | 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) { | |||
130 | } | 130 | } |
131 | 131 | ||
132 | // create an empty file as root, and change ownership to user | 132 | // create an empty file as root, and change ownership to user |
133 | FILE *fp = fopen(dest, "w"); | 133 | FILE *fp = fopen(dest, "we"); |
134 | if (fp) { | 134 | if (fp) { |
135 | fprintf(fp, "\n"); | 135 | fprintf(fp, "\n"); |
136 | SET_PERMS_STREAM(fp, getuid(), getgid(), 0600); | 136 | SET_PERMS_STREAM(fp, getuid(), getgid(), 0600); |
@@ -178,7 +178,7 @@ static int store_asoundrc(void) { | |||
178 | } | 178 | } |
179 | 179 | ||
180 | // create an empty file as root, and change ownership to user | 180 | // create an empty file as root, and change ownership to user |
181 | FILE *fp = fopen(dest, "w"); | 181 | FILE *fp = fopen(dest, "we"); |
182 | if (fp) { | 182 | if (fp) { |
183 | fprintf(fp, "\n"); | 183 | fprintf(fp, "\n"); |
184 | SET_PERMS_STREAM(fp, getuid(), getgid(), 0644); | 184 | 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) { | |||
47 | printf("Creating a new /etc/hosts file\n"); | 47 | printf("Creating a new /etc/hosts file\n"); |
48 | // copy /etc/host into our new file, and modify it on the fly | 48 | // copy /etc/host into our new file, and modify it on the fly |
49 | /* coverity[toctou] */ | 49 | /* coverity[toctou] */ |
50 | FILE *fp1 = fopen("/etc/hosts", "r"); | 50 | FILE *fp1 = fopen("/etc/hosts", "re"); |
51 | if (!fp1) | 51 | if (!fp1) |
52 | goto errexit; | 52 | goto errexit; |
53 | 53 | ||
54 | FILE *fp2 = fopen(RUN_HOSTS_FILE, "w"); | 54 | FILE *fp2 = fopen(RUN_HOSTS_FILE, "we"); |
55 | if (!fp2) { | 55 | if (!fp2) { |
56 | fclose(fp1); | 56 | fclose(fp1); |
57 | goto errexit; | 57 | goto errexit; |
@@ -165,7 +165,7 @@ void fs_resolvconf(void) { | |||
165 | 165 | ||
166 | if (arg_debug) | 166 | if (arg_debug) |
167 | printf("Creating a new /etc/resolv.conf file\n"); | 167 | printf("Creating a new /etc/resolv.conf file\n"); |
168 | FILE *fp = fopen("/etc/resolv.conf", "w"); | 168 | FILE *fp = fopen("/etc/resolv.conf", "wxe"); |
169 | if (!fp) { | 169 | if (!fp) { |
170 | fprintf(stderr, "Error: cannot create /etc/resolv.conf file\n"); | 170 | fprintf(stderr, "Error: cannot create /etc/resolv.conf file\n"); |
171 | exit(1); | 171 | 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) { | |||
221 | sbox_run(mask | SBOX_SECCOMP | SBOX_CAPS_NONE, 3, PATH_FLDD, full_path, RUN_LIB_FILE); | 221 | sbox_run(mask | SBOX_SECCOMP | SBOX_CAPS_NONE, 3, PATH_FLDD, full_path, RUN_LIB_FILE); |
222 | 222 | ||
223 | // open the list of libraries and install them on by one | 223 | // open the list of libraries and install them on by one |
224 | FILE *fp = fopen(RUN_LIB_FILE, "r"); | 224 | FILE *fp = fopen(RUN_LIB_FILE, "re"); |
225 | if (!fp) | 225 | if (!fp) |
226 | errExit("fopen"); | 226 | errExit("fopen"); |
227 | 227 | ||
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) { | |||
92 | if (!head) | 92 | if (!head) |
93 | return; | 93 | return; |
94 | 94 | ||
95 | FILE *fp = fopen(RUN_FSLOGGER_FILE, "a"); | 95 | FILE *fp = fopen(RUN_FSLOGGER_FILE, "ae"); |
96 | if (!fp) { | 96 | if (!fp) { |
97 | perror("fopen"); | 97 | perror("fopen"); |
98 | return; | 98 | return; |
@@ -123,15 +123,8 @@ void fs_logger_print_log(pid_t pid) { | |||
123 | // in case the pid is that of a firejail process, use the pid of the first child process | 123 | // in case the pid is that of a firejail process, use the pid of the first child process |
124 | pid = switch_to_child(pid); | 124 | pid = switch_to_child(pid); |
125 | 125 | ||
126 | // check privileges for non-root users | 126 | // exit if no permission to join the sandbox |
127 | uid_t uid = getuid(); | 127 | check_join_permission(pid); |
128 | if (uid != 0) { | ||
129 | uid_t sandbox_uid = pid_get_uid(pid); | ||
130 | if (uid != sandbox_uid) { | ||
131 | fprintf(stderr, "Error: permission denied\n"); | ||
132 | exit(1); | ||
133 | } | ||
134 | } | ||
135 | 128 | ||
136 | // print RUN_FSLOGGER_FILE | 129 | // print RUN_FSLOGGER_FILE |
137 | char *fname; | 130 | char *fname; |
@@ -139,24 +132,16 @@ void fs_logger_print_log(pid_t pid) { | |||
139 | errExit("asprintf"); | 132 | errExit("asprintf"); |
140 | 133 | ||
141 | EUID_ROOT(); | 134 | EUID_ROOT(); |
142 | struct stat s; | 135 | FILE *fp = fopen(fname, "re"); |
143 | if (stat(fname, &s) == -1 || s.st_uid != 0) { | 136 | free(fname); |
144 | fprintf(stderr, "Error: Cannot access filesystem log\n"); | ||
145 | exit(1); | ||
146 | } | ||
147 | |||
148 | /* coverity[toctou] */ | ||
149 | FILE *fp = fopen(fname, "r"); | ||
150 | if (!fp) { | 137 | if (!fp) { |
151 | fprintf(stderr, "Error: Cannot open filesystem log\n"); | 138 | fprintf(stderr, "Error: Cannot open filesystem log\n"); |
152 | exit(1); | 139 | exit(1); |
153 | } | 140 | } |
154 | |||
155 | char buf[MAXBUF]; | 141 | char buf[MAXBUF]; |
156 | while (fgets(buf, MAXBUF, fp)) | 142 | while (fgets(buf, MAXBUF, fp)) |
157 | printf("%s", buf); | 143 | printf("%s", buf); |
158 | fclose(fp); | 144 | fclose(fp); |
159 | free(fname); | ||
160 | 145 | ||
161 | exit(0); | 146 | exit(0); |
162 | } | 147 | } |
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) { | |||
33 | if (stat("/etc/ld.so.preload", &s)) { | 33 | if (stat("/etc/ld.so.preload", &s)) { |
34 | if (arg_debug) | 34 | if (arg_debug) |
35 | printf("Creating an empty /etc/ld.so.preload file\n"); | 35 | printf("Creating an empty /etc/ld.so.preload file\n"); |
36 | /* coverity[toctou] */ | 36 | FILE *fp = fopen("/etc/ld.so.preload", "wxe"); |
37 | FILE *fp = fopen("/etc/ld.so.preload", "w"); | ||
38 | if (!fp) | 37 | if (!fp) |
39 | errExit("fopen"); | 38 | errExit("fopen"); |
40 | SET_PERMS_STREAM(fp, 0, 0, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH); | 39 | SET_PERMS_STREAM(fp, 0, 0, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH); |
@@ -64,11 +63,11 @@ void fs_tracefile(void) { | |||
64 | if (ftruncate(fd, 0) == -1) | 63 | if (ftruncate(fd, 0) == -1) |
65 | errExit("ftruncate"); | 64 | errExit("ftruncate"); |
66 | EUID_ROOT(); | 65 | EUID_ROOT(); |
67 | FILE *fp = fopen(RUN_TRACE_FILE, "w"); | 66 | FILE *fp = fopen(RUN_TRACE_FILE, "we"); |
68 | if (!fp) | 67 | if (!fp) |
69 | errExit("fopen " RUN_TRACE_FILE); | 68 | errExit("fopen " RUN_TRACE_FILE); |
70 | fclose(fp); | 69 | fclose(fp); |
71 | fs_logger2("touch ", arg_tracefile); | 70 | fs_logger2("touch", arg_tracefile); |
72 | // mount using the symbolic link in /proc/self/fd | 71 | // mount using the symbolic link in /proc/self/fd |
73 | if (arg_debug) | 72 | if (arg_debug) |
74 | printf("Bind mount %s to %s\n", arg_tracefile, RUN_TRACE_FILE); | 73 | printf("Bind mount %s to %s\n", arg_tracefile, RUN_TRACE_FILE); |
@@ -88,7 +87,7 @@ void fs_trace(void) { | |||
88 | if (arg_debug) | 87 | if (arg_debug) |
89 | printf("Create the new ld.so.preload file\n"); | 88 | printf("Create the new ld.so.preload file\n"); |
90 | 89 | ||
91 | FILE *fp = fopen(RUN_LDPRELOAD_FILE, "w"); | 90 | FILE *fp = fopen(RUN_LDPRELOAD_FILE, "we"); |
92 | if (!fp) | 91 | if (!fp) |
93 | errExit("fopen"); | 92 | errExit("fopen"); |
94 | const char *prefix = RUN_FIREJAIL_LIB_DIR; | 93 | 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) { | |||
127 | 127 | ||
128 | // create an empty /var/log/wtmp file | 128 | // create an empty /var/log/wtmp file |
129 | /* coverity[toctou] */ | 129 | /* coverity[toctou] */ |
130 | FILE *fp = fopen("/var/log/wtmp", "w"); | 130 | FILE *fp = fopen("/var/log/wtmp", "wxe"); |
131 | if (fp) { | 131 | if (fp) { |
132 | SET_PERMS_STREAM(fp, 0, wtmp_group, S_IRUSR | S_IWRITE | S_IRGRP | S_IWGRP | S_IROTH); | 132 | SET_PERMS_STREAM(fp, 0, wtmp_group, S_IRUSR | S_IWRITE | S_IRGRP | S_IWGRP | S_IROTH); |
133 | fclose(fp); | 133 | fclose(fp); |
@@ -135,7 +135,7 @@ void fs_var_log(void) { | |||
135 | fs_logger("touch /var/log/wtmp"); | 135 | fs_logger("touch /var/log/wtmp"); |
136 | 136 | ||
137 | // create an empty /var/log/btmp file | 137 | // create an empty /var/log/btmp file |
138 | fp = fopen("/var/log/btmp", "w"); | 138 | fp = fopen("/var/log/btmp", "wxe"); |
139 | if (fp) { | 139 | if (fp) { |
140 | SET_PERMS_STREAM(fp, 0, wtmp_group, S_IRUSR | S_IWRITE | S_IRGRP | S_IWGRP); | 140 | SET_PERMS_STREAM(fp, 0, wtmp_group, S_IRUSR | S_IWRITE | S_IRGRP | S_IWGRP); |
141 | fclose(fp); | 141 | fclose(fp); |
@@ -158,8 +158,7 @@ void fs_var_lib(void) { | |||
158 | fs_logger("tmpfs /var/lib/dhcp"); | 158 | fs_logger("tmpfs /var/lib/dhcp"); |
159 | 159 | ||
160 | // isc dhcp server requires a /var/lib/dhcp/dhcpd.leases file | 160 | // isc dhcp server requires a /var/lib/dhcp/dhcpd.leases file |
161 | FILE *fp = fopen("/var/lib/dhcp/dhcpd.leases", "w"); | 161 | FILE *fp = fopen("/var/lib/dhcp/dhcpd.leases", "wxe"); |
162 | |||
163 | if (fp) { | 162 | if (fp) { |
164 | fprintf(fp, "\n"); | 163 | fprintf(fp, "\n"); |
165 | SET_PERMS_STREAM(fp, 0, 0, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); | 164 | SET_PERMS_STREAM(fp, 0, 0, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); |
@@ -296,7 +295,7 @@ void fs_var_utmp(void) { | |||
296 | printf("Create the new utmp file\n"); | 295 | printf("Create the new utmp file\n"); |
297 | 296 | ||
298 | /* coverity[toctou] */ | 297 | /* coverity[toctou] */ |
299 | FILE *fp = fopen(RUN_UTMP_FILE, "w"); | 298 | FILE *fp = fopen(RUN_UTMP_FILE, "wxe"); |
300 | if (!fp) | 299 | if (!fp) |
301 | errExit("fopen"); | 300 | errExit("fopen"); |
302 | 301 | ||
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) { | |||
103 | if (asprintf(&fname, "%s/%d", RUN_FIREJAIL_X11_DIR, pid) == -1) | 103 | if (asprintf(&fname, "%s/%d", RUN_FIREJAIL_X11_DIR, pid) == -1) |
104 | errExit("asprintf"); | 104 | errExit("asprintf"); |
105 | 105 | ||
106 | FILE *fp = fopen(fname, "r"); | 106 | FILE *fp = fopen(fname, "re"); |
107 | free(fname); | 107 | free(fname); |
108 | if (!fp) | 108 | if (!fp) |
109 | return; | 109 | return; |
@@ -219,7 +219,7 @@ static void extract_caps(pid_t pid) { | |||
219 | perror("asprintf"); | 219 | perror("asprintf"); |
220 | exit(1); | 220 | exit(1); |
221 | } | 221 | } |
222 | FILE *fp = fopen(file, "r"); | 222 | FILE *fp = fopen(file, "re"); |
223 | if (!fp) | 223 | if (!fp) |
224 | goto errexit; | 224 | goto errexit; |
225 | 225 | ||
@@ -266,7 +266,7 @@ static void extract_user_namespace(pid_t pid) { | |||
266 | char *uidmap; | 266 | char *uidmap; |
267 | if (asprintf(&uidmap, "/proc/%u/uid_map", pid) == -1) | 267 | if (asprintf(&uidmap, "/proc/%u/uid_map", pid) == -1) |
268 | errExit("asprintf"); | 268 | errExit("asprintf"); |
269 | FILE *fp = fopen(uidmap, "r"); | 269 | FILE *fp = fopen(uidmap, "re"); |
270 | if (!fp) { | 270 | if (!fp) { |
271 | free(uidmap); | 271 | free(uidmap); |
272 | return; | 272 | 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) { | |||
221 | 221 | ||
222 | if (arg_debug) | 222 | if (arg_debug) |
223 | printf("cat %s\n", path); | 223 | printf("cat %s\n", path); |
224 | FILE *fp = fopen(path, "r"); | 224 | FILE *fp = fopen(path, "re"); |
225 | if (!fp) { | 225 | if (!fp) { |
226 | fprintf(stderr, "Error: cannot read %s\n", path); | 226 | fprintf(stderr, "Error: cannot read %s\n", path); |
227 | exit(1); | 227 | 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) { | |||
99 | 99 | ||
100 | if (asprintf(&fname, "%s/.config/user-dirs.dirs", cfg.homedir) == -1) | 100 | if (asprintf(&fname, "%s/.config/user-dirs.dirs", cfg.homedir) == -1) |
101 | errExit("asprintf"); | 101 | errExit("asprintf"); |
102 | FILE *fp = fopen(fname, "r"); | 102 | FILE *fp = fopen(fname, "re"); |
103 | if (!fp) { | 103 | if (!fp) { |
104 | free(fname); | 104 | free(fname); |
105 | return NULL; | 105 | 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) { | |||
535 | char *fname; | 535 | char *fname; |
536 | if (asprintf(&fname, RUN_FIREJAIL_PROFILE_DIR "/%d", pid) == -1) | 536 | if (asprintf(&fname, RUN_FIREJAIL_PROFILE_DIR "/%d", pid) == -1) |
537 | errExit("asprintf"); | 537 | errExit("asprintf"); |
538 | FILE *fp = fopen(fname, "r"); | 538 | FILE *fp = fopen(fname, "re"); |
539 | if (!fp) { | 539 | if (!fp) { |
540 | fprintf(stderr, "Error: sandbox %s not found\n", argv[i] + 16); | 540 | fprintf(stderr, "Error: sandbox %s not found\n", argv[i] + 16); |
541 | exit(1); | 541 | exit(1); |
@@ -1043,7 +1043,7 @@ int main(int argc, char **argv, char **envp) { | |||
1043 | preproc_build_firejail_dir(); | 1043 | preproc_build_firejail_dir(); |
1044 | const char *container_name = env_get("container"); | 1044 | const char *container_name = env_get("container"); |
1045 | if (!container_name || strcmp(container_name, "firejail")) { | 1045 | if (!container_name || strcmp(container_name, "firejail")) { |
1046 | lockfd_directory = open(RUN_DIRECTORY_LOCK_FILE, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); | 1046 | lockfd_directory = open(RUN_DIRECTORY_LOCK_FILE, O_WRONLY | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR); |
1047 | if (lockfd_directory != -1) { | 1047 | if (lockfd_directory != -1) { |
1048 | int rv = fchown(lockfd_directory, 0, 0); | 1048 | int rv = fchown(lockfd_directory, 0, 0); |
1049 | (void) rv; | 1049 | (void) rv; |
@@ -1145,7 +1145,7 @@ int main(int argc, char **argv, char **envp) { | |||
1145 | 1145 | ||
1146 | #ifdef DEBUG_RESTRICTED_SHELL | 1146 | #ifdef DEBUG_RESTRICTED_SHELL |
1147 | {EUID_ROOT(); | 1147 | {EUID_ROOT(); |
1148 | FILE *fp = fopen("/firelog", "w"); | 1148 | FILE *fp = fopen("/firelog", "we"); |
1149 | if (fp) { | 1149 | if (fp) { |
1150 | int i; | 1150 | int i; |
1151 | fprintf(fp, "argc %d: ", argc); | 1151 | fprintf(fp, "argc %d: ", argc); |
@@ -1164,7 +1164,7 @@ int main(int argc, char **argv, char **envp) { | |||
1164 | strncmp(argv[2], "scp ", 4) == 0) { | 1164 | strncmp(argv[2], "scp ", 4) == 0) { |
1165 | #ifdef DEBUG_RESTRICTED_SHELL | 1165 | #ifdef DEBUG_RESTRICTED_SHELL |
1166 | {EUID_ROOT(); | 1166 | {EUID_ROOT(); |
1167 | FILE *fp = fopen("/firelog", "a"); | 1167 | FILE *fp = fopen("/firelog", "ae"); |
1168 | if (fp) { | 1168 | if (fp) { |
1169 | fprintf(fp, "run without a sandbox\n"); | 1169 | fprintf(fp, "run without a sandbox\n"); |
1170 | fclose(fp); | 1170 | fclose(fp); |
@@ -1197,7 +1197,7 @@ int main(int argc, char **argv, char **envp) { | |||
1197 | 1197 | ||
1198 | #ifdef DEBUG_RESTRICTED_SHELL | 1198 | #ifdef DEBUG_RESTRICTED_SHELL |
1199 | {EUID_ROOT(); | 1199 | {EUID_ROOT(); |
1200 | FILE *fp = fopen("/firelog", "a"); | 1200 | FILE *fp = fopen("/firelog", "ae"); |
1201 | if (fp) { | 1201 | if (fp) { |
1202 | fprintf(fp, "fullargc %d: ", fullargc); | 1202 | fprintf(fp, "fullargc %d: ", fullargc); |
1203 | int i; | 1203 | int i; |
@@ -1219,7 +1219,7 @@ int main(int argc, char **argv, char **envp) { | |||
1219 | 1219 | ||
1220 | #ifdef DEBUG_RESTRICTED_SHELL | 1220 | #ifdef DEBUG_RESTRICTED_SHELL |
1221 | {EUID_ROOT(); | 1221 | {EUID_ROOT(); |
1222 | FILE *fp = fopen("/firelog", "a"); | 1222 | FILE *fp = fopen("/firelog", "ae"); |
1223 | if (fp) { | 1223 | if (fp) { |
1224 | fprintf(fp, "argc %d: ", argc); | 1224 | fprintf(fp, "argc %d: ", argc); |
1225 | int i; | 1225 | int i; |
@@ -2852,7 +2852,7 @@ int main(int argc, char **argv, char **envp) { | |||
2852 | // check and assign an IP address - for macvlan it will be done again in the sandbox! | 2852 | // check and assign an IP address - for macvlan it will be done again in the sandbox! |
2853 | if (any_bridge_configured()) { | 2853 | if (any_bridge_configured()) { |
2854 | EUID_ROOT(); | 2854 | EUID_ROOT(); |
2855 | lockfd_network = open(RUN_NETWORK_LOCK_FILE, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); | 2855 | lockfd_network = open(RUN_NETWORK_LOCK_FILE, O_WRONLY | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR); |
2856 | if (lockfd_network != -1) { | 2856 | if (lockfd_network != -1) { |
2857 | int rv = fchown(lockfd_network, 0, 0); | 2857 | int rv = fchown(lockfd_network, 0, 0); |
2858 | (void) rv; | 2858 | (void) rv; |
@@ -2892,7 +2892,7 @@ int main(int argc, char **argv, char **envp) { | |||
2892 | 2892 | ||
2893 | // set name and x11 run files | 2893 | // set name and x11 run files |
2894 | EUID_ROOT(); | 2894 | EUID_ROOT(); |
2895 | lockfd_directory = open(RUN_DIRECTORY_LOCK_FILE, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); | 2895 | lockfd_directory = open(RUN_DIRECTORY_LOCK_FILE, O_WRONLY | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR); |
2896 | if (lockfd_directory != -1) { | 2896 | if (lockfd_directory != -1) { |
2897 | int rv = fchown(lockfd_directory, 0, 0); | 2897 | int rv = fchown(lockfd_directory, 0, 0); |
2898 | (void) rv; | 2898 | (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) { | |||
217 | 217 | ||
218 | #define BUFSIZE 1024 | 218 | #define BUFSIZE 1024 |
219 | uint32_t network_get_defaultgw(void) { | 219 | uint32_t network_get_defaultgw(void) { |
220 | FILE *fp = fopen("/proc/self/net/route", "r"); | 220 | FILE *fp = fopen("/proc/self/net/route", "re"); |
221 | if (!fp) | 221 | if (!fp) |
222 | errExit("fopen"); | 222 | errExit("fopen"); |
223 | 223 | ||
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) { | |||
292 | errExit("chdir"); | 292 | errExit("chdir"); |
293 | 293 | ||
294 | // access /etc/resolv.conf | 294 | // access /etc/resolv.conf |
295 | FILE *fp = fopen("/etc/resolv.conf", "r"); | 295 | FILE *fp = fopen("/etc/resolv.conf", "re"); |
296 | if (!fp) { | 296 | if (!fp) { |
297 | fprintf(stderr, "Error: cannot access /etc/resolv.conf\n"); | 297 | fprintf(stderr, "Error: cannot access /etc/resolv.conf\n"); |
298 | exit(1); | 298 | 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 @@ | |||
20 | #include "firejail.h" | 20 | #include "firejail.h" |
21 | #include <sys/types.h> | 21 | #include <sys/types.h> |
22 | #include <sys/stat.h> | 22 | #include <sys/stat.h> |
23 | #include <errno.h> | ||
23 | #include <unistd.h> | 24 | #include <unistd.h> |
24 | #include <grp.h> | 25 | #include <grp.h> |
25 | 26 | ||
@@ -47,7 +48,7 @@ int check_namespace_virt(void) { | |||
47 | 48 | ||
48 | // check PID 1 container environment variable | 49 | // check PID 1 container environment variable |
49 | EUID_ROOT(); | 50 | EUID_ROOT(); |
50 | FILE *fp = fopen("/proc/1/environ", "r"); | 51 | FILE *fp = fopen("/proc/1/environ", "re"); |
51 | if (fp) { | 52 | if (fp) { |
52 | int c = 0; | 53 | int c = 0; |
53 | while (c != EOF) { | 54 | while (c != EOF) { |
@@ -105,20 +106,15 @@ int check_kernel_procs(void) { | |||
105 | // look at the first 10 processes | 106 | // look at the first 10 processes |
106 | // if a kernel process is found, return 1 | 107 | // if a kernel process is found, return 1 |
107 | for (i = 1; i <= 10; i++) { | 108 | for (i = 1; i <= 10; i++) { |
108 | struct stat s; | ||
109 | char *fname; | 109 | char *fname; |
110 | if (asprintf(&fname, "/proc/%d/comm", i) == -1) | 110 | if (asprintf(&fname, "/proc/%d/comm", i) == -1) |
111 | errExit("asprintf"); | 111 | errExit("asprintf"); |
112 | if (stat(fname, &s) == -1) { | ||
113 | free(fname); | ||
114 | continue; | ||
115 | } | ||
116 | 112 | ||
117 | // open file | 113 | // open file |
118 | /* coverity[toctou] */ | 114 | FILE *fp = fopen(fname, "re"); |
119 | FILE *fp = fopen(fname, "r"); | ||
120 | if (!fp) { | 115 | if (!fp) { |
121 | fwarning("cannot open %s\n", fname); | 116 | if (errno != ENOENT) |
117 | fwarning("cannot open %s\n", fname); | ||
122 | free(fname); | 118 | free(fname); |
123 | continue; | 119 | continue; |
124 | } | 120 | } |
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) { | |||
164 | int max_pids=32769; | 164 | int max_pids=32769; |
165 | int start_pid = 100; | 165 | int start_pid = 100; |
166 | // extract real max_pids | 166 | // extract real max_pids |
167 | FILE *fp = fopen("/proc/sys/kernel/pid_max", "r"); | 167 | FILE *fp = fopen("/proc/sys/kernel/pid_max", "re"); |
168 | if (fp) { | 168 | if (fp) { |
169 | int val; | 169 | int val; |
170 | if (fscanf(fp, "%d", &val) == 1) { | 170 | 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) { | |||
1691 | } | 1691 | } |
1692 | 1692 | ||
1693 | // open profile file: | 1693 | // open profile file: |
1694 | FILE *fp = fopen(fname, "r"); | 1694 | FILE *fp = fopen(fname, "re"); |
1695 | if (fp == NULL) { | 1695 | if (fp == NULL) { |
1696 | fprintf(stderr, "Error: cannot open profile file %s\n", fname); | 1696 | fprintf(stderr, "Error: cannot open profile file %s\n", fname); |
1697 | exit(1); | 1697 | 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 @@ | |||
23 | 23 | ||
24 | void protocol_filter_save(void) { | 24 | void protocol_filter_save(void) { |
25 | // save protocol filter configuration in PROTOCOL_CFG | 25 | // save protocol filter configuration in PROTOCOL_CFG |
26 | FILE *fp = fopen(RUN_PROTOCOL_CFG, "w"); | 26 | FILE *fp = fopen(RUN_PROTOCOL_CFG, "wxe"); |
27 | if (!fp) | 27 | if (!fp) |
28 | errExit("fopen"); | 28 | errExit("fopen"); |
29 | fprintf(fp, "%s\n", cfg.protocol); | 29 | fprintf(fp, "%s\n", cfg.protocol); |
@@ -35,7 +35,7 @@ void protocol_filter_load(const char *fname) { | |||
35 | assert(fname); | 35 | assert(fname); |
36 | 36 | ||
37 | // read protocol filter configuration from PROTOCOL_CFG | 37 | // read protocol filter configuration from PROTOCOL_CFG |
38 | FILE *fp = fopen(fname, "r"); | 38 | FILE *fp = fopen(fname, "re"); |
39 | if (!fp) | 39 | if (!fp) |
40 | return; | 40 | return; |
41 | 41 | ||
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) { | |||
106 | errExit("asprintf"); | 106 | errExit("asprintf"); |
107 | if (copy_file(PULSE_CLIENT_SYSCONF, pulsecfg, -1, -1, 0644)) // root needed | 107 | if (copy_file(PULSE_CLIENT_SYSCONF, pulsecfg, -1, -1, 0644)) // root needed |
108 | errExit("copy_file"); | 108 | errExit("copy_file"); |
109 | FILE *fp = fopen(pulsecfg, "a"); | 109 | FILE *fp = fopen(pulsecfg, "ae"); |
110 | if (!fp) | 110 | if (!fp) |
111 | errExit("fopen"); | 111 | errExit("fopen"); |
112 | fprintf(fp, "%s", "\nenable-shm = no\n"); | 112 | 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) { | |||
183 | 183 | ||
184 | // open files | 184 | // open files |
185 | /* coverity[toctou] */ | 185 | /* coverity[toctou] */ |
186 | fpin = fopen("/etc/passwd", "r"); | 186 | fpin = fopen("/etc/passwd", "re"); |
187 | if (!fpin) | 187 | if (!fpin) |
188 | goto errout; | 188 | goto errout; |
189 | fpout = fopen(RUN_PASSWD_FILE, "w"); | 189 | fpout = fopen(RUN_PASSWD_FILE, "we"); |
190 | if (!fpout) | 190 | if (!fpout) |
191 | goto errout; | 191 | goto errout; |
192 | 192 | ||
@@ -318,10 +318,10 @@ static void sanitize_group(void) { | |||
318 | 318 | ||
319 | // open files | 319 | // open files |
320 | /* coverity[toctou] */ | 320 | /* coverity[toctou] */ |
321 | fpin = fopen("/etc/group", "r"); | 321 | fpin = fopen("/etc/group", "re"); |
322 | if (!fpin) | 322 | if (!fpin) |
323 | goto errout; | 323 | goto errout; |
324 | fpout = fopen(RUN_GROUP_FILE, "w"); | 324 | fpout = fopen(RUN_GROUP_FILE, "we"); |
325 | if (!fpout) | 325 | if (!fpout) |
326 | goto errout; | 326 | goto errout; |
327 | 327 | ||
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) { | |||
32 | char *fname; | 32 | char *fname; |
33 | if (asprintf(&fname, "%s/login.users", SYSCONFDIR) == -1) | 33 | if (asprintf(&fname, "%s/login.users", SYSCONFDIR) == -1) |
34 | errExit("asprintf"); | 34 | errExit("asprintf"); |
35 | FILE *fp = fopen(fname, "r"); | 35 | FILE *fp = fopen(fname, "re"); |
36 | free(fname); | 36 | free(fname); |
37 | if (fp == NULL) | 37 | if (fp == NULL) |
38 | return 0; | 38 | return 0; |
@@ -96,7 +96,7 @@ int restricted_shell(const char *user) { | |||
96 | fullargv[i] = ptr; | 96 | fullargv[i] = ptr; |
97 | #ifdef DEBUG_RESTRICTED_SHELL | 97 | #ifdef DEBUG_RESTRICTED_SHELL |
98 | {EUID_ROOT(); | 98 | {EUID_ROOT(); |
99 | FILE *fp = fopen("/firelog", "a"); | 99 | FILE *fp = fopen("/firelog", "ae"); |
100 | if (fp) { | 100 | if (fp) { |
101 | fprintf(fp, "i %d ptr #%s#\n", i, fullargv[i]); | 101 | fprintf(fp, "i %d ptr #%s#\n", i, fullargv[i]); |
102 | fclose(fp); | 102 | 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) { | |||
101 | errExit("asprintf"); | 101 | errExit("asprintf"); |
102 | 102 | ||
103 | // the file is deleted first | 103 | // the file is deleted first |
104 | FILE *fp = fopen(fname, "w"); | 104 | FILE *fp = fopen(fname, "we"); |
105 | if (!fp) { | 105 | if (!fp) { |
106 | fprintf(stderr, "Error: cannot create %s\n", fname); | 106 | fprintf(stderr, "Error: cannot create %s\n", fname); |
107 | exit(1); | 107 | exit(1); |
@@ -120,7 +120,7 @@ void set_x11_run_file(pid_t pid, int display) { | |||
120 | errExit("asprintf"); | 120 | errExit("asprintf"); |
121 | 121 | ||
122 | // the file is deleted first | 122 | // the file is deleted first |
123 | FILE *fp = fopen(fname, "w"); | 123 | FILE *fp = fopen(fname, "we"); |
124 | if (!fp) { | 124 | if (!fp) { |
125 | fprintf(stderr, "Error: cannot create %s\n", fname); | 125 | fprintf(stderr, "Error: cannot create %s\n", fname); |
126 | exit(1); | 126 | exit(1); |
@@ -139,7 +139,7 @@ void set_profile_run_file(pid_t pid, const char *fname) { | |||
139 | 139 | ||
140 | EUID_ROOT(); | 140 | EUID_ROOT(); |
141 | // the file is deleted first | 141 | // the file is deleted first |
142 | FILE *fp = fopen(runfile, "w"); | 142 | FILE *fp = fopen(runfile, "we"); |
143 | if (!fp) { | 143 | if (!fp) { |
144 | fprintf(stderr, "Error: cannot create %s\n", runfile); | 144 | fprintf(stderr, "Error: cannot create %s\n", runfile); |
145 | exit(1); | 145 | 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){ | |||
67 | if (asprintf(&monfile, "/proc/%d/cmdline", monitored_pid) == -1) | 67 | if (asprintf(&monfile, "/proc/%d/cmdline", monitored_pid) == -1) |
68 | errExit("asprintf"); | 68 | errExit("asprintf"); |
69 | while (monsec) { | 69 | while (monsec) { |
70 | FILE *fp = fopen(monfile, "r"); | 70 | FILE *fp = fopen(monfile, "re"); |
71 | if (!fp) | 71 | if (!fp) |
72 | break; | 72 | break; |
73 | 73 | ||
@@ -162,7 +162,7 @@ static void save_nogroups(void) { | |||
162 | if (arg_nogroups == 0) | 162 | if (arg_nogroups == 0) |
163 | return; | 163 | return; |
164 | 164 | ||
165 | FILE *fp = fopen(RUN_GROUPS_CFG, "w"); | 165 | FILE *fp = fopen(RUN_GROUPS_CFG, "wxe"); |
166 | if (fp) { | 166 | if (fp) { |
167 | fprintf(fp, "\n"); | 167 | fprintf(fp, "\n"); |
168 | SET_PERMS_STREAM(fp, 0, 0, 0644); // assume mode 0644 | 168 | 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) { | |||
86 | static void seccomp_save_file_list(const char *fname) { | 86 | static void seccomp_save_file_list(const char *fname) { |
87 | assert(fname); | 87 | assert(fname); |
88 | 88 | ||
89 | FILE *fp = fopen(RUN_SECCOMP_LIST, "a+"); | 89 | FILE *fp = fopen(RUN_SECCOMP_LIST, "ae"); |
90 | if (!fp) | 90 | if (!fp) |
91 | errExit("fopen"); | 91 | errExit("fopen"); |
92 | 92 | ||
@@ -99,7 +99,7 @@ static void seccomp_save_file_list(const char *fname) { | |||
99 | #define MAXBUF 4096 | 99 | #define MAXBUF 4096 |
100 | static int load_file_list_flag = 0; | 100 | static int load_file_list_flag = 0; |
101 | void seccomp_load_file_list(void) { | 101 | void seccomp_load_file_list(void) { |
102 | FILE *fp = fopen(RUN_SECCOMP_LIST, "r"); | 102 | FILE *fp = fopen(RUN_SECCOMP_LIST, "re"); |
103 | if (!fp) | 103 | if (!fp) |
104 | return; // no seccomp configuration whatsoever | 104 | return; // no seccomp configuration whatsoever |
105 | 105 | ||
@@ -122,7 +122,7 @@ int seccomp_load(const char *fname) { | |||
122 | assert(fname); | 122 | assert(fname); |
123 | 123 | ||
124 | // open filter file | 124 | // open filter file |
125 | int fd = open(fname, O_RDONLY); | 125 | int fd = open(fname, O_RDONLY|O_CLOEXEC); |
126 | if (fd == -1) | 126 | if (fd == -1) |
127 | goto errexit; | 127 | goto errexit; |
128 | 128 | ||
@@ -438,7 +438,7 @@ void seccomp_print_filter(pid_t pid) { | |||
438 | if (stat(fname, &s) == -1) | 438 | if (stat(fname, &s) == -1) |
439 | goto errexit; | 439 | goto errexit; |
440 | 440 | ||
441 | FILE *fp = fopen(fname, "r"); | 441 | FILE *fp = fopen(fname, "re"); |
442 | if (!fp) | 442 | if (!fp) |
443 | goto errexit; | 443 | goto errexit; |
444 | free(fname); | 444 | 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) { | |||
64 | monsec--; | 64 | monsec--; |
65 | 65 | ||
66 | EUID_ROOT(); | 66 | EUID_ROOT(); |
67 | FILE *fp = fopen(monfile, "r"); | 67 | FILE *fp = fopen(monfile, "re"); |
68 | EUID_USER(); | 68 | EUID_USER(); |
69 | if (!fp) { | 69 | if (!fp) { |
70 | killdone = 1; | 70 | 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 | |||
298 | assert(destname); | 298 | assert(destname); |
299 | 299 | ||
300 | // open source | 300 | // open source |
301 | int src = open(srcname, O_RDONLY); | 301 | int src = open(srcname, O_RDONLY|O_CLOEXEC); |
302 | if (src < 0) { | 302 | if (src < 0) { |
303 | fwarning("cannot open source file %s, file not copied\n", srcname); | 303 | fwarning("cannot open source file %s, file not copied\n", srcname); |
304 | return -1; | 304 | return -1; |
305 | } | 305 | } |
306 | 306 | ||
307 | // open destination | 307 | // open destination |
308 | int dst = open(destname, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); | 308 | int dst = open(destname, O_CREAT|O_WRONLY|O_TRUNC|O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); |
309 | if (dst < 0) { | 309 | if (dst < 0) { |
310 | fwarning("cannot open destination file %s, file not copied\n", destname); | 310 | fwarning("cannot open destination file %s, file not copied\n", destname); |
311 | close(src); | 311 | close(src); |
@@ -348,7 +348,7 @@ void copy_file_as_user(const char *srcname, const char *destname, uid_t uid, gid | |||
348 | 348 | ||
349 | void copy_file_from_user_to_root(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode) { | 349 | void copy_file_from_user_to_root(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode) { |
350 | // open destination | 350 | // open destination |
351 | int dst = open(destname, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); | 351 | int dst = open(destname, O_CREAT|O_WRONLY|O_TRUNC|O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); |
352 | if (dst < 0) { | 352 | if (dst < 0) { |
353 | fwarning("cannot open destination file %s, file not copied\n", destname); | 353 | fwarning("cannot open destination file %s, file not copied\n", destname); |
354 | return; | 354 | return; |
@@ -361,7 +361,7 @@ void copy_file_from_user_to_root(const char *srcname, const char *destname, uid_ | |||
361 | // drop privileges | 361 | // drop privileges |
362 | drop_privs(0); | 362 | drop_privs(0); |
363 | 363 | ||
364 | int src = open(srcname, O_RDONLY); | 364 | int src = open(srcname, O_RDONLY|O_CLOEXEC); |
365 | if (src < 0) { | 365 | if (src < 0) { |
366 | fwarning("cannot open source file %s, file not copied\n", srcname); | 366 | fwarning("cannot open source file %s, file not copied\n", srcname); |
367 | } else { | 367 | } else { |
@@ -616,7 +616,7 @@ int find_child(pid_t parent, pid_t *child) { | |||
616 | perror("asprintf"); | 616 | perror("asprintf"); |
617 | exit(1); | 617 | exit(1); |
618 | } | 618 | } |
619 | FILE *fp = fopen(file, "r"); | 619 | FILE *fp = fopen(file, "re"); |
620 | if (!fp) { | 620 | if (!fp) { |
621 | free(file); | 621 | free(file); |
622 | continue; | 622 | continue; |
@@ -722,7 +722,7 @@ void update_map(char *mapping, char *map_file) { | |||
722 | if (mapping[j] == ',') | 722 | if (mapping[j] == ',') |
723 | mapping[j] = '\n'; | 723 | mapping[j] = '\n'; |
724 | 724 | ||
725 | fd = open(map_file, O_RDWR); | 725 | fd = open(map_file, O_RDWR|O_CLOEXEC); |
726 | if (fd == -1) { | 726 | if (fd == -1) { |
727 | fprintf(stderr, "Error: cannot open %s: %s\n", map_file, strerror(errno)); | 727 | fprintf(stderr, "Error: cannot open %s: %s\n", map_file, strerror(errno)); |
728 | exit(EXIT_FAILURE); | 728 | exit(EXIT_FAILURE); |
@@ -742,9 +742,9 @@ void wait_for_other(int fd) { | |||
742 | // wait for the parent to be initialized | 742 | // wait for the parent to be initialized |
743 | //**************************** | 743 | //**************************** |
744 | char childstr[BUFLEN + 1]; | 744 | char childstr[BUFLEN + 1]; |
745 | int newfd = dup(fd); | 745 | int newfd = fcntl(fd, F_DUPFD_CLOEXEC, 0); |
746 | if (newfd == -1) | 746 | if (newfd == -1) |
747 | errExit("dup"); | 747 | errExit("fcntl"); |
748 | FILE* stream; | 748 | FILE* stream; |
749 | stream = fdopen(newfd, "r"); | 749 | stream = fdopen(newfd, "r"); |
750 | *childstr = '\0'; | 750 | *childstr = '\0'; |
@@ -791,9 +791,9 @@ void wait_for_other(int fd) { | |||
791 | 791 | ||
792 | void notify_other(int fd) { | 792 | void notify_other(int fd) { |
793 | FILE* stream; | 793 | FILE* stream; |
794 | int newfd = dup(fd); | 794 | int newfd = fcntl(fd, F_DUPFD_CLOEXEC, 0); |
795 | if (newfd == -1) | 795 | if (newfd == -1) |
796 | errExit("dup"); | 796 | errExit("fcntl"); |
797 | stream = fdopen(newfd, "w"); | 797 | stream = fdopen(newfd, "w"); |
798 | fprintf(stream, "arg_noroot=%d\n", arg_noroot); | 798 | fprintf(stream, "arg_noroot=%d\n", arg_noroot); |
799 | fflush(stream); | 799 | fflush(stream); |
@@ -811,7 +811,7 @@ uid_t pid_get_uid(pid_t pid) { | |||
811 | exit(1); | 811 | exit(1); |
812 | } | 812 | } |
813 | EUID_ROOT(); // grsecurity fix | 813 | EUID_ROOT(); // grsecurity fix |
814 | FILE *fp = fopen(file, "r"); | 814 | FILE *fp = fopen(file, "re"); |
815 | if (!fp) { | 815 | if (!fp) { |
816 | free(file); | 816 | free(file); |
817 | fprintf(stderr, "Error: cannot open /proc file\n"); | 817 | fprintf(stderr, "Error: cannot open /proc file\n"); |
@@ -1021,8 +1021,7 @@ void create_empty_file_as_root(const char *fname, mode_t mode) { | |||
1021 | if (arg_debug) | 1021 | if (arg_debug) |
1022 | printf("Creating empty %s file\n", fname); | 1022 | printf("Creating empty %s file\n", fname); |
1023 | 1023 | ||
1024 | /* coverity[toctou] */ | 1024 | FILE *fp = fopen(fname, "wxe"); |
1025 | FILE *fp = fopen(fname, "w"); | ||
1026 | if (!fp) | 1025 | if (!fp) |
1027 | errExit("fopen"); | 1026 | errExit("fopen"); |
1028 | SET_PERMS_STREAM(fp, 0, 0, mode); | 1027 | 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) { | |||
84 | static int x11_abstract_sockets_present(void) { | 84 | static int x11_abstract_sockets_present(void) { |
85 | 85 | ||
86 | EUID_ROOT(); // grsecurity fix | 86 | EUID_ROOT(); // grsecurity fix |
87 | FILE *fp = fopen("/proc/net/unix", "r"); | 87 | FILE *fp = fopen("/proc/net/unix", "re"); |
88 | if (!fp) | 88 | if (!fp) |
89 | errExit("fopen"); | 89 | errExit("fopen"); |
90 | EUID_USER(); | 90 | EUID_USER(); |
@@ -1363,7 +1363,7 @@ void fs_x11(void) { | |||
1363 | fs_logger("tmpfs /tmp/.X11-unix"); | 1363 | fs_logger("tmpfs /tmp/.X11-unix"); |
1364 | 1364 | ||
1365 | // create an empty root-owned file which will have the desired socket bind-mounted over it | 1365 | // create an empty root-owned file which will have the desired socket bind-mounted over it |
1366 | int fd = open(x11file, O_RDONLY|O_CREAT|O_EXCL, S_IRUSR | S_IWUSR); | 1366 | int fd = open(x11file, O_RDONLY|O_CREAT|O_EXCL|O_CLOEXEC, S_IRUSR | S_IWUSR); |
1367 | if (fd < 0) | 1367 | if (fd < 0) |
1368 | errExit(x11file); | 1368 | errExit(x11file); |
1369 | close(fd); | 1369 | close(fd); |