X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fxen%2Fprivcmd%2Fprivcmd.c;h=af9e13cee4480c5a1adf70da111fdf25b8ac3165;hb=e0ff8aa1acd079b70e796571917ae0449b7c465b;hp=501aa5fe3e73a0f116f9d5d6dc127443aeba6728;hpb=bef9ea3086d47cf98cfd0ea389953a0af0b60114;p=linux-2.6.git diff --git a/drivers/xen/privcmd/privcmd.c b/drivers/xen/privcmd/privcmd.c index 501aa5fe3..af9e13cee 100644 --- a/drivers/xen/privcmd/privcmd.c +++ b/drivers/xen/privcmd/privcmd.c @@ -34,6 +34,10 @@ static struct proc_dir_entry *privcmd_intf; static struct proc_dir_entry *capabilities_intf; +#ifndef HAVE_ARCH_PRIVCMD_MMAP +static int privcmd_enforce_singleshot_mapping(struct vm_area_struct *vma); +#endif + static int privcmd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data) { @@ -121,12 +125,10 @@ static int privcmd_ioctl(struct inode *inode, struct file *file, vma = find_vma(mm, msg.va); rc = -EINVAL; - if (!vma || (msg.va != vma->vm_start) || vma->vm_private_data) + if (!vma || (msg.va != vma->vm_start) || + !privcmd_enforce_singleshot_mapping(vma)) goto mmap_out; - /* Mapping is a one-shot operation per vma. */ - vma->vm_private_data = (void *)1; - va = vma->vm_start; for (i = 0; i < mmapcmd.num; i++) { @@ -136,7 +138,7 @@ static int privcmd_ioctl(struct inode *inode, struct file *file, /* Do not allow range to wrap the address space. */ rc = -EINVAL; - if ((msg.npages > (INT_MAX >> PAGE_SHIFT)) || + if ((msg.npages > (LONG_MAX >> PAGE_SHIFT)) || ((unsigned long)(msg.npages << PAGE_SHIFT) >= -va)) goto mmap_out; @@ -180,7 +182,7 @@ static int privcmd_ioctl(struct inode *inode, struct file *file, if (copy_from_user(&m, udata, sizeof(m))) return -EFAULT; - if ((m.num <= 0) || (m.num > (INT_MAX >> PAGE_SHIFT))) + if ((m.num <= 0) || (m.num > (LONG_MAX >> PAGE_SHIFT))) return -EINVAL; down_read(&mm->mmap_sem); @@ -188,15 +190,13 @@ static int privcmd_ioctl(struct inode *inode, struct file *file, vma = find_vma(mm, m.addr); if (!vma || (m.addr != vma->vm_start) || - ((m.addr + (m.num<vm_end) || - vma->vm_private_data) { + ((m.addr + ((unsigned long)m.num<vm_end) || + !privcmd_enforce_singleshot_mapping(vma)) { up_read(&mm->mmap_sem); return -EINVAL; } - /* Mapping is a one-shot operation per vma. */ - vma->vm_private_data = (void *)1; - p = m.arr; addr = m.addr; for (i = 0; i < m.num; i++, addr += PAGE_SIZE, p++) { @@ -250,6 +250,11 @@ static int privcmd_mmap(struct file * file, struct vm_area_struct * vma) return 0; } + +static int privcmd_enforce_singleshot_mapping(struct vm_area_struct *vma) +{ + return (xchg(&vma->vm_private_data, (void *)1) == NULL); +} #endif static struct file_operations privcmd_file_ops = {