bunpen: pasta: share /proc/self/ns/net with pasta in a way that will be friendlier to sandboxing
This commit is contained in:
@@ -32,6 +32,11 @@ fn pasta_restrict(net: resources::net_subset) void = {
|
|||||||
// TODO: stronger isolation (mount namespace).
|
// TODO: stronger isolation (mount namespace).
|
||||||
// errors::ext::check("[namespace/pasta] unshare PID", rt::ext::unshare(rt::ext::clone_flag::NEWPID));
|
// 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_parent_rd, pipe_child_wr) = unix::pipe()!;
|
||||||
let (pipe_child_rd, pipe_parent_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");
|
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("namespace: unshare net", rt::ext::unshare(rt::ext::clone_flag::NEWNET));
|
||||||
errors::ext::check("setup_pasta: config routing", config_routing_in_ns(net));
|
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.
|
// 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.
|
// TODO: just set the desired caps here, and then don't try to do it again.
|
||||||
capability_restrict(rt::ext::CAPS_NONE);
|
capability_restrict(rt::ext::CAPS_NONE);
|
||||||
|
|
||||||
// let the other thread know we're ready for pasta to attach to us
|
// let the other thread know we're ready for pasta to attach to us
|
||||||
let netns_fd_bytes = [
|
io::write(pipe_parent_wr, [1u8])!;
|
||||||
netns_fd: u8,
|
|
||||||
(netns_fd >> 8): u8,
|
|
||||||
(netns_fd >> 16): u8,
|
|
||||||
(netns_fd >> 24): u8,
|
|
||||||
];
|
|
||||||
io::write(pipe_parent_wr, netns_fd_bytes)!;
|
|
||||||
|
|
||||||
// wait for the other thread to attach pasta.
|
// wait for the other thread to attach pasta.
|
||||||
// pasta signals readiness by writing its pid (followed by \n) to a file.
|
// 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_wr)!;
|
||||||
io::close(pipe_parent_rd)!;
|
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.
|
// 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, &[0u8])!;
|
||||||
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),
|
|
||||||
);
|
|
||||||
|
|
||||||
// exec into pasta.
|
// 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
|
// XXX: this code below never actually gets run
|
||||||
// cleanup: we're done with the pipes
|
// cleanup: we're done with the pipes
|
||||||
|
Reference in New Issue
Block a user