mirror of
https://github.com/opencontainers/runc.git
synced 2026-07-11 06:03:57 +08:00
runc-dmz: reduce memfd binary cloning cost with small C binary
The idea is to remove the need for cloning the entire runc binary by replacing the final execve() call of the container process with an execve() call to a clone of a small C binary which just does an execve() of its arguments. This provides similar protection against CVE-2019-5736 but without requiring a >10MB binary copy for each "runc init". When compiled with musl, runc-dmz is 13kB (though unfortunately with glibc, it is 1.1MB which is still quite large). It should be noted that there is still a window where the container processes could get access to the host runc binary, but because we set ourselves as non-dumpable the container would need CAP_SYS_PTRACE (which is not enabled by default in Docker) in order to get around the proc_fd_access_allowed() checks. In addition, since Linux 4.10[1] the kernel blocks access entirely for user namespaced containers in this scenario. For those cases we cannot use runc-dmz, but most containers won't have this issue. This new runc-dmz binary can be opted out of at compile time by setting the "runc_nodmz" buildtag, and at runtime by setting the RUNC_DMZ=legacy environment variable. In both cases, runc will fall back to the classic /proc/self/exe-based cloning trick. If /proc/self/exe is already a sealed memfd (namely if the user is using contrib/cmd/memfd-bind to create a persistent sealed memfd for runc), neither runc-dmz nor /proc/self/exe cloning will be used because they are not necessary. [1]: https://github.com/torvalds/linux/commit/bfedb589252c01fa505ac9f6f2a3d5d68d707ef4 Co-authored-by: lifubang <lifubang@acmcoder.com> Signed-off-by: lifubang <lifubang@acmcoder.com> [cyphar: address various review nits] [cyphar: fix runc-dmz cross-compilation] [cyphar: embed runc-dmz into runc binary and clone in Go code] [cyphar: make runc-dmz optional, with fallback to /proc/self/exe cloning] [cyphar: do not use runc-dmz when the container has certain privs] Co-authored-by: Aleksa Sarai <cyphar@cyphar.com> Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
This commit is contained in:
@@ -28,6 +28,7 @@ jobs:
|
||||
rootless: ["rootless", ""]
|
||||
race: ["-race", ""]
|
||||
criu: ["", "criu-dev"]
|
||||
dmz: ["", "runc_nodmz"]
|
||||
exclude:
|
||||
- criu: criu-dev
|
||||
rootless: rootless
|
||||
@@ -35,6 +36,10 @@ jobs:
|
||||
go-version: 1.20.x
|
||||
- criu: criu-dev
|
||||
race: -race
|
||||
- dmz: runc_nodmz
|
||||
criu: criu-dev
|
||||
- dmz: runc_nodmz
|
||||
os: ubuntu-20.04
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
@@ -71,6 +76,8 @@ jobs:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
|
||||
- name: build
|
||||
env:
|
||||
EXTRA_BUILDTAGS: ${{ matrix.dmz }}
|
||||
run: sudo -E PATH="$PATH" make EXTRA_FLAGS="${{ matrix.race }}" all
|
||||
|
||||
- name: install bats
|
||||
@@ -80,6 +87,8 @@ jobs:
|
||||
|
||||
- name: unit test
|
||||
if: matrix.rootless != 'rootless'
|
||||
env:
|
||||
EXTRA_BUILDTAGS: ${{ matrix.dmz }}
|
||||
run: sudo -E PATH="$PATH" -- make TESTFLAGS="${{ matrix.race }}" localunittest
|
||||
|
||||
- name: add rootless user
|
||||
@@ -113,8 +122,12 @@ jobs:
|
||||
# However, we do not have 32-bit ARM CI, so we use i386 for testing 32bit stuff.
|
||||
# We are not interested in providing official support for i386.
|
||||
cross-i386:
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 15
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
dmz: ["", "runc_nodmz"]
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
|
||||
@@ -136,4 +149,6 @@ jobs:
|
||||
go-version: 1.x # Latest stable
|
||||
|
||||
- name: unit test
|
||||
env:
|
||||
EXTRA_BUILDTAGS: ${{ matrix.dmz }}
|
||||
run: sudo -E PATH="$PATH" -- make GOARCH=386 localunittest
|
||||
|
||||
Reference in New Issue
Block a user