From dde509df4e28cec33b3c99c6cda3d4fd5beafc77 Mon Sep 17 00:00:00 2001 From: Aleksa Sarai Date: Thu, 18 Nov 2021 17:01:43 +1100 Subject: [PATCH] specconv: do not permit null bytes in mount fields Using null bytes as control characters for sending strings via netlink opens us up to a user explicitly putting a null byte in a mount string (which JSON will happily let you do) and then causing us to open a mount path different to the one expected. In practice this is more of an issue in an environment such as Kubernetes where you may have path-based access control policies (which are more susceptible to these kinds of flaws). Found by Google Project Zero. Fixes: 9c444070ec7b ("Open bind mount sources from the host userns") Reported-by: Felix Wilhelm Signed-off-by: Aleksa Sarai --- libcontainer/container_linux.go | 3 +++ libcontainer/specconv/spec_linux.go | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/libcontainer/container_linux.go b/libcontainer/container_linux.go index 1632cce06d7..4c56582ff1a 100644 --- a/libcontainer/container_linux.go +++ b/libcontainer/container_linux.go @@ -2195,6 +2195,9 @@ func (c *linuxContainer) bootstrapData(cloneFlags uintptr, nsMaps map[configs.Na var mounts []byte for _, m := range c.config.Mounts { if m.IsBind() { + if strings.IndexByte(m.Source, 0) >= 0 { + return nil, fmt.Errorf("mount source string contains null byte: %q", m.Source) + } mounts = append(mounts, []byte(m.Source)...) } mounts = append(mounts, byte(0)) diff --git a/libcontainer/specconv/spec_linux.go b/libcontainer/specconv/spec_linux.go index 9e39a70bede..cf54cf3dd5a 100644 --- a/libcontainer/specconv/spec_linux.go +++ b/libcontainer/specconv/spec_linux.go @@ -407,6 +407,18 @@ func createLibcontainerMount(cwd string, m specs.Mount) (*configs.Mount, error) mnt.Source = filepath.Join(cwd, m.Source) } } + + // None of the mount arguments can contain a null byte. Normally such + // strings would either cause some other failure or would just be truncated + // when we hit the null byte, but because we serialise these strings as + // netlink messages (which don't have special null-byte handling) we need + // to block this as early as possible. + if strings.IndexByte(mnt.Source, 0) >= 0 || + strings.IndexByte(mnt.Destination, 0) >= 0 || + strings.IndexByte(mnt.Device, 0) >= 0 { + return nil, errors.New("mount field contains null byte") + } + return mnt, nil }