forked from opencontainers/runc
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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]: torvalds/linux@bfedb58 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>
- Loading branch information
Showing
20 changed files
with
608 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,7 @@ | |
run: | ||
build-tags: | ||
- seccomp | ||
- runc_nodmz | ||
|
||
linters: | ||
disable-all: true | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ | |
run: | ||
build-tags: | ||
- seccomp | ||
- runc_nodmz | ||
|
||
linters: | ||
enable: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
# NOTE: Make sure you keep this file in sync with scripts/lib.sh. | ||
|
||
GO ?= go | ||
GOARCH ?= $(shell $(GO) env GOARCH) | ||
|
||
ifneq ($(shell grep -i "ID_LIKE=.*suse" /etc/os-release),) | ||
# openSUSE has a custom PLATFORM | ||
PLATFORM ?= suse-linux | ||
IS_SUSE := 1 | ||
else | ||
PLATFORM ?= linux-gnu | ||
endif | ||
|
||
ifeq ($(GOARCH),$(shell GOARCH= $(GO) env GOARCH)) | ||
# use the native CC and STRIP | ||
HOST := | ||
else ifeq ($(GOARCH),386) | ||
# Always use the 64-bit compiler to build the 386 binary, which works for | ||
# the more common cross-build method for x86 (namely, the equivalent of | ||
# dpkg --add-architecture). | ||
ifdef IS_SUSE | ||
# There is no x86_64-suse-linux-gcc, so use the native one. | ||
HOST := | ||
CPU_TYPE := i586 | ||
else | ||
HOST := x86_64-$(PLATFORM)- | ||
CPU_TYPE := i686 | ||
endif | ||
CFLAGS := -m32 -march=$(CPU_TYPE) $(CFLAGS) | ||
else ifeq ($(GOARCH),amd64) | ||
ifdef IS_SUSE | ||
# There is no x86_64-suse-linux-gcc, so use the native one. | ||
HOST := | ||
else | ||
HOST := x86_64-$(PLATFORM)- | ||
endif | ||
else ifeq ($(GOARCH),arm64) | ||
HOST := aarch64-$(PLATFORM)- | ||
else ifeq ($(GOARCH),arm) | ||
# HOST already configured by release_build.sh in this case. | ||
else ifeq ($(GOARCH),armel) | ||
HOST := arm-$(PLATFORM)eabi- | ||
else ifeq ($(GOARCH),armhf) | ||
HOST := arm-$(PLATFORM)eabihf- | ||
else ifeq ($(GOARCH),ppc64le) | ||
HOST := powerpc64le-$(PLATFORM)- | ||
else ifeq ($(GOARCH),riscv64) | ||
HOST := riscv64-$(PLATFORM)- | ||
else ifeq ($(GOARCH),s390x) | ||
HOST := s390x-$(PLATFORM)- | ||
else | ||
$(error Unsupported GOARCH $(GOARCH)) | ||
endif | ||
|
||
ifeq ($(origin CC),$(filter $(origin CC),undefined default)) | ||
# Override CC if it's undefined or just the default value set by Make. | ||
CC := $(HOST)gcc | ||
export CC | ||
endif | ||
STRIP ?= $(HOST)strip | ||
export STRIP |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/runc-dmz |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# Get CC values for cross-compilation. | ||
include ../../cc_platform.mk | ||
|
||
runc-dmz: _dmz.c | ||
$(CC) $(CFLAGS) -static -o $@ $^ | ||
$(STRIP) -gs $@ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
#include <unistd.h> | ||
|
||
extern char **environ; | ||
|
||
int main(int argc, char **argv) | ||
{ | ||
if (argc < 1) | ||
return 127; | ||
return execve(argv[0], argv, environ); | ||
} |
Oops, something went wrong.