Skip to content

Commit

Permalink
Staging: bcm: Fix information leak in ioctl: IOCTL_BCM_REGISTER_READ_…
Browse files Browse the repository at this point in the history
…PRIVATE, IOCTL_BCM_EEPROM_REGISTER_READ

This patch fixes an information leak in ioctl
IOCTL_BCM_REGISTER_READ_PRIVATE and
IOCTL_BCM_EEPROM_REGISTER_READ when determining
the number of bytes to copy to user space.  Function,
usb_control_msg, returns the correct number of
bytes from the hardware.  Instead of using
this value, we were using a value derived from
user space. In this case, this value could be more
than the hardware allocated.  Therefore, this
patch copies the proper number of bytes from
the hardware, and uses this value as the maximum
number of bytes for user space.

Signed-off-by: Kevin McKinney <klmckinney1@gmail.com>
Reviewed-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Kevin McKinney authored and Greg Kroah-Hartman committed Nov 27, 2011
1 parent 57bfa9d commit 41c7b7c
Show file tree
Hide file tree
Showing 7 changed files with 153 additions and 104 deletions.
49 changes: 34 additions & 15 deletions drivers/staging/bcm/Bcmchar.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
INT Status = STATUS_FAILURE;
int timeout = 0;
IOCTL_BUFFER IoBuffer;
int bytes;

BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Parameters Passed to control IOCTL cmd=0x%X arg=0x%lX", cmd, arg);

Expand Down Expand Up @@ -230,11 +231,14 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
if (!temp_buff)
return -ENOMEM;

Status = rdmalt(Adapter, (UINT)sRdmBuffer.Register,
bytes = rdmalt(Adapter, (UINT)sRdmBuffer.Register,
(PUINT)temp_buff, Bufflen);
if (Status == STATUS_SUCCESS) {
if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, IoBuffer.OutputLength))
if (bytes > 0) {
Status = STATUS_SUCCESS;
if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, bytes))
Status = -EFAULT;
} else {
Status = bytes;
}

kfree(temp_buff);
Expand Down Expand Up @@ -318,11 +322,15 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
}

uiTempVar = sRdmBuffer.Register & EEPROM_REJECT_MASK;
Status = rdmaltWithLock(Adapter, (UINT)sRdmBuffer.Register, (PUINT)temp_buff, IoBuffer.OutputLength);
bytes = rdmaltWithLock(Adapter, (UINT)sRdmBuffer.Register, (PUINT)temp_buff, IoBuffer.OutputLength);

if (Status == STATUS_SUCCESS)
if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, IoBuffer.OutputLength))
if (bytes > 0) {
Status = STATUS_SUCCESS;
if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, bytes))
Status = -EFAULT;
} else {
Status = bytes;
}

kfree(temp_buff);
break;
Expand Down Expand Up @@ -437,12 +445,14 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
}
}

Status = rdmaltWithLock(Adapter, (UINT)GPIO_MODE_REGISTER, (PUINT)ucResetValue, sizeof(UINT));

if (STATUS_SUCCESS != Status) {
bytes = rdmaltWithLock(Adapter, (UINT)GPIO_MODE_REGISTER, (PUINT)ucResetValue, sizeof(UINT));
if (bytes < 0) {
Status = bytes;
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
"GPIO_MODE_REGISTER read failed");
break;
} else {
Status = STATUS_SUCCESS;
}

/* Set the gpio mode register to output */
Expand Down Expand Up @@ -519,12 +529,15 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
uiBit = gpio_info.uiGpioNumber;

/* Set the gpio output register */
Status = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER,
bytes = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER,
(PUINT)ucRead, sizeof(UINT));

if (Status != STATUS_SUCCESS) {
if (bytes < 0) {
Status = bytes;
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "RDM Failed\n");
return Status;
} else {
Status = STATUS_SUCCESS;
}
}
break;
Expand Down Expand Up @@ -590,11 +603,14 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
}

if (pgpio_multi_info[WIMAX_IDX].uiGPIOMask) {
Status = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER, (PUINT)ucResetValue, sizeof(UINT));
bytes = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER, (PUINT)ucResetValue, sizeof(UINT));

if (Status != STATUS_SUCCESS) {
if (bytes < 0) {
Status = bytes;
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "RDM to GPIO_PIN_STATE_REGISTER Failed.");
return Status;
} else {
Status = STATUS_SUCCESS;
}

