aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOliver Neukum <oneukum@suse.de>2007-06-11 09:36:02 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2007-06-26 02:38:06 -0400
commit5afeb104e7901168b21aad0437fb51dc620dfdd3 (patch)
tree4e4176d96fb6df1ad12078967bceb058d544ecbe
parentfc0f8fc9be654bbff08ede04a49bd8f9805b9e13 (diff)
USB: usblcd doesn't limit memory consumption during write
usblcd currently has no way to limit memory consumption by fast writers. This is a security problem, as it allows users with write access to this device to drive the system into oom despite resource limits. Here's the fix taken from the modern skeleton driver. Signed-off-by: Oliver Neukum <oneukum@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/usb/misc/usblcd.c22
1 files changed, 18 insertions, 4 deletions
diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c
index 887ef953f3d8..12bad8a205a7 100644
--- a/drivers/usb/misc/usblcd.c
+++ b/drivers/usb/misc/usblcd.c
@@ -42,10 +42,14 @@ struct usb_lcd {
42 size_t bulk_in_size; /* the size of the receive buffer */ 42 size_t bulk_in_size; /* the size of the receive buffer */
43 __u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */ 43 __u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */
44 __u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */ 44 __u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */
45 struct kref kref; 45 struct kref kref;
46 struct semaphore limit_sem; /* to stop writes at full throttle from
47 * using up all RAM */
46}; 48};
47#define to_lcd_dev(d) container_of(d, struct usb_lcd, kref) 49#define to_lcd_dev(d) container_of(d, struct usb_lcd, kref)
48 50
51#define USB_LCD_CONCURRENT_WRITES 5
52
49static struct usb_driver lcd_driver; 53static struct usb_driver lcd_driver;
50static DEFINE_MUTEX(usb_lcd_open_mutex); 54static DEFINE_MUTEX(usb_lcd_open_mutex);
51 55
@@ -186,12 +190,13 @@ static void lcd_write_bulk_callback(struct urb *urb)
186 /* free up our allocated buffer */ 190 /* free up our allocated buffer */
187 usb_buffer_free(urb->dev, urb->transfer_buffer_length, 191 usb_buffer_free(urb->dev, urb->transfer_buffer_length,
188 urb->transfer_buffer, urb->transfer_dma); 192 urb->transfer_buffer, urb->transfer_dma);
193 up(&dev->limit_sem);
189} 194}
190 195
191static ssize_t lcd_write(struct file *file, const char __user * user_buffer, size_t count, loff_t *ppos) 196static ssize_t lcd_write(struct file *file, const char __user * user_buffer, size_t count, loff_t *ppos)
192{ 197{
193 struct usb_lcd *dev; 198 struct usb_lcd *dev;
194 int retval = 0; 199 int retval = 0, r;
195 struct urb *urb = NULL; 200 struct urb *urb = NULL;
196 char *buf = NULL; 201 char *buf = NULL;
197 202
@@ -201,10 +206,16 @@ static ssize_t lcd_write(struct file *file, const char __user * user_buffer, siz
201 if (count == 0) 206 if (count == 0)
202 goto exit; 207 goto exit;
203 208
209 r = down_interruptible(&dev->limit_sem);
210 if (r < 0)
211 return -EINTR;
212
204 /* create a urb, and a buffer for it, and copy the data to the urb */ 213 /* create a urb, and a buffer for it, and copy the data to the urb */
205 urb = usb_alloc_urb(0, GFP_KERNEL); 214 urb = usb_alloc_urb(0, GFP_KERNEL);
206 if (!urb) 215 if (!urb) {
207 return -ENOMEM; 216 retval = -ENOMEM;
217 goto err_no_buf;
218 }
208 219
209 buf = usb_buffer_alloc(dev->udev, count, GFP_KERNEL, &urb->transfer_dma); 220 buf = usb_buffer_alloc(dev->udev, count, GFP_KERNEL, &urb->transfer_dma);
210 if (!buf) { 221 if (!buf) {
@@ -239,6 +250,8 @@ exit:
239error: 250error:
240 usb_buffer_free(dev->udev, count, buf, urb->transfer_dma); 251 usb_buffer_free(dev->udev, count, buf, urb->transfer_dma);
241 usb_free_urb(urb); 252 usb_free_urb(urb);
253err_no_buf:
254 up(&dev->limit_sem);
242 return retval; 255 return retval;
243} 256}
244 257
@@ -277,6 +290,7 @@ static int lcd_probe(struct usb_interface *interface, const struct usb_device_id
277 goto error; 290 goto error;
278 } 291 }
279 kref_init(&dev->kref); 292 kref_init(&dev->kref);
293 sema_init(&dev->limit_sem, USB_LCD_CONCURRENT_WRITES);
280 294
281 dev->udev = usb_get_dev(interface_to_usbdev(interface)); 295 dev->udev = usb_get_dev(interface_to_usbdev(interface));
282 dev->interface = interface; 296 dev->interface = interface;