From 2c140ded48fc31e3c80a92a1f755a2b1ab6e1a30 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 22 Jan 2015 18:12:31 +0100 Subject: [PATCH] import: drop all capabilities when invoking tar --- src/import/import-common.c | 79 ++++++++++++++++++++++++++++++++++++++ src/import/import-common.h | 2 + src/import/import-dkr.c | 56 ++------------------------- src/import/import-tar.c | 55 ++------------------------ 4 files changed, 87 insertions(+), 105 deletions(-) diff --git a/src/import/import-common.c b/src/import/import-common.c index 561c77abd..b490c435d 100644 --- a/src/import/import-common.c +++ b/src/import/import-common.c @@ -25,6 +25,7 @@ #include "strv.h" #include "copy.h" #include "btrfs-util.h" +#include "capability.h" #include "import-job.h" #include "import-common.h" @@ -447,3 +448,81 @@ finish: return r; } + +int import_fork_tar(const char *path, pid_t *ret) { + _cleanup_close_pair_ int pipefd[2] = { -1, -1 }; + pid_t pid; + int r; + + assert(path); + assert(ret); + + if (pipe2(pipefd, O_CLOEXEC) < 0) + return log_error_errno(errno, "Failed to create pipe for tar: %m"); + + pid = fork(); + if (pid < 0) + return log_error_errno(errno, "Failed to fork off tar: %m"); + + if (pid == 0) { + int null_fd; + uint64_t retain = + (1ULL << CAP_CHOWN) | + (1ULL << CAP_FOWNER) | + (1ULL << CAP_FSETID) | + (1ULL << CAP_MKNOD) | + (1ULL << CAP_SETFCAP); + + /* Child */ + + reset_all_signal_handlers(); + reset_signal_mask(); + assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); + + pipefd[1] = safe_close(pipefd[1]); + + if (dup2(pipefd[0], STDIN_FILENO) != STDIN_FILENO) { + log_error_errno(errno, "Failed to dup2() fd: %m"); + _exit(EXIT_FAILURE); + } + + if (pipefd[0] != STDIN_FILENO) + pipefd[0] = safe_close(pipefd[0]); + + null_fd = open("/dev/null", O_WRONLY|O_NOCTTY); + if (null_fd < 0) { + log_error_errno(errno, "Failed to open /dev/null: %m"); + _exit(EXIT_FAILURE); + } + + if (dup2(null_fd, STDOUT_FILENO) != STDOUT_FILENO) { + log_error_errno(errno, "Failed to dup2() fd: %m"); + _exit(EXIT_FAILURE); + } + + if (null_fd != STDOUT_FILENO) + null_fd = safe_close(null_fd); + + fd_cloexec(STDIN_FILENO, false); + fd_cloexec(STDOUT_FILENO, false); + fd_cloexec(STDERR_FILENO, false); + + r = capability_bounding_set_drop(~retain, true); + if (r < 0) { + log_error_errno(errno, "Failed to drop capabilities, ignoring: %m"); + _exit(EXIT_FAILURE); + } + + execlp("tar", "tar", "--numeric-owner", "-C", path, "-px", NULL); + log_error_errno(errno, "Failed to execute tar: %m"); + _exit(EXIT_FAILURE); + } + + pipefd[0] = safe_close(pipefd[0]); + r = pipefd[1]; + pipefd[1] = -1; + + *ret = pid; + + return r; +} diff --git a/src/import/import-common.h b/src/import/import-common.h index 39ac6acd0..f6b4268fd 100644 --- a/src/import/import-common.h +++ b/src/import/import-common.h @@ -37,3 +37,5 @@ int import_make_path(const char *url, const char *etag, const char *image_root, int import_make_verification_jobs(ImportJob **ret_checksum_job, ImportJob **ret_signature_job, ImportVerify verify, const char *url, CurlGlue *glue, ImportJobFinished on_finished, void *userdata); int import_verify(ImportJob *main_job, ImportJob *checksum_job, ImportJob *signature_job); + +int import_fork_tar(const char *path, pid_t *ret); diff --git a/src/import/import-dkr.c b/src/import/import-dkr.c index 0e9927509..24ba766b1 100644 --- a/src/import/import-dkr.c +++ b/src/import/import-dkr.c @@ -401,7 +401,6 @@ static int dkr_import_make_local_copy(DkrImport *i) { } static int dkr_import_job_on_open_disk(ImportJob *j) { - _cleanup_close_pair_ int pipefd[2] = { -1, -1 }; const char *base; DkrImport *i; int r; @@ -432,58 +431,9 @@ static int dkr_import_job_on_open_disk(ImportJob *j) { if (r < 0) return log_error_errno(r, "Failed to make btrfs subvolume %s: %m", i->temp_path); - if (pipe2(pipefd, O_CLOEXEC) < 0) - return log_error_errno(errno, "Failed to create pipe for tar: %m"); - - i->tar_pid = fork(); - if (i->tar_pid < 0) - return log_error_errno(errno, "Failed to fork off tar: %m"); - if (i->tar_pid == 0) { - int null_fd; - - /* Child */ - - reset_all_signal_handlers(); - reset_signal_mask(); - assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); - - pipefd[1] = safe_close(pipefd[1]); - - if (dup2(pipefd[0], STDIN_FILENO) != STDIN_FILENO) { - log_error_errno(errno, "Failed to dup2() fd: %m"); - _exit(EXIT_FAILURE); - } - - if (pipefd[0] != STDIN_FILENO) - pipefd[0] = safe_close(pipefd[0]); - - null_fd = open("/dev/null", O_WRONLY|O_NOCTTY); - if (null_fd < 0) { - log_error_errno(errno, "Failed to open /dev/null: %m"); - _exit(EXIT_FAILURE); - } - - if (dup2(null_fd, STDOUT_FILENO) != STDOUT_FILENO) { - log_error_errno(errno, "Failed to dup2() fd: %m"); - _exit(EXIT_FAILURE); - } - - if (null_fd != STDOUT_FILENO) - null_fd = safe_close(null_fd); - - fd_cloexec(STDIN_FILENO, false); - fd_cloexec(STDOUT_FILENO, false); - fd_cloexec(STDERR_FILENO, false); - - execlp("tar", "tar", "--numeric-owner", "-C", i->temp_path, "-px", NULL); - log_error_errno(errno, "Failed to execute tar: %m"); - _exit(EXIT_FAILURE); - } - - pipefd[0] = safe_close(pipefd[0]); - - j->disk_fd = pipefd[1]; - pipefd[1] = -1; + j->disk_fd = import_fork_tar(i->temp_path, &i->tar_pid); + if (j->disk_fd < 0) + return j->disk_fd; return 0; } diff --git a/src/import/import-tar.c b/src/import/import-tar.c index e311ad277..80ae83971 100644 --- a/src/import/import-tar.c +++ b/src/import/import-tar.c @@ -270,58 +270,9 @@ static int tar_import_job_on_open_disk(ImportJob *j) { } else if (r < 0) return log_error_errno(errno, "Failed to create subvolume %s: %m", i->temp_path); - if (pipe2(pipefd, O_CLOEXEC) < 0) - return log_error_errno(errno, "Failed to create pipe for tar: %m"); - - i->tar_pid = fork(); - if (i->tar_pid < 0) - return log_error_errno(errno, "Failed to fork off tar: %m"); - if (i->tar_pid == 0) { - int null_fd; - - /* Child */ - - reset_all_signal_handlers(); - reset_signal_mask(); - assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); - - pipefd[1] = safe_close(pipefd[1]); - - if (dup2(pipefd[0], STDIN_FILENO) != STDIN_FILENO) { - log_error_errno(errno, "Failed to dup2() fd: %m"); - _exit(EXIT_FAILURE); - } - - if (pipefd[0] != STDIN_FILENO) - pipefd[0] = safe_close(pipefd[0]); - - null_fd = open("/dev/null", O_WRONLY|O_NOCTTY); - if (null_fd < 0) { - log_error_errno(errno, "Failed to open /dev/null: %m"); - _exit(EXIT_FAILURE); - } - - if (dup2(null_fd, STDOUT_FILENO) != STDOUT_FILENO) { - log_error_errno(errno, "Failed to dup2() fd: %m"); - _exit(EXIT_FAILURE); - } - - if (null_fd != STDOUT_FILENO) - null_fd = safe_close(null_fd); - - fd_cloexec(STDIN_FILENO, false); - fd_cloexec(STDOUT_FILENO, false); - fd_cloexec(STDERR_FILENO, false); - - execlp("tar", "tar", "--numeric-owner", "-C", i->temp_path, "-px", NULL); - log_error_errno(errno, "Failed to execute tar: %m"); - _exit(EXIT_FAILURE); - } - - pipefd[0] = safe_close(pipefd[0]); - - j->disk_fd = pipefd[1]; - pipefd[1] = -1; + j->disk_fd = import_fork_tar(i->temp_path, &i->tar_pid); + if (j->disk_fd < 0) + return j->disk_fd; return 0; } -- 2.30.2