chiark / gitweb /
import: drop all capabilities when invoking tar
[elogind.git] / src / import / import-common.c
index 395f998..b490c43 100644 (file)
@@ -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"
 
@@ -358,8 +359,7 @@ int import_verify(
                         "--no-auto-check-trustdb",
                         "--batch",
                         "--trust-model=always",
-                        "--keyring=" VENDOR_KEYRING_PATH,
-                        NULL, /* maybe user keyring */
+                        NULL, /* keyring to use */
                         NULL, /* --verify */
                         NULL, /* signature file */
                         NULL, /* dash */
@@ -403,6 +403,8 @@ int import_verify(
                  * otherwise. */
                 if (access(USER_KEYRING_PATH, F_OK) >= 0)
                         cmd[k++] = "--keyring=" USER_KEYRING_PATH;
+                else
+                        cmd[k++] = "--keyring=" VENDOR_KEYRING_PATH;
 
                 cmd[k++] = "--verify";
                 cmd[k++] = sig_file_path;
@@ -446,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;
+}