Message ID | 20240125063225.2796234-1-suhui@nfschina.com |
---|---|
State | Accepted |
Commit | a3bdcdd022c68942a774e8e63424cc11c85aab78 |
Headers | show |
Series | HID: hidraw: fix a problem of memory leak in hidraw_release() | expand |
On Thu, Jan 25, 2024 at 02:32:26PM +0800, Su Hui wrote: > 'struct hidraw_list' is a circular queue whose head can be smaller than > tail. Using 'list->tail != list->head' to release all memory that should > be released. > > Fixes: a5623a203cff ("HID: hidraw: fix memory leak in hidraw_release()") > Signed-off-by: Su Hui <suhui@nfschina.com> This is very clever. How did you find that? Was it through static analysis or just review? Perhaps using syzkaller? Reviewed-by: Dan Carpenter <dan.carpenter@linaro.org> I imagine we could write a checker heuristic to identify ->tail and ->head struct members and then complain if they were ever used in a < or > comparison. regards, dan carpenter
On Thu, 25 Jan 2024, Su Hui wrote: > 'struct hidraw_list' is a circular queue whose head can be smaller than > tail. Using 'list->tail != list->head' to release all memory that should > be released. > > Fixes: a5623a203cff ("HID: hidraw: fix memory leak in hidraw_release()") > Signed-off-by: Su Hui <suhui@nfschina.com> Good catch, thanks. Applied.
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index 13c8dd8cd350..2bc762d31ac7 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c @@ -357,8 +357,11 @@ static int hidraw_release(struct inode * inode, struct file * file) down_write(&minors_rwsem); spin_lock_irqsave(&hidraw_table[minor]->list_lock, flags); - for (int i = list->tail; i < list->head; i++) - kfree(list->buffer[i].value); + while (list->tail != list->head) { + kfree(list->buffer[list->tail].value); + list->buffer[list->tail].value = NULL; + list->tail = (list->tail + 1) & (HIDRAW_BUFFER_SIZE - 1); + } list_del(&list->node); spin_unlock_irqrestore(&hidraw_table[minor]->list_lock, flags); kfree(list);
'struct hidraw_list' is a circular queue whose head can be smaller than tail. Using 'list->tail != list->head' to release all memory that should be released. Fixes: a5623a203cff ("HID: hidraw: fix memory leak in hidraw_release()") Signed-off-by: Su Hui <suhui@nfschina.com> --- drivers/hid/hidraw.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)