minijail: Check for symlinks immediately before mount().
Checking for symlinks at minijail_bind() time still leaves a pretty big
window for the check to be raced and the source path of a bind mount to
be modified between minijail_bind() and the corresponding mount() call.
Check immediately before the mount() call to make the window as small
as possible.
BUG=b:243161816
TEST=security.Minijail*, login.Chrome, arc.Boot.
Change-Id: I232274afb650df217ff94db647e535593b80fbdd
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/minijail/+/3841217
Auto-Submit: Jorge Lucangeli Obes <jorgelo@chromium.org>
Reviewed-by: Ben Scarlato <akhna@google.com>
Commit-Queue: Jorge Lucangeli Obes <jorgelo@chromium.org>
Tested-by: Jorge Lucangeli Obes <jorgelo@chromium.org>
diff --git a/libminijail.c b/libminijail.c
index 794a896..150b0c2 100644
--- a/libminijail.c
+++ b/libminijail.c
@@ -996,12 +996,20 @@
{
unsigned long flags = MS_BIND;
+ /*
+ * Check for symlinks in bind-mount source paths to warn the user early.
+ * Minijail will perform one final check immediately before the mount()
+ * call.
+ */
if (!is_valid_bind_path(src)) {
warn("src '%s' is not a valid bind mount path", src);
return -ELOOP;
}
- /* |dest| might not yet exist. */
+ /*
+ * Symlinks in |dest| are blocked by the ChromiumOS LSM:
+ * <kernel>/security/chromiumos/lsm.c#77
+ */
if (!writeable)
flags |= MS_RDONLY;
@@ -1870,6 +1878,19 @@
}
}
+ /*
+ * Do a final check for symlinks in |m->src|.
+ * |m->src| will only contain a valid path when purely bind-mounting
+ * (but not when remounting a bind mount).
+ *
+ * Short of having a version of mount(2) that can take fd's, this is the
+ * smallest we can make the TOCTOU window.
+ */
+ if (has_bind_flag && !has_remount_flag && !is_valid_bind_path(m->src)) {
+ warn("src '%s' is not a valid bind mount path", m->src);
+ goto error;
+ }
+
ret = mount(m->src, dest, m->type, m->flags, m->data);
if (ret) {
pwarn("cannot mount '%s' as '%s' with flags %#lx", m->src, dest,