From: Matthew Wilcox (Oracle) <willy@infradead.org>
Date: Mon, 10 Aug 2020 14:05:22 +0000 (-0400)
Subject: mshare: Store the base/len in the mm_struct
X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=ad6f463cc4b9ebd7b7e8ed3b40a6911088f8443a;p=users%2Fwilly%2Flinux.git

mshare: Store the base/len in the mm_struct

Also add a read operation so the recipient can find out what
address range the donor shared.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---

diff --git a/mm/mshare.c b/mm/mshare.c
index 525f624adede..75eb0796584f 100644
--- a/mm/mshare.c
+++ b/mm/mshare.c
@@ -3,7 +3,21 @@
 #include <linux/sched/mm.h>
 #include <linux/syscalls.h>
 
-int mshare_release(struct inode *inode, struct file *file)
+static ssize_t mshare_read(struct kiocb *iocb, struct iov_iter *iov)
+{
+	struct mm_struct *mm = iocb->ki_filp->private_data;
+	size_t ret;
+	u64 tmp[2];
+
+	tmp[0] = mm->mmap_base;
+	tmp[1] = mm->task_size - mm->mmap_base;
+	ret = copy_to_iter(&tmp, sizeof(tmp), iov);
+	if (!ret)
+		return -EFAULT;
+	return ret;
+}
+
+static int mshare_release(struct inode *inode, struct file *file)
 {
 	struct mm_struct *mm = file->private_data;
 
@@ -13,6 +27,7 @@ int mshare_release(struct inode *inode, struct file *file)
 }
 
 static const struct file_operations mshare_fops = {
+	.read_iter = mshare_read,
 	.release = mshare_release,
 };
 
@@ -24,10 +39,16 @@ SYSCALL_DEFINE3(mshare, unsigned long, addr, unsigned long, len,
 
 	if ((addr | len) & (PGDIR_SIZE - 1))
 		return -EINVAL;
+	if ((addr + len - 1) < addr)
+		return -EINVAL;
 
 	mm = mm_alloc();
 	if (!mm)
 		return -ENOMEM;
+	mm->mmap_base = addr;
+	mm->task_size = addr + len;
+	if (!mm->task_size)
+		mm->task_size--;
 
 	fd = anon_inode_getfd("mshare", &mshare_fops, mm, O_RDWR);