[Devel] [PATCH RHEL7 COMMIT] ve/fs: Port diff-ve-fs-security-check-for-mount

Konstantin Khorenko khorenko at virtuozzo.com
Wed Jun 24 05:32:58 PDT 2015


The commit is pushed to "branch-rh7-3.10.0-123.1.2-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-123.1.2.vz7.5.17
------>
commit f88edca9fdacdb4cb8f9a1709d06d1e81ebed244
Author: Vladimir Davydov <vdavydov at parallels.com>
Date:   Wed Jun 24 16:32:58 2015 +0400

    ve/fs: Port diff-ve-fs-security-check-for-mount
    
    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 9064370..15bd3ae 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 519e183..1c53f52 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -972,7 +972,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 908f9c3..fdade5c 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 33a9883..375711e 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;
 }



More information about the Devel mailing list