Skip to content

Commit 5d21ac3

Browse files
committed
fix(bootstrap,sandbox): add Tegra detection logging and extract CDI GID preservation
- Log when Tegra platform is detected and host-files bind mount is added, including the kernel version from the Docker daemon. - Extract CDI GID snapshot logic into `snapshot_cdi_gids()` function that only activates when GPU devices are present (/dev/nvidiactl exists). - Log preserved CDI-injected GIDs when they are restored after initgroups. - Fix cargo fmt formatting issue in docker.rs.
1 parent 168a901 commit 5d21ac3

2 files changed

Lines changed: 42 additions & 19 deletions

File tree

crates/openshell-bootstrap/src/docker.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -613,8 +613,11 @@ pub async fn ensure_container(
613613
.as_deref()
614614
.map_or(false, |k| k.contains("tegra"));
615615
if is_tegra {
616-
const HOST_FILES_DIR: &str =
617-
"/etc/nvidia-container-runtime/host-files-for-container.d";
616+
const HOST_FILES_DIR: &str = "/etc/nvidia-container-runtime/host-files-for-container.d";
617+
tracing::info!(
618+
kernel_version = info.kernel_version.as_deref().unwrap_or("unknown"),
619+
"Detected Tegra platform, bind-mounting {HOST_FILES_DIR} for CDI spec generation"
620+
);
618621
let mut binds = host_config.binds.take().unwrap_or_default();
619622
binds.push(format!("{HOST_FILES_DIR}:{HOST_FILES_DIR}:ro"));
620623
host_config.binds = Some(binds);

crates/openshell-sandbox/src/process.rs

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -414,26 +414,22 @@ pub fn drop_privileges(policy: &SandboxPolicy) -> Result<()> {
414414
target_os = "redox"
415415
)))]
416416
{
417-
// Snapshot the container-level supplemental GIDs (e.g. injected by
418-
// CDI for GPU device access) before initgroups replaces them.
419-
// Exclude GID 0 (root) to avoid inadvertent privilege retention.
420-
let root_gid = nix::unistd::Gid::from_raw(0);
421-
let container_gids: Vec<nix::unistd::Gid> = nix::unistd::getgroups()
422-
.unwrap_or_default()
423-
.into_iter()
424-
.filter(|&g| g != root_gid)
425-
.collect();
417+
let cdi_gids = snapshot_cdi_gids();
426418
nix::unistd::initgroups(user_cstr.as_c_str(), group.gid).into_diagnostic()?;
427-
// Merge back any CDI-injected GIDs that initgroups dropped so that
428-
// exec'd processes retain access to GPU devices (e.g. /dev/nvmap on
429-
// Tegra requires the video GID).
430-
let mut merged: Vec<nix::unistd::Gid> = nix::unistd::getgroups().unwrap_or_default();
431-
for gid in container_gids {
432-
if !merged.contains(&gid) {
433-
merged.push(gid);
419+
if !cdi_gids.is_empty() {
420+
let mut merged: Vec<nix::unistd::Gid> =
421+
nix::unistd::getgroups().unwrap_or_default();
422+
for gid in &cdi_gids {
423+
if !merged.contains(gid) {
424+
merged.push(*gid);
425+
}
434426
}
427+
tracing::info!(
428+
gids = ?cdi_gids.iter().map(|g| g.as_raw()).collect::<Vec<_>>(),
429+
"Preserving CDI-injected supplementary GIDs across initgroups"
430+
);
431+
nix::unistd::setgroups(&merged).into_diagnostic()?;
435432
}
436-
nix::unistd::setgroups(&merged).into_diagnostic()?;
437433
}
438434
}
439435

@@ -477,6 +473,30 @@ pub fn drop_privileges(policy: &SandboxPolicy) -> Result<()> {
477473
Ok(())
478474
}
479475

476+
/// Snapshot supplementary GIDs injected by the container runtime (e.g. via CDI
477+
/// `additionalGids`) before `initgroups` replaces them.
478+
///
479+
/// Only captures GIDs when GPU devices are present — on non-GPU sandboxes the
480+
/// runtime won't inject device-access GIDs so there is nothing to preserve.
481+
/// GID 0 (root) is always excluded to avoid inadvertent privilege retention.
482+
#[cfg(not(any(
483+
target_os = "macos",
484+
target_os = "ios",
485+
target_os = "haiku",
486+
target_os = "redox"
487+
)))]
488+
fn snapshot_cdi_gids() -> Vec<nix::unistd::Gid> {
489+
if !std::path::Path::new("/dev/nvidiactl").exists() {
490+
return Vec::new();
491+
}
492+
let root_gid = nix::unistd::Gid::from_raw(0);
493+
nix::unistd::getgroups()
494+
.unwrap_or_default()
495+
.into_iter()
496+
.filter(|&g| g != root_gid)
497+
.collect()
498+
}
499+
480500
/// Process exit status.
481501
#[derive(Debug, Clone, Copy)]
482502
pub struct ProcessStatus {

0 commit comments

Comments
 (0)