bootc-docs/exec-in-host-mount-namespace/bootc-exec-in-host-mount-namespace-technical-guide.md
robojerk 526f1c1afd Initial commit: Comprehensive Debian bootc documentation
- Complete documentation for all bootc commands and subcommands
- Debian-specific adaptations and workarounds
- Manual installation methods to bypass bootc reliability issues
- Technical guides with Rust source code analysis
- Flowcharts and external command references
- Hidden command documentation (bootc internals, state, etc.)
- Composefs integration analysis
- Base image creation guides (with and without bootc binary)
- Management scripts and automation
- Comprehensive troubleshooting and examples
2025-09-15 14:02:28 -07:00

492 lines
13 KiB
Markdown

# bootc exec-in-host-mount-namespace - Technical Guide
## Overview
`bootc exec-in-host-mount-namespace` is a hidden command that executes a given command in the host mount namespace. This is a critical low-level operation used internally by bootc for system operations that need to access the host's mount namespace from within a container or isolated environment.
## Purpose
The exec-in-host-mount-namespace command serves several critical functions:
1. **Namespace Isolation**: Execute commands in the host mount namespace from within containers
2. **System Operations**: Perform operations that require access to the host's filesystem view
3. **Installation Support**: Support installation operations that need host mount access
4. **Debugging**: Provide access to host mount namespace for debugging and maintenance
## Command Structure
```rust
/// Execute the given command in the host mount namespace
#[clap(hide = true)]
ExecInHostMountNamespace {
#[clap(trailing_var_arg = true, allow_hyphen_values = true)]
args: Vec<OsString>,
}
```
## Core Functionality
### Purpose
The command executes a specified command in the host mount namespace, allowing operations that need to access the host's filesystem view from within a container or isolated environment.
### Usage
```bash
bootc exec-in-host-mount-namespace [ARGS]...
```
### Implementation
```rust
#[context("Re-exec in host mountns")]
pub(crate) fn exec_in_host_mountns(args: &[std::ffi::OsString]) -> Result<()> {
let (cmd, args) = args
.split_first()
.ok_or_else(|| anyhow::anyhow!("Missing command"))?;
tracing::trace!("{cmd:?} {args:?}");
// Open the host mount namespace
let pid1mountns = std::fs::File::open("/proc/1/ns/mnt").context("open pid1 mountns")?;
// Move into the host mount namespace
rustix::thread::move_into_link_name_space(
pid1mountns.as_fd(),
Some(rustix::thread::LinkNameSpaceType::Mount),
)
.context("setns")?;
// Change to root directory
rustix::process::chdir("/").context("chdir")?;
// Work around supermin doing chroot() and not pivot_root
if !Utf8Path::new("/usr").try_exists().context("/usr")?
&& Utf8Path::new("/root/usr")
.try_exists()
.context("/root/usr")?
{
tracing::debug!("Using supermin workaround");
rustix::process::chroot("/root").context("chroot")?;
}
// Execute the command
Err(Command::new(cmd).args(args).arg0(bootc_utils::NAME).exec()).context("exec")?
}
```
## Technical Details
### 1. Mount Namespace Operations
The command uses Linux mount namespace operations to switch to the host's mount namespace:
```rust
// Open the host mount namespace (PID 1)
let pid1mountns = std::fs::File::open("/proc/1/ns/mnt").context("open pid1 mountns")?;
// Move into the host mount namespace
rustix::thread::move_into_link_name_space(
pid1mountns.as_fd(),
Some(rustix::thread::LinkNameSpaceType::Mount),
)
.context("setns")?;
```
### 2. Directory Operations
After switching namespaces, the command ensures proper directory context:
```rust
// Change to root directory
rustix::process::chdir("/").context("chdir")?;
// Work around supermin doing chroot() and not pivot_root
if !Utf8Path::new("/usr").try_exists().context("/usr")?
&& Utf8Path::new("/root/usr")
.try_exists()
.context("/root/usr")?
{
tracing::debug!("Using supermin workaround");
rustix::process::chroot("/root").context("chroot")?;
}
```
### 3. Command Execution
The command executes the specified command with proper argument handling:
```rust
// Execute the command
Err(Command::new(cmd).args(args).arg0(bootc_utils::NAME).exec()).context("exec")?
```
## Command Routing
The command is routed through the main CLI dispatcher:
```rust
Opt::ExecInHostMountNamespace { args } => {
crate::install::exec_in_host_mountns(args.as_slice())
}
```
## Helper Functions
### 1. run_in_host_mountns
A helper function to create a command that will execute in the host mount namespace:
```rust
/// Run a command in the host mount namespace
pub(crate) fn run_in_host_mountns(cmd: &str) -> Result<Command> {
let mut c = Command::new(bootc_utils::reexec::executable_path()?);
c.lifecycle_bind()
.args(["exec-in-host-mount-namespace", cmd]);
Ok(c)
}
```
### 2. ensure_self_unshared_mount_namespace
A function to ensure the process is in an unshared mount namespace:
```rust
#[context("Ensuring mountns")]
pub(crate) fn ensure_self_unshared_mount_namespace() -> Result<()> {
let uid = rustix::process::getuid();
if !uid.is_root() {
tracing::debug!("Not root, assuming no need to unshare");
return Ok(());
}
let recurse_env = "_ostree_unshared";
let ns_pid1 = std::fs::read_link("/proc/1/ns/mnt").context("Reading /proc/1/ns/mnt")?;
let ns_self = std::fs::read_link("/proc/self/ns/mnt").context("Reading /proc/self/ns/mnt")?;
// If we already appear to be in a mount namespace, or we're already pid1, we're done
if ns_pid1 != ns_self {
tracing::debug!("Already in a mount namespace");
return Ok(());
}
if std::env::var_os(recurse_env).is_some() {
let am_pid1 = rustix::process::getpid().is_init();
if am_pid1 {
tracing::debug!("We are pid 1");
return Ok(());
} else {
anyhow::bail!("Failed to unshare mount namespace");
}
}
bootc_utils::reexec::reexec_with_guardenv(recurse_env, &["unshare", "-m", "--"])
}
```
## Use Cases
### 1. Container Operations
When running inside a container, this command allows access to the host's mount namespace:
```bash
# Execute a command in the host mount namespace
bootc exec-in-host-mount-namespace ls /host/path
# Mount something in the host namespace
bootc exec-in-host-mount-namespace mount /dev/sda1 /mnt
```
### 2. Installation Support
During installation operations, this command provides access to the host filesystem:
```bash
# Access host filesystem during installation
bootc exec-in-host-mount-namespace mkdir -p /host/var/lib/bootc
# Copy files to host filesystem
bootc exec-in-host-mount-namespace cp /source/file /host/destination/
```
### 3. Debugging and Maintenance
For debugging and maintenance operations that need host access:
```bash
# Check host filesystem
bootc exec-in-host-mount-namespace df -h
# View host processes
bootc exec-in-host-mount-namespace ps aux
# Check host system status
bootc exec-in-host-mount-namespace systemctl status
```
### 4. System Integration
For system integration operations that require host mount namespace access:
```bash
# Update host bootloader
bootc exec-in-host-mount-namespace grub-mkconfig -o /boot/grub/grub.cfg
# Update host initramfs
bootc exec-in-host-mount-namespace update-initramfs -u
```
## Technical Implementation
### 1. Namespace Switching
The command uses the `setns` system call to switch to the host mount namespace:
```rust
rustix::thread::move_into_link_name_space(
pid1mountns.as_fd(),
Some(rustix::thread::LinkNameSpaceType::Mount),
)
.context("setns")?;
```
### 2. Process Execution
The command uses `exec` to replace the current process with the target command:
```rust
Err(Command::new(cmd).args(args).arg0(bootc_utils::NAME).exec()).context("exec")?
```
### 3. Error Handling
Comprehensive error handling with context:
```rust
#[context("Re-exec in host mountns")]
pub(crate) fn exec_in_host_mountns(args: &[std::ffi::OsString]) -> Result<()> {
// Implementation with automatic error context
}
```
## Security Considerations
### 1. Privilege Requirements
The command requires appropriate privileges to access mount namespaces:
```rust
let uid = rustix::process::getuid();
if !uid.is_root() {
tracing::debug!("Not root, assuming no need to unshare");
return Ok(());
}
```
### 2. Namespace Access
The command accesses the host mount namespace through `/proc/1/ns/mnt`:
```rust
let pid1mountns = std::fs::File::open("/proc/1/ns/mnt").context("open pid1 mountns")?;
```
### 3. Process Isolation
The command executes in a different mount namespace, which provides isolation:
- **Mount Isolation**: Commands run in the host mount namespace
- **Process Replacement**: The current process is replaced with the target command
- **Namespace Switching**: Uses `setns` to switch mount namespaces
## Performance Characteristics
### 1. Execution Time
- **Fast**: Minimal overhead for namespace switching
- **Atomic**: Single atomic operation
- **Efficient**: Direct system call usage
### 2. Resource Usage
- **Low CPU**: Minimal CPU usage
- **Low Memory**: Minimal memory usage
- **Namespace Overhead**: Small overhead for namespace operations
### 3. System Impact
- **Namespace Switch**: Changes mount namespace
- **Process Replacement**: Replaces current process
- **Host Access**: Provides access to host filesystem
## Integration Points
### 1. Installation System
The command is used by the installation system for host operations:
```rust
// Used during installation
pub(crate) fn run_in_host_mountns(cmd: &str) -> Result<Command> {
let mut c = Command::new(bootc_utils::reexec::executable_path()?);
c.lifecycle_bind()
.args(["exec-in-host-mount-namespace", cmd]);
Ok(c)
}
```
### 2. Mount Namespace Management
The command integrates with mount namespace management:
```rust
// Ensure unshared mount namespace
ensure_self_unshared_mount_namespace()?;
```
### 3. Container Operations
The command supports container operations that need host access:
```rust
// Used in container contexts
if !external_source && std::env::var_os("BOOTC_SKIP_UNSHARE").is_none() {
super::cli::ensure_self_unshared_mount_namespace()?;
}
```
## Error Handling
### 1. Common Error Scenarios
#### Missing Command
```rust
let (cmd, args) = args
.split_first()
.ok_or_else(|| anyhow::anyhow!("Missing command"))?;
```
#### Namespace Access Error
```rust
let pid1mountns = std::fs::File::open("/proc/1/ns/mnt").context("open pid1 mountns")?;
```
#### Namespace Switch Error
```rust
rustix::thread::move_into_link_name_space(
pid1mountns.as_fd(),
Some(rustix::thread::LinkNameSpaceType::Mount),
)
.context("setns")?;
```
### 2. Error Recovery
The command provides comprehensive error context:
```rust
#[context("Re-exec in host mountns")]
pub(crate) fn exec_in_host_mountns(args: &[std::ffi::OsString]) -> Result<()> {
// Implementation with automatic error context
}
```
## Testing and Validation
### 1. Unit Tests
```rust
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_exec_in_host_mountns() {
// Test command execution
let args = vec!["ls".into(), "/".into()];
let result = exec_in_host_mountns(&args);
// Verify result
}
}
```
### 2. Integration Tests
```rust
#[tokio::test]
async fn test_exec_in_host_mountns_integration() {
// Test namespace switching
let test_env = TestEnvironment::new().await.unwrap();
// Test command execution in host namespace
let result = test_env.run_command("bootc", &["exec-in-host-mount-namespace", "ls", "/"]).await;
assert!(result.is_ok());
}
```
## Best Practices
### 1. Usage Guidelines
- **Internal Use**: This is an internal command, not for direct user use
- **Container Context**: Use within container environments
- **Host Access**: Use when host mount namespace access is needed
- **Debugging**: Use for debugging and maintenance operations
### 2. Security Considerations
- **Privilege Requirements**: Ensure appropriate privileges
- **Namespace Access**: Verify namespace access permissions
- **Command Validation**: Validate commands before execution
- **Error Handling**: Implement proper error handling
### 3. Performance Optimization
- **Minimal Overhead**: Use only when necessary
- **Efficient Execution**: Use direct system calls
- **Resource Management**: Manage resources appropriately
- **Error Recovery**: Implement proper error recovery
## Future Enhancements
### 1. Additional Namespace Support
Potential support for other namespaces:
```rust
pub(crate) enum NamespaceType {
Mount,
PID,
Network,
User,
IPC,
UTS,
Cgroup,
}
```
### 2. Enhanced Security
Enhanced security features:
```rust
pub(crate) struct SecurityOptions {
pub drop_capabilities: bool,
pub restrict_filesystem: bool,
pub sandbox_command: bool,
}
```
### 3. Monitoring and Logging
Enhanced monitoring and logging:
```rust
pub(crate) struct ExecutionOptions {
pub log_execution: bool,
pub monitor_resources: bool,
pub track_namespace_changes: bool,
}
```
This technical guide provides comprehensive understanding of the bootc exec-in-host-mount-namespace system's functionality, implementation, and usage patterns.