| From 5f6279da3760ce48f478f2856aacebe0c59a39f3 Mon Sep 17 00:00:00 2001 |
| From: Dan Rosenberg <drosenberg@vsecurity.com> |
| Date: Tue, 5 Apr 2011 13:27:31 -0400 |
| Subject: [SCSI] pmcraid: reject negative request size |
| |
| From: Dan Rosenberg <drosenberg@vsecurity.com> |
| |
| commit 5f6279da3760ce48f478f2856aacebe0c59a39f3 upstream. |
| |
| There's a code path in pmcraid that can be reached via device ioctl that |
| causes all sorts of ugliness, including heap corruption or triggering |
| the OOM killer due to consecutive allocation of large numbers of pages. |
| Not especially relevant from a security perspective, since users must |
| have CAP_SYS_ADMIN to open the character device. |
| |
| First, the user can call pmcraid_chr_ioctl() with a type |
| PMCRAID_PASSTHROUGH_IOCTL. A pmcraid_passthrough_ioctl_buffer |
| is copied in, and the request_size variable is set to |
| buffer->ioarcb.data_transfer_length, which is an arbitrary 32-bit signed |
| value provided by the user. |
| |
| If a negative value is provided here, bad things can happen. For |
| example, pmcraid_build_passthrough_ioadls() is called with this |
| request_size, which immediately calls pmcraid_alloc_sglist() with a |
| negative size. The resulting math on allocating a scatter list can |
| result in an overflow in the kzalloc() call (if num_elem is 0, the |
| sglist will be smaller than expected), or if num_elem is unexpectedly |
| large the subsequent loop will call alloc_pages() repeatedly, a high |
| number of pages will be allocated and the OOM killer might be invoked. |
| |
| Prevent this value from being negative in pmcraid_ioctl_passthrough(). |
| |
| Signed-off-by: Dan Rosenberg <drosenberg@vsecurity.com> |
| Cc: Anil Ravindranath <anil_ravindranath@pmc-sierra.com> |
| Signed-off-by: James Bottomley <James.Bottomley@suse.de> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| drivers/scsi/pmcraid.c | 3 +++ |
| 1 file changed, 3 insertions(+) |
| |
| --- a/drivers/scsi/pmcraid.c |
| +++ b/drivers/scsi/pmcraid.c |
| @@ -3527,6 +3527,9 @@ static long pmcraid_ioctl_passthrough( |
| rc = -EFAULT; |
| goto out_free_buffer; |
| } |
| + } else if (request_size < 0) { |
| + rc = -EINVAL; |
| + goto out_free_buffer; |
| } |
| |
| /* check if we have any additional command parameters */ |