The usbip stack dynamically allocates the transfer_buffer of each urb in stub_recv_cmd_submit depending on the requested transfer_buffer_length set via the received tcp packet. As the usbip layer never reuses the always different sized transfer_buffer it can add URB_FREE_BUFFER to every urbs transfer_flags and let urb_destroy call the kfree for it. This patch fixes double kfree situations where the usbip remote side added the URB_FREE_BUFFER. Cc: stable@xxxxxxxxxxxxxxx Signed-off-by: Michael Grzeschik <m.grzeschik@xxxxxxxxxxxxxx> --- v1 -> v2: - rephrased patch subject from: "usb: usbip: avoid the usb layer to kfree our allocated buffer" - changed to always let urb_destoy remove the transfer_buffer v2 -> v3: - added stable to cc - wraped long line with over 80 chars drivers/usb/usbip/stub_main.c | 1 - drivers/usb/usbip/stub_tx.c | 1 - drivers/usb/usbip/usbip_common.c | 9 ++++++++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/usb/usbip/stub_main.c b/drivers/usb/usbip/stub_main.c index 44ab43fc4fcc7..898e0d271fd47 100644 --- a/drivers/usb/usbip/stub_main.c +++ b/drivers/usb/usbip/stub_main.c @@ -261,7 +261,6 @@ void stub_device_cleanup_urbs(struct stub_device *sdev) kmem_cache_free(stub_priv_cache, priv); - kfree(urb->transfer_buffer); kfree(urb->setup_packet); usb_free_urb(urb); } diff --git a/drivers/usb/usbip/stub_tx.c b/drivers/usb/usbip/stub_tx.c index 6b1e8c3f0e4b2..23d1d76766d2c 100644 --- a/drivers/usb/usbip/stub_tx.c +++ b/drivers/usb/usbip/stub_tx.c @@ -28,7 +28,6 @@ static void stub_free_priv_and_urb(struct stub_priv *priv) struct urb *urb = priv->urb; kfree(urb->setup_packet); - kfree(urb->transfer_buffer); list_del(&priv->list); kmem_cache_free(stub_priv_cache, priv); usb_free_urb(urb); diff --git a/drivers/usb/usbip/usbip_common.c b/drivers/usb/usbip/usbip_common.c index cab2b71a80d02..829b608135989 100644 --- a/drivers/usb/usbip/usbip_common.c +++ b/drivers/usb/usbip/usbip_common.c @@ -381,6 +381,12 @@ static unsigned int tweak_transfer_flags(unsigned int flags) return flags; } +static unsigned int tweak_submit_transfer_flags(unsigned int flags) +{ + flags |= URB_FREE_BUFFER; + return flags; +} + static void usbip_pack_cmd_submit(struct usbip_header *pdu, struct urb *urb, int pack) { @@ -398,7 +404,8 @@ static void usbip_pack_cmd_submit(struct usbip_header *pdu, struct urb *urb, spdu->number_of_packets = urb->number_of_packets; spdu->interval = urb->interval; } else { - urb->transfer_flags = spdu->transfer_flags; + urb->transfer_flags = + tweak_submit_transfer_flags(spdu->transfer_flags); urb->transfer_buffer_length = spdu->transfer_buffer_length; urb->start_frame = spdu->start_frame; urb->number_of_packets = spdu->number_of_packets; -- 2.11.0