bunpen: finish wiring the xdg-dbus-proxy instance

this isn't tested, except to see that it doesn't interfere with the *existing* bunpen use
This commit is contained in:
2025-01-03 11:55:46 +00:00
parent 66103854fa
commit 22f3a19165
2 changed files with 44 additions and 9 deletions

View File

@@ -61,24 +61,33 @@
use config; use config;
use errors; use errors;
use errors::ext; use errors::ext;
use strings; use io;
use os; use os;
use os::exec; use os::exec;
use path; use path;
use ps; use ps;
use resources; use resources;
use rt;
use rt::ext; use rt::ext;
use strings;
// given an existing, unfiltered bus at the fs path `upstream`, // given an existing, unfiltered bus at the fs path `upstream`,
// proxy the bus into the fs path indicated by `downstream`. // proxy the bus into the fs path indicated by `downstream`.
// clients attaching to the `downstream` path are provided access only to the // clients attaching to the `downstream` path are provided access only to the
// resources indicated by `dbus`. // 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()) { match (ps::fork_and_die_with_parent()) {
case let child_pid: os::exec::process => 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 = [ let proxy_args: []str = [
"xdg-dbus-proxy", "xdg-dbus-proxy",
"--filter", "--filter",
path::string(&downstream_path),
]; ];
for (let spec .. dbus.talk) { for (let spec .. dbus.talk) {
append(proxy_args, "--talk"); append(proxy_args, "--talk");

View File

@@ -1,9 +1,12 @@
// vim: set shiftwidth=2 : // vim: set shiftwidth=2 :
use errors; use errors;
use errors::ext;
use io;
use log; use log;
use path; use path;
use resources; use resources;
use restrict::ns; use restrict::ns;
use rt;
export fn restrict(what: *resources::resources) void = { export fn restrict(what: *resources::resources) void = {
// map the user-requested networking into internal mechanisms: // map the user-requested networking into internal mechanisms:
@@ -18,14 +21,26 @@ export fn restrict(what: *resources::resources) void = {
yield (true, void); yield (true, void);
}; };
let (any_dbus, dbus_session_path, dbus_resources): (bool, path::buffer, resources::dbus_subset) = match (what.dbus) { // map the user-requested dbus settings into internal mechanisms:
case let d: resources::dbus_subset => yield match (get_dbus_session_path()) { // also, obtain a handle to the bus *before* entering the outer sandbox,
case let s: path::buffer => yield (true, s, d); // 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 => case =>
log::println("restrict: dbus requested, but failed to parse dbus session path"); 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. // 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); append(outer_paths, p);
if (outer_pid) if (outer_pid)
append(outer_paths, path::init("/proc")!); append(outer_paths, path::init("/proc")!);
if (any_dbus)
append(outer_paths, dbus_session_path);
let outer_ns_resources = ns::ns_resources { let outer_ns_resources = ns::ns_resources {
paths = outer_paths, paths = outer_paths,
ipc = what.ipc, ipc = what.ipc,
@@ -58,6 +71,13 @@ export fn restrict(what: *resources::resources) void = {
}; };
// sandbox the user process // 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 { let user_ns_resources = ns::ns_resources {
paths = what.paths, paths = what.paths,
ipc = what.ipc, ipc = what.ipc,
@@ -68,3 +88,9 @@ export fn restrict(what: *resources::resources) void = {
ns::namespace_restrict(&user_ns_resources); ns::namespace_restrict(&user_ns_resources);
capability_restrict(what.caps); capability_restrict(what.caps);
}; };
type dbus_details = struct {
outer_fd: io::file,
session_path: path::buffer,
resources: resources::dbus_subset,
};