diff mbox series

[v1,13/14] mm/mshare: Enforce mshare'd region permissions

Message ID 40cfc1e065f27d1d119371c54b6e80421078c791.1649370874.git.khalid.aziz@oracle.com (mailing list archive)
State New
Headers show
Series Add support for shared PTEs across processes | expand

Commit Message

Khalid Aziz April 11, 2022, 4:05 p.m. UTC
When a process creates an mshare region, it specifies permissions
allowed for others to access this region as well as permissions
for the file to be created in msharefs that allows other processes
to get information on mshare'd region. Ensure those permissions
are enforced for other tasks accessing this region.

Signed-off-by: Khalid Aziz <khalid.aziz@oracle.com>
---
 mm/mshare.c | 24 ++++++++++++++++--------
 1 file changed, 16 insertions(+), 8 deletions(-)
diff mbox series

Patch

diff --git a/mm/mshare.c b/mm/mshare.c
index 88c7cefc933d..fba31f3c190f 100644
--- a/mm/mshare.c
+++ b/mm/mshare.c
@@ -24,7 +24,7 @@ 
 
 struct mshare_data {
 	struct mm_struct *mm, *host_mm;
-	mode_t mode;
+	int flags;
 	refcount_t refcnt;
 };
 
@@ -131,7 +131,7 @@  static struct dentry
 }
 
 static struct inode
-*msharefs_get_inode(struct super_block *sb, int mode)
+*msharefs_get_inode(struct super_block *sb, mode_t mode)
 {
 	struct inode *inode = new_inode(sb);
 
@@ -161,19 +161,22 @@  static struct inode
 }
 
 static int
-mshare_file_create(struct filename *fname, int flags,
+mshare_file_create(struct filename *fname, mode_t mode,
 			struct mshare_data *info)
 {
 	struct inode *inode;
 	struct dentry *root, *dentry;
 	int err = 0;
+	mode_t fmode;
 
 	root = msharefs_sb->s_root;
 
 	/*
-	 * This is a read only file.
+	 * This is a read only file so mask out all other bits. Make sure
+	 * it is readable by owner at least.
 	 */
-	inode = msharefs_get_inode(msharefs_sb, S_IFREG | 0400);
+	fmode = (mode & 0444) | S_IFREG | 0400;
+	inode = msharefs_get_inode(msharefs_sb, fmode);
 	if (IS_ERR(inode))
 		return PTR_ERR(inode);
 
@@ -247,6 +250,7 @@  SYSCALL_DEFINE5(mshare, const char __user *, name, unsigned long, addr,
 		dput(dentry);
 		goto err_unlock_inode;
 	}
+	oflag &= (O_RDONLY | O_WRONLY | O_RDWR);
 
 	if (dentry) {
 		unsigned long mapaddr, prot = PROT_NONE;
@@ -276,7 +280,11 @@  SYSCALL_DEFINE5(mshare, const char __user *, name, unsigned long, addr,
 		/*
 		 * Map in the address range as anonymous mappings
 		 */
-		oflag &= (O_RDONLY | O_WRONLY | O_RDWR);
+		if (oflag != (oflag & info->flags)) {
+			err = -EPERM;
+			goto err_unlock_inode;
+		}
+
 		if (oflag & O_RDONLY)
 			prot |= PROT_READ;
 		else if (oflag & O_WRONLY)
@@ -331,7 +339,7 @@  SYSCALL_DEFINE5(mshare, const char __user *, name, unsigned long, addr,
 			new_mm->task_size--;
 		info->mm = new_mm;
 		info->host_mm = old_mm;
-		info->mode = mode;
+		info->flags = oflag;
 		refcount_set(&info->refcnt, 1);
 
 		/*
@@ -412,7 +420,7 @@  SYSCALL_DEFINE5(mshare, const char __user *, name, unsigned long, addr,
 		mmap_write_unlock(old_mm);
 		mmap_write_unlock(new_mm);
 
-		err = mshare_file_create(fname, oflag, info);
+		err = mshare_file_create(fname, mode, info);
 		if (err)
 			goto free_info;
 	}