[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