#define BUFFER_SIZE 1024 * 64
#define ENVIRON_SIZE 128
#define EPOLL_MAX_EVENTS 2
+#define MAX_MOUNTPOINTS 8
// The default environment that will be set for every command
static const struct environ {
{ NULL, NULL },
};
+struct pakfire_jail_mountpoint {
+ char source[PATH_MAX];
+ char target[PATH_MAX];
+ int flags;
+};
+
struct pakfire_jail {
struct pakfire* pakfire;
int nrefs;
// Logging
pakfire_jail_log_callback log_callback;
void* log_data;
+
+ // Mountpoints
+ struct pakfire_jail_mountpoint mountpoints[MAX_MOUNTPOINTS];
+ unsigned int num_mountpoints;
};
struct pakfire_log_buffer {
return r;
}
+// Mountpoints
+
+int pakfire_jail_bind(struct pakfire_jail* jail,
+ const char* source, const char* target, int flags) {
+ struct pakfire_jail_mountpoint* mp = NULL;
+ int r;
+
+ // Check if there is any space left
+ if (jail->num_mountpoints >= MAX_MOUNTPOINTS) {
+ errno = ENOSPC;
+ return 1;
+ }
+
+ // Check for valid inputs
+ if (!source || !target) {
+ errno = EINVAL;
+ return 1;
+ }
+
+ // Select the next free slot
+ mp = &jail->mountpoints[jail->num_mountpoints];
+
+ // Copy source
+ r = pakfire_string_set(mp->source, source);
+ if (r < 0) {
+ ERROR(jail->pakfire, "Could not copy source: %m\n");
+ return 1;
+ }
+
+ // Copy target
+ r = pakfire_string_set(mp->target, target);
+ if (r < 0) {
+ ERROR(jail->pakfire, "Could not copy target: %m\n");
+ return 1;
+ }
+
+ // Copy flags
+ mp->flags = flags;
+
+ // Increment counter
+ jail->num_mountpoints++;
+
+ return 0;
+}
+
+/*
+ Mounts everything that we require in the new namespace
+*/
+static int pakfire_jail_mount(struct pakfire_jail* jail) {
+ struct pakfire_jail_mountpoint* mp = NULL;
+ int r;
+
+ // Mount all default stuff
+ r = pakfire_mount_all(jail->pakfire);
+ if (r)
+ return r;
+
+ // Mount all custom stuff
+ for (unsigned int i = 0; i < jail->num_mountpoints; i++) {
+ // Fetch mountpoint
+ mp = &jail->mountpoints[i];
+
+ // Mount it
+ r = pakfire_bind(jail->pakfire, mp->source, mp->target, mp->flags);
+ if (r)
+ return r;
+ }
+
+ // Log all mountpoints
+ pakfire_mount_list(jail->pakfire);
+
+ return 0;
+}
+
// UID/GID Mapping
static int pakfire_jail_write_uidgid_mapping(struct pakfire_jail* jail,
// Change root (unless root is /)
if (!pakfire_on_root(jail->pakfire)) {
// Mount everything
- r = pakfire_mount_all(jail->pakfire);
+ r = pakfire_jail_mount(jail);
if (r)
return r;
- // Log all mountpoints
- pakfire_mount_list(jail->pakfire);
-
// Call chroot()
r = chroot(root);
if (r) {
# #
#############################################################################*/
+#include <sys/mount.h>
+
#include <pakfire/cgroup.h>
#include <pakfire/jail.h>
return r;
}
+static int test_bind(const struct test* t) {
+ struct pakfire_jail* jail = NULL;
+ char* output = NULL;
+ int r = EXIT_FAILURE;
+
+ const char* source = "/";
+ const char* target = "/oldroot";
+
+ const char* argv[] = {
+ "/command", "check-mountpoint", target, NULL,
+ };
+
+ // Create a new jail
+ ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire, 0));
+
+ // Bind-mount nonsense
+ ASSERT_ERRNO(pakfire_jail_bind(jail, NULL, target, 0), EINVAL);
+ ASSERT_ERRNO(pakfire_jail_bind(jail, source, NULL, 0), EINVAL);
+
+ // Bind-mount something
+ ASSERT_SUCCESS(pakfire_jail_bind(jail, source, target, MS_RDONLY));
+
+ // Check if the mount actually works
+ ASSERT_SUCCESS(pakfire_jail_exec(jail, argv, NULL));
+
+ // Success
+ r = EXIT_SUCCESS;
+
+FAIL:
+ if (jail)
+ pakfire_jail_unref(jail);
+
+ return r;
+}
+
int main(int argc, const char* argv[]) {
testsuite_add_test(test_create);
testsuite_add_test(test_env);
testsuite_add_test(test_memory_limit);
testsuite_add_test(test_pid_limit);
testsuite_add_test(test_file_ownership);
+ testsuite_add_test(test_bind);
return testsuite_run(argc, argv);
}