]> git.ipfire.org Git - pakfire.git/commitdiff
execute: Use clone3()
authorMichael Tremer <michael.tremer@ipfire.org>
Mon, 29 Mar 2021 22:46:45 +0000 (22:46 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Mon, 29 Mar 2021 22:46:45 +0000 (22:46 +0000)
This is a new syscall which does not come with a glibc wrapper. This
makes it slightly uncomfortable to use, but it brings us new features
that we want to use.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/execute.c

index 8ba178d549559f7e0840301a0312c0697d652591..078b20387eda331aa41921c07d9a6b2041925223 100644 (file)
@@ -61,6 +61,24 @@ struct pakfire_execute_buffer {
        size_t used;
 };
 
+#ifndef __NR_clone3
+#define __NR_clone3 435
+#endif
+
+struct clone_args {
+       uint64_t flags;
+       uint64_t pidfd;
+       uint64_t child_tid;
+       uint64_t parent_tid;
+       uint64_t exit_signal;
+       uint64_t stack;
+       uint64_t stack_size;
+       uint64_t tls;
+       uint64_t set_tid;
+       uint64_t set_tid_size;
+       uint64_t cgroup;
+};
+
 static int pakfire_execute_buffer_is_full(const struct pakfire_execute_buffer* buffer) {
        return (sizeof(buffer->data) == buffer->used);
 }
@@ -337,9 +355,6 @@ PAKFIRE_EXPORT int pakfire_execute(Pakfire pakfire, const char* argv[], char* en
        // Make cgroup name
        snprintf(env.cgroup, sizeof(env.cgroup) - 1, "%s", "pakfire/execute-XXXXXX");
 
-       // Allocate stack
-       char stack[4096];
-
        // argv is invalid
        if (!argv || !argv[0])
                return -EINVAL;
@@ -350,13 +365,20 @@ PAKFIRE_EXPORT int pakfire_execute(Pakfire pakfire, const char* argv[], char* en
        if (!logging_callback)
                logging_callback = &default_logging_callback;
 
-       // Configure the new namespace
-       int cflags = CLONE_VFORK | SIGCHLD | CLONE_NEWIPC | CLONE_NEWNS | CLONE_NEWUTS
-               | CLONE_NEWCGROUP;
+       // Configure child process
+       struct clone_args args = {
+               .flags =
+                       CLONE_VFORK |
+                       CLONE_NEWCGROUP |
+                       CLONE_NEWIPC |
+                       CLONE_NEWNS |
+                       CLONE_NEWUTS,
+               .exit_signal = SIGCHLD,
+       };
 
        // Enable network?
        if (!(flags & PAKFIRE_EXECUTE_ENABLE_NETWORK))
-               cflags |= CLONE_NEWNET;
+               args.flags |= CLONE_NEWNET;
 
        // Make some file descriptors for stdout & stderr
        if (!(flags & PAKFIRE_EXECUTE_INTERACTIVE)) {
@@ -381,10 +403,15 @@ PAKFIRE_EXPORT int pakfire_execute(Pakfire pakfire, const char* argv[], char* en
                goto ERROR;
 
        // Fork this process
-       pid_t pid = clone(pakfire_execute_fork, stack + sizeof(stack), cflags, &env);
+       pid_t pid = syscall(__NR_clone3, &args, sizeof(args));
        if (pid < 0) {
                ERROR(pakfire, "Could not fork: %s\n", strerror(errno));
                return -errno;
+
+       // Child process
+       } else if (pid == 0) {
+               r = pakfire_execute_fork(&env);
+               exit(r);
        }
 
        // Attach the process to the cgroup