[Devel] [PATCH rh7 14/14] Port diff-ve-fs-security-check-for-mount

Vladimir Davydov vdavydov at parallels.com
Tue Jun 23 09:29:50 PDT 2015


Author: "Maxim V. Patlasov"
Email: MPatlasov at parallels.com
Subject: fs: differentiate exclusive opens
Date: Wed, 28 Nov 2012 15:12:52 +0400

We're going to control access to ploop-device in CT by proper checks in
__devcgroup_inode_permission(). Ordinary open(2) comes there like this:

blkdev_open() -->
  blkdev_get() -->
    __blkdev_get() -->
      devcgroup_inode_permission() -->
        __devcgroup_inode_permission()

while mount(2) does it via open_bdev_exclusive():

get_sb_bdev() -->
  open_bdev_exclusive() -->
    blkdev_get() -->
      __blkdev_get() -->
        devcgroup_inode_permission() -->
          __devcgroup_inode_permission()

The patch introduces FMODE_EXCLUSIVE - the flag differentiating these two
cases.

Signed-off-by: Maxim V. Patlasov <MPatlasov at parallels.com>
=============================================================================

Author: "Maxim V. Patlasov"
Email: MPatlasov at parallels.com
Subject: security: check for mount
Date: Wed, 28 Nov 2012 15:13:02 +0400

The patch introduces two new flags: MAY_MOUNT and ACC_MOUNT.

MAY_MOUNT is used to let devcgroup_inode_permission() know that it's being
called due to mount. I.e. it means "someone up in stack wants mount some FS
on given block-device".

ACC_MOUNT is devperms flag enabling mount on a device without ACC_WRITE
permission. I.e. it means "let's allow mount even if WRITEs are disallowed".

Userspace vzctl ParseDevPerm() already uses:
S_IXOTH for ACC_MKNOD
S_IXGRP for ACC_QUOTA
With this patch applied it will be also able to use:
S_IXUSR for ACC_MOUNT.

Signed-off-by: Maxim V. Patlasov <MPatlasov at parallels.com>
=============================================================================

Note, I renamed FMODE_EXCLUSIVE to FMODE_MOUNT and moved setting of this
flag to mount_bdev, because (1) there is no more open_bdev_exclusive and
(2) FMODE_MOUNT fits better than FMODE_EXCLUSIVE IMO.

Related to https://jira.sw.ru/browse/PSBM-33650

Signed-off-by: Vladimir Davydov <vdavydov at parallels.com>
---
 fs/block_dev.c           |  2 ++
 fs/super.c               |  2 +-
 include/linux/fs.h       |  4 ++++
 security/device_cgroup.c | 19 +++++++++++++++++--
 4 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/fs/block_dev.c b/fs/block_dev.c
index 906437010651..15bd3ae25122 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -1075,6 +1075,8 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
 		perm |= MAY_READ;
 	if (mode & FMODE_WRITE)
 		perm |= MAY_WRITE;
+	if (mode & FMODE_MOUNT)
+		perm |= MAY_MOUNT;
 	/*
 	 * hooks: /n/, see "layering violations".
 	 */
diff --git a/fs/super.c b/fs/super.c
index bf3a8c1a0d4d..54db934e202f 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -991,7 +991,7 @@ struct dentry *mount_bdev(struct file_system_type *fs_type,
 	if (!(flags & MS_RDONLY))
 		mode |= FMODE_WRITE;
 
-	bdev = blkdev_get_by_path(dev_name, mode, fs_type);
+	bdev = blkdev_get_by_path(dev_name, mode | FMODE_MOUNT, fs_type);
 	if (IS_ERR(bdev))
 		return ERR_CAST(bdev);
 
diff --git a/include/linux/fs.h b/include/linux/fs.h
index e7709448a243..a0c2a36f3a53 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -78,6 +78,7 @@ typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
 #define MAY_NOT_BLOCK		0x00000080
 /* for devgroup-vs-openvz only */
 #define MAY_QUOTACTL		0x00010000
+#define MAY_MOUNT		0x00020000
 
 /*
  * flags in file.f_mode.  Note that FMODE_READ and FMODE_WRITE must correspond
@@ -128,6 +129,9 @@ typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
 /* Can do sys_quotactl (for devperms) */
 #define FMODE_QUOTACTL		((__force fmode_t)0x8000)
 
+/* File is a block device opened by mount(2)  */
+#define FMODE_MOUNT		((__force fmode_t)0x10000)
+
 /* File was opened by fanotify and shouldn't generate fanotify events */
 #define FMODE_NONOTIFY		((__force fmode_t)0x1000000)
 
diff --git a/security/device_cgroup.c b/security/device_cgroup.c
index 33a9883b6566..375711e70103 100644
--- a/security/device_cgroup.c
+++ b/security/device_cgroup.c
@@ -24,7 +24,8 @@
 #define ACC_WRITE 4
 #define ACC_QUOTA 8
 #define ACC_HIDDEN 16
-#define ACC_MASK (ACC_MKNOD | ACC_READ | ACC_WRITE | ACC_QUOTA)
+#define ACC_MOUNT 64
+#define ACC_MASK (ACC_MKNOD | ACC_READ | ACC_WRITE | ACC_QUOTA | ACC_MOUNT)
 
 #define DEV_BLOCK 1
 #define DEV_CHAR  2
@@ -354,6 +355,9 @@ static bool match_exception(struct list_head *exceptions, short type,
 	struct dev_exception_item *ex;
 
 	list_for_each_entry_rcu(ex, exceptions, list) {
+		short mismatched_bits;
+		bool allowed_mount;
+
 		if ((type & DEV_BLOCK) && !(ex->type & DEV_BLOCK))
 			continue;
 		if ((type & DEV_CHAR) && !(ex->type & DEV_CHAR))
@@ -363,7 +367,12 @@ static bool match_exception(struct list_head *exceptions, short type,
 		if (ex->minor != ~0 && ex->minor != minor)
 			continue;
 		/* provided access cannot have more than the exception rule */
-		if (access & (~ex->access))
+		mismatched_bits = access & (~ex->access) & ~ACC_MOUNT;
+		allowed_mount = !(mismatched_bits & ~ACC_WRITE) &&
+				(ex->access & ACC_MOUNT) &&
+				(access & ACC_MOUNT);
+
+		if (mismatched_bits && !allowed_mount)
 			continue;
 		return true;
 	}
@@ -908,6 +917,8 @@ int __devcgroup_inode_permission(struct inode *inode, int mask)
 		access |= ACC_READ;
 	if (mask & MAY_QUOTACTL)
 		access |= ACC_QUOTA;
+	if (mask & MAY_MOUNT)
+		access |= ACC_MOUNT;
 
 	return __devcgroup_check_permission(type, imajor(inode), iminor(inode),
 			access);
@@ -1041,6 +1052,8 @@ static unsigned decode_ve_perms(unsigned perm)
 		mask |= ACC_WRITE;
 	if (perm & S_IXGRP)
 		mask |= ACC_QUOTA;
+	if (perm & S_IXUSR)
+		mask |= ACC_MOUNT;
 
 	return mask;
 }
@@ -1055,6 +1068,8 @@ static unsigned encode_ve_perms(unsigned mask)
 		perm |= S_IWOTH;
 	if (mask & ACC_QUOTA)
 		perm |= S_IXGRP;
+	if (mask & ACC_MOUNT)
+		perm |= S_IXUSR;
 
 	return perm;
 }
-- 
2.1.4




More information about the Devel mailing list