mirror of https://gitee.com/openkylin/linux.git
usb: gadget: printer: eliminate random pointer dereference
struct printer_dev contains 3 list heads: tx_reqs, rx_reqs and rx_buffers. There is just one instance of this structure in the driver and it is file static, and as such initialized with all zeros. If device_create() or cdev_add() fails then "goto fail" branch is taken, which results in printer_cfg_unbind() call. The latter checks if tx_reqs, rx_reqs and rx_buffers lists are empty. The check for emptiness is in fact a check whether the "next" member of struct list_head points to the head of the list. But the heads of the lists in question have not been initialized yet and, as mentioned above, contain all zeros, so list_empty() returns false and respective "while" loop body starts executing. Here, container_of() just subtracts the offset of a struct usb_request member from an address of this same member, which results in a value somewhere near 0 or 0xfff...ff. And the argument to list_del() dereferences such a pointer which causes a disaster. This patch moves respective INIT_LIST_HEAD() invocations to a point before "goto fail" branch can be taken. Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
This commit is contained in:
parent
050f571264
commit
c69b818694
|
@ -1190,6 +1190,9 @@ static int __init printer_bind_config(struct usb_configuration *c)
|
|||
dev->function.unbind = printer_func_unbind;
|
||||
dev->function.set_alt = printer_func_set_alt;
|
||||
dev->function.disable = printer_func_disable;
|
||||
INIT_LIST_HEAD(&dev->tx_reqs);
|
||||
INIT_LIST_HEAD(&dev->rx_reqs);
|
||||
INIT_LIST_HEAD(&dev->rx_buffers);
|
||||
|
||||
status = usb_add_function(c, &dev->function);
|
||||
if (status)
|
||||
|
@ -1233,11 +1236,8 @@ static int __init printer_bind_config(struct usb_configuration *c)
|
|||
|
||||
spin_lock_init(&dev->lock);
|
||||
mutex_init(&dev->lock_printer_io);
|
||||
INIT_LIST_HEAD(&dev->tx_reqs);
|
||||
INIT_LIST_HEAD(&dev->tx_reqs_active);
|
||||
INIT_LIST_HEAD(&dev->rx_reqs);
|
||||
INIT_LIST_HEAD(&dev->rx_reqs_active);
|
||||
INIT_LIST_HEAD(&dev->rx_buffers);
|
||||
init_waitqueue_head(&dev->rx_wait);
|
||||
init_waitqueue_head(&dev->tx_wait);
|
||||
init_waitqueue_head(&dev->tx_flush_wait);
|
||||
|
|
Loading…
Reference in New Issue