Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 89877e42827f16fa5f86b1df0c2860b1 > files > 2360

kernel-2.6.18-128.1.10.el5.src.rpm

From: Anton Arapov <aarapov@redhat.com>
Subject: To: [RHEL5.1 PATCH] BZ276011: CVE-2007-3513 Locally triggerable memory consumption in usblcd
Date: Sat, 08 Sep 2007 21:24:31 +0200
Bugzilla: 276011
Message-Id: <h8d4wtyn80.fsf@pepelac.englab.brq.redhat.com>
Changelog: [usb] usblcd: Locally triggerable memory consumption


BZ#276011: (tracking bug number)
  https://bugzilla.redhat.com/show_bug.cgi?id=276011

Description: [from upstream patch]
  sblcd 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 despiteds resource
limits.

Upstream status:
  commit# 5afeb104e7901168b21aad0437fb51dc620dfdd3

Test status:
  Patch has been tested for compilation an boot.
  Has not been tested with real HW, because of appropriate HW absence. :)

Notice:
  BZ#247728 - original bug number.

==
diff -urpN linux-2.6.18.noarch.orig/drivers/usb/misc/usblcd.c linux-2.6.18.noarch/drivers/usb/misc/usblcd.c
--- linux-2.6.18.noarch.orig/drivers/usb/misc/usblcd.c	2007-09-06 16:44:13.000000000 +0200
+++ linux-2.6.18.noarch/drivers/usb/misc/usblcd.c	2007-09-06 16:45:02.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;
 
 
@@ -183,12 +187,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;
 	
@@ -197,11 +202,17 @@ static ssize_t lcd_write(struct file *fi
 	/* verify that we actually have some data to write */
 	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) {
@@ -236,6 +247,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;
 }
 
@@ -274,6 +287,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;

-- 
Anton Arapov, <aarapov@redhat.com>
Kernel Development, Red Hat
GPG Key ID: 0x6FA8C812