runc/libcontainer: insecure handling of null-bytes in bind mount sources

We discussed this vulnerability as part of our weekly podcast on 15 December 2021

Basic idea here is that you could mount unintended paths due to embeding null-bytes in acceptable mount and generally improper handling of null-bytes within a mount source. While Go does not provide any special handling for strings containing null bytes, the send_mountsources written in C just iterates over the provided message mounting every null-terminated substring and passes the resultant fds to the child. An attacker with partial control of those mount sources may be able to bypass restrictions implemented by something like Kubernetes on hostpaths that can be mounted.

This can also be utilized by exploiting another bug, an integer overflow in the serialization process. To forward the mount sources to nsexec.c the type Bytemsg is used, this is sent along with a small header containing a 16bit unsigned integer reflecting the size of the data. The Len() method however can overflow the 16bit size. This creates a situation where the reciever things the bytes over the 16bit length are part of a new message allowing arbitrary messages to be crafted; such the CLONE_FLAGS_ATTR message which can be used to provide clone flags enabling the final container to run with the host’s namespace.

Patch: The Len() bug was patched by panicing when length goes beyond 16bits. The patch commit does not seem to deal with the embedded null-bytes.