pgpio_multi_info[WIMAX_IDX].uiGPIOValue = (*(UINT *)ucResetValue &
Expand Down Expand Up @@ -629,11 +645,14 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
if (copy_from_user(&gpio_multi_mode, IoBuffer.InputBuffer, IoBuffer.InputLength))
return -EFAULT;

Status = rdmaltWithLock(Adapter, (UINT)GPIO_MODE_REGISTER, (PUINT)ucResetValue, sizeof(UINT));
bytes = rdmaltWithLock(Adapter, (UINT)GPIO_MODE_REGISTER, (PUINT)ucResetValue, sizeof(UINT));

if (STATUS_SUCCESS != Status) {
if (bytes < 0) {
Status = bytes;
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Read of GPIO_MODE_REGISTER failed");
return Status;
} else {
Status = STATUS_SUCCESS;
}

/* Validating the request */
Expand Down
12 changes: 8 additions & 4 deletions drivers/staging/bcm/InterfaceDld.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ int InterfaceFileReadbackFromChip(PVOID arg, struct file *flp, unsigned int on_c
static int fw_down;
INT Status = STATUS_SUCCESS;
PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)arg;
int bytes;

buff = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_DMA);
buff_readback = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB , GFP_DMA);
Expand Down Expand Up @@ -94,8 +95,9 @@ int InterfaceFileReadbackFromChip(PVOID arg, struct file *flp, unsigned int on_c
break;
}

Status = InterfaceRDM(psIntfAdapter, on_chip_loc, buff_readback, len);
if (Status) {
bytes = InterfaceRDM(psIntfAdapter, on_chip_loc, buff_readback, len);
if (bytes < 0) {
Status = bytes;
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "RDM of len %d Failed! %d", len, reg);
goto exit;
}
Expand Down Expand Up @@ -302,6 +304,7 @@ static INT buffRdbkVerify(PMINI_ADAPTER Adapter, PUCHAR mappedbuffer, UINT u32Fi
UINT len = u32FirmwareLength;
INT retval = STATUS_SUCCESS;
PUCHAR readbackbuff = kzalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL);
int bytes;

