Linux kernel and device drivers for NXP i.MX platforms
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Greg Ungerer" <gerg@linux-m68k.org>
Cc: "Oleksij Rempel" <o.rempel@pengutronix.de>,
	Frank.Li@kernel.org, "Vincent Mailhol" <mailhol@kernel.org>,
	imx@lists.linux.dev, linux-can@vger.kernel.org,
	"Oliver Hartkopp" <socketcan@hartkopp.net>,
	"Marc Kleine-Budde" <mkl@pengutronix.de>
Subject: Re: [PATCHv3 1/3] net: fec: do not use readl()/writel() for ColdFire
Date: Tue, 08 Sep 2026 13:43:11 +0000	[thread overview]
Message-ID: <20260908134312.00C441F00A3A@smtp.kernel.org> (raw)
In-Reply-To: <20260907134037.1855408-2-gerg@linux-m68k.org>

Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider:

Pre-existing issues:
- [Critical] Heap buffer overflow in TX bounce buffer due to unvalidated packet and fragment lengths.
- [High] The hardware PPS interrupt handler accesses and modifies shared PTP state without acquiring the required lock, racing with configuration paths on other CPUs.
- [High] Unbounded hardware polling loops can cause a hard lockup if the hardware enters an error state.
- [High] Integer underflow in RX packet length calculation leads to out-of-bounds memory access.
- [High] Out-of-bounds read and write in `fec_enet_clear_csum` due to missing `pskb_may_pull`.
- [High] Missing dma_rmb() after reading descriptor status in RX paths.
--

commit b19b9a07ca8eff68179fb339b69d5c4690fdf442
Author: Greg Ungerer <gerg@linux-m68k.org>
net: fec: do not use readl()/writel() for ColdFire

This patch modifies the FEC driver to use local fec_readl() and fec_writel() 
methods instead of direct hardware register accesses. This avoids incorrect
byte swapping on big-endian architectures like ColdFire.

> diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
> --- a/drivers/net/ethernet/freescale/fec_main.c
> +++ b/drivers/net/ethernet/freescale/fec_main.c
[ ... ]
> @@ -1923,7 +1924,7 @@ static int fec_enet_rx_queue(struct fec_enet_private *fep,
>  			break;
>  		pkt_received++;
>  
> -		writel(FEC_ENET_RXF_GET(queue), fep->hwp + FEC_IEVENT);
> +		fec_writel(FEC_ENET_RXF_GET(queue), fep->hwp + FEC_IEVENT);

[Severity: High]
This is a pre-existing issue, but is a memory barrier missing in the RX
loop?

The loop checks the status to confirm ownership in the while condition, but
without a dma_rmb() immediately after, couldn't speculative execution on
architectures with weak memory ordering cause the subsequent read of
cbd_datlen to happen before the DMA transfer is completely visible?

>  
>  		/* Check for errors. */
>  		status ^= BD_ENET_RX_LAST;

[ ... ]

> diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c
> --- a/drivers/net/ethernet/freescale/fec_ptp.c
> +++ b/drivers/net/ethernet/freescale/fec_ptp.c
[ ... ]
> @@ -142,17 +142,17 @@ static int fec_ptp_enable_pps(struct fec_enet_private *fep, uint enable)
>  	if (enable) {
>  		/* clear capture or output compare interrupt status if have.
>  		 */
> -		writel(FEC_T_TF_MASK, fep->hwp + FEC_TCSR(fep->pps_channel));
> +		fec_writel(FEC_T_TF_MASK, fep->hwp + FEC_TCSR(fep->pps_channel));
>  
>  		/* It is recommended to double check the TMODE field in the
>  		 * TCSR register to be cleared before the first compare counter
>  		 * is written into TCCR register. Just add a double check.
>  		 */
> -		val = readl(fep->hwp + FEC_TCSR(fep->pps_channel));
> +		val = fec_readl(fep->hwp + FEC_TCSR(fep->pps_channel));
>  		do {
>  			val &= ~(FEC_T_TMODE_MASK);
> -			writel(val, fep->hwp + FEC_TCSR(fep->pps_channel));
> -			val = readl(fep->hwp + FEC_TCSR(fep->pps_channel));
> +			fec_writel(val, fep->hwp + FEC_TCSR(fep->pps_channel));
> +			val = fec_readl(fep->hwp + FEC_TCSR(fep->pps_channel));
>  		} while (val & FEC_T_TMODE_MASK);

[Severity: High]
This is a pre-existing issue, but is it safe to have an unbounded polling
loop here while IRQs are disabled?

If the hardware transitions into a faulty state and perpetually returns a
value with FEC_T_TMODE_MASK set, could this loop cause a hard lockup or
kernel panic?

>  
>  		/* Dummy read counter to update the counter */
[ ... ]
> @@ -194,31 +194,31 @@ static int fec_ptp_enable_pps(struct fec_enet_private *fep, uint enable)
>  		 * is bigger than fep->cc.mask would be a error.
>  		 */
>  		val &= fep->cc.mask;
> -		writel(val, fep->hwp + FEC_TCCR(fep->pps_channel));
> +		fec_writel(val, fep->hwp + FEC_TCCR(fep->pps_channel));
>  
>  		/* Calculate the second the compare event timestamp */
>  		fep->next_counter = (val + fep->reload_period) & fep->cc.mask;

[Severity: High]
This is a pre-existing issue, but I noticed a potential data race between
this configuration path and the interrupt handler.

Here, fep->next_counter is updated while holding fep->tmreg_lock. However,
the interrupt handler fec_pps_interrupt() modifies fep->next_counter
locklessly. Could this cause the PTP timer to miss events or corrupt the
hardware state if this is triggered concurrently from userspace?

>  
>  		/* * Enable compare event when overflow */
> -		val = readl(fep->hwp + FEC_ATIME_CTRL);
[ ... ]
> @@ -701,15 +701,15 @@ static irqreturn_t fec_pps_interrupt(int irq, void *dev_id)
>  	u8 channel = fep->pps_channel;
>  	struct ptp_clock_event event;
>  
> -	val = readl(fep->hwp + FEC_TCSR(channel));
> +	val = fec_readl(fep->hwp + FEC_TCSR(channel));
>  	if (val & FEC_T_TF_MASK) {
>  		/* Write the next next compare(not the next according the spec)
>  		 * value to the register
>  		 */
> -		writel(fep->next_counter, fep->hwp + FEC_TCCR(channel));
> +		fec_writel(fep->next_counter, fep->hwp + FEC_TCCR(channel));
>  		do {
> -			writel(val, fep->hwp + FEC_TCSR(channel));
> -		} while (readl(fep->hwp + FEC_TCSR(channel)) & FEC_T_TF_MASK);
> +			fec_writel(val, fep->hwp + FEC_TCSR(channel));
> +		} while (fec_readl(fep->hwp + FEC_TCSR(channel)) & FEC_T_TF_MASK);

[Severity: High]
This is a pre-existing issue, but similar to the loop in
fec_ptp_enable_pps(), does this unbounded loop risk a hard lockup?

Since this runs in hardirq context, a faulty hardware state that fails to
clear FEC_T_TF_MASK would keep the CPU spinning indefinitely.

[ ... ]

I also noticed a few other pre-existing issues in this driver that fall
outside the immediate diff context of this patch:

[Severity: Critical]
This is a pre-existing issue, but does fec_enet_txq_submit_frag_skb()
overflow the TX bounce buffer?

index = fec_enet_get_bd_index(bdp, &txq->bd);
if (((unsigned long) bufaddr) & fep->tx_align ||
    fep->quirks & FEC_QUIRK_SWAP_FRAME) {
    memcpy(txq->tx_bounce[index], bufaddr, frag_len);
    bufaddr = txq->tx_bounce[index];

Since fragments can be up to PAGE_SIZE (4KB or 64KB), but the tx_bounce
buffers are statically sized to 2048 bytes, couldn't a large unaligned
packet or jumbo frame cause an out-of-bounds heap write?

[Severity: High]
This is a pre-existing issue, but I have a question about the packet length
calculation in fec_enet_rx_queue_xdp() and fec_enet_rx_queue():

pkt_len = fec16_to_cpu(bdp->cbd_datlen);
...
pkt_len -= sub_len;
xdp_prepare_buff(&xdp, page_address(page), data_start, pkt_len, false);

If a corrupted or maliciously crafted DMA descriptor reports a pkt_len less
than sub_len, pkt_len will underflow. Won't this pass a very large length
to xdp_prepare_buff() (or skb_put() in fec_build_skb()), potentially
allowing a BPF program to read/write out of bounds or causing an
skb_over_panic()?

[Severity: High]
This is a pre-existing issue, but I noticed a potential out-of-bounds
access on non-linear SKBs in fec_enet_clear_csum():

static bool is_ipv4_pkt(struct sk_buff *skb)
{
    return skb->protocol == htons(ETH_P_IP) && ip_hdr(skb)->version == 4;
}

If an AF_PACKET socket transmits a packet where the IP header is in a
non-linear fragment, wouldn't ip_hdr(skb)->version and the subsequent
ip_hdr(skb)->check = 0 assignment read and write past the linear buffer
into unallocated memory, since pskb_may_pull() hasn't been called?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260907134037.1855408-2-gerg@linux-m68k.org?part=1

  reply	other threads:[~2026-09-08 13:43 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-07 13:37 [PATCHv3 0/3] m68k: coldfire: fix non-standard readX()/writeX() functions Greg Ungerer
2026-09-07 13:37 ` [PATCHv3 1/3] net: fec: do not use readl()/writel() for ColdFire Greg Ungerer
2026-09-08 13:43   ` sashiko-bot [this message]
2026-09-11 13:09     ` Greg Ungerer
2026-09-11  0:42   ` Jakub Kicinski
2026-09-11  7:39     ` Arnd Bergmann
2026-09-11 13:03     ` Greg Ungerer
2026-09-11 23:04       ` Jakub Kicinski
2026-09-07 13:37 ` [PATCHv3 2/3] net: smc91x: do not use readw()/writew() on ColdFire platforms Greg Ungerer
2026-09-07 13:37 ` [PATCHv3 3/3] m68k: coldfire: fix non-standard readX()/writeX() functions Greg Ungerer
2026-09-08 13:43   ` sashiko-bot

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=20260908134312.00C441F00A3A@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=Frank.Li@kernel.org \
    --cc=gerg@linux-m68k.org \
    --cc=imx@lists.linux.dev \
    --cc=linux-can@vger.kernel.org \
    --cc=mailhol@kernel.org \
    --cc=mkl@pengutronix.de \
    --cc=o.rempel@pengutronix.de \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=socketcan@hartkopp.net \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox