Re: [PATCH] staging: octeon-usb: prevent memory corruption

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On Thu, 20 Mar 2014, Aaro Koskinen wrote:

> octeon-hcd will crash the kernel when SLOB is used. This usually happens
> after the 18-byte control transfer when a device descriptor is read.
> The DMA engine is always transfering full 32-bit words and if the
> transfer is shorter, some random garbage appears after the buffer.
> The problem is not visible with SLUB since it rounds up the allocations
> to word boundary, and the extra bytes will go undetected.
> 
> Fix by providing quirk functions for DMA map/unmap that allocate a bigger
> temporary buffer when necessary. Tested by booting EdgeRouter Lite
> to USB stick root file system with SLAB, SLOB and SLUB kernels.
> 
> Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=72121
> Reported-by: Sergey Popov <pinkbyte@xxxxxxxxxx>
> Signed-off-by: Aaro Koskinen <aaro.koskinen@xxxxxx>
> ---
>  drivers/staging/octeon-usb/octeon-hcd.c | 108 ++++++++++++++++++++++++++++++++
>  1 file changed, 108 insertions(+)
> 
> diff --git a/drivers/staging/octeon-usb/octeon-hcd.c b/drivers/staging/octeon-usb/octeon-hcd.c
> index 5a001d9..9c152f9 100644
> --- a/drivers/staging/octeon-usb/octeon-hcd.c
> +++ b/drivers/staging/octeon-usb/octeon-hcd.c
> @@ -465,6 +465,112 @@ struct octeon_hcd {
>  #define USB_FIFO_ADDRESS(channel, usb_index) (CVMX_USBCX_GOTGCTL(usb_index) + ((channel)+1)*0x1000)
>  
>  /**
> + * struct octeon_temp_buffer - a bounce buffer for USB transfers
> + * @temp_buffer: the newly allocated temporary buffer (including meta-data)
> + * @orig_buffer: the original buffer passed by the USB stack
> + * @data:	 the newly allocated temporary buffer (excluding meta-data)
> + *
> + * Both the DMA engine and FIFO mode will always transfer full 32-bit words. If
> + * the buffer is too short, we need to allocate a temporary one, and this struct
> + * represents it.
> + */
> +struct octeon_temp_buffer {
> +	void *temp_buffer;
> +	void *orig_buffer;
> +	u8 data[0];
> +};
> +
> +/**
> + * octeon_alloc_temp_buffer - allocate a temporary buffer for USB transfer
> + *                            (if needed)
> + * @urb:	URB.
> + * @mem_flags:	Memory allocation flags.
> + *
> + * This function allocates a temporary bounce buffer whenever it's needed
> + * due to HW limitations.
> + */
> +static int octeon_alloc_temp_buffer(struct urb *urb, gfp_t mem_flags)
> +{
> +	struct octeon_temp_buffer *temp;
> +
> +	if (urb->num_sgs || urb->sg ||
> +	    (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) ||
> +	    !(urb->transfer_buffer_length % sizeof(u32)))
> +		return 0;
> +
> +	temp = kmalloc(ALIGN(urb->transfer_buffer_length, sizeof(u32)) +
> +		       sizeof(*temp), mem_flags);
> +	if (!temp)
> +		return -ENOMEM;
> +
> +	temp->temp_buffer = temp;
> +	temp->orig_buffer = urb->transfer_buffer;
> +	if (usb_urb_dir_out(urb))
> +		memcpy(temp->data, urb->transfer_buffer,
> +		       urb->transfer_buffer_length);
> +	urb->transfer_buffer = temp->data;
> +	urb->transfer_flags |= URB_ALIGNED_TEMP_BUFFER;
> +
> +	return 0;
> +}
> +
> 

I don't think you need the temp_buffer in struct octeon_temp_buffer.  
Once you have temp in octeon_free_temp_buffer via container_of, just free 
temp.  There is no need to look at temp_buffer to get its address.

Thomas Pugliese
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux