- 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
492 lines
13 KiB
Markdown
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.
|