Block symlinks in bind mount source paths.

Minijail is sometimes asked to bind mount directories owned by
less-privileged users. These less-privileged users can manufacture
a "mount-anything-anywhere" primitive by replacing bind mount paths
with symlinks.

Prevent this by checking whether the bind mount source path is a
canonical path. Because this happens at minijail_bind() time, there is
still the risk of TOCTOU issues. A follow-up patch will re-check things
closer to the mount() call. Unfortunately mount() takes paths so it is
not possible to fully eliminate this race.

Because some files that processes might want to bind mount (like files
in /sys or /dev) can be symlinks, allow users to specify a set of
prefixes exempt from these restrictions. This can also help with
rolling this restriction out (exclude some prefixes, fix the callers,
then remove the exclusions).

A follow-up to this change will add checks on the destination path,
which need to happen after the path is created. Ideally, these would
happen as close as possible to the mount() call.

Bug: 219093918
Test: New unit tests.
Change-Id: Ia747e4318ed4eabf27c64e04e0dd71723735bae2
diff --git a/Makefile b/Makefile
index 6728cdb..3e41b5d 100644
--- a/Makefile
+++ b/Makefile
@@ -60,6 +60,18 @@
 endif
 endif
 
+# Prevent Minijail from following symlinks when performing bind mounts.
+# BINDMOUNT_ALLOWED_PREFIXES allows some flexibility. This is especially useful
+# for directories that are not normally modifiable by non-root users.
+# If a process can modify these directories, they probably don't need to mess
+# with Minijail bind mounts to gain root privileges.
+BINDMOUNT_ALLOWED_PREFIXES ?= /dev,/sys
+CPPFLAGS += -DBINDMOUNT_ALLOWED_PREFIXES='"$(BINDMOUNT_ALLOWED_PREFIXES)"'
+BLOCK_SYMLINKS_IN_BINDMOUNT_PATHS ?= no
+ifeq ($(BLOCK_SYMLINKS_IN_BINDMOUNT_PATHS),yes)
+CPPFLAGS += -DBLOCK_SYMLINKS_IN_BINDMOUNT_PATHS
+endif
+
 ifeq ($(USE_ASAN),yes)
 CPPFLAGS += -fsanitize=address -fno-omit-frame-pointer
 LDFLAGS += -fsanitize=address -fno-omit-frame-pointer