Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion crates/ostree-ext/src/container/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,11 @@ pub fn merge_default_container_proxy_opts_with_isolation(
if let Some(authfile) = config.authfile.take() {
config.auth_data = Some(std::fs::File::open(authfile)?);
}
let cmd = crate::isolation::unprivileged_subprocess(bootc_utils::skopeo_bin(), user);
// When passing auth via fd, skopeo needs to re-open /proc/self/fd/N,
// which requires CAP_DAC_READ_SEARCH. Keep this capability when auth is present.
let keep_dac = config.auth_data.is_some();
let cmd =
crate::isolation::unprivileged_subprocess(bootc_utils::skopeo_bin(), user, keep_dac);
config.skopeo_cmd = Some(cmd);
}
Ok(())
Expand Down
20 changes: 18 additions & 2 deletions crates/ostree-ext/src/isolation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,15 @@ pub(crate) fn running_in_systemd() -> bool {
/// Return a prepared subprocess configuration that will run as an unprivileged user if possible.
///
/// This currently only drops privileges when run under systemd with DynamicUser.
pub(crate) fn unprivileged_subprocess(binary: &str, user: &str) -> Command {
///
/// If `keep_dac_read_search` is true, the CAP_DAC_READ_SEARCH capability is retained.
/// This is needed when passing file descriptors via /proc/self/fd that the subprocess
/// needs to re-open (e.g., auth files for skopeo).
pub(crate) fn unprivileged_subprocess(
binary: &str,
user: &str,
keep_dac_read_search: bool,
) -> Command {
// TODO: if we detect we're running in a container as uid 0, perhaps at least switch to the
// "bin" user if we can?
if !running_in_systemd() {
Expand All @@ -31,13 +39,21 @@ pub(crate) fn unprivileged_subprocess(binary: &str, user: &str) -> Command {
cmd.env_remove("HOME");
cmd.env_remove("XDG_DATA_DIR");
cmd.env_remove("USER");

// Determine which capabilities to keep
let cap_set = if keep_dac_read_search {
"-all,+dac_read_search"
} else {
"-all"
};

cmd.args([
"--no-new-privs",
"--init-groups",
"--reuid",
user,
"--bounding-set",
"-all",
cap_set,
"--pdeathsig",
"TERM",
"--",
Expand Down
Loading