Commit 41c7b7c0 authored by Kevin McKinney's avatar Kevin McKinney Committed by Greg Kroah-Hartman
Browse files

Staging: bcm: Fix information leak in ioctl: IOCTL_BCM_REGISTER_READ_PRIVATE,...


Staging: bcm: Fix information leak in ioctl: IOCTL_BCM_REGISTER_READ_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: default avatarKevin McKinney <klmckinney1@gmail.com>
Reviewed-by: default avatarDan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 57bfa9d4
Loading
Loading
Loading
Loading
+34 −15
Original line number Diff line number Diff line
@@ -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);

@@ -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);
@@ -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;
@@ -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 */
@@ -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;
@@ -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 &
@@ -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 */
+8 −4
Original line number Diff line number Diff line
@@ -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);
@@ -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;
		}
@@ -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");
@@ -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;
		}
+18 −15
Original line number Diff line number Diff line
@@ -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));

@@ -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;
				}
@@ -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;
				}
@@ -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.
@@ -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;
		}
+7 −5
Original line number Diff line number Diff line
@@ -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);
@@ -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;
@@ -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));
@@ -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;
	}
+11 −13
Original line number Diff line number Diff line
@@ -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) {
@@ -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,
@@ -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 (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);

	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;
	}
	return bytes;
}

INT InterfaceWRM(PS_INTERFACE_ADAPTER psIntfAdapter,
Loading