From 110eb808324fd9713b04d874c97283d965e43d2a Mon Sep 17 00:00:00 2001 From: Piotr Kubik Date: Mon, 19 Oct 2026 18:24:53 +0200 Subject: [PATCH] net: pse-pd: si3474: validate the channels of a PI si3474_get_of_channels() accepted channel 8, one past the last channel. The driver then accessed channel 4 instead: quad 1, channel index 0. It also accepted a 4-pair PI whose two channels are not a channel pair of one quad. The chip forms a 4-pair port only from channels 0+1 or 2+3 of a quad (2P/4P mode bit in POWER_ALLOCATION, PORT_REMAP default), and the driver sends every register access of a PI to the quad of its first channel, so such a PI enabled and measured the wrong channels. Reject both at probe. Discovered by an AI code review agent; no shipped device tree triggers it. Validated and tested on an SDG-9000 board (MediaTek MT7988A, two Si3474) with Linux 6.18 and a modified device tree: one chip with a channel at reg 8, the other with a 4-pair PI on channels 1 and 2. The driver now rejects both at probe, and the unmodified device tree still probes all eight PIs. No kernel selftest covers PSE hardware. Fixes: a2317231df4b ("net: pse-pd: Add Si3474 PSE controller driver") Signed-off-by: Piotr Kubik Reviewed-by: Kory Maincent Link: https://patch.msgid.link/20261019162453.1244120-3-piotr@kubik.pl Signed-off-by: Jakub Kicinski --- drivers/net/pse-pd/si3474.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/net/pse-pd/si3474.c b/drivers/net/pse-pd/si3474.c index a66a982e5ec4..35152d462e82 100644 --- a/drivers/net/pse-pd/si3474.c +++ b/drivers/net/pse-pd/si3474.c @@ -250,9 +250,9 @@ static int si3474_get_of_channels(struct si3474_priv *priv) "Failed to read channel reg property\n"); return ret; } - if (chan_id > SI3474_MAX_CHANS) { + if (chan_id >= SI3474_MAX_CHANS) { dev_err(&priv->client[0]->dev, - "Incorrect channel number: %d\n", chan_id); + "Incorrect channel number: %u\n", chan_id); return -EINVAL; } @@ -267,6 +267,16 @@ static int si3474_get_of_channels(struct si3474_priv *priv) pi->np); return -EINVAL; } + + /* The 2P/4P mode bit pairs channels 0+1 and 2+3 of a quad */ + if (pairset_found && + (priv->pi[pi_no].chan[0] ^ 1) != priv->pi[pi_no].chan[1]) { + dev_err(&priv->client[0]->dev, + "PI %pOF: channels %u and %u are not a channel pair\n", + pi->np, priv->pi[pi_no].chan[0], + priv->pi[pi_no].chan[1]); + return -EINVAL; + } } return 0;