Re: [PATCH] USB: do not convert negative transfer_buffer_lengths to positive

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

 



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

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

  Powered by Linux