if (NULL == readbackbuff) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "MEMORY ALLOCATION FAILED");
Expand All @@ -310,9 +313,10 @@ static INT buffRdbkVerify(PMINI_ADAPTER Adapter, PUCHAR mappedbuffer, UINT u32Fi

while (u32FirmwareLength && !retval) {
len = MIN_VAL(u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB);
retval = rdm(Adapter, u32StartingAddress, readbackbuff, len);
bytes = rdm(Adapter, u32StartingAddress, readbackbuff, len);

if (retval) {
if (bytes < 0) {
retval = bytes;
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "rdm failed with status %d", retval);
break;
}
Expand Down
33 changes: 18 additions & 15 deletions drivers/staging/bcm/InterfaceIdleMode.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ int InterfaceIdleModeRespond(PMINI_ADAPTER Adapter, unsigned int* puiBuffer)
{
int status = STATUS_SUCCESS;
unsigned int uiRegRead = 0;
int bytes;

BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"SubType of Message :0x%X", ntohl(*puiBuffer));

Expand Down Expand Up @@ -77,16 +78,16 @@ int InterfaceIdleModeRespond(PMINI_ADAPTER Adapter, unsigned int* puiBuffer)
else if(Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE)
{
//clear on read Register
status = rdmalt(Adapter, DEVICE_INT_OUT_EP_REG0, &uiRegRead, sizeof(uiRegRead));
if(status)
{
bytes = rdmalt(Adapter, DEVICE_INT_OUT_EP_REG0, &uiRegRead, sizeof(uiRegRead));
if (bytes < 0) {
status = bytes;
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "rdm failed while clearing H/W Abort Reg0");
return status;
}
//clear on read Register
status = rdmalt (Adapter, DEVICE_INT_OUT_EP_REG1, &uiRegRead, sizeof(uiRegRead));
if(status)
{
bytes = rdmalt(Adapter, DEVICE_INT_OUT_EP_REG1, &uiRegRead, sizeof(uiRegRead));
if (bytes < 0) {
status = bytes;
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "rdm failed while clearing H/W Abort Reg1");
return status;
}
Expand Down Expand Up @@ -117,9 +118,9 @@ int InterfaceIdleModeRespond(PMINI_ADAPTER Adapter, unsigned int* puiBuffer)
Adapter->chip_id== BCS220_3)
{

status = rdmalt(Adapter, HPM_CONFIG_MSW, &uiRegRead, sizeof(uiRegRead));
if(status)
{
bytes = rdmalt(Adapter, HPM_CONFIG_MSW, &uiRegRead, sizeof(uiRegRead));
if (bytes < 0) {
status = bytes;
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "rdm failed while Reading HPM_CONFIG_LDO145 Reg 0\n");
return status;
}
Expand Down Expand Up @@ -266,6 +267,8 @@ void InterfaceHandleShutdownModeWakeup(PMINI_ADAPTER Adapter)
{
unsigned int uiRegVal = 0;
INT Status = 0;
int bytes;

if(Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING)
{
// clear idlemode interrupt.
Expand All @@ -282,16 +285,16 @@ void InterfaceHandleShutdownModeWakeup(PMINI_ADAPTER Adapter)
{

//clear Interrupt EP registers.
Status = rdmalt(Adapter,DEVICE_INT_OUT_EP_REG0, &uiRegVal, sizeof(uiRegVal));
if(Status)
{
bytes = rdmalt(Adapter,DEVICE_INT_OUT_EP_REG0, &uiRegVal, sizeof(uiRegVal));
if (bytes < 0) {
Status = bytes;
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"RDM of DEVICE_INT_OUT_EP_REG0 failed with Err :%d", Status);
return;
}

Status = rdmalt(Adapter,DEVICE_INT_OUT_EP_REG1, &uiRegVal, sizeof(uiRegVal));
if(Status)
{
bytes = rdmalt(Adapter,DEVICE_INT_OUT_EP_REG1, &uiRegVal, sizeof(uiRegVal));
if (bytes < 0) {
Status = bytes;
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"RDM of DEVICE_INT_OUT_EP_REG1 failed with Err :%d", Status);
return;
}
Expand Down
12 changes: 7 additions & 5 deletions drivers/staging/bcm/InterfaceInit.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ static void InterfaceAdapterFree(PS_INTERFACE_ADAPTER psIntfAdapter)
static void ConfigureEndPointTypesThroughEEPROM(PMINI_ADAPTER Adapter)
{
unsigned long ulReg = 0;
int ret;
int bytes;

/* Program EP2 MAX_PKT_SIZE */
ulReg = ntohl(EP2_MPS_REG);
Expand All @@ -94,8 +94,8 @@ static void ConfigureEndPointTypesThroughEEPROM(PMINI_ADAPTER Adapter)
BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&ulReg, 0x140, 4, TRUE);

/* Program TX EP as interrupt(Alternate Setting) */
ret = rdmalt(Adapter, 0x0F0110F8, (u32 *)&ulReg, sizeof(u32));
if (ret) {
bytes = rdmalt(Adapter, 0x0F0110F8, (u32 *)&ulReg, sizeof(u32));
if (bytes < 0) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,
"reading of Tx EP failed\n");
return;
Expand Down Expand Up @@ -430,6 +430,7 @@ static int InterfaceAdapterInit(PS_INTERFACE_ADAPTER psIntfAdapter)
int usedIntOutForBulkTransfer = 0 ;
BOOLEAN bBcm16 = FALSE;
UINT uiData = 0;
int bytes;

/* Store the usb dev into interface adapter */
psIntfAdapter->udev = usb_get_dev(interface_to_usbdev(psIntfAdapter->interface));
Expand All @@ -438,9 +439,10 @@ static int InterfaceAdapterInit(PS_INTERFACE_ADAPTER psIntfAdapter)
psIntfAdapter->psAdapter->interface_rdm = BcmRDM;
psIntfAdapter->psAdapter->interface_wrm = BcmWRM;

retval = rdmalt(psIntfAdapter->psAdapter, CHIP_ID_REG,
bytes = rdmalt(psIntfAdapter->psAdapter, CHIP_ID_REG,
(u32 *)&(psIntfAdapter->psAdapter->chip_id), sizeof(u32));
if (retval) {
if (bytes < 0) {
retval = bytes;
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "CHIP ID Read Failed\n");
return retval;
}
Expand Down
24 changes: 11 additions & 13 deletions drivers/staging/bcm/InterfaceMisc.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ INT InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter,
PVOID buff,
INT len)
{
int retval = 0;
int bytes;
USHORT usRetries = 0;

if (psIntfAdapter == NULL) {
Expand All @@ -30,7 +30,7 @@ INT InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter,
psIntfAdapter->psAdapter->DeviceAccess = TRUE;

do {
retval = usb_control_msg(psIntfAdapter->udev,
bytes = usb_control_msg(psIntfAdapter->udev,
usb_rcvctrlpipe(psIntfAdapter->udev, 0),
0x02,
0xC2,
Expand All @@ -41,22 +41,20 @@ INT InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter,
5000);

usRetries++;
if (-ENODEV == retval) {
if (-ENODEV == bytes) {
psIntfAdapter->psAdapter->device_removed = TRUE;
break;
}

} while ((retval < 0) && (usRetries < MAX_RDM_WRM_RETIRES));
} while ((bytes < 0) && (usRetries < MAX_RDM_WRM_RETIRES));

if (retval < 0) {
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM failed status :%d, retires :%d", retval, usRetries);
psIntfAdapter->psAdapter->DeviceAccess = FALSE;
return retval;
} else {
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM sent %d", retval);
psIntfAdapter->psAdapter->DeviceAccess = FALSE;
return STATUS_SUCCESS;
}
if (bytes < 0)
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM failed status :%d, retires :%d", bytes, usRetries);
else
BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM sent %d", bytes);

psIntfAdapter->psAdapter->DeviceAccess = FALSE;
return bytes;
}

INT InterfaceWRM(PS_INTERFACE_ADAPTER psIntfAdapter,
Expand Down
Loading

0 comments on commit 41c7b7c

Please sign in to comment.