[TOMOYO #7 14/30] Shadow mount prevention part.

From: Tetsuo Handa
Date: Fri Apr 04 2008 - 08:55:36 EST


It is usually an undesirable thing to allow mount requests that shadow
already mounted tree. For example, mounting /usr when /usr/local is
already mounted is undesirable because it makes /usr/local inaccessible.

This file forbids such mount request.

Signed-off-by: Kentaro Takeda <takedakn@xxxxxxxxxxxxx>
Signed-off-by: Tetsuo Handa <penguin-kernel@xxxxxxxxxxxxxxxxxxx>
Signed-off-by: Toshiharu Harada <haradats@xxxxxxxxxxxxx>
---
fs/sakura_maymount.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 113 insertions(+)

--- /dev/null
+++ linux-2.6.25-rc8-mm1/fs/sakura_maymount.c
@@ -0,0 +1,113 @@
+/*
+ * fs/sakura_maymount.c
+ *
+ * Implementation of the Domain-Free Mandatory Access Control.
+ *
+ * Copyright (C) 2005-2008 NTT DATA CORPORATION
+ *
+ * Version: 1.6.0 2008/04/01
+ *
+ */
+
+#include <linux/ccs_common.h>
+#include <linux/sakura.h>
+#include <linux/realpath.h>
+#include <linux/mount.h>
+#include <linux/mnt_namespace.h>
+#include <linux/namei.h>
+
+/**
+ * check_conceal_mount - Check whether this mount request shadows existing mounts.
+ *
+ * @nd: Pointer to "struct nameidata".
+ * @vfsmnt: Pointer to "struct vfsmount".
+ * @dentry: Pointer to "struct dentry".
+ *
+ * Returns true if @vfsmnt is parent directory compared to @nd, false otherwise.
+ */
+static bool check_conceal_mount(struct nameidata *nd, struct vfsmount *vfsmnt,
+ struct dentry *dentry)
+{
+ /***** CRITICAL SECTION START *****/
+ while (1) {
+ if (nd->path.mnt->mnt_root == vfsmnt->mnt_root &&
+ nd->path.dentry == dentry)
+ return true;
+ if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
+ if (vfsmnt->mnt_parent == vfsmnt)
+ break;
+ dentry = vfsmnt->mnt_mountpoint;
+ vfsmnt = vfsmnt->mnt_parent;
+ continue;
+ }
+ dentry = dentry->d_parent;
+ }
+ return false;
+ /***** CRITICAL SECTION END *****/
+}
+
+/**
+ * print_error - Print error message.
+ *
+ * @nd: Pointer to "struct nameidata".
+ * @mode: Access control mode.
+ *
+ * Returns 0 if @mode is not enforcing or permitted by the administrator's
+ * decision, negative value otherwise.
+ */
+static int print_error(struct nameidata *nd, const u8 mode)
+{
+ int error;
+ const bool is_enforce = (mode == 3);
+ const char *dir = ccs_realpath_from_dentry(nd->path.dentry,
+ nd->path.mnt);
+ const char *exename = ccs_get_exe();
+ printk(KERN_WARNING "SAKURA-%s: mount %s (pid=%d:exe=%s): "
+ "Permission denied.\n", ccs_get_msg(is_enforce), dir,
+ current->pid, exename);
+ if (is_enforce)
+ error = ccs_check_supervisor("# %s is requesting\n"
+ "mount on %s\n", exename, dir);
+ else
+ error = 0;
+ ccs_free(exename);
+ ccs_free(dir);
+ return error;
+}
+
+/**
+ * ccs_may_mount - Check whether this mount request shadows existing mounts.
+ *
+ * @nd: Pointer to "struct nameidata".
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+int ccs_may_mount(struct nameidata *nd)
+{
+ struct list_head *p;
+ bool flag = false;
+ const u8 mode = ccs_check_flags(CCS_SAKURA_DENY_CONCEAL_MOUNT);
+ struct mnt_namespace *namespace = current->nsproxy->mnt_ns;
+ if (!mode)
+ return 0;
+ if (!namespace)
+ return 0;
+ list_for_each(p, &namespace->list) {
+ struct vfsmount *vfsmnt = list_entry(p, struct vfsmount,
+ mnt_list);
+ struct dentry *dentry = vfsmnt->mnt_root;
+ /***** CRITICAL SECTION START *****/
+ spin_lock(&dcache_lock);
+ spin_lock(&vfsmount_lock);
+ if (IS_ROOT(dentry) || !d_unhashed(dentry))
+ flag = check_conceal_mount(nd, vfsmnt, dentry);
+ spin_unlock(&vfsmount_lock);
+ spin_unlock(&dcache_lock);
+ /***** CRITICAL SECTION END *****/
+ if (flag)
+ break;
+ }
+ if (flag)
+ return print_error(nd, mode);
+ return 0;
+}

--
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/