aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/firejail/firejail.h6
-rw-r--r--src/firejail/ls.c184
-rw-r--r--src/firejail/main.c27
-rwxr-xr-xtest/features/3.5.exp3
4 files changed, 166 insertions, 54 deletions
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h
index 9c4dcc9a6..99705f0e6 100644
--- a/src/firejail/firejail.h
+++ b/src/firejail/firejail.h
@@ -532,8 +532,10 @@ int x11_display(void);
532int x11_check_xpra(void); 532int x11_check_xpra(void);
533 533
534// ls.c 534// ls.c
535void ls_name(const char *name, const char *path); 535#define SANDBOX_FS_LS 0
536void ls(pid_t pid, const char *path); 536#define SANDBOX_FS_GET 1
537void sandboxfs_name(int op, const char *name, const char *path);
538void sandboxfs(int op, pid_t pid, const char *path);
537 539
538#endif 540#endif
539 541
diff --git a/src/firejail/ls.c b/src/firejail/ls.c
index fe6348312..6a8d6acbd 100644
--- a/src/firejail/ls.c
+++ b/src/firejail/ls.c
@@ -184,7 +184,7 @@ static void print_directory(const char *path) {
184 free(namelist); 184 free(namelist);
185} 185}
186 186
187void ls_name(const char *name, const char *path) { 187void sandboxfs_name(int op, const char *name, const char *path) {
188 EUID_ASSERT(); 188 EUID_ASSERT();
189 189
190 if (!name || strlen(name) == 0) { 190 if (!name || strlen(name) == 0) {
@@ -197,10 +197,10 @@ void ls_name(const char *name, const char *path) {
197 exit(1); 197 exit(1);
198 } 198 }
199 199
200 ls(pid, path); 200 sandboxfs(op, pid, path);
201} 201}
202 202
203void ls(pid_t pid, const char *path) { 203void sandboxfs(int op, pid_t pid, const char *path) {
204 EUID_ASSERT(); 204 EUID_ASSERT();
205 205
206 // if the pid is that of a firejail process, use the pid of the first child process 206 // if the pid is that of a firejail process, use the pid of the first child process
@@ -225,16 +225,6 @@ void ls(pid_t pid, const char *path) {
225 } 225 }
226 } 226 }
227 227
228 EUID_ROOT();
229 // chroot
230 char *rootdir;
231 if (asprintf(&rootdir, "/proc/%d/root", pid) == -1)
232 errExit("asprintf");
233 if (chroot(rootdir) < 0)
234 errExit("chroot");
235 if (chdir("/") < 0)
236 errExit("chdir");
237
238 // full path or file in current directory? 228 // full path or file in current directory?
239 char *fname; 229 char *fname;
240 if (*path == '/') { 230 if (*path == '/') {
@@ -251,55 +241,151 @@ void ls(pid_t pid, const char *path) {
251 exit(1); 241 exit(1);
252 } 242 }
253 243
254 // access chek is performed with the real UID 244 // sandbox root directory
255 if (access(fname, R_OK) == -1) { 245 char *rootdir;
256 fprintf(stderr, "Error: Cannot access file %s\n", fname); 246 if (asprintf(&rootdir, "/proc/%d/root", pid) == -1)
257 exit(1); 247 errExit("asprintf");
258 }
259 248
260 // list directory contents 249 if (op == SANDBOX_FS_LS) {
261 struct stat s; 250 EUID_ROOT();
262 if (stat(fname, &s) == -1) { 251 // chroot
263 fprintf(stderr, "Error: Cannot access file %s\n", fname); 252 if (chroot(rootdir) < 0)
264 exit(1); 253 errExit("chroot");
254 if (chdir("/") < 0)
255 errExit("chdir");
256
257 // access chek is performed with the real UID
258 if (access(fname, R_OK) == -1) {
259 fprintf(stderr, "Error: Cannot access file %s\n", fname);
260 exit(1);
261 }
262
263 // list directory contents
264 struct stat s;
265 if (stat(fname, &s) == -1) {
266 fprintf(stderr, "Error: Cannot access file %s\n", fname);
267 exit(1);
268 }
269 if (S_ISDIR(s.st_mode)) {
270 char *rp = realpath(fname, NULL);
271 if (!rp) {
272 fprintf(stderr, "Error: Cannot access file %s\n", fname);
273 exit(1);
274 }
275 if (arg_debug)
276 printf("realpath %s\n", rp);
277
278 char *dir;
279 if (asprintf(&dir, "%s/", rp) == -1)
280 errExit("asprintf");
281
282 print_directory(dir);
283 free(rp);
284 free(dir);
285 }
286 else {
287 char *rp = realpath(fname, NULL);
288 if (!rp) {
289 fprintf(stderr, "Error: Cannot access file %s\n", fname);
290 exit(1);
291 }
292 if (arg_debug)
293 printf("realpath %s\n", rp);
294 char *split = strrchr(rp, '/');
295 if (split) {
296 *split = '\0';
297 char *rp2 = split + 1;
298 if (arg_debug)
299 printf("path %s, file %s\n", rp, rp2);
300 print_file_or_dir(rp, rp2, 1);
301 }
302 free(rp);
303 }
265 } 304 }
266 if (S_ISDIR(s.st_mode)) { 305
267 char *rp = realpath(fname, NULL); 306 // get file from sandbox
268 if (!rp) { 307 else if (op == SANDBOX_FS_GET) {
308 // check source file (sandbox)
309 char *src_fname;
310 if (asprintf(&src_fname, "%s%s", rootdir, fname) == -1)
311 errExit("asprintf");
312 EUID_ROOT();
313 struct stat s;
314 if (stat(src_fname, &s) == -1) {
269 fprintf(stderr, "Error: Cannot access file %s\n", fname); 315 fprintf(stderr, "Error: Cannot access file %s\n", fname);
270 exit(1); 316 exit(1);
271 } 317 }
272 if (arg_debug) 318
273 printf("realpath %s\n", rp); 319
320 // try to open the source file - we need to chroot
321 pid_t child = fork();
322 if (child < 0)
323 errExit("fork");
324 if (child == 0) {
325 // chroot
326 if (chroot(rootdir) < 0)
327 errExit("chroot");
328 if (chdir("/") < 0)
329 errExit("chdir");
330
331 // drop privileges
332 drop_privs(0);
333
334 // try to read the file
335 if (access(fname, R_OK) == -1) {
336 fprintf(stderr, "Error: Cannot read file %s\n", fname);
337 exit(1);
338 }
339 exit(0);
340 }
274 341
275 char *dir; 342 // wait for the child to finish
276 if (asprintf(&dir, "%s/", rp) == -1) 343 int status = NULL;
277 errExit("asprintf"); 344 waitpid(child, &status, 0);
345 if (WIFEXITED(status) && WEXITSTATUS(status) == 0);
346 else
347 exit(1);
348 EUID_USER();
278 349
279 print_directory(dir); 350 // check destination file (host)
280 free(rp); 351 char *dest_fname = strrchr(fname, '/');
281 free(dir); 352 if (!dest_fname || *(++dest_fname) == '\0') {
282 } 353 fprintf(stderr, "Error: invalid file name %s\n", fname);
283 else {
284 char *rp = realpath(fname, NULL);
285 if (!rp) {
286 fprintf(stderr, "Error: Cannot access file %s\n", fname);
287 exit(1); 354 exit(1);
288 } 355 }
289 if (arg_debug) 356
290 printf("realpath %s\n", rp); 357 if (access(dest_fname, F_OK) == -1) {
291 char *split = strrchr(rp, '/'); 358 // try to create the file
292 if (split) { 359 FILE *fp = fopen(dest_fname, "w");
293 *split = '\0'; 360 if (!fp) {
294 char *rp2 = split + 1; 361 fprintf(stderr, "Error: cannot create %s file\n", dest_fname);
295 if (arg_debug) 362 exit(1);
296 printf("path %s, file %s\n", rp, rp2); 363 }
297 print_file_or_dir(rp, rp2, 1); 364 fclose(fp);
298 } 365 }
299 free(rp); 366 else {
367 if (access(dest_fname, W_OK) == -1) {
368 fprintf(stderr, "Error: cannot writee %s file\n", dest_fname);
369 exit(1);
370 }
371 }
372 // copy file
373 EUID_ROOT();
374 copy_file(src_fname, dest_fname);
375 if (chown(dest_fname, getuid(), getgid()) == -1)
376 errExit("chown");
377 if (chmod(dest_fname, 0644) == -1)
378 errExit("chmod");
379 EUID_USER();
300 } 380 }
381
382 // put file in sandbox
383 else if (op == SANDBOX_FS_LS) {
384printf("todo!\n");
385 }
301 386
302 free(fname); 387 free(fname);
388 free(rootdir);
303 389
304 exit(0); 390 exit(0);
305} 391}
diff --git a/src/firejail/main.c b/src/firejail/main.c
index eebb04fcc..2c6b5a5e1 100644
--- a/src/firejail/main.c
+++ b/src/firejail/main.c
@@ -426,6 +426,29 @@ static void run_cmd_and_exit(int i, int argc, char **argv) {
426 exit(0); 426 exit(0);
427 } 427 }
428#endif 428#endif
429 else if (strncmp(argv[i], "--get=", 6) == 0) {
430 logargs(argc, argv);
431
432 // verify path
433 if ((i + 2) != argc) {
434 fprintf(stderr, "Error: invalid --get option, path expected\n");
435 exit(1);
436 }
437 char *path = argv[i + 1];
438 invalid_filename(path);
439 if (strstr(path, "..")) {
440 fprintf(stderr, "Error: invalid file name %s\n", path);
441 exit(1);
442 }
443
444 // get file
445 pid_t pid;
446 if (read_pid(argv[i] + 6, &pid) == 0)
447 sandboxfs(SANDBOX_FS_GET, pid, path);
448 else
449 sandboxfs_name(SANDBOX_FS_GET, argv[i] + 6, path);
450 exit(0);
451 }
429 else if (strncmp(argv[i], "--ls=", 5) == 0) { 452 else if (strncmp(argv[i], "--ls=", 5) == 0) {
430 logargs(argc, argv); 453 logargs(argc, argv);
431 454
@@ -444,9 +467,9 @@ static void run_cmd_and_exit(int i, int argc, char **argv) {
444 // list directory contents 467 // list directory contents
445 pid_t pid; 468 pid_t pid;
446 if (read_pid(argv[i] + 5, &pid) == 0) 469 if (read_pid(argv[i] + 5, &pid) == 0)
447 ls(pid, path); 470 sandboxfs(SANDBOX_FS_LS, pid, path);
448 else 471 else
449 ls_name(argv[i] + 5, path); 472 sandboxfs_name(SANDBOX_FS_LS, argv[i] + 5, path);
450 exit(0); 473 exit(0);
451 } 474 }
452 else if (strncmp(argv[i], "--join=", 7) == 0) { 475 else if (strncmp(argv[i], "--join=", 7) == 0) {
diff --git a/test/features/3.5.exp b/test/features/3.5.exp
index dfa8fae10..b1a16830d 100755
--- a/test/features/3.5.exp
+++ b/test/features/3.5.exp
@@ -44,7 +44,8 @@ if { $overlay == "overlay" } {
44 send -- "ls -l /dev | wc -l\r" 44 send -- "ls -l /dev | wc -l\r"
45 expect { 45 expect {
46 timeout {puts "TESTING ERROR 3.1\n";exit} 46 timeout {puts "TESTING ERROR 3.1\n";exit}
47 "11" 47 "12" { puts "Debian\n"}
48 "11" { puts "Centos\n"}
48 } 49 }
49 50
50 after 100 51 after 100