+++ /dev/null
-/*#############################################################################
-# #
-# Pakfire - The IPFire package management system #
-# Copyright (C) 2023 Pakfire development team #
-# #
-# This program is free software: you can redistribute it and/or modify #
-# it under the terms of the GNU General Public License as published by #
-# the Free Software Foundation, either version 3 of the License, or #
-# (at your option) any later version. #
-# #
-# This program is distributed in the hope that it will be useful, #
-# but WITHOUT ANY WARRANTY; without even the implied warranty of #
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
-# GNU General Public License for more details. #
-# #
-# You should have received a copy of the GNU General Public License #
-# along with this program. If not, see <http://www.gnu.org/licenses/>. #
-# #
-#############################################################################*/
-
-#ifndef PAKFIRE_NAMESPACE_H
-#define PAKFIRE_NAMESPACE_H
-
-#ifdef PAKFIRE_PRIVATE
-
-#include <pakfire/ctx.h>
-
-int pakfire_setup_namespace(struct pakfire_ctx* ctx, int* userfd);
-
-#endif /* PAKFIRE_PRIVATE */
-
-#endif /* PAKFIRE_NAMESPACE_H */
+++ /dev/null
-/*#############################################################################
-# #
-# Pakfire - The IPFire package management system #
-# Copyright (C) 2023 Pakfire development team #
-# #
-# This program is free software: you can redistribute it and/or modify #
-# it under the terms of the GNU General Public License as published by #
-# the Free Software Foundation, either version 3 of the License, or #
-# (at your option) any later version. #
-# #
-# This program is distributed in the hope that it will be useful, #
-# but WITHOUT ANY WARRANTY; without even the implied warranty of #
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
-# GNU General Public License for more details. #
-# #
-# You should have received a copy of the GNU General Public License #
-# along with this program. If not, see <http://www.gnu.org/licenses/>. #
-# #
-#############################################################################*/
-
-#include <errno.h>
-#include <fcntl.h>
-#include <linux/sched.h>
-#include <sched.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/eventfd.h>
-#include <sys/syscall.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include <pakfire/ctx.h>
-#include <pakfire/logging.h>
-#include <pakfire/namespace.h>
-
-static int clone3(struct clone_args* args, size_t size) {
- return syscall(__NR_clone3, args, size);
-}
-
-static int pakfire_namespace_parent(struct pakfire_ctx* ctx, int* userfd, int efd, int pidfd) {
- siginfo_t status;
- int r;
-
- // Read from the file descriptor
- r = eventfd_read(efd, (eventfd_t*)userfd);
- if (r) {
- CTX_ERROR(ctx, "Could not read file descriptor: %s\n", strerror(errno));
- return -errno;
- }
-
- CTX_DEBUG(ctx, "Waiting for the child process to set up the namespace...\n");
-
- // Wait for the child process to finish
- r = waitid(P_PIDFD, pidfd, &status, WEXITED);
- if (r) {
- CTX_ERROR(ctx, "Failed waiting for the child process: %s\n", strerror(errno));
- return -errno;
- }
-
- switch (status.si_code) {
- case CLD_EXITED:
- if (status.si_status) {
- CTX_ERROR(ctx, "Child process exited with status %d\n", status.si_status);
-
- // Pass exit code
- return status.si_status;
- }
- break;
-
- case CLD_KILLED:
- CTX_ERROR(ctx, "The child process was killed\n");
- return 139;
-
- case CLD_DUMPED:
- CTX_ERROR(ctx, "The child process terminated abnormally\n");
- return 1;
-
- // Log anything else
- default:
- CTX_ERROR(ctx, "Unknown child exit code: %d\n", status.si_code);
- break;
- }
-
- CTX_DEBUG(ctx, "User Namespace successfully set up as fd %d\n", *userfd);
-
- return 0;
-}
-
-static void pakfire_namespace_child(struct pakfire_ctx* ctx, int efd) {
- pid_t pid = getpid();
- int fd = -1;
- int r;
-
- CTX_DEBUG(ctx, "Launched a new process in a new namespace as PID %d\n", pid);
-
- // Open the usernamespace
- fd = open("/proc/self/ns/user", O_RDONLY);
- if (fd < 0) {
- CTX_ERROR(ctx, "Could not open the user namespace: %s\n", strerror(errno));
- _exit(1);
- }
-
- // Send the file descriptor to the parent process
- r = eventfd_write(efd, (eventfd_t)fd);
- if (r) {
- CTX_ERROR(ctx, "Could not write the file descriptor: %s\n", strerror(errno));
- _exit(1);
- }
-
- _exit(0);
-}
-
-int pakfire_setup_namespace(struct pakfire_ctx* ctx, int* userfd) {
- int pidfd = -1;
- int efd = -1;
- int r;
-
- CTX_DEBUG(ctx, "Creating a new user namespace...\n");
-
- struct clone_args args = {
- .flags =
- CLONE_NEWUSER |
- CLONE_FILES |
- CLONE_PIDFD,
- .exit_signal = SIGCHLD,
- .pidfd = (long long unsigned int)&pidfd,
- };
-
- // Setup an event file descriptor
- efd = eventfd(0, EFD_CLOEXEC);
- if (efd < 0) {
- CTX_ERROR(ctx, "eventfd() failed: %s\n", strerror(errno));
- r = -errno;
- goto ERROR;
- }
-
- // Fork a new process
- pid_t pid = clone3(&args, sizeof(args));
-
- // Fail on error
- if (pid < 0) {
- CTX_ERROR(ctx, "Could not create a new namespace: %s\n", strerror(errno));
- return -errno;
-
- // Child process
- } else if (pid == 0) {
- pakfire_namespace_child(ctx, efd);
-
- // We should never reach this
- abort();
-
- // Parent process
- } else {
- r = pakfire_namespace_parent(ctx, userfd, efd, pidfd);
- }
-
-ERROR:
- if (pidfd >= 0)
- close(pidfd);
- if (efd >= 0)
- close(efd);
-
- return r;
-}
#include <pakfire/dist.h>
#include <pakfire/logging.h>
#include <pakfire/mount.h>
-#include <pakfire/namespace.h>
#include <pakfire/os.h>
#include <pakfire/package.h>
#include <pakfire/packagelist.h>
int flags;
- // User Namespace
- int userfd;
-
// Lock
FILE* lock;
pakfire_rmtree(pakfire->path, 0);
}
- // Release the namespace
- if (pakfire->userfd >= 0)
- close(pakfire->userfd);
-
pakfire_repo_free_all(pakfire);
if (pakfire->pool)
goto ERROR;
}
- // Setup a new namespace
- r = pakfire_setup_namespace(p->ctx, &p->userfd);
- if (r)
- goto ERROR;
-
// Create a ramdisk if no path was given
if (!path) {
r = pakfire_make_ramdisk(p, tempdir, NULL);