]> git.ipfire.org Git - pakfire.git/commitdiff
jail: Create a callback function that is called in the child process
authorMichael Tremer <michael.tremer@ipfire.org>
Sun, 29 Dec 2024 12:52:10 +0000 (12:52 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sun, 29 Dec 2024 12:52:10 +0000 (12:52 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/include/pakfire/jail.h
src/libpakfire/jail.c

index 4b82b08bdfad9285f51f071f1ca0ec440461a718..6aac94bdadb37eb12182e6ccdf47122ac73f7dbe 100644 (file)
@@ -49,6 +49,8 @@ const char* pakfire_jail_get_env(struct pakfire_jail* jail, const char* key);
 int pakfire_jail_set_env(struct pakfire_jail* jail, const char* key, const char* value);
 int pakfire_jail_import_env(struct pakfire_jail* jail, const char* env[]);
 
+typedef int (*pakfire_jail_callback)(struct pakfire_jail* jail, void* data);
+
 // Standard Input
 typedef int (*pakfire_jail_stdin_callback)
        (struct pakfire_ctx* ctx, struct pakfire_jail* jail, void* data, int fd);
index e702428ac92b6ea0fa132279bc9e08b27a4c84ee..073436fc016fd3dad7580eb63dcae0ace8988711 100644 (file)
@@ -148,6 +148,10 @@ struct pakfire_jail_exec {
 
        struct pakfire_cgroup* cgroup;
        struct pakfire_cgroup_stats cgroup_stats;
+
+       // The function to be called once the jail has been set up
+       int (*callback)(struct pakfire_jail* jail, void* data);
+       void* data;
 };
 
 static int pivot_root(const char* new_root, const char* old_root) {
@@ -1063,6 +1067,47 @@ static int pakfire_jail_exited(sd_event_source* source, const siginfo_t* si, voi
        return sd_event_exit(sd_event_source_get_event(source), 0);
 }
 
+static int pakfire_jail_launch_command(struct pakfire_jail* jail, void* data) {
+       char** argv = data;
+       int r;
+
+       // Check if argv is valid
+       if (!argv || !argv[0])
+               return -EINVAL;
+
+       DEBUG(jail->ctx, "Launching command:\n");
+
+       // Log argv
+       for (unsigned int i = 0; argv[i]; i++)
+               DEBUG(jail->ctx, "  argv[%u] = %s\n", i, argv[i]);
+
+       // exec() command
+       r = execvpe(argv[0], argv, jail->env);
+       if (r < 0) {
+               // Translate errno into regular exit code
+               switch (errno) {
+                       case ENOENT:
+#if 0
+                               // Ignore if the command doesn't exist
+                               if (ctx->flags & PAKFIRE_JAIL_NOENT_OK)
+                                       r = 0;
+                               else
+                                       r = 127;
+
+                               break;
+#endif
+
+                       default:
+                               r = 1;
+               }
+
+               ERROR(jail->ctx, "Could not execve(%s): %m\n", argv[0]);
+       }
+
+       // We should not get here
+       return r;
+}
+
 /*
        Performs the initialisation that needs to happen in the parent part
 */
@@ -1144,14 +1189,9 @@ static int pakfire_jail_switch_root(struct pakfire_jail* jail, const char* root)
        return 0;
 }
 
-static int pakfire_jail_child(struct pakfire_jail* jail, struct pakfire_jail_exec* ctx,
-               const char* argv[]) {
+static int pakfire_jail_child(struct pakfire_jail* jail, struct pakfire_jail_exec* ctx) {
        int r;
 
-       // Check if we have received a command
-       if (!argv || !*argv)
-               return -EINVAL;
-
        // Redirect any logging to our log pipe
        pakfire_ctx_set_log_callback(jail->ctx, pakfire_jail_log_redirect, ctx);
 
@@ -1330,50 +1370,26 @@ static int pakfire_jail_child(struct pakfire_jail* jail, struct pakfire_jail_exe
                return r;
 
        DEBUG(jail->ctx, "Child process initialization done\n");
-       DEBUG(jail->ctx, "Launching command:\n");
-
-       // Log argv
-       for (unsigned int i = 0; argv[i]; i++)
-               DEBUG(jail->ctx, "  argv[%u] = %s\n", i, argv[i]);
 
-       // exec() command
-       r = execvpe(argv[0], (char**)argv, jail->env);
-       if (r < 0) {
-               // Translate errno into regular exit code
-               switch (errno) {
-                       case ENOENT:
-                               // Ignore if the command doesn't exist
-                               if (ctx->flags & PAKFIRE_JAIL_NOENT_OK)
-                                       r = 0;
-                               else
-                                       r = 127;
-
-                               break;
-
-                       default:
-                               r = 1;
-               }
-
-               ERROR(jail->ctx, "Could not execve(%s): %m\n", argv[0]);
+       // Check if we have a callback
+       if (!ctx->callback) {
+               ERROR(jail->ctx, "No callback set\n");
+               return 126;
        }
 
-       // We should not get here
-       return r;
+       // Call the callback
+       return ctx->callback(jail, ctx->data);
 }
 
 // Run a command in the jail
 static int __pakfire_jail_exec(struct pakfire_jail* jail,
-               const char* argv[], int flags,
+               pakfire_jail_callback callback, void* data, int flags,
                pakfire_pty_stdin_callback stdin_callback, void* stdin_data,
                pakfire_pty_stdout_callback stdout_callback, void* stdout_data,
                char** output, size_t* output_length) {
        int pty_flags = 0;
        int r;
 
-       // Check if argv is valid
-       if (!argv || !argv[0])
-               return -EINVAL;
-
        // We cannot have both, an output callback and buffer
        if (stdout_callback && output)
                return -EINVAL;
@@ -1384,6 +1400,10 @@ static int __pakfire_jail_exec(struct pakfire_jail* jail,
                .flags = flags,
                .pidfd = -1,
 
+               // Callback & Data
+               .callback = callback,
+               .data     = data,
+
                // Exit Code
                .exit  = -1,
        };
@@ -1538,7 +1558,7 @@ static int __pakfire_jail_exec(struct pakfire_jail* jail,
 
        // Child process
        } else if (ctx.pid == 0) {
-               r = pakfire_jail_child(jail, &ctx, argv);
+               r = pakfire_jail_child(jail, &ctx);
                _exit(r);
        }
 
@@ -1600,19 +1620,21 @@ ERROR:
 }
 
 int pakfire_jail_exec(struct pakfire_jail* jail, const char* argv[], int flags) {
-       return __pakfire_jail_exec(jail, argv, flags, NULL, NULL, NULL, NULL, NULL, NULL);
+       return __pakfire_jail_exec(jail, pakfire_jail_launch_command, argv, flags,
+               NULL, NULL, NULL, NULL, NULL, NULL);
 }
 
 int pakfire_jail_exec_capture_output(struct pakfire_jail* jail,
                const char* argv[], int flags, char** output, size_t* length) {
-       return __pakfire_jail_exec(jail, argv, flags, NULL, NULL, NULL, NULL, output, length);
+       return __pakfire_jail_exec(jail, pakfire_jail_launch_command, argv, flags,
+               NULL, NULL, NULL, NULL, output, length);
 }
 
 int pakfire_jail_communicate(
                struct pakfire_jail* jail, const char* argv[], int flags,
                pakfire_pty_stdin_callback stdin_callback, void* stdin_data,
                pakfire_pty_stdout_callback stdout_callback, void* stdout_data) {
-       return __pakfire_jail_exec(jail, argv, flags,
+       return __pakfire_jail_exec(jail, pakfire_jail_launch_command, argv, flags,
                stdin_callback, stdin_data, stdout_callback, stdout_data, NULL, NULL);
 }