summaryrefslogtreecommitdiff
path: root/internal/namespace/launcher_src
diff options
context:
space:
mode:
authorJames O'Doherty <james@theodohertyfamily.com>2026-05-22 10:05:38 -0400
committerJames O'Doherty <james@theodohertyfamily.com>2026-05-22 10:05:38 -0400
commit764d3e67fc783c487f42d398d1b85a5a1f0d8ef0 (patch)
tree5eed72f4e2371efe4d341fe61ce8bcf7717ac780 /internal/namespace/launcher_src
parenta78401b6b5023c3c924c0884b222c329975b3ad6 (diff)
feat: implement rootless network isolation bootstrap and C launcher
Diffstat (limited to 'internal/namespace/launcher_src')
-rw-r--r--internal/namespace/launcher_src/launcher.c77
1 files changed, 77 insertions, 0 deletions
diff --git a/internal/namespace/launcher_src/launcher.c b/internal/namespace/launcher_src/launcher.c
new file mode 100644
index 0000000..70737e4
--- /dev/null
+++ b/internal/namespace/launcher_src/launcher.c
@@ -0,0 +1,77 @@
+#define _GNU_SOURCE
+#include <sched.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <grp.h>
+
+int main(int argc, char **argv) {
+ if (argc < 1) {
+ fprintf(stderr, "Usage: %s <command> [args...]\n", argv[0]);
+ return 1;
+ }
+
+ // 1. Capture host identities BEFORE unsharing
+ uid_t current_uid = getuid();
+ gid_t current_gid = getgid();
+
+ // 2. Combined Unshare for User and Network namespaces
+ if (unshare(CLONE_NEWUSER | CLONE_NEWNET) == -1) {
+ perror("unshare(CLONE_NEWUSER | CLONE_NEWNET)");
+ return 1;
+ }
+
+ char map[64];
+
+ // 3. Write UID map
+ snprintf(map, sizeof(map), "0 %u 1\n", current_uid);
+ int fd = open("/proc/self/uid_map", O_WRONLY);
+ if (fd == -1) {
+ perror("open uid_map");
+ return 1;
+ }
+ if (write(fd, map, strlen(map)) == -1) {
+ perror("write uid_map");
+ close(fd);
+ return 1;
+ }
+ close(fd);
+
+ // 4. Disable setgroups
+ fd = open("/proc/self/setgroups", O_WRONLY);
+ if (fd != -1) {
+ write(fd, "deny", 4);
+ close(fd);
+ }
+
+ // 5. Write GID map
+ snprintf(map, sizeof(map), "0 %u 1\n", current_gid);
+ fd = open("/proc/self/gid_map", O_WRONLY);
+ if (fd == -1) {
+ perror("open gid_map");
+ return 1;
+ }
+ if (write(fd, map, strlen(map)) == -1) {
+ perror("write gid_map");
+ close(fd);
+ return 1;
+ }
+ close(fd);
+
+ // 6. Execute the target command
+ // In this architecture, the Go Bootstrap code passes the target binary
+ // as the first element of the argv array.
+ // Therefore, argv[0] is the path to the binary we want to execute.
+ if (argv[0] == NULL) {
+ fprintf(stderr, "No target binary provided in argv[0]\n");
+ return 1;
+ }
+
+ fprintf(stderr, "[launcher] Executing binary: %s\n", argv[0]);
+ execvp(argv[0], argv);
+
+ perror("execvp");
+ return 1;
+}