]> www.infradead.org Git - users/willy/linux.git/commitdiff
mshare: Store the base/len in the mm_struct
authorMatthew Wilcox (Oracle) <willy@infradead.org>
Mon, 10 Aug 2020 14:05:22 +0000 (10:05 -0400)
committerMatthew Wilcox (Oracle) <willy@infradead.org>
Tue, 11 Aug 2020 14:03:52 +0000 (10:03 -0400)
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>
mm/mshare.c

index 525f624adedec5eb1ef0189295afd26710af91c5..75eb0796584f5a94e5333fe5186f564894b974e2 100644 (file)
@@ -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);