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: 9c444070ec ("Open bind mount sources from the host userns")
Reported-by: Felix Wilhelm <fwilhelm@google.com>
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
This commit is contained in:
Aleksa Sarai
2021-11-18 17:01:43 +11:00
parent 0d5ac13200
commit dde509df4e
2 changed files with 15 additions and 0 deletions
+3
View File
@@ -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))
+12
View File
@@ -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
}