[ Upstream commit 61356088ace1866a847a727d4d40da7bf00b67fc ]

The QMAP code in the qmi_wwan driver is based on the CodeAurora GobiNet
driver which does not process QMAP padding in the RX path correctly.
Add support for QMAP padding to qmimux_rx_fixup() according to the
description of the rmnet driver.

Fixes: c6adf77953bc ("net: usb: qmi_wwan: add qmap mux protocol support")
Cc: Daniele Palmas <dnl...@gmail.com>
Signed-off-by: Reinhard Speyerer <rs...@arcor.de>
Signed-off-by: David S. Miller <da...@davemloft.net>
Signed-off-by: Sasha Levin <sas...@kernel.org>
---
 drivers/net/usb/qmi_wwan.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index e657d8947125..090227118d3d 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -153,7 +153,7 @@ static bool qmimux_has_slaves(struct usbnet *dev)
 
 static int qmimux_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 {
-       unsigned int len, offset = 0;
+       unsigned int len, offset = 0, pad_len, pkt_len;
        struct qmimux_hdr *hdr;
        struct net_device *net;
        struct sk_buff *skbn;
@@ -171,10 +171,16 @@ static int qmimux_rx_fixup(struct usbnet *dev, struct 
sk_buff *skb)
                if (hdr->pad & 0x80)
                        goto skip;
 
+               /* extract padding length and check for valid length info */
+               pad_len = hdr->pad & 0x3f;
+               if (len == 0 || pad_len >= len)
+                       goto skip;
+               pkt_len = len - pad_len;
+
                net = qmimux_find_dev(dev, hdr->mux_id);
                if (!net)
                        goto skip;
-               skbn = netdev_alloc_skb(net, len);
+               skbn = netdev_alloc_skb(net, pkt_len);
                if (!skbn)
                        return 0;
                skbn->dev = net;
@@ -191,7 +197,7 @@ static int qmimux_rx_fixup(struct usbnet *dev, struct 
sk_buff *skb)
                        goto skip;
                }
 
-               skb_put_data(skbn, skb->data + offset + qmimux_hdr_sz, len);
+               skb_put_data(skbn, skb->data + offset + qmimux_hdr_sz, pkt_len);
                if (netif_rx(skbn) != NET_RX_SUCCESS)
                        return 0;
 
-- 
2.20.1



Reply via email to