[Fedora kexec-tools 2/7] kexec: Remount /proc and /sys in private mount namespace

Vivek Goyal vgoyal at redhat.com
Thu Sep 5 01:56:59 UTC 2013


With secureboot enabled, we don't even trust root. And when kexec is launched
it might happen that root has already rigged /proc and /sys which kexec
reads to get important data.

So create a private mount namespace which is not visible to root, unmount
old /proc and /sys and remount these to get to actual data kernel exported.

Signed-off-by: Vivek Goyal <vgoyal at redhat.com>
---
 kexec/kexec.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 65 insertions(+)

diff --git a/kexec/kexec.c b/kexec/kexec.c
index 21ff0e7..9187fb8 100644
--- a/kexec/kexec.c
+++ b/kexec/kexec.c
@@ -31,6 +31,8 @@
 #include <sys/reboot.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <sys/mount.h>
+#include <sched.h>
 #ifndef _O_BINARY
 #define _O_BINARY 0
 #endif
@@ -1053,6 +1055,64 @@ char *concat_cmdline(const char *base, const char *append)
 }
 
 
+/*
+ * In secureboot environment, even root is not trusted. /sbin/kexec reads
+ * files from /proc and /sys and it might happen root faked these files
+ * using bind mounts or other techniques. create a private namespace and
+ * remount /proc to make sure kexec is looking at what has been exported
+ * by kernel and not faked by root.
+ */
+static int remount_proc_and_sys(void)
+{
+	int ret = 0;
+
+	ret = unshare(CLONE_NEWNS);
+	if (ret == -1) {
+		fprintf(stderr, "unshare(CLONE_NEWNS) failed:%s\n",
+				strerror(errno));
+		return -1;
+	}
+
+	/*
+	 * make root private so that no mount event from previous namespace
+	 * are propogated
+	 */
+	ret = mount("", "/", "", MS_REC | MS_PRIVATE, "");
+	if (ret == -1) {
+		fprintf(stderr, "mount(MS_REC|MS_PRIVATE) failed:%s\n",
+					strerror(errno));
+		return -1;
+	}
+
+	/* lazy unmount /proc */
+	ret = umount2("/proc", MNT_DETACH);
+	if (ret == -1) {
+		fprintf(stderr, "umount(/proc) failed:%s\n", strerror(errno));
+		return -1;
+	}
+
+	ret = mount("none", "/proc", "proc", 0, "");
+	if (ret == -1) {
+		fprintf(stderr, "mount(/proc) failed:%s\n", strerror(errno));
+		return -1;
+	}
+
+	/* lazy unmount /sys */
+	ret = umount2("/sys", MNT_DETACH);
+	if (ret == -1) {
+		fprintf(stderr, "umount(/sys) failed:%s\n", strerror(errno));
+		return -1;
+	}
+
+	ret = mount("none", "/sys", "sysfs", 0, "");
+	if (ret == -1) {
+		fprintf(stderr, "mount(/sys) failed:%s\n", strerror(errno));
+		return -1;
+	}
+
+	return ret;
+}
+
 int main(int argc, char *argv[])
 {
 	int do_load = 1;
@@ -1212,6 +1272,11 @@ int main(int argc, char *argv[])
 		}
 	}
 
+	result = remount_proc_and_sys();
+
+	if (result)
+		die("Remounting /proc/ and /sys/ failed\n");
+
 	if (do_reuse_initrd){
 		check_reuse_initrd();
 		arch_reuse_initrd();
-- 
1.8.3.1



More information about the kernel mailing list