Commit 6a8dadcc authored by Todd Poynor's avatar Todd Poynor Committed by Martin K. Petersen

scsi: sg: protect against races between mmap() and SG_SET_RESERVED_SIZE

Take f_mutex around mmap() processing to protect against races with the
SG_SET_RESERVED_SIZE ioctl.  Ensure the reserve buffer length remains
consistent during the mapping operation, and set the "mmap called" flag
to prevent further changes to the reserved buffer size as an atomic
operation with the mapping.

[mkp: fixed whitespace]
Signed-off-by: default avatarTodd Poynor <toddpoynor@google.com>
Acked-by: default avatarDouglas Gilbert <dgilbert@interlog.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 8d26f491
...@@ -1262,6 +1262,7 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma) ...@@ -1262,6 +1262,7 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma)
unsigned long req_sz, len, sa; unsigned long req_sz, len, sa;
Sg_scatter_hold *rsv_schp; Sg_scatter_hold *rsv_schp;
int k, length; int k, length;
int ret = 0;
if ((!filp) || (!vma) || (!(sfp = (Sg_fd *) filp->private_data))) if ((!filp) || (!vma) || (!(sfp = (Sg_fd *) filp->private_data)))
return -ENXIO; return -ENXIO;
...@@ -1272,8 +1273,11 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma) ...@@ -1272,8 +1273,11 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma)
if (vma->vm_pgoff) if (vma->vm_pgoff)
return -EINVAL; /* want no offset */ return -EINVAL; /* want no offset */
rsv_schp = &sfp->reserve; rsv_schp = &sfp->reserve;
if (req_sz > rsv_schp->bufflen) mutex_lock(&sfp->f_mutex);
return -ENOMEM; /* cannot map more than reserved buffer */ if (req_sz > rsv_schp->bufflen) {
ret = -ENOMEM; /* cannot map more than reserved buffer */
goto out;
}
sa = vma->vm_start; sa = vma->vm_start;
length = 1 << (PAGE_SHIFT + rsv_schp->page_order); length = 1 << (PAGE_SHIFT + rsv_schp->page_order);
...@@ -1287,7 +1291,9 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma) ...@@ -1287,7 +1291,9 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma)
vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP; vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
vma->vm_private_data = sfp; vma->vm_private_data = sfp;
vma->vm_ops = &sg_mmap_vm_ops; vma->vm_ops = &sg_mmap_vm_ops;
return 0; out:
mutex_unlock(&sfp->f_mutex);
return ret;
} }
static void static void
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment