return 0;
}
-static int pakfire_execute_fork(void* data) {
+static int pakfire_execute_write_uidgid_mapping(struct pakfire* pakfire,
+ const char* path, uid_t mapped_id, size_t length) {
+ int r = 1;
+
+ // Open file for writing
+ FILE* f = fopen(path, "w");
+ if (!f) {
+ ERROR(pakfire, "Could not open %s for writing: %m\n", path);
+ goto ERROR;
+ }
+
+ // Write configuration
+ int bytes_written = fprintf(f, "%d %d %ld\n", 0, mapped_id, length);
+ if (bytes_written < 0) {
+ ERROR(pakfire, "Could not write UID mapping: %m\n");
+ goto ERROR;
+ }
+
+ // Success
+ r = 0;
+
+ERROR:
+ if (f)
+ fclose(f);
+
+ return r;
+}
+
+static int pakfire_execute_setup_uid_mapping(struct pakfire* pakfire) {
+ // XXX hard-coded values
+ const uid_t mapped_uid = 100000;
+ const size_t length = 64536;
+
+ return pakfire_execute_write_uidgid_mapping(pakfire,
+ "/proc/self/uid_map", mapped_uid, length);
+}
+
+static int pakfire_execute_setup_gid_mapping(struct pakfire* pakfire) {
+ // XXX hard-coded values
+ const uid_t mapped_gid = 100000;
+ const size_t length = 64536;
+
+ return pakfire_execute_write_uidgid_mapping(pakfire,
+ "/proc/self/gid_map", mapped_gid, length);
+}
+
+static int pakfire_execute_fork2(void* data) {
struct pakfire_execute* env = (struct pakfire_execute*)data;
int r;
return r;
}
+/*
+ This function is launched in a new process that has its own user namespace.
+
+ It will set up the container.
+*/
+static int pakfire_execute_fork1(struct pakfire_execute* env) {
+ struct pakfire* pakfire = env->pakfire;
+ int r;
+
+ DEBUG(pakfire, "Launched a new container as PID %d\n", getpid());
+
+ // Setup UID mapping
+ r = pakfire_execute_setup_uid_mapping(pakfire);
+ if (r)
+ return r;
+
+ // Setup GID mapping
+ r = pakfire_execute_setup_gid_mapping(pakfire);
+ if (r)
+ return r;
+
+ // Configure child process
+ struct clone_args args = {
+ .flags =
+ CLONE_NEWCGROUP |
+ CLONE_NEWIPC |
+ CLONE_NEWNS |
+ CLONE_NEWPID |
+ CLONE_NEWUTS,
+ .exit_signal = SIGCHLD,
+ };
+
+ // Enable network?
+ if (!(env->flags & PAKFIRE_EXECUTE_ENABLE_NETWORK))
+ args.flags |= CLONE_NEWNET;
+
+ // Fork this process
+ pid_t pid = clone3(&args, sizeof(args));
+ if (pid < 0) {
+ ERROR(pakfire, "Could not fork: %m\n");
+ return -errno;
+
+ // Child process
+ } else if (pid == 0) {
+ r = pakfire_execute_fork2(env);
+ _exit(r);
+ }
+
+ int status = 0;
+
+ // Wait until the child process has finished
+ waitpid(pid, &status, 0);
+
+ // Pass the exit code of the child process
+ return WEXITSTATUS(status);
+}
+
PAKFIRE_EXPORT int pakfire_execute(struct pakfire* pakfire, const char* argv[], char* envp[],
int flags, pakfire_execute_logging_callback logging_callback, void* data) {
int r;
goto ERROR;
}
- if (!logging_callback)
- logging_callback = &default_logging_callback;
-
- // Configure child process
- struct clone_args args = {
- .flags =
- CLONE_VFORK |
- CLONE_NEWCGROUP |
- CLONE_NEWIPC |
- CLONE_NEWNS |
- CLONE_NEWPID |
- CLONE_NEWUTS,
- .exit_signal = SIGCHLD,
- };
-
- // Enable network?
- if (!(flags & PAKFIRE_EXECUTE_ENABLE_NETWORK))
- args.flags |= CLONE_NEWNET;
-
// Setup interactive environment
if (flags & PAKFIRE_EXECUTE_INTERACTIVE) {
// Set environment
}
}
+ if (!logging_callback)
+ logging_callback = &default_logging_callback;
+
+ // Lauch a new user namespace
+ struct clone_args args = {
+ .flags =
+ CLONE_VFORK |
+ CLONE_NEWUSER,
+ .exit_signal = SIGCHLD,
+ };
+
// Fork this process
pid_t pid = clone3(&args, sizeof(args));
if (pid < 0) {
// Child process
} else if (pid == 0) {
- r = pakfire_execute_fork(&env);
+ r = pakfire_execute_fork1(&env);
exit(r);
}