On Thu, 28 Jun 2012, Matthieu CASTET wrote: > If we don't read fast enough hidraw device, hidraw_report_event > will cycle and we will leak list->buffer. > Also list->buffer are not free on release. > After this patch, kmemleak report nothing. > > Signed-off-by: Matthieu CASTET <matthieu.castet@xxxxxxxxxx> > --- > drivers/hid/hidraw.c | 12 +++++++++++- > 1 file changed, 11 insertions(+), 1 deletion(-) > > diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c > index 36fa77b..3b6f7bf 100644 > --- a/drivers/hid/hidraw.c > +++ b/drivers/hid/hidraw.c > @@ -96,6 +96,7 @@ static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, > } > > kfree(list->buffer[list->tail].value); > + list->buffer[list->tail].value = NULL; > list->tail = (list->tail + 1) & (HIDRAW_BUFFER_SIZE - 1); > } > out: > @@ -300,6 +301,7 @@ static int hidraw_release(struct inode * inode, struct file * file) > struct hidraw *dev; > struct hidraw_list *list = file->private_data; > int ret; > + int i; > > mutex_lock(&minors_lock); > if (!hidraw_table[minor]) { > @@ -317,6 +319,9 @@ static int hidraw_release(struct inode * inode, struct file * file) > kfree(list->hidraw); > } > } > + > + for (i = 0; i < HIDRAW_BUFFER_SIZE; ++i) > + kfree(list->buffer[i].value); > kfree(list); > ret = 0; > unlock: > @@ -446,12 +451,17 @@ int hidraw_report_event(struct hid_device *hid, u8 *data, int len) > int ret = 0; > > list_for_each_entry(list, &dev->list, node) { > + int new_head = (list->head + 1) & (HIDRAW_BUFFER_SIZE - 1); > + > + if (new_head == list->tail) > + continue; > + > if (!(list->buffer[list->head].value = kmemdup(data, len, GFP_ATOMIC))) { > ret = -ENOMEM; > break; > } > list->buffer[list->head].len = len; > - list->head = (list->head + 1) & (HIDRAW_BUFFER_SIZE - 1); > + list->head = new_head; > kill_fasync(&list->fasync, SIGIO, POLL_IN); > } > Applied, thank you Matthieu. -- Jiri Kosina SUSE Labs -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html