Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=5afeb104e7901168b21aad0437fb51dc620dfdd3
Commit:     5afeb104e7901168b21aad0437fb51dc620dfdd3
Parent:     fc0f8fc9be654bbff08ede04a49bd8f9805b9e13
Author:     Oliver Neukum <[EMAIL PROTECTED]>
AuthorDate: Mon Jun 11 15:36:02 2007 +0200
Committer:  Greg Kroah-Hartman <[EMAIL PROTECTED]>
CommitDate: Mon Jun 25 23:38:06 2007 -0700

    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 <[EMAIL PROTECTED]>
    Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]>
---
 drivers/usb/misc/usblcd.c |   22 ++++++++++++++++++----
 1 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c
index 887ef95..12bad8a 100644
--- a/drivers/usb/misc/usblcd.c
+++ b/drivers/usb/misc/usblcd.c
@@ -42,10 +42,14 @@ struct usb_lcd {
        size_t                  bulk_in_size;           /* the size of the 
receive buffer */
        __u8                    bulk_in_endpointAddr;   /* the address of the 
bulk in endpoint */
        __u8                    bulk_out_endpointAddr;  /* the address of the 
bulk out endpoint */
-       struct kref             kref;
+       struct kref             kref;
+       struct semaphore        limit_sem;              /* to stop writes at 
full throttle from
+                                                        * using up all RAM */
 };
 #define to_lcd_dev(d) container_of(d, struct usb_lcd, kref)
 
+#define USB_LCD_CONCURRENT_WRITES      5
+
 static struct usb_driver lcd_driver;
 static DEFINE_MUTEX(usb_lcd_open_mutex);
 
@@ -186,12 +190,13 @@ static void lcd_write_bulk_callback(struct urb *urb)
        /* free up our allocated buffer */
        usb_buffer_free(urb->dev, urb->transfer_buffer_length,
                        urb->transfer_buffer, urb->transfer_dma);
+       up(&dev->limit_sem);
 }
 
 static ssize_t lcd_write(struct file *file, const char __user * user_buffer, 
size_t count, loff_t *ppos)
 {
        struct usb_lcd *dev;
-        int retval = 0;
+        int retval = 0, r;
        struct urb *urb = NULL;
        char *buf = NULL;
        
@@ -201,10 +206,16 @@ static ssize_t lcd_write(struct file *file, const char 
__user * user_buffer, siz
        if (count == 0)
                goto exit;
 
+       r = down_interruptible(&dev->limit_sem);
+       if (r < 0)
+               return -EINTR;
+
        /* create a urb, and a buffer for it, and copy the data to the urb */
        urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (!urb)
-               return -ENOMEM;
+       if (!urb) {
+               retval = -ENOMEM;
+               goto err_no_buf;
+       }
        
        buf = usb_buffer_alloc(dev->udev, count, GFP_KERNEL, 
&urb->transfer_dma);
        if (!buf) {
@@ -239,6 +250,8 @@ exit:
 error:
        usb_buffer_free(dev->udev, count, buf, urb->transfer_dma);
        usb_free_urb(urb);
+err_no_buf:
+       up(&dev->limit_sem);
        return retval;
 }
 
@@ -277,6 +290,7 @@ static int lcd_probe(struct usb_interface *interface, const 
struct usb_device_id
                goto error;
        }
        kref_init(&dev->kref);
+       sema_init(&dev->limit_sem, USB_LCD_CONCURRENT_WRITES);
 
        dev->udev = usb_get_dev(interface_to_usbdev(interface));
        dev->interface = interface;
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to