BONAN RUAN / INDUSTRY RESEARCH

CONTAINER RUNTIME BOUNDARIES

Dilemma

A read-only runtime still trusts the kernel

A technical research project I developed in industry: examining the boundary between runC’s read-only protection and the shared kernel, then studying constrained ELF file injection that preserves the original program flow.

KCon 2022 · Original talk title · Source withheld due to attack impact

The boundary between read-only protection and a shared file object A runtime reference in the container passes through a read-only mount but still refers to the host runC file. Ordinary writes stop at the read-only boundary; historical Dirty Pipe conditions allow changes through the shared kernel’s page cache. CONTAINERHOST /proc/…/exeruntime executable reference runC / ELF ro-bind ordinary write blocked still the host file object SHARED KERNEL / PAGE CACHE Dirty Pipe · vulnerable kernel in the 2022 study content changed through page cache ACCESS POLICY ≠ FILE IDENTITY Container, read-only protection, and the shared kernel Ordinary writes are blocked by read-only protection. Under the historical vulnerable conditions in this study, Dirty Pipe can change the host runC file through the kernel. CONTAINER/proc/…/exeREAD-ONLY ACCESS HOSTrunC / ELF ro-bind · SAME FILE SHARED KERNEL / PAGE CACHEDirty Pipe · historical vulnerable conditions
READ-ONLY ≠ A SEPARATE COPY2022 / CONCEPTUAL MODEL
Industry technical research

Bonan Ruan · NSFOCUS Nebula Lab

KCon 2022

Beijing · Technical talk

runC + Linux

Runtime–kernel trust boundary

Source withheld

Based on published materials

A new boundary can still expose the same file

Two questions guide the study: what does read-only protection trust, and can altered file content coexist with the runtime’s original behavior?

01 / OBJECT IDENTITY

Namespace isolation does not create a copy

runC enters container namespaces during initialization. With the required permissions, a /proc executable magic link can refer to a file object outside the namespace. Hidden paths do not necessarily mean unreachable objects.

02 / PROTECTION ASSUMPTION

Read-only protection still trusts the kernel

The 2019 repair used a read-only bind mount to block ordinary writes while reducing copy costs. Dirty Pipe in 2022 changed kernel page-cache content outside that protection. It did not require the old runC vulnerability to remain unpatched.

03 / ENGINEERING CONSTRAINT

Redirect execution, preserve the original flow

Replacing the binary destroys normal runtime behavior. The study instead used static ELF file injection under file-size, space, and PIE / ASLR constraints, returning execution to the original entry point.

Sources: write-up §§2 and 4; slides pp. 6–14 and 19–25. The following models describe the historical mechanisms studied in 2022, without inferring the state of current runC releases. WP ↗

Change the protection, trace the boundary

Choose a runtime protection and a write condition. Trace the object being referenced, the layer that blocks changes, and whether the host file remains in the path.

DILEMMA / FILE IDENTITY & WRITE BOUNDARIESMODEL · NO LIVE TEST

CONTAINER

RUNTIME REFERENCE/proc/…/exe

Executable on a read-only mount

HOST

ORIGINAL FILErunC / ELF

The read-only mount refers to the same host runC file object

Same file object

LINUX / PAGE CACHEHistorical Dirty Pipe conditions
IDENTITY
Host original file
WRITE CONDITION
Not evaluated yet
HOST FILE
Not evaluated yet

Choose the protection and condition, then trace the file reference across the container boundary.

WHERE PROTECTION APPLIES

Separate permission from identity

Read-only restrictions change access policy without necessarily creating a separate file copy. Advance the flow to compare this boundary with memfd.

Start: read-only mount + historical Dirty Pipe conditionsWP §2.3 · Repair designs ↗

Sources: WP §2.3 and slides pp. 12–14. The memfd design copies and seals the executable; the read-only design retains the same object. The 2019 discussion explains the cost and compatibility trade-off. A sealed copy isolates the host original in this study’s scope, without implying protection from arbitrary kernel flaws.

Let the original program keep running

The refinement preserves runC rather than replacing it: redirect the entry within constrained space, then restore the original flow. Normal behavior does not prove file integrity.

runC / ELFFILE SIZE UNCHANGED · NOT TO SCALE
Original entryAdded logic (abstract)Original runC flow
Parent → original entryChild → separate logic

The original entry leads directly into runC’s existing logic.

STATIC FILE INJECTION / STUDY MODEL

Original file, original entry

This diagram shows file structure and control flow. The study modifies an ELF file before execution, rather than injecting memory into a running process.

Two constraints must be solved together

Dirty Pipe cannot grow a file or begin an overwrite at a page boundary. PIE / ASLR changes load addresses, so returning to the original entry must account for runtime address relationships. The diagram omits payloads, offsets, and exploit implementation.

157B

Payload length in the write-up

Documents the historical space constraint. Payload content is not provided here.

168B

NOTE space in the dynamic sample

The tested build had enough space for that length, based on its specific section layout.

68B

NOTE space in the static sample

Too small for the same placement. The study examined another region and tested subsequent behavior in that sample.

Sources: WP §§4.2–4.3; slides pp. 20–25. Byte counts describe particular historical builds and the implementation, rather than success rates, performance results, or cross-version guarantees. Layout compatibility requires per-build verification. Slides ↗ · Original Dirty Pipe analysis ↗

One mechanism, two entry scenarios

A compromised workload and an image-based path have different timing constraints. Compare their prerequisites, reported demonstrations, and points for defensive observation.

The runtime re-enters an existing container

With execution inside a container, the historical scenario examines process and file references when the runtime enters that container again.

PREREQUISITES
Requires the relevant process visibility, permissions, and vulnerable conditions. Dynamic linking is not a general prerequisite for this scenario.
REPORTED DEMONSTRATION
The write-up’s exec demonstration still showed errors, while later Docker container creation worked. Preserving original logic did not eliminate all visible anomalies.

Slides pp. 16, 26 · WP §3.1, demonstration 1 ↗

DEVELOPMENT

Reduce workload entry points

Workload security and least privilege influence initial access. The article recommends rootless operation where feasible to reduce privileges available to later exploitation.

DEPENDENCIES

Inspect images and the supply chain

The article recommends image scanning and allowlists. Runtime build and loading conditions matter; image deployments do not all fit the same scenario.

RUNTIME

Check integrity as well as behavior

Update the kernel and runtime; monitor host runC changes and anomalous processes. Successful container startup alone does not establish runtime file integrity.

Scenarios and demonstrations: WP §3.1 and §4 “Effect testing”; slides pp. 16, 26–27. Defensive recommendations: WP §5 and slides pp. 31–32, presented in the context of the original study.

Dilemma: runC’s Achilles’ Heel

An industry research talk at KCon 2022. The write-up records protection designs, ELF file-injection constraints, and demonstrations in two scenarios. The study had no separate project name; this exhibit uses the original talk title.

Bonan Ruan / 阮博男 · NSFOCUS · Nebula Lab · Security researcher at the time

I did not release the research source code because of its attack impact. These original diagrams explain the published mechanisms, preserving the study’s prerequisites and scope.

Expand sources and a reading route