[Devel] [PATCH RH7 07/22] ebiederm/userns: Simpilify MNT_NODEV handling.

Pavel Tikhomirov ptikhomirov at virtuozzo.com
Thu Mar 10 08:32:00 PST 2016


changes: we do not have fs_fully_visible so skip its hunk
(we do not inherit flags so we do not need to cut them), also
skip hunk in do_remount.

git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace.git for-testing
commit 4aceccd65a57 ("userns: Simpilify MNT_NODEV handling.")

- Consolidate the testing if a device node may be opened in a new
  function may_open_dev.

- Move the check for allowing access to device nodes on filesystems
  not mounted in the initial user namespace from mount time to open
  time and include it in may_open_dev.

This set of changes removes the implicit adding of MNT_NODEV which
simplifies the logic in fs/namespace.c and removes a potentially
problematic difference in how normal and unprivileged mount
namespaces work.  This is a user visible change in behavior for
remount in unpriviliged mount namespaces but is unlikely to cause
problems for existing software.

Signed-off-by: "Eric W. Biederman" <ebiederm at xmission.com>
Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
---
 fs/block_dev.c     | 2 +-
 fs/namei.c         | 9 ++++++++-
 fs/namespace.c     | 7 -------
 include/linux/fs.h | 1 +
 4 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/fs/block_dev.c b/fs/block_dev.c
index 65e7757..b8533ea 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -1656,7 +1656,7 @@ struct block_device *lookup_bdev(const char *pathname)
 	if (!S_ISBLK(inode->i_mode))
 		goto fail;
 	error = -EACCES;
-	if (path.mnt->mnt_flags & MNT_NODEV)
+	if (!may_open_dev(&path))
 		goto fail;
 	error = -ENOMEM;
 	bdev = bd_acquire(inode);
diff --git a/fs/namei.c b/fs/namei.c
index 16820b1..0f12ce7 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2602,6 +2602,13 @@ int vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
 	return error;
 }
 
+bool may_open_dev(const struct path *path)
+{
+	return !(path->mnt->mnt_flags & MNT_NODEV) &&
+		((path->mnt->mnt_sb->s_user_ns == &init_user_ns) ||
+		 (path->mnt->mnt_sb->s_type->fs_flags & FS_USERNS_DEV_MOUNT));
+}
+
 static int may_open(struct path *path, int acc_mode, int flag)
 {
 	struct dentry *dentry = path->dentry;
@@ -2624,7 +2631,7 @@ static int may_open(struct path *path, int acc_mode, int flag)
 		break;
 	case S_IFBLK:
 	case S_IFCHR:
-		if (path->mnt->mnt_flags & MNT_NODEV)
+		if (!may_open_dev(path))
 			return -EACCES;
 		/*FALLTHRU*/
 	case S_IFIFO:
diff --git a/fs/namespace.c b/fs/namespace.c
index 637ed20..bea4ebf 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2232,13 +2232,6 @@ static int do_new_mount(struct path *path, const char *fstype, int flags,
 			put_filesystem(type);
 			return -EPERM;
 		}
-		/* Only in special cases allow devices from mounts
-		 * created outside the initial user namespace.
-		 */
-		if (!(type->fs_flags & FS_USERNS_DEV_MOUNT)) {
-			flags |= MS_NODEV;
-			mnt_flags |= MNT_NODEV | MNT_LOCK_NODEV;
-		}
 	}
 
 	mnt = vfs_kern_mount(type, flags, name, data);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index e6b6e6b..cf439ef 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1728,6 +1728,7 @@ extern void dentry_unhash(struct dentry *dentry);
  */
 extern void inode_init_owner(struct inode *inode, const struct inode *dir,
 			umode_t mode);
+extern bool may_open_dev(const struct path *path);
 /*
  * VFS FS_IOC_FIEMAP helper definitions.
  */
-- 
1.9.3



More information about the Devel mailing list