]> git.ipfire.org Git - people/stevee/pakfire.git/commitdiff
jail: Make dropping users into a shell easier
authorMichael Tremer <michael.tremer@ipfire.org>
Tue, 16 Aug 2022 16:25:42 +0000 (16:25 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Tue, 16 Aug 2022 16:25:42 +0000 (16:25 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/build.c
src/libpakfire/include/pakfire/build.h
src/libpakfire/include/pakfire/jail.h
src/libpakfire/jail.c

index f142c63f2815090c7a15f2e2eef4a3a868c5ea34..51c6e2039083168765adaf91a6876386e3b6d9fd 100644 (file)
@@ -91,6 +91,95 @@ static int pakfire_build_has_flag(struct pakfire_build* build, int flag) {
        return build->flags & flag;
 }
 
+/*
+       This function enables the local repository so that it can be access by
+       a pakfire instance running inside the chroot.
+*/
+static int pakfire_build_enable_repos(struct pakfire_build* build) {
+       char repopath[PATH_MAX];
+       FILE* f = NULL;
+       int r = 1;
+
+       // Fetch the local repository
+       struct pakfire_repo* repo = pakfire_get_repo(build->pakfire, PAKFIRE_REPO_LOCAL);
+       if (!repo) {
+               DEBUG(build->pakfire, "Could not find repository '%s': %m\n", PAKFIRE_REPO_LOCAL);
+               return 0;
+       }
+
+       // Fetch repository configuration
+       char* config = pakfire_repo_get_config(repo);
+       if (!config) {
+               ERROR(build->pakfire, "Could not generate repository configuration: %m\n");
+               goto ERROR;
+       }
+
+       const char* path = pakfire_repo_get_path(repo);
+
+       // Make sure the source directory exists
+       r = pakfire_mkdir(path, 0700);
+       if (r && errno != EEXIST) {
+               ERROR(build->pakfire, "Could not create repository directory %s: %m\n", path);
+               goto ERROR;
+       }
+
+       // Bind-mount the repository data read-only
+       r = pakfire_bind(build->pakfire, path, NULL, MS_RDONLY);
+       if (r) {
+               ERROR(build->pakfire, "Could not bind-mount the repository at %s: %m\n", path);
+               goto ERROR;
+       }
+
+       // Make path for configuration file
+       r = pakfire_make_path(build->pakfire, repopath,
+               PAKFIRE_CONFIG_DIR "/repos/" PAKFIRE_REPO_LOCAL ".repo");
+       if (r < 0)
+               goto ERROR;
+
+       // Open configuration file for writing
+       f = fopen(repopath, "w");
+       if (!f) {
+               ERROR(build->pakfire, "Could not open %s for writing: %m\n", path);
+               r = 1;
+               goto ERROR;
+       }
+
+       // Write configuration
+       size_t bytes_written = fprintf(f, "%s", config);
+       if (bytes_written < strlen(config)) {
+               ERROR(build->pakfire, "Could not write repository configuration: %m\n");
+               r = 1;
+               goto ERROR;
+       }
+
+       // Success
+       r = 0;
+
+ERROR:
+       if (f)
+               fclose(f);
+       if (config)
+               free(config);
+       pakfire_repo_unref(repo);
+
+       return r;
+}
+
+/*
+       Drops the user into a shell
+*/
+static int pakfire_build_shell(struct pakfire_build* build) {
+       int r;
+
+       // Export local repository if running in interactive mode
+       r = pakfire_build_enable_repos(build);
+       if (r)
+               return r;
+
+       // Run shell
+       return pakfire_jail_shell(build->jail);
+}
+
 static int pakfire_build_run_script(struct pakfire_build* build, const char* filename,
                const char* args[], char** output) {
        char* script = NULL;
@@ -712,7 +801,7 @@ static int pakfire_build_makefile(struct pakfire_build* build, const char* path)
                if (r) {
                        // Drop to a shell for debugging
                        if (pakfire_has_flag(build->pakfire, PAKFIRE_FLAGS_INTERACTIVE))
-                               pakfire_jail_shell(build->pakfire);
+                               pakfire_build_shell(build);
 
                        goto ERROR;
                }
@@ -1203,117 +1292,64 @@ ERROR:
        return r;
 }
 
-/*
-       This function enables the local repository so that it can be access by
-       a pakfire instance running inside the chroot.
-*/
-static int pakfire_build_enable_repos(struct pakfire* pakfire) {
-       char repopath[PATH_MAX];
-       FILE* f = NULL;
-       int r = 1;
-
-       // Fetch the local repository
-       struct pakfire_repo* repo = pakfire_get_repo(pakfire, PAKFIRE_REPO_LOCAL);
-       if (!repo) {
-               DEBUG(pakfire, "Could not find repository '%s': %m\n", PAKFIRE_REPO_LOCAL);
-               return 0;
-       }
-
-       // Fetch repository configuration
-       char* config = pakfire_repo_get_config(repo);
-       if (!config) {
-               ERROR(pakfire, "Could not generate repository configuration: %m\n");
-               goto ERROR;
-       }
-
-       const char* path = pakfire_repo_get_path(repo);
-
-       // Make sure the source directory exists
-       r = pakfire_mkdir(path, 0700);
-       if (r && errno != EEXIST) {
-               ERROR(pakfire, "Could not create repository directory %s: %m\n", path);
-               goto ERROR;
-       }
-
-       // Bind-mount the repository data read-only
-       r = pakfire_bind(pakfire, path, NULL, MS_RDONLY);
-       if (r) {
-               ERROR(pakfire, "Could not bind-mount the repository at %s: %m\n", path);
-               goto ERROR;
-       }
-
-       // Make path for configuration file
-       r = pakfire_make_path(pakfire, repopath,
-               PAKFIRE_CONFIG_DIR "/repos/" PAKFIRE_REPO_LOCAL ".repo");
-       if (r < 0)
-               goto ERROR;
+int pakfire_build_clean(struct pakfire* pakfire, int flags) {
+       struct pakfire_repo* local = NULL;
+       int r = 0;
 
-       // Open configuration file for writing
-       f = fopen(repopath, "w");
-       if (!f) {
-               ERROR(pakfire, "Could not open %s for writing: %m\n", path);
-               r = 1;
+       // Fetch local repository
+       local = pakfire_get_repo(pakfire, PAKFIRE_REPO_LOCAL);
+       if (!local) {
+               ERROR(pakfire, "Could not find repository %s: %m\n", PAKFIRE_REPO_LOCAL);
                goto ERROR;
        }
 
-       // Write configuration
-       size_t bytes_written = fprintf(f, "%s", config);
-       if (bytes_written < strlen(config)) {
-               ERROR(pakfire, "Could not write repository configuration: %m\n");
-               r = 1;
+       // Destroy everything in it
+       r = pakfire_repo_clean(local, PAKFIRE_REPO_CLEAN_FLAGS_DESTROY);
+       if (r)
                goto ERROR;
-       }
-
-       // Success
-       r = 0;
 
 ERROR:
-       if (f)
-               fclose(f);
-       if (config)
-               free(config);
-       pakfire_repo_unref(repo);
+       if (local)
+               pakfire_repo_unref(local);
 
        return r;
 }
 
+/*
+       This is a convenience function that sets up a build environment and
+       then drops the user into an interactive shell.
+*/
 PAKFIRE_EXPORT int pakfire_shell(struct pakfire* pakfire, const char** packages) {
+       struct pakfire_build* build = NULL;
        int r;
 
-       // Install any additional packages
-       if (packages) {
-               r = pakfire_install(pakfire, 0, 0, packages, NULL, 0, NULL, NULL, NULL);
-               if (r)
-                       return r;
+       // Create a new build environment
+       r = pakfire_build_create(&build, pakfire, NULL, 0);
+       if (r) {
+               ERROR(pakfire, "Could not create build: %m\n");
+               goto ERROR;
        }
 
-       // Export local repository if running in interactive mode
-       r = pakfire_build_enable_repos(pakfire);
-       if (r)
+       // Extract the snapshot
+       r = pakfire_build_extract_snapshot(build);
+       if (r) {
+               ERROR(build->pakfire, "Could not extract snapshot: %m\n");
                return r;
+       }
 
-       return pakfire_jail_shell(pakfire);
-}
-
-int pakfire_build_clean(struct pakfire* pakfire, int flags) {
-       struct pakfire_repo* local = NULL;
-       int r = 0;
-
-       // Fetch local repository
-       local = pakfire_get_repo(pakfire, PAKFIRE_REPO_LOCAL);
-       if (!local) {
-               ERROR(pakfire, "Could not find repository %s: %m\n", PAKFIRE_REPO_LOCAL);
-               goto ERROR;
+       // Install any additional packages
+       if (packages) {
+               r = pakfire_install(build->pakfire, 0, 0, packages, NULL, 0, NULL, NULL, NULL);
+               if (r)
+                       return r;
        }
 
-       // Destroy everything in it
-       r = pakfire_repo_clean(local, PAKFIRE_REPO_CLEAN_FLAGS_DESTROY);
-       if (r)
-               goto ERROR;
+       // Run shell
+       r = pakfire_build_shell(build);
 
 ERROR:
-       if (local)
-               pakfire_repo_unref(local);
+       if (build)
+               pakfire_build_unref(build);
 
        return r;
 }
index 55ef5bdc6fcc20e1ca9840e5f1bbdff36a3c28c4..b7f109e12116d50e3ca97eea8a77accb040996d9 100644 (file)
@@ -42,7 +42,8 @@ int pakfire_build_exec(struct pakfire_build* build, const char* path);
 
 int pakfire_build(struct pakfire* pakfire, const char* path, const char* target,
        const char* id, int flags);
-int pakfire_shell(struct pakfire* pakfire, const char** packages);
 int pakfire_build_clean(struct pakfire* pakfire, int flags);
 
+int pakfire_shell(struct pakfire* pakfire, const char** packages);
+
 #endif /* PAKFIRE_BUILD_H */
index a9b6531fc94c2bb7422930bc274228736e057ec5..e284c83b81f00a19731f5f9df30c46d2f1d4428b 100644 (file)
@@ -71,7 +71,7 @@ int pakfire_jail_run(struct pakfire* pakfire, const char* argv[], int flags, cha
 int pakfire_jail_run_script(struct pakfire* pakfire,
        const char* script, const size_t length, const char* argv[], int flags, char** output);
 
-int pakfire_jail_shell(struct pakfire* pakfire);
+int pakfire_jail_shell(struct pakfire_jail* jail);
 int pakfire_jail_ldconfig(struct pakfire* pakfire);
 
 #endif /* PAKFIRE_PRIVATE */
index 29d2bb6e7bf0955cc917cc067cc35391731e789b..e022ff4f5f9e91822755944c640cc541d184ac52 100644 (file)
@@ -1631,14 +1631,20 @@ ERROR:
        return r;
 }
 
-
-int pakfire_jail_shell(struct pakfire* pakfire) {
+int pakfire_jail_shell(struct pakfire_jail* jail) {
        const char* argv[] = {
                "/bin/bash", "--login", NULL,
        };
 
+       // Check if this operation is possible
+       if (!pakfire_jail_has_flag(jail, PAKFIRE_JAIL_INTERACTIVE)) {
+               ERROR(jail->pakfire, "You cannot run a shell in a non-interactive jail\n");
+               errno = ENOTSUP;
+               return 1;
+       }
+
        // Execute /bin/bash
-       return pakfire_jail_run(pakfire, argv, PAKFIRE_JAIL_INTERACTIVE, NULL);
+       return pakfire_jail_exec(jail, argv, NULL);
 }
 
 int pakfire_jail_ldconfig(struct pakfire* pakfire) {