From d0759555bfb91be9d193ef4c05e6514651e68cc5 Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Wed, 13 Jan 2021 23:43:38 +0000 Subject: [PATCH] libpakfire: execute: Unshare environment when entering chroot The shell has networking enabled automatically. Signed-off-by: Michael Tremer --- configure.ac | 4 +++- src/_pakfire/pakfire.c | 12 +++++++++--- src/libpakfire/execute.c | 21 ++++++++++++++++++--- src/libpakfire/include/pakfire/execute.h | 5 +++++ src/pakfire/builder.py | 3 ++- 5 files changed, 37 insertions(+), 8 deletions(-) diff --git a/configure.ac b/configure.ac index 2c14addd..c2c5e30e 100644 --- a/configure.ac +++ b/configure.ac @@ -122,6 +122,7 @@ AC_CHECK_HEADERS([ \ ctypes.h \ math.h \ regex.h \ + sched.h \ stdarg.h \ stdlib.h \ string.h \ @@ -136,7 +137,8 @@ AC_CHECK_FUNCS([ \ personality \ secure_getenv \ strcmp \ - strdup + strdup \ + unshare ]) save_LIBS="$LIBS" diff --git a/src/_pakfire/pakfire.c b/src/_pakfire/pakfire.c index 28af1425..253f9972 100644 --- a/src/_pakfire/pakfire.c +++ b/src/_pakfire/pakfire.c @@ -351,12 +351,13 @@ static Py_ssize_t Pakfire_len(PakfireObject* self) { } static PyObject* Pakfire_execute(PakfireObject* self, PyObject* args, PyObject* kwds) { - char* kwlist[] = {"command", "environ", NULL}; + char* kwlist[] = {"command", "environ", "enable_network", NULL}; PyObject* command = NULL; PyObject* environ = NULL; + int enable_network = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist, &command, &environ)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|Op", kwlist, &command, &environ, &enable_network)) return NULL; // Check if command is a list @@ -410,6 +411,7 @@ static PyObject* Pakfire_execute(PakfireObject* self, PyObject* args, PyObject* const char* argv[command_length + 1]; char* envp[environ_length + 1]; + int flags = 0; // Parse arguments for (unsigned int i = 0; i < command_length; i++) { @@ -441,8 +443,12 @@ static PyObject* Pakfire_execute(PakfireObject* self, PyObject* args, PyObject* argv[command_length] = NULL; envp[environ_length] = NULL; + // Enable network? + if (enable_network) + flags |= PAKFIRE_EXECUTE_ENABLE_NETWORK; + // Execute command - int r = pakfire_execute(self->pakfire, argv, envp, 0); + int r = pakfire_execute(self->pakfire, argv, envp, flags); // Cleanup for (unsigned int i = 0; envp[i]; i++) diff --git a/src/libpakfire/execute.c b/src/libpakfire/execute.c index fa4f5256..ad75e05e 100644 --- a/src/libpakfire/execute.c +++ b/src/libpakfire/execute.c @@ -34,7 +34,9 @@ static char* envp_empty[1] = { NULL }; -static int pakfire_execute_fork(Pakfire pakfire, const char* argv[], char* envp[]) { +static int pakfire_execute_fork(Pakfire pakfire, const char* argv[], char* envp[], int flags) { + int r; + pid_t pid = getpid(); const char* root = pakfire_get_path(pakfire); @@ -49,7 +51,7 @@ static int pakfire_execute_fork(Pakfire pakfire, const char* argv[], char* envp[ DEBUG(pakfire, " env : %s\n", envp[i]); // Move / - int r = chroot(root); + r = chroot(root); if (r) { ERROR(pakfire, "chroot() to %s failed: %s\n", root, strerror(errno)); return errno; @@ -67,6 +69,19 @@ static int pakfire_execute_fork(Pakfire pakfire, const char* argv[], char* envp[ return errno; } + // Unshare namespaces + int uflags = CLONE_NEWIPC | CLONE_NEWNS | CLONE_NEWUTS; + + // Enable network? + if (!(flags & PAKFIRE_EXECUTE_ENABLE_NETWORK)) + uflags |= CLONE_NEWNET; + + r = unshare(uflags); + if (r) { + ERROR(pakfire, "Could not run unshare(%d): %s\n", uflags, strerror(errno)); + return errno; + } + // exec() command r = execve(argv[0], (char**)argv, envp); @@ -91,7 +106,7 @@ PAKFIRE_EXPORT int pakfire_execute(Pakfire pakfire, const char* argv[], char* en // Child process } else if (pid == 0) { - int r = pakfire_execute_fork(pakfire, argv, envp); + int r = pakfire_execute_fork(pakfire, argv, envp, flags); ERROR(pakfire, "Forked process returned unexpectedly: %s\n", strerror(r)); diff --git a/src/libpakfire/include/pakfire/execute.h b/src/libpakfire/include/pakfire/execute.h index 6fef62c1..18fa0754 100644 --- a/src/libpakfire/include/pakfire/execute.h +++ b/src/libpakfire/include/pakfire/execute.h @@ -26,4 +26,9 @@ int pakfire_execute(Pakfire pakfire, const char* argv[], char* envp[], int flags); int pakfire_execute_command(Pakfire pakfire, const char* command, char* envp[], int flags); +enum { + PAKFIRE_EXECUTE_NONE = 0, + PAKFIRE_EXECUTE_ENABLE_NETWORK = 1, +}; + #endif /* PAKFIRE_EXECUTE_H */ diff --git a/src/pakfire/builder.py b/src/pakfire/builder.py index 0eae84a2..72f53a07 100644 --- a/src/pakfire/builder.py +++ b/src/pakfire/builder.py @@ -525,4 +525,5 @@ class BuilderContext(object): self._install(packages) # Enter the shell - self.pakfire.execute(["/usr/bin/bash", "--login"], environ=self.environ) + self.pakfire.execute(["/usr/bin/bash", "--login"], + environ=self.environ, enable_network=True) -- 2.39.2