diff --git a/pkgs/by-name/bunpen/restrict/pasta.ha b/pkgs/by-name/bunpen/restrict/pasta.ha index 49ef4b5e8..510da19e6 100644 --- a/pkgs/by-name/bunpen/restrict/pasta.ha +++ b/pkgs/by-name/bunpen/restrict/pasta.ha @@ -32,6 +32,11 @@ fn pasta_restrict(net: resources::net_subset) void = { // TODO: stronger isolation (mount namespace). // errors::ext::check("[namespace/pasta] unshare PID", rt::ext::unshare(rt::ext::clone_flag::NEWPID)); + // grab a handle to the namespaces of the primary process. + // then we can fork, unshare net (in parent) and refer to that unshared netns + // in the child (pasta) via ${ns_fd}/net. + let ns_fd = errors::ext::check_int("setup_pasta: open /proc/self/ns", rt::open("/proc/self/ns", rt::O_RDONLY, 0o400)); + let (pipe_parent_rd, pipe_child_wr) = unix::pipe()!; let (pipe_child_rd, pipe_parent_wr) = unix::pipe()!; log::printfln("[namespace/pasta]: forking: child will launch pasta while parent will exec user code"); @@ -44,22 +49,12 @@ fn pasta_restrict(net: resources::net_subset) void = { errors::ext::check("namespace: unshare net", rt::ext::unshare(rt::ext::clone_flag::NEWNET)); errors::ext::check("setup_pasta: config routing", config_routing_in_ns(net)); - // open the net ns and share that with our child, who can then share it - // with pasta - let netns_fd = errors::ext::check_int("setup_pasta: open /proc/self/ns/net", rt::open("/proc/self/ns/net", rt::O_RDONLY, 0o400)); - // drop enough caps so that pasta has permissions to enter our new netns. // TODO: just set the desired caps here, and then don't try to do it again. capability_restrict(rt::ext::CAPS_NONE); // let the other thread know we're ready for pasta to attach to us - let netns_fd_bytes = [ - netns_fd: u8, - (netns_fd >> 8): u8, - (netns_fd >> 16): u8, - (netns_fd >> 24): u8, - ]; - io::write(pipe_parent_wr, netns_fd_bytes)!; + io::write(pipe_parent_wr, [1u8])!; // wait for the other thread to attach pasta. // pasta signals readiness by writing its pid (followed by \n) to a file. @@ -75,28 +70,15 @@ fn pasta_restrict(net: resources::net_subset) void = { io::close(pipe_parent_wr)!; io::close(pipe_parent_rd)!; - let parent_pid = rt::getppid(); - let parent_pidfd = errors::ext::check_int( - "setup_pasta: pidfd_open(parent_pid)", - rt::ext::pidfd_open(parent_pid), - ); - // wait for the parent to signal that it's ready for us to attach pasta. - let netns_child_fd_bytes: [4]u8 = [0...]; - io::readall(pipe_child_rd, &netns_child_fd_bytes)!; - let netns_child_fd: int = ( - (netns_child_fd_bytes[0]: int) | - (netns_child_fd_bytes[1]: int << 8) | - (netns_child_fd_bytes[1]: int << 16) | - (netns_child_fd_bytes[1]: int << 24) - ); - let netns = errors::ext::check_int( - "setup_pasta: pidfd_getfd(parent_pidfd, netns_u8)", - rt::ext::pidfd_getfd(parent_pidfd, netns_child_fd), - ); + io::readall(pipe_child_rd, &[0u8])!; // exec into pasta. - errors::ext::check("setup_pasta: attach", attach_pasta(net, netns, pipe_child_wr)); + let netns_fd = errors::ext::check_int( + "setup_pasta: open('/proc/self/ns/net')", + rt::openat2(ns_fd, "net", &rt::open_how { ... }, size(rt::open_how)), + ); + errors::ext::check("setup_pasta: attach", attach_pasta(net, netns_fd, pipe_child_wr)); // XXX: this code below never actually gets run // cleanup: we're done with the pipes