summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichal Pecio <michal.pecio@gmail.com>2025-10-14 20:35:28 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2025-10-29 13:59:59 +0100
commita8749742e6dc46ee1419d757240173d4487ff9df (patch)
tree97dbb3c40a9a30413c3c0a098eef77842fe3698f
parent93166bc53c0e3587058327a4121daea34b4fecd5 (diff)
downloadlinux-a8749742e6dc46ee1419d757240173d4487ff9df.tar.gz
linux-a8749742e6dc46ee1419d757240173d4487ff9df.tar.bz2
linux-a8749742e6dc46ee1419d757240173d4487ff9df.zip
net: usb: rtl8150: Fix frame padding
commit 75cea9860aa6b2350d90a8d78fed114d27c7eca2 upstream. TX frames aren't padded and unknown memory is sent into the ether. Theoretically, it isn't even guaranteed that the extra memory exists and can be sent out, which could cause further problems. In practice, I found that plenty of tailroom exists in the skb itself (in my test with ping at least) and skb_padto() easily succeeds, so use it here. In the event of -ENOMEM drop the frame like other drivers do. The use of one more padding byte instead of a USB zero-length packet is retained to avoid regression. I have a dodgy Etron xHCI controller which doesn't seem to support sending ZLPs at all. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Cc: stable@vger.kernel.org Signed-off-by: Michal Pecio <michal.pecio@gmail.com> Reviewed-by: Simon Horman <horms@kernel.org> Link: https://patch.msgid.link/20251014203528.3f9783c4.michal.pecio@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/net/usb/rtl8150.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c
index 1df289e7c130..e4cca92aa4a8 100644
--- a/drivers/net/usb/rtl8150.c
+++ b/drivers/net/usb/rtl8150.c
@@ -705,9 +705,16 @@ static netdev_tx_t rtl8150_start_xmit(struct sk_buff *skb,
rtl8150_t *dev = netdev_priv(netdev);
int count, res;
+ /* pad the frame and ensure terminating USB packet, datasheet 9.2.3 */
+ count = max(skb->len, ETH_ZLEN);
+ if (count % 64 == 0)
+ count++;
+ if (skb_padto(skb, count)) {
+ netdev->stats.tx_dropped++;
+ return NETDEV_TX_OK;
+ }
+
netif_stop_queue(netdev);
- count = (skb->len < 60) ? 60 : skb->len;
- count = (count & 0x3f) ? count : count + 1;
dev->tx_skb = skb;
usb_fill_bulk_urb(dev->tx_urb, dev->udev, usb_sndbulkpipe(dev->udev, 2),
skb->data, count, write_bulk_callback, dev);