WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [linux-2.6.18-xen] xen/privcmd: convert single shot chec

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [linux-2.6.18-xen] xen/privcmd: convert single shot check to be per-page
From: "Xen patchbot-linux-2.6.18-xen" <patchbot-linux-2.6.18-xen@xxxxxxxxxxxxxxxxxxx>
Date: Wed, 06 Jan 2010 01:45:16 -0800
Delivery-date: Wed, 06 Jan 2010 01:46:15 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1262765650 0
# Node ID f6017e7c6615687365ae7e66dd673898285d884d
# Parent  e5d3ccab348c7b3012bb5167c843fea2195c6002
xen/privcmd: convert single shot check to be per-page

For the sake of not breaking the ia64 build, old behavior is being
retained when HAVE_ARCH_PRIVCMD_MMAP. Hopefully someone able to
test ia64 can fix this up in the not too distant future.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>
---
 drivers/xen/privcmd/privcmd.c |   74 +++++++++++++++++++++++++++---------------
 1 files changed, 48 insertions(+), 26 deletions(-)

diff -r e5d3ccab348c -r f6017e7c6615 drivers/xen/privcmd/privcmd.c
--- a/drivers/xen/privcmd/privcmd.c     Mon Jan 04 10:37:14 2010 +0000
+++ b/drivers/xen/privcmd/privcmd.c     Wed Jan 06 08:14:10 2010 +0000
@@ -34,7 +34,22 @@ static struct proc_dir_entry *capabiliti
 static struct proc_dir_entry *capabilities_intf;
 
 #ifndef HAVE_ARCH_PRIVCMD_MMAP
-static int privcmd_enforce_singleshot_mapping(struct vm_area_struct *vma);
+static int enforce_singleshot_mapping_fn(pte_t *pte, pgtable_t token,
+                                        unsigned long addr, void *data)
+{
+       return pte_none(*pte) ? 0 : -EBUSY;
+}
+
+static inline int enforce_singleshot_mapping(struct vm_area_struct *vma,
+                                            unsigned long addr,
+                                            unsigned long npages)
+{
+       return apply_to_page_range(vma->vm_mm, addr, npages << PAGE_SHIFT,
+                                  enforce_singleshot_mapping_fn, NULL) == 0;
+}
+#else
+#define enforce_singleshot_mapping(vma, addr, npages) \
+       privcmd_enforce_singleshot_mapping(vma)
 #endif
 
 static long privcmd_ioctl(struct file *file,
@@ -110,6 +125,9 @@ static long privcmd_ioctl(struct file *f
                if (copy_from_user(&mmapcmd, udata, sizeof(mmapcmd)))
                        return -EFAULT;
 
+               if (mmapcmd.num <= 0)
+                       return -EINVAL;
+
                p = mmapcmd.entry;
                for (i = 0; i < mmapcmd.num;) {
                        int nr = min(mmapcmd.num - i, MMAP_NR_PER_PAGE);
@@ -137,8 +155,7 @@ static long privcmd_ioctl(struct file *f
 
                vma = find_vma(mm, msg->va);
                rc = -EINVAL;
-               if (!vma || (msg->va != vma->vm_start) ||
-                   !privcmd_enforce_singleshot_mapping(vma))
+               if (!vma || (msg->va != vma->vm_start))
                        goto mmap_out;
 
                va = vma->vm_start;
@@ -151,7 +168,6 @@ static long privcmd_ioctl(struct file *f
                        while (i<nr) {
 
                                /* Do not allow range to wrap the address 
space. */
-                               rc = -EINVAL;
                                if ((msg->npages > (LONG_MAX >> PAGE_SHIFT)) ||
                                    ((unsigned long)(msg->npages << PAGE_SHIFT) 
>= -va))
                                        goto mmap_out;
@@ -161,6 +177,23 @@ static long privcmd_ioctl(struct file *f
                                    ((msg->va+(msg->npages<<PAGE_SHIFT)) > 
vma->vm_end))
                                        goto mmap_out;
 
+                               va += msg->npages << PAGE_SHIFT;
+                               msg++;
+                               i++;
+                       }
+               }
+
+               if (!enforce_singleshot_mapping(vma, vma->vm_start,
+                                               (va - vma->vm_start) >> 
PAGE_SHIFT))
+                       goto mmap_out;
+
+               va = vma->vm_start;
+               i = 0;
+               list_for_each(l, &pagelist) {
+                       int nr = i + min(mmapcmd.num - i, MMAP_NR_PER_PAGE);
+
+                       msg = (privcmd_mmap_entry_t*)(l + 1);
+                       while (i < nr) {
                                if ((rc = direct_remap_pfn_range(
                                             vma,
                                             msg->va & PAGE_MASK,
@@ -206,7 +239,9 @@ static long privcmd_ioctl(struct file *f
                        return -EFAULT;
 
                nr_pages = m.num;
-               if ((m.num <= 0) || (nr_pages > (LONG_MAX >> PAGE_SHIFT)))
+               addr = m.addr;
+               if (m.num <= 0 || nr_pages > (LONG_MAX >> PAGE_SHIFT) ||
+                   addr != m.addr || nr_pages > (-addr >> PAGE_SHIFT))
                        return -EINVAL;
 
                p = m.arr;
@@ -231,24 +266,16 @@ static long privcmd_ioctl(struct file *f
 
                down_write(&mm->mmap_sem);
 
-               vma = find_vma(mm, m.addr);
+               vma = find_vma(mm, addr);
                ret = -EINVAL;
                if (!vma ||
-                   (m.addr != vma->vm_start) ||
-                   ((m.addr + (nr_pages << PAGE_SHIFT)) != vma->vm_end) ||
-                   !privcmd_enforce_singleshot_mapping(vma)) {
-                       if (!(vma &&
-                             (m.addr >= vma->vm_start) &&
-                             ((m.addr + (nr_pages << PAGE_SHIFT)) <= 
vma->vm_end) &&
-                             (nr_pages == 1) &&
-                             !privcmd_enforce_singleshot_mapping(vma))) {
-                               up_write(&mm->mmap_sem);
-                               goto mmapbatch_out;
-                       }
-               }
-
-               p = m.arr;
-               addr = m.addr;
+                   addr < vma->vm_start ||
+                   addr + (nr_pages << PAGE_SHIFT) > vma->vm_end ||
+                   !enforce_singleshot_mapping(vma, addr, nr_pages)) {
+                       up_write(&mm->mmap_sem);
+                       goto mmapbatch_out;
+               }
+
                i = 0;
                ret = 0;
                list_for_each(l, &pagelist) {
@@ -331,11 +358,6 @@ static int privcmd_mmap(struct file * fi
 
        return 0;
 }
-
-static int privcmd_enforce_singleshot_mapping(struct vm_area_struct *vma)
-{
-       return (xchg(&vma->vm_private_data, (void *)1) == NULL);
-}
 #endif
 
 static const struct file_operations privcmd_file_ops = {

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [linux-2.6.18-xen] xen/privcmd: convert single shot check to be per-page, Xen patchbot-linux-2.6.18-xen <=