From: Justin Lai <justinlai0215@realtek.com>
To: Simon Horman <horms@kernel.org>
Cc: "kuba@kernel.org" <kuba@kernel.org>,
"davem@davemloft.net" <davem@davemloft.net>,
"edumazet@google.com" <edumazet@google.com>,
"pabeni@redhat.com" <pabeni@redhat.com>,
"andrew+netdev@lunn.ch" <andrew+netdev@lunn.ch>,
"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
"netdev@vger.kernel.org" <netdev@vger.kernel.org>,
"stable@vger.kernel.org" <stable@vger.kernel.org>,
"richardcochran@gmail.com" <richardcochran@gmail.com>,
"david.laight.linux@gmail.com" <david.laight.linux@gmail.com>,
"aleksander.lobakin@intel.com" <aleksander.lobakin@intel.com>,
Ping-Ke Shih <pkshih@realtek.com>,
Larry Chiu <larry.chiu@realtek.com>
Subject: RE: [PATCH net v3] rtase: Workaround for TX hang caused by short UDP packets entering hardware PTP parsing
Date: Mon, 22 Jun 2026 10:56:27 +0000 [thread overview]
Message-ID: <23922667b00c4ec7aba7efca227f85b1@realtek.com> (raw)
In-Reply-To: <20260617085942.843250-2-horms@kernel.org>
Simon Horman <horms@kernel.org> wrote:
>
> This is an AI-generated review of your patch. The human sending this
> email has considered the AI review valid, or at least plausible.
> Full review at: https://sashiko.dev
> ---
> rtase: Workaround for TX hang caused by short UDP packets entering
> hardware PTP parsing
>
> The patch adds a workaround for a hardware bug in rtase where short UDP
> packets triggering PTP parsing can cause a TX hang due to out-of-bounds
> reads.
> It pads affected packets so the transport data reaches a minimum length.
>
> Cc: stable@vger.kernel.org
>
> > diff --git a/drivers/net/ethernet/realtek/rtase/rtase_main.c
> b/drivers/net/ethernet/realtek/rtase/rtase_main.c
> > index 55105d34bc797..4c295a39c7a0c 100644
> > --- a/drivers/net/ethernet/realtek/rtase/rtase_main.c
> > +++ b/drivers/net/ethernet/realtek/rtase/rtase_main.c
> [ ... ]
> > @@ -1249,6 +1250,81 @@ static u32 rtase_tx_csum(struct sk_buff *skb,
> const struct net_device *dev)
> > return csum_cmd;
> > }
> >
> > +static bool rtase_get_udp_offset(struct sk_buff *skb, u32 *udp_offset)
> > +{
> > + int no = skb_network_offset(skb);
> > + struct ipv6hdr *i6h, _i6h;
> > + struct iphdr *ih, _ih;
> > +
> > + switch (vlan_get_protocol(skb)) {
> > + case htons(ETH_P_IP):
>
> [Severity: High]
> Does relying on vlan_get_protocol(skb) allow an unprivileged user to bypass
> this workaround?
>
> If an attacker uses an AF_PACKET/SOCK_RAW socket to inject a raw Ethernet
> frame containing an IPv4/UDP packet, they could set skb->protocol to an
> arbitrary value like htons(ETH_P_ALL). The switch statement will fall
> through to the default case and return false, causing rtase_skb_pad() to
> skip the padding.
>
> Since the hardware independently parses the raw frame based on the
> EtherType,
> could it still process the unpadded packet and trigger the TX hang?
>
Thanks for pointing this out.
Since the hardware parser operates on the actual Ethernet frame
contents, relying on skb protocol metadata is not ideal for this
workaround.
I'll update the code to derive the L3 protocol and network offset from
the Ethernet/VLAN headers in the skb data before parsing IPv4/IPv6.
This makes the software check match what the hardware parser sees and
avoids depending on skb protocol metadata.
> > + ih = skb_header_pointer(skb, no, sizeof(_ih), &_ih);
> > + if (!ih)
> > + return false;
> [ ... ]
> > +static bool rtase_skb_pad(struct sk_buff *skb)
> > +{
> > + __be16 *dest, _dest;
> > + u32 trans_data_len;
> > + u32 udp_offset;
> > + u16 dest_port;
> > + u32 pad_len;
> > +
> > + if (!rtase_get_udp_offset(skb, &udp_offset))
> > + return true;
> > +
> > + trans_data_len = skb->len - udp_offset;
> > + if (trans_data_len < offsetof(struct udphdr, len) ||
> > + trans_data_len >= RTASE_MIN_PAD_LEN)
> > + return true;
>
> [Severity: High]
> Does this logic inadvertently skip padding for underflowed lengths and tiny
> payloads?
>
> If the IP header is malformed such that skb->len < udp_offset, the unsigned
> subtraction for trans_data_len will underflow to a large positive value.
> This causes trans_data_len >= RTASE_MIN_PAD_LEN to be true, bypassing the
> padding.
>
> Additionally, if the packet has fewer than 4 bytes of UDP payload, meaning
> trans_data_len < offsetof(struct udphdr, len), it explicitly returns true.
>
> Since the hardware blindly fetches the UDP destination port at
> udp_offset + 2 via DMA, won't transmitting these short or malformed packets
> without padding still expose the hardware to out-of-bounds reads?
>
Thanks for the review.
I'll add a check for udp_offset > skb->len before calculating
trans_data_len to avoid the potential underflow.
If the computed UDP offset is beyond the packet length, the packet is
malformed and cannot be safely handled by this workaround, so it should
not be transmitted.
The out-of-bounds access occurs after the packet has already matched
the PTP classification criteria (UDP destination port 319/320) and
enters the hardware PTP parsing path.
If the transport data is shorter than the destination port field
itself, the packet cannot match the affected PTP classification path.
> > +
> > + dest = skb_header_pointer(skb,
> > + udp_offset + offsetof(struct udphdr,
> dest),
> > + sizeof(_dest), &_dest);
> [ ... ]
> > @@ -1362,6 +1438,9 @@ static netdev_tx_t rtase_start_xmit(struct sk_buff
> *skb,
> > opts2 |= rtase_tx_csum(skb, dev);
> > }
> >
> > + if (!rtase_skb_pad(skb))
> > + goto err_dma_0;
> > +
> > frags = rtase_xmit_frags(ring, skb, opts1, opts2);
> > if (unlikely(frags < 0))
> > goto err_dma_0;
>
> [Severity: High]
> This is a pre-existing issue, but does the err_dma_1 error path in
> rtase_start_xmit() contain a double free of the skb?
>
> When transmitting a fragmented packet, rtase_xmit_frags() maps the
> fragments and assigns ring->skbuff[entry] = skb for the last fragment
> descriptor. Back in rtase_start_xmit(), if dma_map_single() fails for the
> linear part, it jumps to err_dma_1:
>
> err_dma_1:
> ring->skbuff[entry] = NULL;
> rtase_tx_clear_range(ring, ring->cur_idx + 1, frags);
>
> err_dma_0:
> tp->stats.tx_dropped++;
> dev_kfree_skb_any(skb);
> return NETDEV_TX_OK;
>
> rtase_tx_clear_range() iterates over the mapped fragments and calls
> dev_kfree_skb_any() when it finds the skb pointer. Execution then falls
> through to err_dma_0, which unconditionally calls dev_kfree_skb_any(skb) a
> second time on the same skb pointer.
Thanks for pointing this out.
This appears to be a pre-existing issue and is unrelated to the change
in this patch.
I'll investigate the reported double free scenario further and address
it separately if a fix is needed.
Thanks,
Justin
prev parent reply other threads:[~2026-06-22 11:06 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-15 13:16 [PATCH net v3] rtase: Workaround for TX hang caused by short UDP packets entering hardware PTP parsing Justin Lai
2026-06-17 8:54 ` Simon Horman
2026-06-22 10:46 ` Justin Lai
2026-06-17 8:59 ` Simon Horman
2026-06-22 10:56 ` Justin Lai [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=23922667b00c4ec7aba7efca227f85b1@realtek.com \
--to=justinlai0215@realtek.com \
--cc=aleksander.lobakin@intel.com \
--cc=andrew+netdev@lunn.ch \
--cc=davem@davemloft.net \
--cc=david.laight.linux@gmail.com \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=larry.chiu@realtek.com \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=pkshih@realtek.com \
--cc=richardcochran@gmail.com \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.