|
|
cbf2d8 |
From ad4757373f2ade3e1b238c8967d1b5bf80654820 Mon Sep 17 00:00:00 2001
|
|
|
cbf2d8 |
From: Yannick Cote <ycote@redhat.com>
|
|
|
cbf2d8 |
Date: Wed, 7 Dec 2022 14:07:55 -0500
|
|
|
cbf2d8 |
Subject: [KPATCH CVE-2022-2964] kpatch fixes for CVE-2022-2964
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
Kernels:
|
|
|
cbf2d8 |
3.10.0-1160.66.1.el7
|
|
|
cbf2d8 |
3.10.0-1160.71.1.el7
|
|
|
cbf2d8 |
3.10.0-1160.76.1.el7
|
|
|
cbf2d8 |
3.10.0-1160.80.1.el7
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
Kpatch-MR: https://gitlab.com/redhat/prdsc/rhel/src/kpatch/rhel-7/-/merge_requests/47
|
|
|
cbf2d8 |
Approved-by: Joe Lawrence (@joe.lawrence)
|
|
|
cbf2d8 |
Changes since last build:
|
|
|
cbf2d8 |
arches: x86_64 ppc64le
|
|
|
cbf2d8 |
ax88179_178a.o: changed function: ax88179_rx_fixup
|
|
|
cbf2d8 |
ax88179_178a.o: changed function: ax88179_tx_fixup
|
|
|
cbf2d8 |
---------------------------
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
Modifications: none
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
commit 6887c693d5b263d458cdae235b5ca4cb36d79466
|
|
|
cbf2d8 |
Author: Jose Ignacio Tornos Martinez <jtornosm@redhat.com>
|
|
|
cbf2d8 |
Date: Thu Oct 6 18:32:21 2022 +0200
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
net: usb: ax88179_178a: fix packet alignment padding
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
Bugzilla: https://bugzilla.redhat.com/2120504
|
|
|
cbf2d8 |
CVE: CVE-2022-2964
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
commit e869e7a17798d85829fa7d4f9bbe1eebd4b2d3f6
|
|
|
cbf2d8 |
Author: Jeremy Kerr <jk@ozlabs.org>
|
|
|
cbf2d8 |
Date: Mon Jun 15 10:54:56 2020 +0800
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
net: usb: ax88179_178a: fix packet alignment padding
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
Using a AX88179 device (0b95:1790), I see two bytes of appended data on
|
|
|
cbf2d8 |
every RX packet. For example, this 48-byte ping, using 0xff as a
|
|
|
cbf2d8 |
payload byte:
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
04:20:22.528472 IP 192.168.1.1 > 192.168.1.2: ICMP echo request, id 2447, seq 1, length 64
|
|
|
cbf2d8 |
0x0000: 000a cd35 ea50 000a cd35 ea4f 0800 4500
|
|
|
cbf2d8 |
0x0010: 0054 c116 4000 4001 f63e c0a8 0101 c0a8
|
|
|
cbf2d8 |
0x0020: 0102 0800 b633 098f 0001 87ea cd5e 0000
|
|
|
cbf2d8 |
0x0030: 0000 dcf2 0600 0000 0000 ffff ffff ffff
|
|
|
cbf2d8 |
0x0040: ffff ffff ffff ffff ffff ffff ffff ffff
|
|
|
cbf2d8 |
0x0050: ffff ffff ffff ffff ffff ffff ffff ffff
|
|
|
cbf2d8 |
0x0060: ffff 961f
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
Those last two bytes - 96 1f - aren't part of the original packet.
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
In the ax88179 RX path, the usbnet rx_fixup function trims a 2-byte
|
|
|
cbf2d8 |
'alignment pseudo header' from the start of the packet, and sets the
|
|
|
cbf2d8 |
length from a per-packet field populated by hardware. It looks like that
|
|
|
cbf2d8 |
length field *includes* the 2-byte header; the current driver assumes
|
|
|
cbf2d8 |
that it's excluded.
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
This change trims the 2-byte alignment header after we've set the packet
|
|
|
cbf2d8 |
length, so the resulting packet length is correct. While we're moving
|
|
|
cbf2d8 |
the comment around, this also fixes the spelling of 'pseudo'.
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
|
|
|
cbf2d8 |
Signed-off-by: David S. Miller <davem@davemloft.net>
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
Signed-off-by: Jose Ignacio Tornos Martinez <jtornosm@redhat.com>
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
commit cb4cf1dd8820ba776a91ebf5b88ad1c3d83a0dfb
|
|
|
cbf2d8 |
Author: Jose Ignacio Tornos Martinez <jtornosm@redhat.com>
|
|
|
cbf2d8 |
Date: Thu Oct 6 18:32:21 2022 +0200
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
ax88179_178a: Merge memcpy + le32_to_cpus to get_unaligned_le32
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
Bugzilla: https://bugzilla.redhat.com/2120504
|
|
|
cbf2d8 |
CVE: CVE-2022-2964
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
commit d1854d509d61d36af44f2130423bff8836e1592e
|
|
|
cbf2d8 |
Author: Chuhong Yuan <hslester96@gmail.com>
|
|
|
cbf2d8 |
Date: Fri Jul 19 17:07:15 2019 +0800
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
ax88179_178a: Merge memcpy + le32_to_cpus to get_unaligned_le32
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
Merge the combo use of memcpy and le32_to_cpus.
|
|
|
cbf2d8 |
Use get_unaligned_le32 instead.
|
|
|
cbf2d8 |
This simplifies the code.
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
Signed-off-by: Chuhong Yuan <hslester96@gmail.com>
|
|
|
cbf2d8 |
Signed-off-by: David S. Miller <davem@davemloft.net>
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
Signed-off-by: Jose Ignacio Tornos Martinez <jtornosm@redhat.com>
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
commit 4e6ea26989123e731329323492d30f826aa28010
|
|
|
cbf2d8 |
Author: Jose Ignacio Tornos Martinez <jtornosm@redhat.com>
|
|
|
cbf2d8 |
Date: Thu Oct 6 18:32:21 2022 +0200
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
net: usb: Merge cpu_to_le32s + memcpy to put_unaligned_le32
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
Bugzilla: https://bugzilla.redhat.com/2120504
|
|
|
cbf2d8 |
CVE: CVE-2022-2964
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
Conflicts:
|
|
|
cbf2d8 |
Only ax88179 files
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
commit 7e24b4ed5ac4321e41415b0c6f0f8a8ac14852b2
|
|
|
cbf2d8 |
Author: Chuhong Yuan <hslester96@gmail.com>
|
|
|
cbf2d8 |
Date: Mon Jul 22 15:41:34 2019 +0800
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
net: usb: Merge cpu_to_le32s + memcpy to put_unaligned_le32
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
Merge the combo uses of cpu_to_le32s and memcpy.
|
|
|
cbf2d8 |
Use put_unaligned_le32 instead.
|
|
|
cbf2d8 |
This simplifies the code.
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
Signed-off-by: Chuhong Yuan <hslester96@gmail.com>
|
|
|
cbf2d8 |
Signed-off-by: David S. Miller <davem@davemloft.net>
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
Signed-off-by: Jose Ignacio Tornos Martinez <jtornosm@redhat.com>
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
commit 7faaf2665dcbc3a4fdb31331de699045040ed213
|
|
|
cbf2d8 |
Author: Jose Ignacio Tornos Martinez <jtornosm@redhat.com>
|
|
|
cbf2d8 |
Date: Thu Oct 6 18:32:22 2022 +0200
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
net: usb: ax88179_178a: Fix out-of-bounds accesses in RX fixup
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
Bugzilla: https://bugzilla.redhat.com/2120504
|
|
|
cbf2d8 |
CVE: CVE-2022-2964
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
commit 57bc3d3ae8c14df3ceb4e17d26ddf9eeab304581
|
|
|
cbf2d8 |
Author: Jann Horn <jannh@google.com>
|
|
|
cbf2d8 |
Date: Wed Jan 26 14:14:52 2022 +0100
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
net: usb: ax88179_178a: Fix out-of-bounds accesses in RX fixup
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
ax88179_rx_fixup() contains several out-of-bounds accesses that can be
|
|
|
cbf2d8 |
triggered by a malicious (or defective) USB device, in particular:
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
- The metadata array (hdr_off..hdr_off+2*pkt_cnt) can be out of bounds,
|
|
|
cbf2d8 |
causing OOB reads and (on big-endian systems) OOB endianness flips.
|
|
|
cbf2d8 |
- A packet can overlap the metadata array, causing a later OOB
|
|
|
cbf2d8 |
endianness flip to corrupt data used by a cloned SKB that has already
|
|
|
cbf2d8 |
been handed off into the network stack.
|
|
|
cbf2d8 |
- A packet SKB can be constructed whose tail is far beyond its end,
|
|
|
cbf2d8 |
causing out-of-bounds heap data to be considered part of the SKB's
|
|
|
cbf2d8 |
data.
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
I have tested that this can be used by a malicious USB device to send a
|
|
|
cbf2d8 |
bogus ICMPv6 Echo Request and receive an ICMPv6 Echo Reply in response
|
|
|
cbf2d8 |
that contains random kernel heap data.
|
|
|
cbf2d8 |
It's probably also possible to get OOB writes from this on a
|
|
|
cbf2d8 |
little-endian system somehow - maybe by triggering skb_cow() via IP
|
|
|
cbf2d8 |
options processing -, but I haven't tested that.
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
Fixes: e2ca90c276e1 ("ax88179_178a: ASIX AX88179_178A USB 3.0/2.0 to gigabit ethernet adapter driver")
|
|
|
cbf2d8 |
Cc: stable@kernel.org
|
|
|
cbf2d8 |
Signed-off-by: Jann Horn <jannh@google.com>
|
|
|
cbf2d8 |
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
Signed-off-by: Jose Ignacio Tornos Martinez <jtornosm@redhat.com>
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
commit 4e8b1e4091c6dce2911ffe8b9a8a7c58f8b028bc
|
|
|
cbf2d8 |
Author: Jose Ignacio Tornos Martinez <jtornosm@redhat.com>
|
|
|
cbf2d8 |
Date: Thu Nov 17 08:53:37 2022 +0100
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
net: usb: ax88179_178a: Fix packet receiving
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
Bugzilla: https://bugzilla.redhat.com/2120504
|
|
|
cbf2d8 |
CVE: CVE-2022-2964
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
commit f8ebb3ac881b17712e1d5967c97ab1806b16d3d6
|
|
|
cbf2d8 |
Author: Jose Alonso <joalonsof@gmail.com>
|
|
|
cbf2d8 |
Date: Tue Jun 28 12:13:02 2022 -0300
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
net: usb: ax88179_178a: Fix packet receiving
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
This patch corrects packet receiving in ax88179_rx_fixup.
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
- problem observed:
|
|
|
cbf2d8 |
ifconfig shows allways a lot of 'RX Errors' while packets
|
|
|
cbf2d8 |
are received normally.
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
This occurs because ax88179_rx_fixup does not recognise properly
|
|
|
cbf2d8 |
the usb urb received.
|
|
|
cbf2d8 |
The packets are normally processed and at the end, the code exits
|
|
|
cbf2d8 |
with 'return 0', generating RX Errors.
|
|
|
cbf2d8 |
(pkt_cnt==-2 and ptk_hdr over field rx_hdr trying to identify
|
|
|
cbf2d8 |
another packet there)
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
This is a usb urb received by "tcpdump -i usbmon2 -X" on a
|
|
|
cbf2d8 |
little-endian CPU:
|
|
|
cbf2d8 |
0x0000: eeee f8e3 3b19 87a0 94de 80e3 daac 0800
|
|
|
cbf2d8 |
^ packet 1 start (pkt_len = 0x05ec)
|
|
|
cbf2d8 |
^^^^ IP alignment pseudo header
|
|
|
cbf2d8 |
^ ethernet packet start
|
|
|
cbf2d8 |
last byte ethernet packet v
|
|
|
cbf2d8 |
padding (8-bytes aligned) vvvv vvvv
|
|
|
cbf2d8 |
0x05e0: c92d d444 1420 8a69 83dd 272f e82b 9811
|
|
|
cbf2d8 |
0x05f0: eeee f8e3 3b19 87a0 94de 80e3 daac 0800
|
|
|
cbf2d8 |
... ^ packet 2
|
|
|
cbf2d8 |
0x0be0: eeee f8e3 3b19 87a0 94de 80e3 daac 0800
|
|
|
cbf2d8 |
...
|
|
|
cbf2d8 |
0x1130: 9d41 9171 8a38 0ec5 eeee f8e3 3b19 87a0
|
|
|
cbf2d8 |
...
|
|
|
cbf2d8 |
0x1720: 8cfc 15ff 5e4c e85c eeee f8e3 3b19 87a0
|
|
|
cbf2d8 |
...
|
|
|
cbf2d8 |
0x1d10: ecfa 2a3a 19ab c78c eeee f8e3 3b19 87a0
|
|
|
cbf2d8 |
...
|
|
|
cbf2d8 |
0x2070: eeee f8e3 3b19 87a0 94de 80e3 daac 0800
|
|
|
cbf2d8 |
... ^ packet 7
|
|
|
cbf2d8 |
0x2120: 7c88 4ca5 5c57 7dcc 0d34 7577 f778 7e0a
|
|
|
cbf2d8 |
0x2130: f032 e093 7489 0740 3008 ec05 0000 0080
|
|
|
cbf2d8 |
====1==== ====2====
|
|
|
cbf2d8 |
hdr_off ^
|
|
|
cbf2d8 |
pkt_len = 0x05ec ^^^^
|
|
|
cbf2d8 |
AX_RXHDR_*=0x00830 ^^^^ ^
|
|
|
cbf2d8 |
pkt_len = 0 ^^^^
|
|
|
cbf2d8 |
AX_RXHDR_DROP_ERR=0x80000000 ^^^^ ^
|
|
|
cbf2d8 |
0x2140: 3008 ec05 0000 0080 3008 5805 0000 0080
|
|
|
cbf2d8 |
0x2150: 3008 ec05 0000 0080 3008 ec05 0000 0080
|
|
|
cbf2d8 |
0x2160: 3008 5803 0000 0080 3008 c800 0000 0080
|
|
|
cbf2d8 |
===11==== ===12==== ===13==== ===14====
|
|
|
cbf2d8 |
0x2170: 0000 0000 0e00 3821
|
|
|
cbf2d8 |
^^^^ ^^^^ rx_hdr
|
|
|
cbf2d8 |
^^^^ pkt_cnt=14
|
|
|
cbf2d8 |
^^^^ hdr_off=0x2138
|
|
|
cbf2d8 |
^^^^ ^^^^ padding
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
The dump shows that pkt_cnt is the number of entrys in the
|
|
|
cbf2d8 |
per-packet metadata. It is "2 * packet count".
|
|
|
cbf2d8 |
Each packet have two entrys. The first have a valid
|
|
|
cbf2d8 |
value (pkt_len and AX_RXHDR_*) and the second have a
|
|
|
cbf2d8 |
dummy-header 0x80000000 (pkt_len=0 with AX_RXHDR_DROP_ERR).
|
|
|
cbf2d8 |
Why exists dummy-header for each packet?!?
|
|
|
cbf2d8 |
My guess is that this was done probably to align the
|
|
|
cbf2d8 |
entry for each packet to 64-bits and maintain compatibility
|
|
|
cbf2d8 |
with old firmware.
|
|
|
cbf2d8 |
There is also a padding (0x00000000) before the rx_hdr to
|
|
|
cbf2d8 |
align the end of rx_hdr to 64-bit.
|
|
|
cbf2d8 |
Note that packets have a alignment of 64-bits (8-bytes).
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
This patch assumes that the dummy-header and the last
|
|
|
cbf2d8 |
padding are optional. So it preserves semantics and
|
|
|
cbf2d8 |
recognises the same valid packets as the current code.
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
This patch was made using only the dumpfile information and
|
|
|
cbf2d8 |
tested with only one device:
|
|
|
cbf2d8 |
0b95:1790 ASIX Electronics Corp. AX88179 Gigabit Ethernet
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
Fixes: 57bc3d3ae8c1 ("net: usb: ax88179_178a: Fix out-of-bounds accesses in RX fixup")
|
|
|
cbf2d8 |
Fixes: e2ca90c276e1 ("ax88179_178a: ASIX AX88179_178A USB 3.0/2.0 to gigabit ethernet adapter driver")
|
|
|
cbf2d8 |
Signed-off-by: Jose Alonso <joalonsof@gmail.com>
|
|
|
cbf2d8 |
Acked-by: Paolo Abeni <pabeni@redhat.com>
|
|
|
cbf2d8 |
Link: https://lore.kernel.org/r/d6970bb04bf67598af4d316eaeb1792040b18cfd.camel@gmail.com
|
|
|
cbf2d8 |
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
Signed-off-by: Jose Ignacio Tornos Martinez <jtornosm@redhat.com>
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
Signed-off-by: Yannick Cote <ycote@redhat.com>
|
|
|
cbf2d8 |
---
|
|
|
cbf2d8 |
drivers/net/usb/ax88179_178a.c | 128 ++++++++++++++++++++++++---------
|
|
|
cbf2d8 |
1 file changed, 93 insertions(+), 35 deletions(-)
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c
|
|
|
cbf2d8 |
index 7f496ccdd272..1940f31facf0 100644
|
|
|
cbf2d8 |
--- a/drivers/net/usb/ax88179_178a.c
|
|
|
cbf2d8 |
+++ b/drivers/net/usb/ax88179_178a.c
|
|
|
cbf2d8 |
@@ -1375,58 +1375,119 @@ static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
|
|
|
cbf2d8 |
u16 hdr_off;
|
|
|
cbf2d8 |
u32 *pkt_hdr;
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
- /* This check is no longer done by usbnet */
|
|
|
cbf2d8 |
- if (skb->len < dev->net->hard_header_len)
|
|
|
cbf2d8 |
+ /* At the end of the SKB, there's a header telling us how many packets
|
|
|
cbf2d8 |
+ * are bundled into this buffer and where we can find an array of
|
|
|
cbf2d8 |
+ * per-packet metadata (which contains elements encoded into u16).
|
|
|
cbf2d8 |
+ */
|
|
|
cbf2d8 |
+
|
|
|
cbf2d8 |
+ /* SKB contents for current firmware:
|
|
|
cbf2d8 |
+ * <packet 1> <padding>
|
|
|
cbf2d8 |
+ * ...
|
|
|
cbf2d8 |
+ * <packet N> <padding>
|
|
|
cbf2d8 |
+ * <per-packet metadata entry 1> <dummy header>
|
|
|
cbf2d8 |
+ * ...
|
|
|
cbf2d8 |
+ * <per-packet metadata entry N> <dummy header>
|
|
|
cbf2d8 |
+ * <padding2> <rx_hdr>
|
|
|
cbf2d8 |
+ *
|
|
|
cbf2d8 |
+ * where:
|
|
|
cbf2d8 |
+ * <packet N> contains pkt_len bytes:
|
|
|
cbf2d8 |
+ * 2 bytes of IP alignment pseudo header
|
|
|
cbf2d8 |
+ * packet received
|
|
|
cbf2d8 |
+ * <per-packet metadata entry N> contains 4 bytes:
|
|
|
cbf2d8 |
+ * pkt_len and fields AX_RXHDR_*
|
|
|
cbf2d8 |
+ * <padding> 0-7 bytes to terminate at
|
|
|
cbf2d8 |
+ * 8 bytes boundary (64-bit).
|
|
|
cbf2d8 |
+ * <padding2> 4 bytes to make rx_hdr terminate at
|
|
|
cbf2d8 |
+ * 8 bytes boundary (64-bit)
|
|
|
cbf2d8 |
+ * <dummy-header> contains 4 bytes:
|
|
|
cbf2d8 |
+ * pkt_len=0 and AX_RXHDR_DROP_ERR
|
|
|
cbf2d8 |
+ * <rx-hdr> contains 4 bytes:
|
|
|
cbf2d8 |
+ * pkt_cnt and hdr_off (offset of
|
|
|
cbf2d8 |
+ * <per-packet metadata entry 1>)
|
|
|
cbf2d8 |
+ *
|
|
|
cbf2d8 |
+ * pkt_cnt is number of entrys in the per-packet metadata.
|
|
|
cbf2d8 |
+ * In current firmware there is 2 entrys per packet.
|
|
|
cbf2d8 |
+ * The first points to the packet and the
|
|
|
cbf2d8 |
+ * second is a dummy header.
|
|
|
cbf2d8 |
+ * This was done probably to align fields in 64-bit and
|
|
|
cbf2d8 |
+ * maintain compatibility with old firmware.
|
|
|
cbf2d8 |
+ * This code assumes that <dummy header> and <padding2> are
|
|
|
cbf2d8 |
+ * optional.
|
|
|
cbf2d8 |
+ */
|
|
|
cbf2d8 |
+
|
|
|
cbf2d8 |
+ if (skb->len < 4)
|
|
|
cbf2d8 |
return 0;
|
|
|
cbf2d8 |
-
|
|
|
cbf2d8 |
skb_trim(skb, skb->len - 4);
|
|
|
cbf2d8 |
- memcpy(&rx_hdr, skb_tail_pointer(skb), 4);
|
|
|
cbf2d8 |
- le32_to_cpus(&rx_hdr);
|
|
|
cbf2d8 |
-
|
|
|
cbf2d8 |
+ rx_hdr = get_unaligned_le32(skb_tail_pointer(skb));
|
|
|
cbf2d8 |
pkt_cnt = (u16)rx_hdr;
|
|
|
cbf2d8 |
hdr_off = (u16)(rx_hdr >> 16);
|
|
|
cbf2d8 |
+
|
|
|
cbf2d8 |
+ if (pkt_cnt == 0)
|
|
|
cbf2d8 |
+ return 0;
|
|
|
cbf2d8 |
+
|
|
|
cbf2d8 |
+ /* Make sure that the bounds of the metadata array are inside the SKB
|
|
|
cbf2d8 |
+ * (and in front of the counter at the end).
|
|
|
cbf2d8 |
+ */
|
|
|
cbf2d8 |
+ if (pkt_cnt * 4 + hdr_off > skb->len)
|
|
|
cbf2d8 |
+ return 0;
|
|
|
cbf2d8 |
pkt_hdr = (u32 *)(skb->data + hdr_off);
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
- while (pkt_cnt--) {
|
|
|
cbf2d8 |
+ /* Packets must not overlap the metadata array */
|
|
|
cbf2d8 |
+ skb_trim(skb, hdr_off);
|
|
|
cbf2d8 |
+
|
|
|
cbf2d8 |
+ for (; pkt_cnt > 0; pkt_cnt--, pkt_hdr++) {
|
|
|
cbf2d8 |
+ u16 pkt_len_plus_padd;
|
|
|
cbf2d8 |
u16 pkt_len;
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
le32_to_cpus(pkt_hdr);
|
|
|
cbf2d8 |
pkt_len = (*pkt_hdr >> 16) & 0x1fff;
|
|
|
cbf2d8 |
+ pkt_len_plus_padd = (pkt_len + 7) & 0xfff8;
|
|
|
cbf2d8 |
+
|
|
|
cbf2d8 |
+ /* Skip dummy header used for alignment
|
|
|
cbf2d8 |
+ */
|
|
|
cbf2d8 |
+ if (pkt_len == 0)
|
|
|
cbf2d8 |
+ continue;
|
|
|
cbf2d8 |
+
|
|
|
cbf2d8 |
+ if (pkt_len_plus_padd > skb->len)
|
|
|
cbf2d8 |
+ return 0;
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
/* Check CRC or runt packet */
|
|
|
cbf2d8 |
- if ((*pkt_hdr & AX_RXHDR_CRC_ERR) ||
|
|
|
cbf2d8 |
- (*pkt_hdr & AX_RXHDR_DROP_ERR)) {
|
|
|
cbf2d8 |
- skb_pull(skb, (pkt_len + 7) & 0xFFF8);
|
|
|
cbf2d8 |
- pkt_hdr++;
|
|
|
cbf2d8 |
+ if ((*pkt_hdr & (AX_RXHDR_CRC_ERR | AX_RXHDR_DROP_ERR)) ||
|
|
|
cbf2d8 |
+ pkt_len < 2 + ETH_HLEN) {
|
|
|
cbf2d8 |
+ dev->net->stats.rx_errors++;
|
|
|
cbf2d8 |
+ skb_pull(skb, pkt_len_plus_padd);
|
|
|
cbf2d8 |
continue;
|
|
|
cbf2d8 |
}
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
- if (pkt_cnt == 0) {
|
|
|
cbf2d8 |
- /* Skip IP alignment psudo header */
|
|
|
cbf2d8 |
+ /* last packet */
|
|
|
cbf2d8 |
+ if (pkt_len_plus_padd == skb->len) {
|
|
|
cbf2d8 |
+ skb_trim(skb, pkt_len);
|
|
|
cbf2d8 |
+
|
|
|
cbf2d8 |
+ /* Skip IP alignment pseudo header */
|
|
|
cbf2d8 |
skb_pull(skb, 2);
|
|
|
cbf2d8 |
- skb->len = pkt_len;
|
|
|
cbf2d8 |
- skb_set_tail_pointer(skb, pkt_len);
|
|
|
cbf2d8 |
- skb->truesize = pkt_len + sizeof(struct sk_buff);
|
|
|
cbf2d8 |
+
|
|
|
cbf2d8 |
+ skb->truesize = SKB_TRUESIZE(pkt_len_plus_padd);
|
|
|
cbf2d8 |
ax88179_rx_checksum(skb, pkt_hdr);
|
|
|
cbf2d8 |
return 1;
|
|
|
cbf2d8 |
}
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
ax_skb = skb_clone(skb, GFP_ATOMIC);
|
|
|
cbf2d8 |
- if (ax_skb) {
|
|
|
cbf2d8 |
- ax_skb->len = pkt_len;
|
|
|
cbf2d8 |
- ax_skb->data = skb->data + 2;
|
|
|
cbf2d8 |
- skb_set_tail_pointer(ax_skb, pkt_len);
|
|
|
cbf2d8 |
- ax_skb->truesize = pkt_len + sizeof(struct sk_buff);
|
|
|
cbf2d8 |
- ax88179_rx_checksum(ax_skb, pkt_hdr);
|
|
|
cbf2d8 |
- usbnet_skb_return(dev, ax_skb);
|
|
|
cbf2d8 |
- } else {
|
|
|
cbf2d8 |
+ if (!ax_skb)
|
|
|
cbf2d8 |
return 0;
|
|
|
cbf2d8 |
- }
|
|
|
cbf2d8 |
+ skb_trim(ax_skb, pkt_len);
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
- skb_pull(skb, (pkt_len + 7) & 0xFFF8);
|
|
|
cbf2d8 |
- pkt_hdr++;
|
|
|
cbf2d8 |
+ /* Skip IP alignment pseudo header */
|
|
|
cbf2d8 |
+ skb_pull(ax_skb, 2);
|
|
|
cbf2d8 |
+
|
|
|
cbf2d8 |
+ skb->truesize = pkt_len_plus_padd +
|
|
|
cbf2d8 |
+ SKB_DATA_ALIGN(sizeof(struct sk_buff));
|
|
|
cbf2d8 |
+ ax88179_rx_checksum(ax_skb, pkt_hdr);
|
|
|
cbf2d8 |
+ usbnet_skb_return(dev, ax_skb);
|
|
|
cbf2d8 |
+
|
|
|
cbf2d8 |
+ skb_pull(skb, pkt_len_plus_padd);
|
|
|
cbf2d8 |
}
|
|
|
cbf2d8 |
- return 1;
|
|
|
cbf2d8 |
+
|
|
|
cbf2d8 |
+ return 0;
|
|
|
cbf2d8 |
}
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
static struct sk_buff *
|
|
|
cbf2d8 |
@@ -1436,6 +1497,7 @@ ax88179_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
|
|
|
cbf2d8 |
int frame_size = dev->maxpacket;
|
|
|
cbf2d8 |
int mss = skb_shinfo(skb)->gso_size;
|
|
|
cbf2d8 |
int headroom;
|
|
|
cbf2d8 |
+ void *ptr;
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
tx_hdr1 = skb->len;
|
|
|
cbf2d8 |
tx_hdr2 = mss;
|
|
|
cbf2d8 |
@@ -1450,13 +1512,9 @@ ax88179_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
|
|
|
cbf2d8 |
return NULL;
|
|
|
cbf2d8 |
}
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
- skb_push(skb, 4);
|
|
|
cbf2d8 |
- cpu_to_le32s(&tx_hdr2);
|
|
|
cbf2d8 |
- skb_copy_to_linear_data(skb, &tx_hdr2, 4);
|
|
|
cbf2d8 |
-
|
|
|
cbf2d8 |
- skb_push(skb, 4);
|
|
|
cbf2d8 |
- cpu_to_le32s(&tx_hdr1);
|
|
|
cbf2d8 |
- skb_copy_to_linear_data(skb, &tx_hdr1, 4);
|
|
|
cbf2d8 |
+ ptr = skb_push(skb, 8);
|
|
|
cbf2d8 |
+ put_unaligned_le32(tx_hdr1, ptr);
|
|
|
cbf2d8 |
+ put_unaligned_le32(tx_hdr2, ptr + 4);
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
return skb;
|
|
|
cbf2d8 |
}
|
|
|
cbf2d8 |
--
|
|
|
cbf2d8 |
2.39.0
|
|
|
cbf2d8 |
|
|
|
cbf2d8 |
|