On Tue, Mar 03, 2009 at 03:17:00PM -0800, Greg KH wrote: > On Wed, Mar 04, 2009 at 12:07:49AM +0100, Roel Kluin wrote: > > Greg KH wrote: > > > On Tue, Mar 03, 2009 at 10:48:43PM +0100, Roel Kluin wrote: > > >> vi include/linux/usb.h +1373 > > >> struct urb { > > >> ... > > >> int transfer_buffer_length; > > >> ... > > >> } > > >> So I think something like this is needed? > > > > > > Have you ever seen a transfer_buffer_length set to anywhere close to the > > > MAX_INT value to trigger this? Or a negative value? > > > > I observed this by code inspection. > > > > > How about just changing transfer_buffer_length to a u32, that should > > > solve it, right? > > > > That seems a sensible solution, but transfer_buffer_length is used in many > > drivers. It will require a lot of changes. Maybe better leave it as is at > > least until a real problem occurs. > > How will it require a lot of changes? No one should ever be assuming > that it is signed, do you see any problems? And here's the patch that I just applied to the usb patch queue to resolve this issue. Any objections? thanks, greg k-h >From foo@baz Tue Mar 3 16:44:13 PST 2009 Date: Tue, 03 Mar 2009 16:44:13 -0800 To: Greg KH <greg@xxxxxxxxx> From: Greg Kroah-Hartman <gregkh@xxxxxxx> Subject: USB: make some struct urb fields u32 Roel Kluin pointed out that transfer_buffer_lengths in struct urb was declared as an 'int'. This patch changes this field, and the actual_length field to be 'u32' to prevent any potential negative conversion and comparison errors. This triggered a few compiler warning messages when these fields were being used with the min/max macros, so they have also been fixed up in this patch. Cc: Roel Kluin <roel.kluin@xxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxx> --- drivers/usb/gadget/dummy_hcd.c | 2 +- drivers/usb/host/isp116x-hcd.c | 2 +- drivers/usb/host/r8a66597-hcd.c | 2 +- drivers/usb/host/sl811-hcd.c | 4 ++-- drivers/usb/host/uhci-q.c | 2 +- drivers/usb/misc/ftdi-elan.c | 2 +- drivers/usb/serial/ftdi_sio.c | 2 +- include/linux/usb.h | 4 ++-- 8 files changed, 10 insertions(+), 10 deletions(-) --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -1437,7 +1437,7 @@ restart: } if (urb->transfer_buffer_length > 1) buf [1] = 0; - urb->actual_length = min (2, + urb->actual_length = min ((u32)2, urb->transfer_buffer_length); value = 0; status = 0; --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c @@ -772,7 +772,7 @@ static int isp116x_urb_enqueue(struct us break; case PIPE_INTERRUPT: urb->interval = ep->period; - ep->length = min((int)ep->maxpacket, + ep->length = min((u32)ep->maxpacket, urb->transfer_buffer_length); /* urb submitted for already existing endpoint */ --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -1394,7 +1394,7 @@ static void packet_write(struct r8a66597 (int)urb->iso_frame_desc[td->iso_cnt].length); } else { buf = (u16 *)(urb->transfer_buffer + urb->actual_length); - size = min((int)bufsize, + size = min((u32)bufsize, urb->transfer_buffer_length - urb->actual_length); } --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c @@ -230,7 +230,7 @@ static void in_packet( writeb(usb_pipedevice(urb->pipe), data_reg); sl811_write(sl811, bank + SL11H_HOSTCTLREG, control); - ep->length = min((int)len, + ep->length = min((u32)len, urb->transfer_buffer_length - urb->actual_length); PACKET("IN%s/%d qh%p len%d\n", ep->nak_count ? "/retry" : "", !!usb_gettoggle(urb->dev, ep->epnum, 0), ep, len); @@ -255,7 +255,7 @@ static void out_packet( buf = urb->transfer_buffer + urb->actual_length; prefetch(buf); - len = min((int)ep->maxpacket, + len = min((u32)ep->maxpacket, urb->transfer_buffer_length - urb->actual_length); if (!(control & SL11H_HCTLMASK_ISOCH) --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -1498,7 +1498,7 @@ __acquires(uhci->lock) * complete successfully. Either it failed or the URB was * unlinked first. Regardless, don't confuse people with a * negative length. */ - urb->actual_length = max(urb->actual_length, 0); + urb->actual_length = max(urb->actual_length, (u32)0); } /* When giving back the first URB in an Isochronous queue, --- a/drivers/usb/misc/ftdi-elan.c +++ b/drivers/usb/misc/ftdi-elan.c @@ -1702,7 +1702,7 @@ static int ftdi_elan_edset_output(struct | (address << 0); command->width = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)); - command->follows = min(1024, + command->follows = min((u32)1024, urb->transfer_buffer_length - urb->actual_length); command->value = 0; --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1942,7 +1942,7 @@ static void ftdi_process_read(struct wor priv->prev_status = new_status; } - length = min(PKTSZ, urb->actual_length-packet_offset)-2; + length = min((u32)PKTSZ, urb->actual_length-packet_offset)-2; if (length < 0) { dev_err(&port->dev, "%s - bad packet length: %d\n", __func__, length+2); --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -1177,8 +1177,8 @@ struct urb { unsigned int transfer_flags; /* (in) URB_SHORT_NOT_OK | ...*/ void *transfer_buffer; /* (in) associated data buffer */ dma_addr_t transfer_dma; /* (in) dma addr for transfer_buffer */ - int transfer_buffer_length; /* (in) data buffer length */ - int actual_length; /* (return) actual transfer length */ + u32 transfer_buffer_length; /* (in) data buffer length */ + u32 actual_length; /* (return) actual transfer length */ unsigned char *setup_packet; /* (in) setup packet (control only) */ dma_addr_t setup_dma; /* (in) dma addr for setup_packet */ int start_frame; /* (modify) start frame (ISO) */ -- 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