diff options
author | netblue30 <netblue30@yahoo.com> | 2016-09-22 13:40:32 -0400 |
---|---|---|
committer | netblue30 <netblue30@yahoo.com> | 2016-09-22 13:40:32 -0400 |
commit | 6163ff2a6fd8fa0858ff4f7c57d45dc57c8f39b1 (patch) | |
tree | 38ef7124e4706eca260adfca467890f6f6edff44 /src/firejail/ls.c | |
parent | --get fixes (diff) | |
download | firejail-6163ff2a6fd8fa0858ff4f7c57d45dc57c8f39b1.tar.gz firejail-6163ff2a6fd8fa0858ff4f7c57d45dc57c8f39b1.tar.zst firejail-6163ff2a6fd8fa0858ff4f7c57d45dc57c8f39b1.zip |
add files to sandbox container (--put)
Diffstat (limited to 'src/firejail/ls.c')
-rw-r--r-- | src/firejail/ls.c | 187 |
1 files changed, 152 insertions, 35 deletions
diff --git a/src/firejail/ls.c b/src/firejail/ls.c index 4c1992278..14991ba94 100644 --- a/src/firejail/ls.c +++ b/src/firejail/ls.c | |||
@@ -185,7 +185,7 @@ static void print_directory(const char *path) { | |||
185 | free(namelist); | 185 | free(namelist); |
186 | } | 186 | } |
187 | 187 | ||
188 | void sandboxfs_name(int op, const char *name, const char *path) { | 188 | void sandboxfs_name(int op, const char *name, const char *path1, const char *path2) { |
189 | EUID_ASSERT(); | 189 | EUID_ASSERT(); |
190 | 190 | ||
191 | if (!name || strlen(name) == 0) { | 191 | if (!name || strlen(name) == 0) { |
@@ -198,10 +198,29 @@ void sandboxfs_name(int op, const char *name, const char *path) { | |||
198 | exit(1); | 198 | exit(1); |
199 | } | 199 | } |
200 | 200 | ||
201 | sandboxfs(op, pid, path); | 201 | sandboxfs(op, pid, path1, path2); |
202 | } | 202 | } |
203 | 203 | ||
204 | void sandboxfs(int op, pid_t pid, const char *path) { | 204 | char *expand_path(const char *path) { |
205 | char *fname = NULL; | ||
206 | if (*path == '/') { | ||
207 | fname = strdup(path); | ||
208 | if (!fname) | ||
209 | errExit("strdup"); | ||
210 | } | ||
211 | else if (*path == '~') { | ||
212 | if (asprintf(&fname, "%s%s", cfg.homedir, path + 1) == -1) | ||
213 | errExit("asprintf"); | ||
214 | } | ||
215 | else { | ||
216 | // assume the file is in current working directory | ||
217 | if (asprintf(&fname, "%s/%s", cfg.cwd, path) == -1) | ||
218 | errExit("asprintf"); | ||
219 | } | ||
220 | return fname; | ||
221 | } | ||
222 | |||
223 | void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) { | ||
205 | EUID_ASSERT(); | 224 | EUID_ASSERT(); |
206 | 225 | ||
207 | // if the pid is that of a firejail process, use the pid of the first child process | 226 | // if the pid is that of a firejail process, use the pid of the first child process |
@@ -228,22 +247,17 @@ void sandboxfs(int op, pid_t pid, const char *path) { | |||
228 | } | 247 | } |
229 | } | 248 | } |
230 | 249 | ||
231 | // full path or file in current directory? | 250 | // expand paths |
232 | char *fname; | 251 | char *fname1 = expand_path(path1);; |
233 | if (*path == '/') { | 252 | char *fname2 = NULL; |
234 | fname = strdup(path); | 253 | if (path2 != NULL) { |
235 | if (!fname) | 254 | fname2 = expand_path(path2); |
236 | errExit("strdup"); | ||
237 | } | 255 | } |
238 | else if (*path == '~') { | 256 | if (arg_debug) { |
239 | if (asprintf(&fname, "%s%s", cfg.homedir, path + 1) == -1) | 257 | printf("file1 %s\n", fname1); |
240 | errExit("asprintf"); | 258 | printf("file2 %s\n", fname2); |
241 | } | 259 | } |
242 | else { | 260 | |
243 | fprintf(stderr, "Error: Cannot access %s\n", path); | ||
244 | exit(1); | ||
245 | } | ||
246 | |||
247 | // sandbox root directory | 261 | // sandbox root directory |
248 | char *rootdir; | 262 | char *rootdir; |
249 | if (asprintf(&rootdir, "/proc/%d/root", pid) == -1) | 263 | if (asprintf(&rootdir, "/proc/%d/root", pid) == -1) |
@@ -260,21 +274,21 @@ void sandboxfs(int op, pid_t pid, const char *path) { | |||
260 | // drop privileges | 274 | // drop privileges |
261 | drop_privs(0); | 275 | drop_privs(0); |
262 | 276 | ||
263 | if (access(fname, R_OK) == -1) { | 277 | if (access(fname1, R_OK) == -1) { |
264 | fprintf(stderr, "Error: Cannot access %s\n", fname); | 278 | fprintf(stderr, "Error: Cannot access %s\n", fname1); |
265 | exit(1); | 279 | exit(1); |
266 | } | 280 | } |
267 | 281 | ||
268 | // list directory contents | 282 | // list directory contents |
269 | struct stat s; | 283 | struct stat s; |
270 | if (stat(fname, &s) == -1) { | 284 | if (stat(fname1, &s) == -1) { |
271 | fprintf(stderr, "Error: Cannot access %s\n", fname); | 285 | fprintf(stderr, "Error: Cannot access %s\n", fname1); |
272 | exit(1); | 286 | exit(1); |
273 | } | 287 | } |
274 | if (S_ISDIR(s.st_mode)) { | 288 | if (S_ISDIR(s.st_mode)) { |
275 | char *rp = realpath(fname, NULL); | 289 | char *rp = realpath(fname1, NULL); |
276 | if (!rp) { | 290 | if (!rp) { |
277 | fprintf(stderr, "Error: Cannot access %s\n", fname); | 291 | fprintf(stderr, "Error: Cannot access %s\n", fname1); |
278 | exit(1); | 292 | exit(1); |
279 | } | 293 | } |
280 | if (arg_debug) | 294 | if (arg_debug) |
@@ -289,9 +303,9 @@ void sandboxfs(int op, pid_t pid, const char *path) { | |||
289 | free(dir); | 303 | free(dir); |
290 | } | 304 | } |
291 | else { | 305 | else { |
292 | char *rp = realpath(fname, NULL); | 306 | char *rp = realpath(fname1, NULL); |
293 | if (!rp) { | 307 | if (!rp) { |
294 | fprintf(stderr, "Error: Cannot access %s\n", fname); | 308 | fprintf(stderr, "Error: Cannot access %s\n", fname1); |
295 | exit(1); | 309 | exit(1); |
296 | } | 310 | } |
297 | if (arg_debug) | 311 | if (arg_debug) |
@@ -312,15 +326,18 @@ void sandboxfs(int op, pid_t pid, const char *path) { | |||
312 | else if (op == SANDBOX_FS_GET) { | 326 | else if (op == SANDBOX_FS_GET) { |
313 | // check source file (sandbox) | 327 | // check source file (sandbox) |
314 | char *src_fname; | 328 | char *src_fname; |
315 | if (asprintf(&src_fname, "%s%s", rootdir, fname) == -1) | 329 | if (asprintf(&src_fname, "%s%s", rootdir, fname1) == -1) |
316 | errExit("asprintf"); | 330 | errExit("asprintf"); |
317 | EUID_ROOT(); | 331 | EUID_ROOT(); |
318 | struct stat s; | 332 | struct stat s; |
319 | if (stat(src_fname, &s) == -1) { | 333 | if (stat(src_fname, &s) == -1) { |
320 | fprintf(stderr, "Error: Cannot access %s\n", fname); | 334 | fprintf(stderr, "Error: Cannot access %s\n", fname1); |
335 | exit(1); | ||
336 | } | ||
337 | if (is_dir(src_fname)) { | ||
338 | fprintf(stderr, "Error: source file name is a directory\n"); | ||
321 | exit(1); | 339 | exit(1); |
322 | } | 340 | } |
323 | |||
324 | 341 | ||
325 | // try to open the source file - we need to chroot | 342 | // try to open the source file - we need to chroot |
326 | pid_t child = fork(); | 343 | pid_t child = fork(); |
@@ -337,8 +354,8 @@ void sandboxfs(int op, pid_t pid, const char *path) { | |||
337 | drop_privs(0); | 354 | drop_privs(0); |
338 | 355 | ||
339 | // try to read the file | 356 | // try to read the file |
340 | if (access(fname, R_OK) == -1) { | 357 | if (access(fname1, R_OK) == -1) { |
341 | fprintf(stderr, "Error: Cannot read %s\n", fname); | 358 | fprintf(stderr, "Error: Cannot read %s\n", fname1); |
342 | exit(1); | 359 | exit(1); |
343 | } | 360 | } |
344 | exit(0); | 361 | exit(0); |
@@ -353,9 +370,9 @@ void sandboxfs(int op, pid_t pid, const char *path) { | |||
353 | EUID_USER(); | 370 | EUID_USER(); |
354 | 371 | ||
355 | // check destination file (host) | 372 | // check destination file (host) |
356 | char *dest_fname = strrchr(fname, '/'); | 373 | char *dest_fname = strrchr(fname1, '/'); |
357 | if (!dest_fname || *(++dest_fname) == '\0') { | 374 | if (!dest_fname || *(++dest_fname) == '\0') { |
358 | fprintf(stderr, "Error: invalid file name %s\n", fname); | 375 | fprintf(stderr, "Error: invalid file name %s\n", fname1); |
359 | exit(1); | 376 | exit(1); |
360 | } | 377 | } |
361 | 378 | ||
@@ -376,7 +393,7 @@ void sandboxfs(int op, pid_t pid, const char *path) { | |||
376 | fclose(fp); | 393 | fclose(fp); |
377 | exit(0); | 394 | exit(0); |
378 | } | 395 | } |
379 | 396 | ||
380 | // wait for the child to finish | 397 | // wait for the child to finish |
381 | int status = 0; | 398 | int status = 0; |
382 | waitpid(child, &status, 0); | 399 | waitpid(child, &status, 0); |
@@ -392,6 +409,8 @@ void sandboxfs(int op, pid_t pid, const char *path) { | |||
392 | } | 409 | } |
393 | 410 | ||
394 | // copy file | 411 | // copy file |
412 | if (arg_debug) | ||
413 | printf("copy %s to %s\n", src_fname, dest_fname); | ||
395 | EUID_ROOT(); | 414 | EUID_ROOT(); |
396 | if (copy_file(src_fname, dest_fname, getuid(), getgid(), 0644)) | 415 | if (copy_file(src_fname, dest_fname, getuid(), getgid(), 0644)) |
397 | fprintf(stderr, "Error: transfer failed\n"); | 416 | fprintf(stderr, "Error: transfer failed\n"); |
@@ -399,8 +418,106 @@ void sandboxfs(int op, pid_t pid, const char *path) { | |||
399 | printf("Transfer complete\n"); | 418 | printf("Transfer complete\n"); |
400 | EUID_USER(); | 419 | EUID_USER(); |
401 | } | 420 | } |
402 | 421 | // get file from host and store it in the sandbox | |
403 | free(fname); | 422 | else if (op == SANDBOX_FS_PUT) { |
423 | // verify the source file | ||
424 | const char *src_fname = path1; | ||
425 | struct stat s; | ||
426 | if (stat(src_fname, &s) == -1) { | ||
427 | fprintf(stderr, "Error: Cannot access %s\n", fname1); | ||
428 | exit(1); | ||
429 | } | ||
430 | if (is_dir(src_fname)) { | ||
431 | fprintf(stderr, "Error: source file name is a directory\n"); | ||
432 | exit(1); | ||
433 | } | ||
434 | |||
435 | // try to open the source file | ||
436 | pid_t child = fork(); | ||
437 | if (child < 0) | ||
438 | errExit("fork"); | ||
439 | if (child == 0) { | ||
440 | // drop privileges | ||
441 | drop_privs(0); | ||
442 | |||
443 | // try to read the file | ||
444 | if (access(src_fname, R_OK) == -1) { | ||
445 | fprintf(stderr, "Error: Cannot read %s\n", src_fname); | ||
446 | exit(1); | ||
447 | } | ||
448 | exit(0); | ||
449 | } | ||
450 | |||
451 | // wait for the child to finish | ||
452 | int status = 0; | ||
453 | waitpid(child, &status, 0); | ||
454 | if (WIFEXITED(status) && WEXITSTATUS(status) == 0); | ||
455 | else | ||
456 | exit(1); | ||
457 | |||
458 | // check destination file (sandbox) | ||
459 | char *dest_fname; | ||
460 | if (asprintf(&dest_fname, "%s%s", rootdir, fname2) == -1) | ||
461 | errExit("asprintf"); | ||
462 | EUID_ROOT(); | ||
463 | if (is_dir(dest_fname)) { | ||
464 | fprintf(stderr, "Error: destination file name is a directory inside the sandbox\n"); | ||
465 | exit(1); | ||
466 | } | ||
467 | |||
468 | // check write access on destination | ||
469 | child = fork(); | ||
470 | if (child < 0) | ||
471 | errExit("fork"); | ||
472 | if (child == 0) { | ||
473 | // chroot | ||
474 | if (chroot(rootdir) < 0) | ||
475 | errExit("chroot"); | ||
476 | if (chdir("/") < 0) | ||
477 | errExit("chdir"); | ||
478 | |||
479 | // drop privileges | ||
480 | drop_privs(0); | ||
481 | |||
482 | if (access(path2, F_OK) == -1) { | ||
483 | FILE *fp = fopen(path2, "w"); | ||
484 | if (!fp) { | ||
485 | fprintf(stderr, "Error: cannot create %s\n", path2); | ||
486 | exit(1); | ||
487 | } | ||
488 | fclose(fp); | ||
489 | } | ||
490 | else { | ||
491 | if (access(path2, W_OK) == -1) { | ||
492 | fprintf(stderr, "Error: cannot write %s\n", path2); | ||
493 | exit(1); | ||
494 | } | ||
495 | } | ||
496 | |||
497 | exit(0); | ||
498 | } | ||
499 | |||
500 | // wait for the child to finish | ||
501 | status = 0; | ||
502 | waitpid(child, &status, 0); | ||
503 | if (WIFEXITED(status) && WEXITSTATUS(status) == 0); | ||
504 | else | ||
505 | exit(1); | ||
506 | |||
507 | // copy file | ||
508 | if (arg_debug) | ||
509 | printf("copy %s to %s\n", src_fname, dest_fname); | ||
510 | EUID_ROOT(); | ||
511 | if (copy_file(src_fname, dest_fname, getuid(), getgid(), 0644)) | ||
512 | fprintf(stderr, "Error: transfer failed\n"); | ||
513 | else | ||
514 | printf("Transfer complete\n"); | ||
515 | EUID_USER(); | ||
516 | } | ||
517 | |||
518 | if (fname2) | ||
519 | free(fname2); | ||
520 | free(fname1); | ||
404 | free(rootdir); | 521 | free(rootdir); |
405 | 522 | ||
406 | exit(0); | 523 | exit(0); |