[patch]usblcd doesn't limit memory consumption during write

Oliver Neukum <[email protected]>
Newsgroups gmane.linux.usb.devel
Organization Novell
Message-ID <[email protected]>
Hi,

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.

	Regards
		Oliver
Signed-off-by: Oliver Neukum <[email protected]>
-- 

--- linux-2.6.22-rc4-git2/drivers/usb/misc/usblcd.c.alt	2007-06-11 15:23:11.000000000 +0200
+++ linux-2.6.22-rc4-git2/drivers/usb/misc/usblcd.c	2007-06-11 15:24:27.000000000 +0200
@@ -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;
 
 
@@ -178,12 +182,13 @@ static void lcd_write_bulk_callback(stru
 	/* 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;
 	
@@ -193,10 +198,16 @@ static ssize_t lcd_write(struct file *fi
 	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) {
@@ -231,6 +242,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;
 }
 
@@ -269,6 +282,7 @@ static int lcd_probe(struct usb_interfac
 		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;

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.