Commit fa00c437 authored by Dave Carroll's avatar Dave Carroll Committed by Martin K. Petersen

aacraid: Check size values after double-fetch from user

In aacraid's ioctl_send_fib() we do two fetches from userspace, one the
get the fib header's size and one for the fib itself. Later we use the
size field from the second fetch to further process the fib. If for some
reason the size from the second fetch is different than from the first
fix, we may encounter an out-of- bounds access in aac_fib_send(). We
also check the sender size to insure it is not out of bounds. This was
reported in https://bugzilla.kernel.org/show_bug.cgi?id=116751 and was
assigned CVE-2016-6480.
Reported-by: default avatarPengfei Wang <wpengfeinudt@gmail.com>
Fixes: 7c00ffa3 '[SCSI] 2.6 aacraid: Variable FIB size (updated patch)'
Cc: stable@vger.kernel.org
Signed-off-by: default avatarDave Carroll <david.carroll@microsemi.com>
Reviewed-by: default avatarJohannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent ea0a95d7
...@@ -63,7 +63,7 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg) ...@@ -63,7 +63,7 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
struct fib *fibptr; struct fib *fibptr;
struct hw_fib * hw_fib = (struct hw_fib *)0; struct hw_fib * hw_fib = (struct hw_fib *)0;
dma_addr_t hw_fib_pa = (dma_addr_t)0LL; dma_addr_t hw_fib_pa = (dma_addr_t)0LL;
unsigned size; unsigned int size, osize;
int retval; int retval;
if (dev->in_reset) { if (dev->in_reset) {
...@@ -87,7 +87,8 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg) ...@@ -87,7 +87,8 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
* will not overrun the buffer when we copy the memory. Return * will not overrun the buffer when we copy the memory. Return
* an error if we would. * an error if we would.
*/ */
size = le16_to_cpu(kfib->header.Size) + sizeof(struct aac_fibhdr); osize = size = le16_to_cpu(kfib->header.Size) +
sizeof(struct aac_fibhdr);
if (size < le16_to_cpu(kfib->header.SenderSize)) if (size < le16_to_cpu(kfib->header.SenderSize))
size = le16_to_cpu(kfib->header.SenderSize); size = le16_to_cpu(kfib->header.SenderSize);
if (size > dev->max_fib_size) { if (size > dev->max_fib_size) {
...@@ -118,6 +119,14 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg) ...@@ -118,6 +119,14 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
goto cleanup; goto cleanup;
} }
/* Sanity check the second copy */
if ((osize != le16_to_cpu(kfib->header.Size) +
sizeof(struct aac_fibhdr))
|| (size < le16_to_cpu(kfib->header.SenderSize))) {
retval = -EINVAL;
goto cleanup;
}
if (kfib->header.Command == cpu_to_le16(TakeABreakPt)) { if (kfib->header.Command == cpu_to_le16(TakeABreakPt)) {
aac_adapter_interrupt(dev); aac_adapter_interrupt(dev);
/* /*
......
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