Skip to content

Commit d26ed6b

Browse files
Friedemann Gerolddavem330
authored andcommitted
net: aquantia: memory corruption on jumbo frames
This patch fixes skb_shared area, which will be corrupted upon reception of 4K jumbo packets. Originally build_skb usage purpose was to reuse page for skb to eliminate needs of extra fragments. But that logic does not take into account that skb_shared_info should be reserved at the end of skb data area. In case packet data consumes all the page (4K), skb_shinfo location overflows the page. As a consequence, __build_skb zeroed shinfo data above the allocated page, corrupting next page. The issue is rarely seen in real life because jumbo are normally larger than 4K and that causes another code path to trigger. But it 100% reproducible with simple scapy packet, like: sendp(IP(dst="192.168.100.3") / TCP(dport=443) \ / Raw(RandString(size=(4096-40))), iface="enp1s0") Fixes: 018423e ("net: ethernet: aquantia: Add ring support code") Reported-by: Friedemann Gerold <f.gerold@b-c-s.de> Reported-by: Michael Rauch <michael@rauch.be> Signed-off-by: Friedemann Gerold <f.gerold@b-c-s.de> Tested-by: Nikita Danilov <nikita.danilov@aquantia.com> Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 841dfa4 commit d26ed6b

File tree

1 file changed

+18
-14
lines changed
  • drivers/net/ethernet/aquantia/atlantic

1 file changed

+18
-14
lines changed

drivers/net/ethernet/aquantia/atlantic/aq_ring.c

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -225,9 +225,10 @@ int aq_ring_rx_clean(struct aq_ring_s *self,
225225
}
226226

227227
/* for single fragment packets use build_skb() */
228-
if (buff->is_eop) {
228+
if (buff->is_eop &&
229+
buff->len <= AQ_CFG_RX_FRAME_MAX - AQ_SKB_ALIGN) {
229230
skb = build_skb(page_address(buff->page),
230-
buff->len + AQ_SKB_ALIGN);
231+
AQ_CFG_RX_FRAME_MAX);
231232
if (unlikely(!skb)) {
232233
err = -ENOMEM;
233234
goto err_exit;
@@ -247,18 +248,21 @@ int aq_ring_rx_clean(struct aq_ring_s *self,
247248
buff->len - ETH_HLEN,
248249
SKB_TRUESIZE(buff->len - ETH_HLEN));
249250

250-
for (i = 1U, next_ = buff->next,
251-
buff_ = &self->buff_ring[next_]; true;
252-
next_ = buff_->next,
253-
buff_ = &self->buff_ring[next_], ++i) {
254-
skb_add_rx_frag(skb, i, buff_->page, 0,
255-
buff_->len,
256-
SKB_TRUESIZE(buff->len -
257-
ETH_HLEN));
258-
buff_->is_cleaned = 1;
259-
260-
if (buff_->is_eop)
261-
break;
251+
if (!buff->is_eop) {
252+
for (i = 1U, next_ = buff->next,
253+
buff_ = &self->buff_ring[next_];
254+
true; next_ = buff_->next,
255+
buff_ = &self->buff_ring[next_], ++i) {
256+
skb_add_rx_frag(skb, i,
257+
buff_->page, 0,
258+
buff_->len,
259+
SKB_TRUESIZE(buff->len -
260+
ETH_HLEN));
261+
buff_->is_cleaned = 1;
262+
263+
if (buff_->is_eop)
264+
break;
265+
}
262266
}
263267
}
264268

0 commit comments

Comments
 (0)