@@ -33,13 +33,23 @@ use {
3333 } ,
3434} ;
3535
36+ /// Distinguishes Docker from Podman for behaviour that differs between the two
37+ /// OCI runtimes (hardening flags, host-gateway resolution, etc.).
38+ #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
39+ pub ( crate ) enum BackendKind {
40+ Docker ,
41+ Podman ,
42+ }
43+
3644/// Docker/Podman-based sandbox implementation.
3745///
3846/// The `cli` field selects the container CLI binary (`"docker"` or `"podman"`).
3947/// Podman's CLI is a drop-in replacement for Docker, so both backends share
40- /// this single implementation.
48+ /// this single implementation. `kind` carries the typed backend identity for
49+ /// behaviour branching without string comparisons.
4150pub struct DockerSandbox {
4251 pub config : SandboxConfig ,
52+ kind : BackendKind ,
4353 cli : & ' static str ,
4454 backend_label : & ' static str ,
4555}
@@ -48,6 +58,7 @@ impl DockerSandbox {
4858 pub fn new ( config : SandboxConfig ) -> Self {
4959 Self {
5060 config,
61+ kind : BackendKind :: Docker ,
5162 cli : "docker" ,
5263 backend_label : "docker" ,
5364 }
@@ -56,6 +67,7 @@ impl DockerSandbox {
5667 pub fn podman ( config : SandboxConfig ) -> Self {
5768 Self {
5869 config,
70+ kind : BackendKind :: Podman ,
5971 cli : "podman" ,
6072 backend_label : "podman" ,
6173 }
@@ -138,7 +150,7 @@ impl DockerSandbox {
138150 /// Podman uses a bridge whose gateway we can query via
139151 /// `podman network inspect`.
140152 pub ( crate ) fn resolve_host_gateway ( & self ) -> String {
141- if self . cli != "podman" {
153+ if self . kind != BackendKind :: Podman {
142154 return "host-gateway" . to_string ( ) ;
143155 }
144156
@@ -179,7 +191,7 @@ impl DockerSandbox {
179191 /// `is_prebuilt` controls whether `--read-only` is applied: prebuilt images
180192 /// already have packages baked in so the root FS can be read-only, while
181193 /// non-prebuilt images need a writable root for `apt-get` provisioning.
182- pub ( crate ) fn hardening_args ( is_prebuilt : bool ) -> Vec < String > {
194+ pub ( crate ) fn hardening_args ( is_prebuilt : bool , kind : BackendKind ) -> Vec < String > {
183195 let mut args = vec ! [
184196 // --- Capability / privilege ---
185197 "--cap-drop" . to_string( ) ,
@@ -196,19 +208,28 @@ impl DockerSandbox {
196208 // and the `hostname` command do not reveal the host identity.
197209 "--hostname" . to_string( ) ,
198210 "sandbox" . to_string( ) ,
199- // Mask /sys subtrees that expose host hardware identifiers
200- // (serial numbers, BIOS/UEFI data, disk models, LUKS UUIDs).
201- // Empty read-only tmpfs overlays hide the underlying sysfs entries
202- // and work identically on Docker and Podman.
203- "--tmpfs" . to_string( ) ,
204- "/sys/firmware:ro,nosuid" . to_string( ) ,
205- "--tmpfs" . to_string( ) ,
206- "/sys/class/dmi:ro,nosuid" . to_string( ) ,
207- "--tmpfs" . to_string( ) ,
208- "/sys/devices/virtual/dmi:ro,nosuid" . to_string( ) ,
209- "--tmpfs" . to_string( ) ,
210- "/sys/class/block:ro,nosuid" . to_string( ) ,
211211 ] ;
212+ // Mask /sys subtrees that expose host hardware identifiers
213+ // (serial numbers, BIOS/UEFI data, disk models, LUKS UUIDs).
214+ // Empty read-only tmpfs overlays hide the underlying sysfs entries.
215+ //
216+ // Podman is excluded: its OCI runtime performs "tmpcopyup" on sysfs
217+ // tmpfs mounts, copying directory contents into the tmpfs first.
218+ // With --cap-drop ALL some sysfs files are permission-denied even for
219+ // root, causing the mount (and container startup) to fail. Podman
220+ // already masks /sys/firmware via its built-in OCI MaskedPaths.
221+ if kind != BackendKind :: Podman {
222+ args. extend ( [
223+ "--tmpfs" . to_string ( ) ,
224+ "/sys/firmware:ro,nosuid" . to_string ( ) ,
225+ "--tmpfs" . to_string ( ) ,
226+ "/sys/class/dmi:ro,nosuid" . to_string ( ) ,
227+ "--tmpfs" . to_string ( ) ,
228+ "/sys/devices/virtual/dmi:ro,nosuid" . to_string ( ) ,
229+ "--tmpfs" . to_string ( ) ,
230+ "/sys/class/block:ro,nosuid" . to_string ( ) ,
231+ ] ) ;
232+ }
212233 if is_prebuilt {
213234 args. push ( "--read-only" . to_string ( ) ) ;
214235 }
@@ -321,7 +342,7 @@ impl Sandbox for DockerSandbox {
321342 }
322343
323344 args. extend ( self . resource_args ( ) ) ;
324- args. extend ( Self :: hardening_args ( is_prebuilt) ) ;
345+ args. extend ( Self :: hardening_args ( is_prebuilt, self . kind ) ) ;
325346 args. extend ( self . workspace_args ( ) ) ;
326347 args. extend ( self . home_persistence_args ( id) ?) ;
327348
0 commit comments