aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOliver Neukum <oliver@neukum.org>2005-12-21 13:27:29 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2006-01-04 16:51:44 -0500
commitff90651883093576de2d60bebaae39b0dd2e62f6 (patch)
tree8029f0742384a7f22fbd4175cf9a73194eee33d6
parentaafbf24a1129480157af7ee780eddcea9b76ee5c (diff)
[PATCH] USB: Limiting of resource use in skeleton driver
this introduces limits whose lack in the skeleton driver someone recently complained about. Signed-off-by: Oliver Neukum <oliver@neukum.name> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/usb/usb-skeleton.c25
1 files changed, 18 insertions, 7 deletions
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index 60c458ebaa2d..719d23a4ac51 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -39,10 +39,15 @@ MODULE_DEVICE_TABLE (usb, skel_table);
39/* Get a minor range for your devices from the usb maintainer */ 39/* Get a minor range for your devices from the usb maintainer */
40#define USB_SKEL_MINOR_BASE 192 40#define USB_SKEL_MINOR_BASE 192
41 41
42/* our private defines. if this grows any larger, use your own .h file */
43#define MAX_TRANSFER ( PAGE_SIZE - 512 )
44#define WRITES_IN_FLIGHT 8
45
42/* Structure to hold all of our device specific stuff */ 46/* Structure to hold all of our device specific stuff */
43struct usb_skel { 47struct usb_skel {
44 struct usb_device * udev; /* the usb device for this device */ 48 struct usb_device * udev; /* the usb device for this device */
45 struct usb_interface * interface; /* the interface for this device */ 49 struct usb_interface * interface; /* the interface for this device */
50 struct semaphore limit_sem; /* limiting the number of writes in progress */
46 unsigned char * bulk_in_buffer; /* the buffer to receive data */ 51 unsigned char * bulk_in_buffer; /* the buffer to receive data */
47 size_t bulk_in_size; /* the size of the receive buffer */ 52 size_t bulk_in_size; /* the size of the receive buffer */
48 __u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */ 53 __u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */
@@ -152,6 +157,7 @@ static void skel_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
152 /* free up our allocated buffer */ 157 /* free up our allocated buffer */
153 usb_buffer_free(urb->dev, urb->transfer_buffer_length, 158 usb_buffer_free(urb->dev, urb->transfer_buffer_length,
154 urb->transfer_buffer, urb->transfer_dma); 159 urb->transfer_buffer, urb->transfer_dma);
160 up(&dev->limit_sem);
155} 161}
156 162
157static ssize_t skel_write(struct file *file, const char *user_buffer, size_t count, loff_t *ppos) 163static ssize_t skel_write(struct file *file, const char *user_buffer, size_t count, loff_t *ppos)
@@ -160,6 +166,7 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
160 int retval = 0; 166 int retval = 0;
161 struct urb *urb = NULL; 167 struct urb *urb = NULL;
162 char *buf = NULL; 168 char *buf = NULL;
169 size_t writesize = max(count, MAX_TRANSFER);
163 170
164 dev = (struct usb_skel *)file->private_data; 171 dev = (struct usb_skel *)file->private_data;
165 172
@@ -167,6 +174,9 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
167 if (count == 0) 174 if (count == 0)
168 goto exit; 175 goto exit;
169 176
177 /* limit the number of URBs in flight to stop a user from using up all RAM */
178 down (&dev->limit_sem);
179
170 /* create a urb, and a buffer for it, and copy the data to the urb */ 180 /* create a urb, and a buffer for it, and copy the data to the urb */
171 urb = usb_alloc_urb(0, GFP_KERNEL); 181 urb = usb_alloc_urb(0, GFP_KERNEL);
172 if (!urb) { 182 if (!urb) {
@@ -174,13 +184,13 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
174 goto error; 184 goto error;
175 } 185 }
176 186
177 buf = usb_buffer_alloc(dev->udev, count, GFP_KERNEL, &urb->transfer_dma); 187 buf = usb_buffer_alloc(dev->udev, writesize, GFP_KERNEL, &urb->transfer_dma);
178 if (!buf) { 188 if (!buf) {
179 retval = -ENOMEM; 189 retval = -ENOMEM;
180 goto error; 190 goto error;
181 } 191 }
182 192
183 if (copy_from_user(buf, user_buffer, count)) { 193 if (copy_from_user(buf, user_buffer, writesize)) {
184 retval = -EFAULT; 194 retval = -EFAULT;
185 goto error; 195 goto error;
186 } 196 }
@@ -188,7 +198,7 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
188 /* initialize the urb properly */ 198 /* initialize the urb properly */
189 usb_fill_bulk_urb(urb, dev->udev, 199 usb_fill_bulk_urb(urb, dev->udev,
190 usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr), 200 usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
191 buf, count, skel_write_bulk_callback, dev); 201 buf, writesize, skel_write_bulk_callback, dev);
192 urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 202 urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
193 203
194 /* send the data out the bulk port */ 204 /* send the data out the bulk port */
@@ -202,11 +212,12 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
202 usb_free_urb(urb); 212 usb_free_urb(urb);
203 213
204exit: 214exit:
205 return count; 215 return writesize;
206 216
207error: 217error:
208 usb_buffer_free(dev->udev, count, buf, urb->transfer_dma); 218 usb_buffer_free(dev->udev, writesize, buf, urb->transfer_dma);
209 usb_free_urb(urb); 219 usb_free_urb(urb);
220 up(&dev->limit_sem);
210 return retval; 221 return retval;
211} 222}
212 223
@@ -238,13 +249,13 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
238 int retval = -ENOMEM; 249 int retval = -ENOMEM;
239 250
240 /* allocate memory for our device state and initialize it */ 251 /* allocate memory for our device state and initialize it */
241 dev = kmalloc(sizeof(*dev), GFP_KERNEL); 252 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
242 if (dev == NULL) { 253 if (dev == NULL) {
243 err("Out of memory"); 254 err("Out of memory");
244 goto error; 255 goto error;
245 } 256 }
246 memset(dev, 0x00, sizeof(*dev));
247 kref_init(&dev->kref); 257 kref_init(&dev->kref);
258 sema_init(&dev->limit_sem, WRITES_IN_FLIGHT);
248 259
249 dev->udev = usb_get_dev(interface_to_usbdev(interface)); 260 dev->udev = usb_get_dev(interface_to_usbdev(interface));
250 dev->interface = interface; 261 dev->interface = interface;