rootfs: fix 'can we mount on top of /proc' check

Our previous test for whether we can mount on top of /proc incorrectly
assumed that it would only be called with bind-mount sources. This meant
that having a non bind-mount entry for a pseudo-filesystem (like
overlayfs) with a dummy source set to /proc on the host would let you
bypass the check, which could easily lead to security issues.

In addition, the check should be applied more uniformly to all mount
types, so fix that as well. And add some tests for some of the tricky
cases to make sure we protect against them properly.

Fixes: 331692baa7 ("Only allow proc mount if it is procfs")
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
This commit is contained in:
Aleksa Sarai
2023-12-07 16:23:24 +11:00
parent 8e8b136c49
commit cdff09ab87
3 changed files with 93 additions and 45 deletions
+36 -3
View File
@@ -35,8 +35,7 @@ func TestCheckProcMountOnProc(t *testing.T) {
dest := "/rootfs/proc/"
err := checkProcMount("/rootfs", dest, m)
if err != nil {
// TODO: This test failure is fixed in a later commit in this series.
t.Logf("procfs type mount on /proc should not return an error: %v", err)
t.Fatalf("procfs type mount on /proc should not return an error: %v", err)
}
}
@@ -52,7 +51,41 @@ func TestCheckBindMountOnProc(t *testing.T) {
dest := "/rootfs/proc/"
err := checkProcMount("/rootfs", dest, m)
if err != nil {
t.Fatalf("bind-mount of procfs on top of /proc should not return an error: %v", err)
t.Fatalf("bind-mount of procfs on top of /proc should not return an error (for now): %v", err)
}
}
func TestCheckTrickyMountOnProc(t *testing.T) {
// Make a non-bind mount that looks like a bit like a bind-mount.
m := mountEntry{
Mount: &configs.Mount{
Destination: "/proc",
Source: "/proc",
Device: "overlay",
Data: "lowerdir=/tmp/fakeproc,upperdir=/tmp/fakeproc2,workdir=/tmp/work",
},
}
dest := "/rootfs/proc/"
err := checkProcMount("/rootfs", dest, m)
if err == nil {
t.Fatalf("dodgy overlayfs mount on top of /proc should return an error")
}
}
func TestCheckTrickyBindMountOnProc(t *testing.T) {
// Make a bind mount that looks like it might be a procfs mount.
m := mountEntry{
Mount: &configs.Mount{
Destination: "/proc",
Source: "/sys",
Device: "proc",
Flags: unix.MS_BIND,
},
}
dest := "/rootfs/proc/"
err := checkProcMount("/rootfs", dest, m)
if err == nil {
t.Fatalf("dodgy bind-mount on top of /proc should return an error")
}
}