[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [linux-2.6.18-xen] xen/privcmd: convert single shot check to be per-page
# 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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |