All of lore.kernel.org
 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 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.