diff options
author | netblue30 <netblue30@yahoo.com> | 2016-11-18 09:11:30 -0500 |
---|---|---|
committer | netblue30 <netblue30@yahoo.com> | 2016-11-18 09:11:30 -0500 |
commit | 8c2b460d143d8dda4a86b826c0920918aa15f1f7 (patch) | |
tree | eae4c3a6f4805f0940e487299ccad8804665c843 | |
parent | testing appimage (diff) | |
download | firejail-8c2b460d143d8dda4a86b826c0920918aa15f1f7.tar.gz firejail-8c2b460d143d8dda4a86b826c0920918aa15f1f7.tar.zst firejail-8c2b460d143d8dda4a86b826c0920918aa15f1f7.zip |
fcopy part 4
-rw-r--r-- | src/fcopy/main.c | 9 | ||||
-rw-r--r-- | src/firejail/firejail.h | 1 | ||||
-rw-r--r-- | src/firejail/fs_bin.c | 171 | ||||
-rw-r--r-- | src/firejail/fs_etc.c | 16 | ||||
-rw-r--r-- | src/firejail/fs_home.c | 67 | ||||
-rw-r--r-- | src/firejail/fs_hostname.c | 28 | ||||
-rw-r--r-- | src/firejail/main.c | 1 | ||||
-rw-r--r-- | src/firejail/profile.c | 1 | ||||
-rw-r--r-- | src/firejail/sandbox.c | 1 | ||||
-rw-r--r-- | src/firemon/netstats.c | 3 | ||||
-rw-r--r-- | src/firemon/top.c | 3 | ||||
-rwxr-xr-x | test/environment/dns.exp | 26 | ||||
-rwxr-xr-x | test/fs/invalid_filename.exp | 15 | ||||
-rwxr-xr-x | test/fs/private-etc.exp | 34 | ||||
-rwxr-xr-x | test/fs/private-home.exp | 62 |
15 files changed, 211 insertions, 227 deletions
diff --git a/src/fcopy/main.c b/src/fcopy/main.c index 56d297c9a..e3a04a515 100644 --- a/src/fcopy/main.c +++ b/src/fcopy/main.c | |||
@@ -244,7 +244,7 @@ static void duplicate_file(const char *src, const char *dest, struct stat *s) { | |||
244 | } | 244 | } |
245 | 245 | ||
246 | static void duplicate_link(const char *src, const char *dest, struct stat *s) { | 246 | static void duplicate_link(const char *src, const char *dest, struct stat *s) { |
247 | char *rsrc = check(src); | 247 | char *rsrc = check(src); // we drop the result and use the original name |
248 | char *rdest = check(dest); | 248 | char *rdest = check(dest); |
249 | uid_t uid = s->st_uid; | 249 | uid_t uid = s->st_uid; |
250 | gid_t gid = s->st_gid; | 250 | gid_t gid = s->st_gid; |
@@ -252,7 +252,8 @@ static void duplicate_link(const char *src, const char *dest, struct stat *s) { | |||
252 | 252 | ||
253 | // build destination file name | 253 | // build destination file name |
254 | char *name; | 254 | char *name; |
255 | char *ptr = strrchr(rsrc, '/'); | 255 | // char *ptr = strrchr(rsrc, '/'); |
256 | char *ptr = strrchr(src, '/'); | ||
256 | ptr++; | 257 | ptr++; |
257 | if (asprintf(&name, "%s/%s", rdest, ptr) == -1) | 258 | if (asprintf(&name, "%s/%s", rdest, ptr) == -1) |
258 | errExit("asprintf"); | 259 | errExit("asprintf"); |
@@ -272,7 +273,7 @@ static void usage(void) { | |||
272 | } | 273 | } |
273 | 274 | ||
274 | int main(int argc, char **argv) { | 275 | int main(int argc, char **argv) { |
275 | //#if 0 | 276 | #if 0 |
276 | { | 277 | { |
277 | //system("cat /proc/self/status"); | 278 | //system("cat /proc/self/status"); |
278 | int i; | 279 | int i; |
@@ -280,7 +281,7 @@ for (i = 0; i < argc; i++) | |||
280 | printf("*%s* ", argv[i]); | 281 | printf("*%s* ", argv[i]); |
281 | printf("\n"); | 282 | printf("\n"); |
282 | } | 283 | } |
283 | //#endif | 284 | #endif |
284 | if (argc != 3) { | 285 | if (argc != 3) { |
285 | fprintf(stderr, "Error fcopy: files missing\n"); | 286 | fprintf(stderr, "Error fcopy: files missing\n"); |
286 | usage(); | 287 | usage(); |
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 80627fda8..2562094d3 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -587,7 +587,6 @@ void pulseaudio_init(void); | |||
587 | void pulseaudio_disable(void); | 587 | void pulseaudio_disable(void); |
588 | 588 | ||
589 | // fs_bin.c | 589 | // fs_bin.c |
590 | void fs_check_bin_list(void); | ||
591 | void fs_private_bin_list(void); | 590 | void fs_private_bin_list(void); |
592 | 591 | ||
593 | // protocol.c | 592 | // protocol.c |
diff --git a/src/firejail/fs_bin.c b/src/firejail/fs_bin.c index 6cc1bf3ab..421df717d 100644 --- a/src/firejail/fs_bin.c +++ b/src/firejail/fs_bin.c | |||
@@ -39,7 +39,6 @@ static char *paths[] = { | |||
39 | // return 1 if found, 0 if not found | 39 | // return 1 if found, 0 if not found |
40 | static char *check_dir_or_file(const char *name) { | 40 | static char *check_dir_or_file(const char *name) { |
41 | assert(name); | 41 | assert(name); |
42 | invalid_filename(name); | ||
43 | 42 | ||
44 | struct stat s; | 43 | struct stat s; |
45 | char *fname = NULL; | 44 | char *fname = NULL; |
@@ -94,68 +93,13 @@ static char *check_dir_or_file(const char *name) { | |||
94 | return paths[i]; | 93 | return paths[i]; |
95 | } | 94 | } |
96 | 95 | ||
97 | void fs_check_bin_list(void) { | 96 | static void duplicate(char *fname) { |
98 | EUID_ASSERT(); | 97 | if (*fname == '~' || *fname == '/' || strstr(fname, "..")) { |
99 | if (strstr(cfg.bin_private_keep, "..")) { | 98 | fprintf(stderr, "Error: \"%s\" is an invalid filename\n", fname); |
100 | fprintf(stderr, "Error: invalid private bin list\n"); | ||
101 | exit(1); | 99 | exit(1); |
102 | } | 100 | } |
103 | 101 | invalid_filename(fname); | |
104 | char *dlist = strdup(cfg.bin_private_keep); | ||
105 | if (!dlist) | ||
106 | errExit("strdup"); | ||
107 | |||
108 | // create a new list removing files not found | ||
109 | char *newlist = malloc(strlen(dlist) + 1 + 1); // +',' + '\0' | ||
110 | if (!newlist) | ||
111 | errExit("malloc"); | ||
112 | *newlist = '\0'; | ||
113 | char *newlistptr = newlist; | ||
114 | |||
115 | // check the first file | ||
116 | char *ptr = strtok(dlist, ","); | ||
117 | int notfound = 0; | ||
118 | if (check_dir_or_file(ptr)) { | ||
119 | // file found, copy the name in the new list | ||
120 | strcpy(newlistptr, ptr); | ||
121 | strcat(newlistptr, ","); | ||
122 | newlistptr += strlen(newlistptr); | ||
123 | } | ||
124 | else | ||
125 | notfound = 1; | ||
126 | |||
127 | // check the rest of the list | ||
128 | while ((ptr = strtok(NULL, ",")) != NULL) { | ||
129 | if (check_dir_or_file(ptr)) { | ||
130 | // file found, copy the name in the new list | ||
131 | strcpy(newlistptr, ptr); | ||
132 | strcat(newlistptr, ","); | ||
133 | newlistptr += strlen(newlistptr); | ||
134 | } | ||
135 | else | ||
136 | notfound = 1; | ||
137 | } | ||
138 | |||
139 | if (*newlist == '\0') { | ||
140 | // fprintf(stderr, "Warning: no --private-bin list executable found, option disabled\n"); | ||
141 | // cfg.bin_private_keep = NULL; | ||
142 | // arg_private_bin = 0; | ||
143 | free(newlist); | ||
144 | } | ||
145 | else { | ||
146 | ptr = strrchr(newlist, ','); | ||
147 | assert(ptr); | ||
148 | *ptr = '\0'; | ||
149 | if (notfound && !arg_quiet) | ||
150 | fprintf(stderr, "Warning: not all executables from --private-bin list were found. The current list is %s\n", newlist); | ||
151 | |||
152 | cfg.bin_private_keep = newlist; | ||
153 | } | ||
154 | |||
155 | free(dlist); | ||
156 | } | ||
157 | 102 | ||
158 | static void duplicate(char *fname) { | ||
159 | char *path = check_dir_or_file(fname); | 103 | char *path = check_dir_or_file(fname); |
160 | if (!path) | 104 | if (!path) |
161 | return; | 105 | return; |
@@ -165,44 +109,9 @@ static void duplicate(char *fname) { | |||
165 | if (asprintf(&full_path, "%s/%s", path, fname) == -1) | 109 | if (asprintf(&full_path, "%s/%s", path, fname) == -1) |
166 | errExit("asprintf"); | 110 | errExit("asprintf"); |
167 | 111 | ||
168 | char *actual_path = realpath(full_path, NULL); | 112 | // copy the file |
169 | if (actual_path) { | 113 | sbox_run(SBOX_ROOT| SBOX_SECCOMP, 3, PATH_FCOPY, full_path, RUN_BIN_DIR); |
170 | // if the file is a symbolic link not under path, make a symbolic link | 114 | fs_logger2("clone", fname); |
171 | if (is_link(full_path) && strncmp(actual_path, path, strlen(path))) { | ||
172 | char *lnkname; | ||
173 | if (asprintf(&lnkname, "%s/%s", RUN_BIN_DIR, fname) == -1) | ||
174 | errExit("asprintf"); | ||
175 | int rv = symlink(actual_path, lnkname); | ||
176 | if (rv) | ||
177 | fprintf(stderr, "Warning cannot create symbolic link %s\n", lnkname); | ||
178 | else if (arg_debug) | ||
179 | printf("Created symbolic link %s -> %s\n", lnkname, actual_path); | ||
180 | free(lnkname); | ||
181 | } | ||
182 | else { | ||
183 | // copy the file | ||
184 | if (arg_debug) | ||
185 | printf("running: %s -a %s %s/%s", RUN_CP_COMMAND, actual_path, RUN_BIN_DIR, fname); | ||
186 | |||
187 | pid_t child = fork(); | ||
188 | if (child < 0) | ||
189 | errExit("fork"); | ||
190 | if (child == 0) { | ||
191 | char *f; | ||
192 | if (asprintf(&f, "%s/%s", RUN_BIN_DIR, fname) == -1) | ||
193 | errExit("asprintf"); | ||
194 | clearenv(); | ||
195 | execlp(RUN_CP_COMMAND, RUN_CP_COMMAND, "-a", actual_path, f, NULL); | ||
196 | perror("execlp"); | ||
197 | _exit(1); | ||
198 | } | ||
199 | // wait for the child to finish | ||
200 | waitpid(child, NULL, 0); | ||
201 | |||
202 | } | ||
203 | free(actual_path); | ||
204 | } | ||
205 | |||
206 | free(full_path); | 115 | free(full_path); |
207 | } | 116 | } |
208 | 117 | ||
@@ -214,42 +123,20 @@ void fs_private_bin_list(void) { | |||
214 | // create /run/firejail/mnt/bin directory | 123 | // create /run/firejail/mnt/bin directory |
215 | mkdir_attr(RUN_BIN_DIR, 0755, 0, 0); | 124 | mkdir_attr(RUN_BIN_DIR, 0755, 0, 0); |
216 | 125 | ||
217 | // copy the list of files in the new etc directory | 126 | if (arg_debug) |
218 | // using a new child process without root privileges | 127 | printf("Copying files in the new bin directory\n"); |
219 | fs_logger_print(); // save the current log | ||
220 | pid_t child = fork(); | ||
221 | if (child < 0) | ||
222 | errExit("fork"); | ||
223 | if (child == 0) { | ||
224 | if (arg_debug) | ||
225 | printf("Copying files in the new home:\n"); | ||
226 | 128 | ||
227 | // elevate privileges - files in the new /bin directory belong to root | 129 | // copy the list of files in the new home directory |
228 | if (setreuid(0, 0) < 0) | 130 | char *dlist = strdup(private_list); |
229 | errExit("setreuid"); | 131 | if (!dlist) |
230 | if (setregid(0, 0) < 0) | 132 | errExit("strdup"); |
231 | errExit("setregid"); | ||
232 | |||
233 | // copy the list of files in the new home directory | ||
234 | char *dlist = strdup(private_list); | ||
235 | if (!dlist) | ||
236 | errExit("strdup"); | ||
237 | |||
238 | 133 | ||
239 | char *ptr = strtok(dlist, ","); | 134 | char *ptr = strtok(dlist, ","); |
135 | duplicate(ptr); | ||
136 | while ((ptr = strtok(NULL, ",")) != NULL) | ||
240 | duplicate(ptr); | 137 | duplicate(ptr); |
241 | 138 | free(dlist); | |
242 | while ((ptr = strtok(NULL, ",")) != NULL) | ||
243 | duplicate(ptr); | ||
244 | free(dlist); | ||
245 | fs_logger_print(); | 139 | fs_logger_print(); |
246 | #ifdef HAVE_GCOV | ||
247 | __gcov_flush(); | ||
248 | #endif | ||
249 | _exit(0); | ||
250 | } | ||
251 | // wait for the child to finish | ||
252 | waitpid(child, NULL, 0); | ||
253 | 140 | ||
254 | // mount-bind | 141 | // mount-bind |
255 | int i = 0; | 142 | int i = 0; |
@@ -265,29 +152,5 @@ void fs_private_bin_list(void) { | |||
265 | } | 152 | } |
266 | i++; | 153 | i++; |
267 | } | 154 | } |
268 | |||
269 | // log cloned files | ||
270 | char *dlist = strdup(private_list); | ||
271 | if (!dlist) | ||
272 | errExit("strdup"); | ||
273 | |||
274 | |||
275 | char *ptr = strtok(dlist, ","); | ||
276 | while (ptr) { | ||
277 | i = 0; | ||
278 | while (paths[i]) { | ||
279 | struct stat s; | ||
280 | if (stat(paths[i], &s) == 0) { | ||
281 | char *fname; | ||
282 | if (asprintf(&fname, "%s/%s", paths[i], ptr) == -1) | ||
283 | errExit("asprintf"); | ||
284 | fs_logger2("clone", fname); | ||
285 | free(fname); | ||
286 | } | ||
287 | i++; | ||
288 | } | ||
289 | ptr = strtok(NULL, ","); | ||
290 | } | ||
291 | free(dlist); | ||
292 | } | 155 | } |
293 | 156 | ||
diff --git a/src/firejail/fs_etc.c b/src/firejail/fs_etc.c index 7d4ffa938..80329d5ba 100644 --- a/src/firejail/fs_etc.c +++ b/src/firejail/fs_etc.c | |||
@@ -26,11 +26,8 @@ | |||
26 | // return 0 if file not found, 1 if found | 26 | // return 0 if file not found, 1 if found |
27 | static int check_dir_or_file(const char *fname) { | 27 | static int check_dir_or_file(const char *fname) { |
28 | assert(fname); | 28 | assert(fname); |
29 | invalid_filename(fname); | ||
30 | 29 | ||
31 | struct stat s; | 30 | struct stat s; |
32 | if (arg_debug) | ||
33 | printf("Checking %s\n", fname); | ||
34 | if (stat(fname, &s) == -1) { | 31 | if (stat(fname, &s) == -1) { |
35 | if (arg_debug) | 32 | if (arg_debug) |
36 | printf("Warning: file %s not found.\n", fname); | 33 | printf("Warning: file %s not found.\n", fname); |
@@ -51,6 +48,12 @@ errexit: | |||
51 | } | 48 | } |
52 | 49 | ||
53 | static void duplicate(char *fname) { | 50 | static void duplicate(char *fname) { |
51 | if (*fname == '~' || *fname == '/' || strstr(fname, "..")) { | ||
52 | fprintf(stderr, "Error: \"%s\" is an invalid filename\n", fname); | ||
53 | exit(1); | ||
54 | } | ||
55 | invalid_filename(fname); | ||
56 | |||
54 | char *src; | 57 | char *src; |
55 | if (asprintf(&src, "/etc/%s", fname) == -1) | 58 | if (asprintf(&src, "/etc/%s", fname) == -1) |
56 | errExit("asprintf"); | 59 | errExit("asprintf"); |
@@ -61,7 +64,6 @@ static void duplicate(char *fname) { | |||
61 | return; | 64 | return; |
62 | } | 65 | } |
63 | 66 | ||
64 | |||
65 | struct stat s; | 67 | struct stat s; |
66 | if (stat(src, &s) == 0 && S_ISDIR(s.st_mode)) { | 68 | if (stat(src, &s) == 0 && S_ISDIR(s.st_mode)) { |
67 | // create the directory in RUN_ETC_DIR | 69 | // create the directory in RUN_ETC_DIR |
@@ -84,12 +86,6 @@ void fs_private_etc_list(void) { | |||
84 | char *private_list = cfg.etc_private_keep; | 86 | char *private_list = cfg.etc_private_keep; |
85 | assert(private_list); | 87 | assert(private_list); |
86 | 88 | ||
87 | struct stat s; | ||
88 | if (stat("/etc", &s) == -1) { | ||
89 | fprintf(stderr, "Error: cannot find user /etc directory\n"); | ||
90 | exit(1); | ||
91 | } | ||
92 | |||
93 | // create /run/firejail/mnt/etc directory | 89 | // create /run/firejail/mnt/etc directory |
94 | mkdir_attr(RUN_ETC_DIR, 0755, 0, 0); | 90 | mkdir_attr(RUN_ETC_DIR, 0755, 0, 0); |
95 | fs_logger("tmpfs /etc"); | 91 | fs_logger("tmpfs /etc"); |
diff --git a/src/firejail/fs_home.c b/src/firejail/fs_home.c index d8cd9ce4d..1612da5d3 100644 --- a/src/firejail/fs_home.c +++ b/src/firejail/fs_home.c | |||
@@ -212,12 +212,6 @@ void fs_private_homedir(void) { | |||
212 | 212 | ||
213 | uid_t u = getuid(); | 213 | uid_t u = getuid(); |
214 | gid_t g = getgid(); | 214 | gid_t g = getgid(); |
215 | struct stat s; | ||
216 | if (stat(homedir, &s) == -1) { | ||
217 | fprintf(stderr, "Error: cannot find user home directory\n"); | ||
218 | exit(1); | ||
219 | } | ||
220 | |||
221 | 215 | ||
222 | // mount bind private_homedir on top of homedir | 216 | // mount bind private_homedir on top of homedir |
223 | if (arg_debug) | 217 | if (arg_debug) |
@@ -351,11 +345,9 @@ void fs_check_private_dir(void) { | |||
351 | //*********************************************************************************** | 345 | //*********************************************************************************** |
352 | static char *check_dir_or_file(const char *name) { | 346 | static char *check_dir_or_file(const char *name) { |
353 | assert(name); | 347 | assert(name); |
354 | struct stat s; | ||
355 | 348 | ||
356 | // basic checks | 349 | // basic checks |
357 | invalid_filename(name); | 350 | invalid_filename(name); |
358 | |||
359 | if (arg_debug) | 351 | if (arg_debug) |
360 | printf("Private home: checking %s\n", name); | 352 | printf("Private home: checking %s\n", name); |
361 | 353 | ||
@@ -372,28 +364,44 @@ static char *check_dir_or_file(const char *name) { | |||
372 | fname = tmp; | 364 | fname = tmp; |
373 | } | 365 | } |
374 | 366 | ||
375 | // check the file is in user home directory, a full home directory is not allowed | 367 | // we allow only files in user home directory or symbolic links to files or directories owned by the user |
376 | char *rname = realpath(fname, NULL); | 368 | struct stat s; |
377 | if (!rname || | 369 | if (lstat(fname, &s) == 0 && S_ISLNK(s.st_mode)) { |
378 | strncmp(rname, cfg.homedir, strlen(cfg.homedir)) != 0 || | 370 | if (stat(fname, &s) == 0) { |
379 | strcmp(rname, cfg.homedir) == 0) { | 371 | if (s.st_uid != getuid()) { |
380 | fprintf(stderr, "Error: invalid file %s\n", name); | 372 | fprintf(stderr, "Error: symbolic link %s to file or directory not owned by the user\n", fname); |
381 | exit(1); | 373 | exit(1); |
374 | } | ||
375 | return fname; | ||
376 | } | ||
377 | else { | ||
378 | fprintf(stderr, "Error: invalid file %s\n", name); | ||
379 | exit(1); | ||
380 | } | ||
382 | } | 381 | } |
383 | 382 | else { | |
384 | // only top files and directories in user home are allowed | 383 | // check the file is in user home directory, a full home directory is not allowed |
385 | char *ptr = rname + strlen(cfg.homedir); | 384 | char *rname = realpath(fname, NULL); |
386 | assert(*ptr != '\0'); | 385 | if (!rname || |
387 | ptr = strchr(++ptr, '/'); | 386 | strncmp(rname, cfg.homedir, strlen(cfg.homedir)) != 0 || |
388 | if (ptr) { | 387 | strcmp(rname, cfg.homedir) == 0) { |
389 | if (*ptr != '\0') { | 388 | fprintf(stderr, "Error: invalid file %s\n", name); |
390 | fprintf(stderr, "Error: only top files and directories in user home are allowed\n"); | ||
391 | exit(1); | 389 | exit(1); |
392 | } | 390 | } |
391 | |||
392 | // only top files and directories in user home are allowed | ||
393 | char *ptr = rname + strlen(cfg.homedir); | ||
394 | assert(*ptr != '\0'); | ||
395 | ptr = strchr(++ptr, '/'); | ||
396 | if (ptr) { | ||
397 | if (*ptr != '\0') { | ||
398 | fprintf(stderr, "Error: only top files and directories in user home are allowed\n"); | ||
399 | exit(1); | ||
400 | } | ||
401 | } | ||
402 | free(fname); | ||
403 | return rname; | ||
393 | } | 404 | } |
394 | |||
395 | free(fname); | ||
396 | return rname; | ||
397 | } | 405 | } |
398 | 406 | ||
399 | static void duplicate(char *name) { | 407 | static void duplicate(char *name) { |
@@ -405,7 +413,7 @@ static void duplicate(char *name) { | |||
405 | assert(strncmp(fname, cfg.homedir, strlen(cfg.homedir)) == 0); | 413 | assert(strncmp(fname, cfg.homedir, strlen(cfg.homedir)) == 0); |
406 | 414 | ||
407 | struct stat s; | 415 | struct stat s; |
408 | if (stat(fname, &s) == -1) { | 416 | if (lstat(fname, &s) == -1) { |
409 | free(fname); | 417 | free(fname); |
410 | return; | 418 | return; |
411 | } | 419 | } |
@@ -445,11 +453,6 @@ void fs_private_home_list(void) { | |||
445 | 453 | ||
446 | uid_t uid = getuid(); | 454 | uid_t uid = getuid(); |
447 | gid_t gid = getgid(); | 455 | gid_t gid = getgid(); |
448 | struct stat s; | ||
449 | if (stat(homedir, &s) == -1) { | ||
450 | fprintf(stderr, "Error: cannot find user home directory\n"); | ||
451 | exit(1); | ||
452 | } | ||
453 | 456 | ||
454 | // create /run/firejail/mnt/home directory | 457 | // create /run/firejail/mnt/home directory |
455 | mkdir_attr(RUN_HOME_DIR, 0755, uid, gid); | 458 | mkdir_attr(RUN_HOME_DIR, 0755, uid, gid); |
diff --git a/src/firejail/fs_hostname.c b/src/firejail/fs_hostname.c index 04197eb8f..dcf06fc6f 100644 --- a/src/firejail/fs_hostname.c +++ b/src/firejail/fs_hostname.c | |||
@@ -33,15 +33,7 @@ void fs_hostname(const char *hostname) { | |||
33 | if (arg_debug) | 33 | if (arg_debug) |
34 | printf("Creating a new /etc/hostname file\n"); | 34 | printf("Creating a new /etc/hostname file\n"); |
35 | 35 | ||
36 | FILE *fp = fopen(RUN_HOSTNAME_FILE, "w"); | 36 | create_empty_file_as_root(RUN_HOSTNAME_FILE, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH); |
37 | if (!fp) { | ||
38 | fprintf(stderr, "Error: cannot create %s\n", RUN_HOSTNAME_FILE); | ||
39 | exit(1); | ||
40 | } | ||
41 | fprintf(fp, "%s\n", hostname); | ||
42 | // mode and owner | ||
43 | SET_PERMS_STREAM(fp, 0, 0, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH); | ||
44 | fclose(fp); | ||
45 | 37 | ||
46 | // bind-mount the file on top of /etc/hostname | 38 | // bind-mount the file on top of /etc/hostname |
47 | if (mount(RUN_HOSTNAME_FILE, "/etc/hostname", NULL, MS_BIND|MS_REC, NULL) < 0) | 39 | if (mount(RUN_HOSTNAME_FILE, "/etc/hostname", NULL, MS_BIND|MS_REC, NULL) < 0) |
@@ -56,15 +48,12 @@ void fs_hostname(const char *hostname) { | |||
56 | // 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 |
57 | /* coverity[toctou] */ | 49 | /* coverity[toctou] */ |
58 | FILE *fp1 = fopen("/etc/hosts", "r"); | 50 | FILE *fp1 = fopen("/etc/hosts", "r"); |
59 | if (!fp1) { | 51 | if (!fp1) |
60 | fprintf(stderr, "Error: cannot open /etc/hosts\n"); | 52 | goto errexit; |
61 | exit(1); | 53 | |
62 | } | ||
63 | FILE *fp2 = fopen(RUN_HOSTS_FILE, "w"); | 54 | FILE *fp2 = fopen(RUN_HOSTS_FILE, "w"); |
64 | if (!fp2) { | 55 | if (!fp2) |
65 | fprintf(stderr, "Error: cannot create %s\n", RUN_HOSTS_FILE); | 56 | goto errexit; |
66 | exit(1); | ||
67 | } | ||
68 | 57 | ||
69 | char buf[4096]; | 58 | char buf[4096]; |
70 | int done = 0; | 59 | int done = 0; |
@@ -92,6 +81,11 @@ void fs_hostname(const char *hostname) { | |||
92 | errExit("mount bind /etc/hosts"); | 81 | errExit("mount bind /etc/hosts"); |
93 | fs_logger("create /etc/hosts"); | 82 | fs_logger("create /etc/hosts"); |
94 | } | 83 | } |
84 | return; | ||
85 | |||
86 | errexit: | ||
87 | fprintf(stderr, "Error: cannot create hostname file\n"); | ||
88 | exit(1); | ||
95 | } | 89 | } |
96 | 90 | ||
97 | void fs_resolvconf(void) { | 91 | void fs_resolvconf(void) { |
diff --git a/src/firejail/main.c b/src/firejail/main.c index 5bfa04cc9..ff7b762cd 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c | |||
@@ -1634,7 +1634,6 @@ int main(int argc, char **argv) { | |||
1634 | exit(1); | 1634 | exit(1); |
1635 | } | 1635 | } |
1636 | arg_private_bin = 1; | 1636 | arg_private_bin = 1; |
1637 | fs_check_bin_list(); | ||
1638 | } | 1637 | } |
1639 | else if (strcmp(argv[i], "--private-tmp") == 0) { | 1638 | else if (strcmp(argv[i], "--private-tmp") == 0) { |
1640 | arg_private_tmp = 1; | 1639 | arg_private_tmp = 1; |
diff --git a/src/firejail/profile.c b/src/firejail/profile.c index 693b1dc30..688fa9609 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c | |||
@@ -745,7 +745,6 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
745 | if (strncmp(ptr, "private-bin ", 12) == 0) { | 745 | if (strncmp(ptr, "private-bin ", 12) == 0) { |
746 | cfg.bin_private_keep = ptr + 12; | 746 | cfg.bin_private_keep = ptr + 12; |
747 | arg_private_bin = 1; | 747 | arg_private_bin = 1; |
748 | fs_check_bin_list(); | ||
749 | return 0; | 748 | return 0; |
750 | } | 749 | } |
751 | 750 | ||
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index 109daf552..c2e053b0c 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c | |||
@@ -696,7 +696,6 @@ int sandbox(void* sandbox_arg) { | |||
696 | if (asprintf(&tmp, "%s,xauth", cfg.bin_private_keep) == -1) | 696 | if (asprintf(&tmp, "%s,xauth", cfg.bin_private_keep) == -1) |
697 | errExit("asprintf"); | 697 | errExit("asprintf"); |
698 | cfg.bin_private_keep = tmp; | 698 | cfg.bin_private_keep = tmp; |
699 | fs_check_bin_list(); | ||
700 | EUID_ROOT(); | 699 | EUID_ROOT(); |
701 | } | 700 | } |
702 | fs_private_bin_list(); | 701 | fs_private_bin_list(); |
diff --git a/src/firemon/netstats.c b/src/firemon/netstats.c index 3c020d630..534d783cb 100644 --- a/src/firemon/netstats.c +++ b/src/firemon/netstats.c | |||
@@ -216,6 +216,9 @@ void netstats(void) { | |||
216 | print_proc(i, itv, col); | 216 | print_proc(i, itv, col); |
217 | } | 217 | } |
218 | } | 218 | } |
219 | #ifdef HAVE_GCOV | ||
220 | __gcov_flush(); | ||
221 | #endif | ||
219 | } | 222 | } |
220 | } | 223 | } |
221 | 224 | ||
diff --git a/src/firemon/top.c b/src/firemon/top.c index b804761dd..94271523c 100644 --- a/src/firemon/top.c +++ b/src/firemon/top.c | |||
@@ -292,6 +292,9 @@ void top(void) { | |||
292 | } | 292 | } |
293 | } | 293 | } |
294 | head_print(col, row); | 294 | head_print(col, row); |
295 | #ifdef HAVE_GCOV | ||
296 | __gcov_flush(); | ||
297 | #endif | ||
295 | } | 298 | } |
296 | } | 299 | } |
297 | 300 | ||
diff --git a/test/environment/dns.exp b/test/environment/dns.exp index 6ffb124cf..a6a7171eb 100755 --- a/test/environment/dns.exp +++ b/test/environment/dns.exp | |||
@@ -22,9 +22,33 @@ expect { | |||
22 | timeout {puts "TESTING ERROR 1.2\n";exit} | 22 | timeout {puts "TESTING ERROR 1.2\n";exit} |
23 | "53" | 23 | "53" |
24 | } | 24 | } |
25 | |||
26 | after 100 | 25 | after 100 |
27 | 26 | ||
28 | send -- "rm index.html\r" | 27 | send -- "rm index.html\r" |
29 | after 100 | 28 | after 100 |
29 | send -- "exit\r" | ||
30 | sleep 1 | ||
31 | |||
32 | send -- "firejail --dns=8.8.4.4 --dns=8.8.8.8 --dns=4.2.2.1\r" | ||
33 | expect { | ||
34 | timeout {puts "TESTING ERROR 2.1\n";exit} | ||
35 | "Child process initialized" | ||
36 | } | ||
37 | sleep 1 | ||
38 | |||
39 | send -- "cat /etc/resolv.conf\r" | ||
40 | expect { | ||
41 | timeout {puts "TESTING ERROR 2.2\n";exit} | ||
42 | "nameserver 8.8.4.4" | ||
43 | } | ||
44 | expect { | ||
45 | timeout {puts "TESTING ERROR 2.3\n";exit} | ||
46 | "nameserver 8.8.8.8" | ||
47 | } | ||
48 | expect { | ||
49 | timeout {puts "TESTING ERROR 2.4\n";exit} | ||
50 | "nameserver 4.2.2.1" | ||
51 | } | ||
52 | after 100 | ||
53 | |||
30 | puts "\nall done\n" | 54 | puts "\nall done\n" |
diff --git a/test/fs/invalid_filename.exp b/test/fs/invalid_filename.exp index 1acc85491..a6efc24b6 100755 --- a/test/fs/invalid_filename.exp +++ b/test/fs/invalid_filename.exp | |||
@@ -109,6 +109,21 @@ expect { | |||
109 | } | 109 | } |
110 | after 100 | 110 | after 100 |
111 | 111 | ||
112 | send -- "firejail --debug-check-filename --noprofile --private-home=\"bla&&bla\"\r" | ||
113 | expect { | ||
114 | timeout {puts "TESTING ERROR 8.1\n";exit} | ||
115 | "Checking filename bla&&bla" | ||
116 | } | ||
117 | expect { | ||
118 | timeout {puts "TESTING ERROR 8.2\n";exit} | ||
119 | "Error:" | ||
120 | } | ||
121 | expect { | ||
122 | timeout {puts "TESTING ERROR 8.3\n";exit} | ||
123 | "is an invalid filename" | ||
124 | } | ||
125 | after 100 | ||
126 | |||
112 | send -- "firejail --debug-check-filename --noprofile --private-etc=\"bla&&bla\"\r" | 127 | send -- "firejail --debug-check-filename --noprofile --private-etc=\"bla&&bla\"\r" |
113 | expect { | 128 | expect { |
114 | timeout {puts "TESTING ERROR 9.1\n";exit} | 129 | timeout {puts "TESTING ERROR 9.1\n";exit} |
diff --git a/test/fs/private-etc.exp b/test/fs/private-etc.exp index e692f7382..36b5d247c 100755 --- a/test/fs/private-etc.exp +++ b/test/fs/private-etc.exp | |||
@@ -33,12 +33,40 @@ expect { | |||
33 | "resolv.conf" | 33 | "resolv.conf" |
34 | } | 34 | } |
35 | 35 | ||
36 | send -- "ls -al /etc; echo done\r" | 36 | |
37 | send -- "file /etc/shadow\r" | ||
37 | expect { | 38 | expect { |
38 | timeout {puts "TESTING ERROR 7\n";exit} | 39 | timeout {puts "TESTING ERROR 7\n";exit} |
39 | "shadow" {puts "TESTING ERROR 8\n";exit} | 40 | "No such file or directory" |
40 | "done" | 41 | } |
42 | after 100 | ||
43 | send -- "exit\r" | ||
44 | sleep 1 | ||
45 | |||
46 | send -- "firejail --private-etc=shadow\r" | ||
47 | expect { | ||
48 | timeout {puts "TESTING ERROR 8\n";exit} | ||
49 | "invalid file type" | ||
50 | } | ||
51 | after 100 | ||
52 | |||
53 | send -- "firejail --private-etc=\"bla;bla\"\r" | ||
54 | expect { | ||
55 | timeout {puts "TESTING ERROR 9\n";exit} | ||
56 | "is an invalid filename" | ||
41 | } | 57 | } |
58 | after 100 | ||
59 | |||
60 | send -- "firejail --private-etc=../bin/ls\r" | ||
61 | expect { | ||
62 | timeout {puts "TESTING ERROR 10\n";exit} | ||
63 | "is an invalid filename" | ||
64 | } | ||
65 | after 100 | ||
66 | |||
67 | |||
68 | |||
69 | |||
42 | 70 | ||
43 | after 100 | 71 | after 100 |
44 | puts "\nall done\n" | 72 | puts "\nall done\n" |
diff --git a/test/fs/private-home.exp b/test/fs/private-home.exp index de5a88dea..3840d1cb8 100755 --- a/test/fs/private-home.exp +++ b/test/fs/private-home.exp | |||
@@ -9,11 +9,19 @@ match_max 100000 | |||
9 | 9 | ||
10 | # create some test files in user home directory | 10 | # create some test files in user home directory |
11 | send -- "touch ~/_firejail_test_file1\r" | 11 | send -- "touch ~/_firejail_test_file1\r" |
12 | after 100 | ||
12 | send -- "touch ~/_firejail_test_file2\r" | 13 | send -- "touch ~/_firejail_test_file2\r" |
14 | after 100 | ||
13 | send -- "mkdir ~/_firejail_test_dir1\r" | 15 | send -- "mkdir ~/_firejail_test_dir1\r" |
16 | after 100 | ||
14 | send -- "mkdir ~/_firejail_test_dir1/_firejail_test_dir2\r" | 17 | send -- "mkdir ~/_firejail_test_dir1/_firejail_test_dir2\r" |
18 | after 100 | ||
15 | send -- "touch ~/_firejail_test_dir1/_firejail_test_dir2/_firejail_test_file3\r" | 19 | send -- "touch ~/_firejail_test_dir1/_firejail_test_dir2/_firejail_test_file3\r" |
16 | after 100 | 20 | after 100 |
21 | send -- "ln -s /etc ~/_firejail_test_link1\r" | ||
22 | after 100 | ||
23 | send -- "ln -s ~/_firejail_test_dir1 ~/_firejail_test_link2\r" | ||
24 | after 100 | ||
17 | 25 | ||
18 | send -- "firejail --private-home=_firejail_test_file1,_firejail_test_file2,_firejail_test_dir1\r" | 26 | send -- "firejail --private-home=_firejail_test_file1,_firejail_test_file2,_firejail_test_dir1\r" |
19 | expect { | 27 | expect { |
@@ -37,8 +45,58 @@ expect { | |||
37 | } | 45 | } |
38 | after 100 | 46 | after 100 |
39 | 47 | ||
40 | send -- "rm -f ~/_firejail_test_file*\r" | 48 | send -- "exit\r" |
41 | send -- "rm -fr ~/_firejail_test_dir*\r" | 49 | sleep 1 |
50 | |||
51 | send -- "firejail --private-home=\"bla;bla\"\r" | ||
52 | expect { | ||
53 | timeout {puts "TESTING ERROR 5\n";exit} | ||
54 | "is an invalid filename" | ||
55 | } | ||
56 | after 100 | ||
57 | |||
58 | send -- "firejail --private-home=/etc/shadow\r" | ||
59 | expect { | ||
60 | timeout {puts "TESTING ERROR 6\n";exit} | ||
61 | "invalid file" | ||
62 | } | ||
63 | after 100 | ||
64 | |||
65 | send -- "firejail --private-home=/etc/passwd\r" | ||
66 | expect { | ||
67 | timeout {puts "TESTING ERROR 7\n";exit} | ||
68 | "invalid file" | ||
69 | } | ||
70 | after 100 | ||
71 | |||
72 | send -- "firejail --private-home=../../etc/passwd\r" | ||
73 | expect { | ||
74 | timeout {puts "TESTING ERROR 8\n";exit} | ||
75 | "invalid file" | ||
76 | } | ||
77 | after 100 | ||
78 | |||
79 | send -- "firejail --private-home=_firejail_test_link1\r" | ||
80 | expect { | ||
81 | timeout {puts "TESTING ERROR 9\n";exit} | ||
82 | "to file or directory not owned by the user" | ||
83 | } | ||
84 | after 100 | ||
85 | |||
86 | send -- "firejail --private-home=_firejail_test_link2\r" | ||
87 | expect { | ||
88 | timeout {puts "TESTING ERROR 10\n";exit} | ||
89 | "Child process initialized" | ||
90 | } | ||
91 | after 100 | ||
92 | send -- "file file ~/_firejail_test_link2\r" | ||
93 | expect { | ||
94 | timeout {puts "TESTING ERROR 11\n";exit} | ||
95 | "broken symbolic link" | ||
96 | } | ||
97 | send -- "exit\r" | ||
98 | |||
99 | send -- "rm -f ~/_firejail_test*\r" | ||
42 | after 100 | 100 | after 100 |
43 | 101 | ||
44 | puts "\nall done\n" | 102 | puts "\nall done\n" |