diff --git a/pkgs/by-name/bunpen/restrict/dbus_proxy.ha b/pkgs/by-name/bunpen/restrict/dbus_proxy.ha index 94488b5bd..bf3fb4fdf 100644 --- a/pkgs/by-name/bunpen/restrict/dbus_proxy.ha +++ b/pkgs/by-name/bunpen/restrict/dbus_proxy.ha @@ -61,24 +61,33 @@ use config; use errors; use errors::ext; -use strings; +use io; use os; use os::exec; use path; use ps; use resources; +use rt; use rt::ext; +use strings; // given an existing, unfiltered bus at the fs path `upstream`, // proxy the bus into the fs path indicated by `downstream`. // clients attaching to the `downstream` path are provided access only to the // resources indicated by `dbus`. -fn dbus_restrict(dbus: resources::dbus_subset, upstream: str, downstream: str) void = { +fn dbus_restrict(dbus: resources::dbus_subset, upstream_fd: io::file, downstream_path: path::buffer) void = { + // TODO: restrict resources to the xdg-dbus-proxy instance match (ps::fork_and_die_with_parent()) { case let child_pid: os::exec::process => + // dup the upstream to give it a predictable fd + rt::dup2(upstream_fd, 0)!; + io::close(upstream_fd)!; + os::setenv("DBUS_SESSION_BUS_ADDRES", "path:unix=/proc/self/fd/0")!; // TODO: pass this to execvpe's env instead of setenv'ing it here + let proxy_args: []str = [ "xdg-dbus-proxy", "--filter", + path::string(&downstream_path), ]; for (let spec .. dbus.talk) { append(proxy_args, "--talk"); diff --git a/pkgs/by-name/bunpen/restrict/restrict.ha b/pkgs/by-name/bunpen/restrict/restrict.ha index d6827b378..b78532b70 100644 --- a/pkgs/by-name/bunpen/restrict/restrict.ha +++ b/pkgs/by-name/bunpen/restrict/restrict.ha @@ -1,9 +1,12 @@ // vim: set shiftwidth=2 : use errors; +use errors::ext; +use io; use log; use path; use resources; use restrict::ns; +use rt; export fn restrict(what: *resources::resources) void = { // map the user-requested networking into internal mechanisms: @@ -18,14 +21,26 @@ export fn restrict(what: *resources::resources) void = { yield (true, void); }; - let (any_dbus, dbus_session_path, dbus_resources): (bool, path::buffer, resources::dbus_subset) = match (what.dbus) { - case let d: resources::dbus_subset => yield match (get_dbus_session_path()) { - case let s: path::buffer => yield (true, s, d); + // map the user-requested dbus settings into internal mechanisms: + // also, obtain a handle to the bus *before* entering the outer sandbox, + // so that we can proxy it into the main sandbox. + let dbus_proxy: (void | dbus_details) = match (what.dbus) { + case let res: resources::dbus_subset => yield match (get_dbus_session_path()) { + case let session: path::buffer => + yield match (rt::open(path::string(&session), rt::O_RDONLY, 0o400)) { //< TODO: correct mode? + case let outer_fd: int => yield dbus_details { + outer_fd = outer_fd, + session_path = session, + resources = res, + }; + case let err: rt::errno => + errors::ext::swallow("restrict: open(DBUS_SESSION_BUS_ADDRESS)", err); + }; case => log::println("restrict: dbus requested, but failed to parse dbus session path"); - yield (false, path::init("")!, resources::dbus_subset { ... }); + yield void; }; - case void => yield (false, path::init("")!, resources::dbus_subset { ... }); + case void => yield void; }; // sandbox the entire process early, now, before any forking/exec'ing. @@ -40,8 +55,6 @@ export fn restrict(what: *resources::resources) void = { append(outer_paths, p); if (outer_pid) append(outer_paths, path::init("/proc")!); - if (any_dbus) - append(outer_paths, dbus_session_path); let outer_ns_resources = ns::ns_resources { paths = outer_paths, ipc = what.ipc, @@ -58,6 +71,13 @@ export fn restrict(what: *resources::resources) void = { }; // sandbox the user process + match (dbus_proxy) { + case void => void; + case let details: dbus_details => + dbus_restrict(details.resources, details.outer_fd, details.session_path); + // the bus at this path is now proxied, so grant access to the user + append(what.paths, details.session_path); + }; let user_ns_resources = ns::ns_resources { paths = what.paths, ipc = what.ipc, @@ -68,3 +88,9 @@ export fn restrict(what: *resources::resources) void = { ns::namespace_restrict(&user_ns_resources); capability_restrict(what.caps); }; + +type dbus_details = struct { + outer_fd: io::file, + session_path: path::buffer, + resources: resources::dbus_subset, +};