* [PATCH v5 1/3] net: dsa: microchip: implement KSZ87xx Module 3 low-loss cable errata
From: Fidelio Lawson @ 2026-05-05 11:42 UTC (permalink / raw)
To: Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Marek Vasut, Maxime Chevallier, Simon Horman, Heiner Kallweit,
Russell King, Tristram Ha
Cc: Woojung Huh, netdev, linux-kernel, Fidelio Lawson
In-Reply-To: <20260505-ksz87xx_errata_low_loss_connections-v5-0-da4002b21c42@exotec.com>
Implement the "Module 3: Equalizer fix for short cables" erratum from
Microchip document DS80000687C for KSZ87xx switches.
The issue affects short or low-loss cable links (e.g. CAT5e/CAT6),
where the PHY receiver equalizer may amplify high-amplitude signals
excessively, resulting in internal distortion and link establishment
failures.
KSZ87xx devices require a workaround for the Module 3 low-loss cable
condition, controlled through the switch TABLE_LINK_MD_V indirect
registers.
This change models the erratum handling as vendor-specific Clause 22 PHY
registers, virtualized by the KSZ8 DSA driver and accessed via
ksz8_r_phy() / ksz8_w_phy(). The following controls are provided:
- A boolean “short-cable” preset, which applies a documented and
conservative configuration (LPF 62 MHz bandwidth and DSP EQ initial
value 0), and is the recommended interface for typical use cases.
- Separate LPF bandwidth and DSP EQ initial value controls intended for
advanced or experimental tuning. These are orthogonal and independent,
and override the corresponding settings without requiring any specific
ordering.
The preset and tunables act as simple setters with no implicit state
machine or invalid combinations, keeping the API predictable and aligned
with the KISS principle.
The erratum affects the shared PHY analog front-end and therefore applies
globally to the switch.
Fixes: e66f840c08a2 ("net: dsa: ksz: Add Microchip KSZ8795 DSA driver")
Signed-off-by: Fidelio Lawson <fidelio.lawson@exotec.com>
---
drivers/net/dsa/microchip/ksz8.c | 73 ++++++++++++++++++++++++++++++++++
drivers/net/dsa/microchip/ksz8.h | 1 +
drivers/net/dsa/microchip/ksz8_reg.h | 24 ++++++++++-
drivers/net/dsa/microchip/ksz_common.h | 4 ++
4 files changed, 101 insertions(+), 1 deletion(-)
diff --git a/drivers/net/dsa/microchip/ksz8.c b/drivers/net/dsa/microchip/ksz8.c
index c354abdafc1b..62fc59c3da7e 100644
--- a/drivers/net/dsa/microchip/ksz8.c
+++ b/drivers/net/dsa/microchip/ksz8.c
@@ -1058,6 +1058,22 @@ int ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
if (ret)
return ret;
+ break;
+ case PHY_REG_KSZ87XX_SHORT_CABLE:
+ if (!ksz_is_ksz87xx(dev))
+ return -EOPNOTSUPP;
+ data = !!(dev->lpf_bw == KSZ87XX_PHY_LPF_62MHZ &&
+ dev->eq_init == KSZ87XX_DSP_EQ_INIT_LOW_LOSS);
+ break;
+ case PHY_REG_KSZ87XX_LPF_BW:
+ if (!ksz_is_ksz87xx(dev))
+ return -EOPNOTSUPP;
+ data = dev->lpf_bw;
+ break;
+ case PHY_REG_KSZ87XX_EQ_INIT:
+ if (!ksz_is_ksz87xx(dev))
+ return -EOPNOTSUPP;
+ data = dev->eq_init;
break;
default:
processed = false;
@@ -1271,6 +1287,35 @@ int ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
if (ret)
return ret;
break;
+ case PHY_REG_KSZ87XX_SHORT_CABLE:
+ if (!ksz_is_ksz87xx(dev))
+ return -EOPNOTSUPP;
+ ret = ksz87xx_apply_low_loss_preset(dev, !!val);
+ if (ret)
+ return ret;
+ break;
+ case PHY_REG_KSZ87XX_LPF_BW:
+ if (!ksz_is_ksz87xx(dev))
+ return -EOPNOTSUPP;
+ /* Only accept LPF bandwidth bits [7:6] */
+ if (val & ~KSZ87XX_LPF_VALID_MASK)
+ return -EINVAL;
+ ret = ksz8_ind_write8(dev, TABLE_LINK_MD, KSZ87XX_REG_PHY_LPF, (u8)val);
+ if (ret)
+ return ret;
+ dev->lpf_bw = val;
+ break;
+ case PHY_REG_KSZ87XX_EQ_INIT:
+ if (!ksz_is_ksz87xx(dev))
+ return -EOPNOTSUPP;
+ /* Only accept DSP EQ initial value bits [5:0] */
+ if (val & ~KSZ87XX_DSP_EQ_VALID_MASK)
+ return -EINVAL;
+ ret = ksz8_ind_write8(dev, TABLE_LINK_MD, KSZ87XX_REG_DSP_EQ, (u8)val);
+ if (ret)
+ return ret;
+ dev->eq_init = val;
+ break;
default:
break;
}
@@ -2096,11 +2141,39 @@ int ksz8463_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
return 0;
}
+int ksz87xx_apply_low_loss_preset(struct ksz_device *dev, bool enable)
+{
+ /* Apply the Microchip erratum short-cable preset (LPF 62 MHz, EQ init 0) */
+ /* providing a conservative configuration for short or low-loss cables. */
+ u8 lpf_bw, eq_init;
+ int ret;
+
+ lpf_bw = KSZ87XX_PHY_LPF_62MHZ;
+ eq_init = KSZ87XX_DSP_EQ_INIT_LOW_LOSS;
+
+ if (!ksz_is_ksz87xx(dev))
+ return -EOPNOTSUPP;
+ if (!enable)
+ return 0;
+ ret = ksz8_ind_write8(dev, TABLE_LINK_MD, KSZ87XX_REG_PHY_LPF, lpf_bw);
+ if (ret)
+ return ret;
+ dev->lpf_bw = lpf_bw;
+ ret = ksz8_ind_write8(dev, TABLE_LINK_MD, KSZ87XX_REG_DSP_EQ, eq_init);
+ if (ret)
+ return ret;
+ dev->eq_init = eq_init;
+
+ return ret;
+}
+
int ksz8_switch_init(struct ksz_device *dev)
{
dev->cpu_port = fls(dev->info->cpu_ports) - 1;
dev->phy_port_cnt = dev->info->port_cnt - 1;
dev->port_mask = (BIT(dev->phy_port_cnt) - 1) | dev->info->cpu_ports;
+ dev->lpf_bw = KSZ87XX_PHY_LPF_90MHZ;
+ dev->eq_init = KSZ87XX_DSP_EQ_INIT_FACTORY;
return 0;
}
diff --git a/drivers/net/dsa/microchip/ksz8.h b/drivers/net/dsa/microchip/ksz8.h
index 0f2cd1474b44..5cf7bd90af0f 100644
--- a/drivers/net/dsa/microchip/ksz8.h
+++ b/drivers/net/dsa/microchip/ksz8.h
@@ -66,5 +66,6 @@ int ksz8_all_queues_split(struct ksz_device *dev, int queues);
u32 ksz8463_get_port_addr(int port, int offset);
int ksz8463_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val);
int ksz8463_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val);
+int ksz87xx_apply_low_loss_preset(struct ksz_device *dev, bool enable);
#endif
diff --git a/drivers/net/dsa/microchip/ksz8_reg.h b/drivers/net/dsa/microchip/ksz8_reg.h
index 332408567b47..cd41214f874e 100644
--- a/drivers/net/dsa/microchip/ksz8_reg.h
+++ b/drivers/net/dsa/microchip/ksz8_reg.h
@@ -202,6 +202,13 @@
#define REG_PORT_3_STATUS_0 0x38
#define REG_PORT_4_STATUS_0 0x48
+/* KSZ87xx LinkMD registers (TABLE_LINK_MD_V) */
+#define KSZ87XX_REG_DSP_EQ 0x08 /* DSP EQ initial value */
+#define KSZ87XX_REG_PHY_LPF 0x4C /* RX LPF bandwidth */
+
+#define KSZ87XX_DSP_EQ_VALID_MASK GENMASK(5, 0)
+#define KSZ87XX_LPF_VALID_MASK GENMASK(7, 6)
+
/* For KSZ8765. */
#define PORT_REMOTE_ASYM_PAUSE BIT(5)
#define PORT_REMOTE_SYM_PAUSE BIT(4)
@@ -342,7 +349,7 @@
#define TABLE_EEE (TABLE_EEE_V << TABLE_EXT_SELECT_S)
#define TABLE_ACL (TABLE_ACL_V << TABLE_EXT_SELECT_S)
#define TABLE_PME (TABLE_PME_V << TABLE_EXT_SELECT_S)
-#define TABLE_LINK_MD (TABLE_LINK_MD << TABLE_EXT_SELECT_S)
+#define TABLE_LINK_MD (TABLE_LINK_MD_V << TABLE_EXT_SELECT_S)
#define TABLE_READ BIT(4)
#define TABLE_SELECT_S 2
#define TABLE_STATIC_MAC_V 0
@@ -729,6 +736,21 @@
#define PHY_POWER_SAVING_ENABLE BIT(2)
#define PHY_REMOTE_LOOPBACK BIT(1)
+/* Vendor-specific Clause 22 PHY registers (virtualized) */
+#define PHY_REG_KSZ87XX_SHORT_CABLE 0x1A
+#define PHY_REG_KSZ87XX_LPF_BW 0x1B
+#define PHY_REG_KSZ87XX_EQ_INIT 0x1C
+
+/* LPF bandwidth bits [7:6]: 00 = 90MHz (default), 01 = 62MHz, 10 = 55MHz, 11 = 44MHz */
+#define KSZ87XX_PHY_LPF_90MHZ 0x00
+#define KSZ87XX_PHY_LPF_62MHZ 0x40
+#define KSZ87XX_PHY_LPF_55MHZ 0x80
+#define KSZ87XX_PHY_LPF_44MHZ 0xC0
+
+/* Low-loss workaround DSP EQ INIT VALUE */
+#define KSZ87XX_DSP_EQ_INIT_LOW_LOSS 0x00
+#define KSZ87XX_DSP_EQ_INIT_FACTORY 0x0F
+
/* KSZ8463 specific registers. */
#define P1MBCR 0x4C
#define P1MBSR 0x4E
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index 929aff4c55de..482e79cf6ae6 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -219,6 +219,10 @@ struct ksz_device {
* the switch’s internal PHYs, bypassing the main SPI interface.
*/
struct mii_bus *parent_mdio_bus;
+
+ /* KSZ87xx low-loss tuning state */
+ u8 lpf_bw; /* KSZ87XX_PHY_LPF_* */
+ u8 eq_init; /* DSP EQ initial value */
};
/* List of supported models */
--
2.54.0
^ permalink raw reply related
* [PATCH v5 0/3] ksz87xx: add support for low-loss cable equalizer errata
From: Fidelio Lawson @ 2026-05-05 11:42 UTC (permalink / raw)
To: Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Marek Vasut, Maxime Chevallier, Simon Horman, Heiner Kallweit,
Russell King, Tristram Ha
Cc: Woojung Huh, netdev, linux-kernel, Fidelio Lawson
Hello,
This patch implements the “Module 3: Equalizer fix for short cables” erratum
described in Microchip document DS80000687C for KSZ87xx switches.
According to the erratum, the embedded PHY receiver in KSZ87xx switches is
tuned by default for long, high-loss Ethernet cables. When operating with
short or low-loss cables (for example CAT5e or CAT6), the PHY equalizer may
over-amplify the incoming signal, leading to internal distortion and link
establishment failures.
Microchip documents two independent mechanisms to mitigate this issue:
adjusting the receiver low‑pass filter bandwidth and reducing the DSP
equalizer initial value. These registers are located in the switch’s
internal LinkMD table and cannot be accessed directly through a
stand‑alone PHY driver.
To keep the PHY‑facing API clean, this series models the erratum handling
as vendor‑specific Clause 22 PHY registers, virtualized by the KSZ8 DSA
driver. Accesses are intercepted by ksz8_r_phy() / ksz8_w_phy() and
translated into the appropriate indirect LinkMD register writes. The
erratum affects the shared PHY analog front‑end and therefore applies
globally to the switch.
Based on review feedback, the user‑visible interface is kept deliberately
simple and predictable:
- A boolean “short‑cable” PHY tunable applies a documented and
conservative preset (LPF bandwidth 62MHz, DSP EQ initial value 0).
This is the recommended KISS interface for the common short‑cable
scenario.
- Two additional integer PHY tunables allow advanced or experimental
tuning of the LPF bandwidth and the DSP EQ initial value. These
controls are orthogonal, have no ordering requirements, and simply
override the corresponding setting when written.
The tunables act as simple setters with no implicit state machine or
invalid combinations, avoiding surprises for userspace and not relying
on extended error reporting or netlink ethtool support.
This series contains:
1. Support for the KSZ87xx low‑loss cable erratum in the KSZ8 DSA driver,
including the short‑cable preset and orthogonal tuning controls.
2. Addition of vendor‑specific PHY tunable identifiers for the
short‑cable preset, LPF bandwidth, and DSP EQ initial value.
3. Exposure of these tunables through the Micrel PHY driver via
get_tunable / set_tunable callbacks.
This version follows the design agreed upon during v3 review and
reworks the interface accordingly.
This series is based on Linux v7.0-rc1.
Signed-off-by: Fidelio Lawson <fidelio.lawson@exotec.com>
---
Changes in v5:
- Added Fixes tag
- Added validation to ensure that only the documented bitfields are accepted before writing the registers
- Link to v4: https://patch.msgid.link/20260417-ksz87xx_errata_low_loss_connections-v4-0-6c7044ec4363@exotec.com
Changes in v4:
- Reworked the user‑visible API to a boolean short‑cable preset plus
orthogonal advanced tunables, following the KISS principle.
- Dropped the previous mode‑selector semantics in favor of simple
setters with no ordering requirements
- Added persistent tracking of LPF bandwidth and EQ initial value.
- Clarified defaults and preset values to match Microchip documentation.
- Link to v3: https://patch.msgid.link/20260414-ksz87xx_errata_low_loss_connections-v3-0-0e3838ca98c9@exotec.com
Changes in v3:
- Exposed all LPF bandwidth values supported by the hardware.
- Added phy tunable.
- Link to v2: https://patch.msgid.link/20260408-ksz87xx_errata_low_loss_connections-v2-1-9cfe38691713@exotec.com
Changes in v2:
- Dropped the device tree approach based on review feedback
- Modeled the errata control as a vendor-specific Clause 22 PHY register
- Added KSZ87xx-specific guards and replaced magic values with named macros
- Rebased on Linux v7.0-rc1
- Link to v1: https://patch.msgid.link/20260326-ksz87xx_errata_low_loss_connections-v1-0-79a698f43626@exotec.com
---
Fidelio Lawson (3):
net: dsa: microchip: implement KSZ87xx Module 3 low-loss cable errata
net: ethtool: add KSZ87xx low-loss cable PHY tunables
net: phy: micrel: expose KSZ87xx low-loss cable tunables
drivers/net/dsa/microchip/ksz8.c | 73 ++++++++++++++++++++++++++++++++++
drivers/net/dsa/microchip/ksz8.h | 1 +
drivers/net/dsa/microchip/ksz8_reg.h | 24 ++++++++++-
drivers/net/dsa/microchip/ksz_common.h | 4 ++
drivers/net/phy/micrel.c | 54 +++++++++++++++++++++++++
include/uapi/linux/ethtool.h | 3 ++
net/ethtool/common.c | 3 ++
net/ethtool/ioctl.c | 3 ++
8 files changed, 164 insertions(+), 1 deletion(-)
---
base-commit: 2d1373e4246da3b58e1df058374ed6b101804e07
change-id: 20260323-ksz87xx_errata_low_loss_connections-b65e76e2b403
Best regards,
--
Fidelio Lawson <fidelio.lawson@exotec.com>
^ permalink raw reply
* Re: [PATCH net-next v3 1/2] dpll: add fractional frequency offset to pin-parent-device
From: Jiri Pirko @ 2026-05-05 11:31 UTC (permalink / raw)
To: Ivan Vecera
Cc: netdev, Andrew Lunn, Arkadiusz Kubalewski, David S. Miller,
Donald Hunter, Eric Dumazet, Jakub Kicinski, Jonathan Corbet,
Leon Romanovsky, Mark Bloch, Michal Schmidt, Paolo Abeni,
Pasi Vaananen, Petr Oros, Prathosh Satish, Saeed Mahameed,
Shuah Khan, Simon Horman, Tariq Toukan, Vadim Fedorenko,
linux-doc, linux-kernel, linux-rdma
In-Reply-To: <20260504155340.411063-2-ivecera@redhat.com>
Mon, May 04, 2026 at 05:53:39PM +0200, ivecera@redhat.com wrote:
>Add both fractional-frequency-offset (PPM) and
>fractional-frequency-offset-ppt (PPT) attributes to the
>pin-parent-device nested attribute set, alongside the existing
>top-level pin attributes. Both carry the same measurement at
>different precisions.
>
>Distinguish the two contexts in the ffo_get callback by passing
>dpll=NULL for the top-level call and a valid dpll pointer for the
>nested per-parent call. This allows drivers to report a different
>value per parent DPLL if needed. Update mlx5 and zl3073x drivers
>to return -ENODATA for the context they do not yet support.
>
>Add documentation for both FFO attributes to dpll.rst.
>
>Signed-off-by: Ivan Vecera <ivecera@redhat.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
^ permalink raw reply
* Re: [PATCH net 06/12] netfilter: nf_conntrack_expect: honor expectation helper field
From: Pablo Neira Ayuso @ 2026-05-05 11:26 UTC (permalink / raw)
To: Ilya Maximets
Cc: netfilter-devel, fw, davem, netdev, kuba, pabeni, edumazet, horms,
Eelco Chaudron, Aaron Conole
In-Reply-To: <f0557cdd-738b-4d19-969d-94310b553d0b@ovn.org>
On Tue, May 05, 2026 at 01:01:22PM +0200, Ilya Maximets wrote:
> On 5/5/26 1:40 AM, Pablo Neira Ayuso wrote:
> > On Tue, May 05, 2026 at 01:16:05AM +0200, Pablo Neira Ayuso wrote:
> >> Thanks for the detailed report. It seems I changed the semantics of
> >> exp->helper, this used to be use to set a new helper for an expected
> >> connection, which is the case for sip and h323.
> >>
> >> Would this patch help address the issue you are observing?
> >
> > Actually, this needs to set to NULL the new exp->assign_helper field,
> > see new patch, untested.
>
> I ran this through OVS system tests and all passed. So, this restores
> the old behavior, at least for FTP (we do not support sip/h323). For
> that part:
>
> Tested-by: Ilya Maximets <i.maximets@ovn.org>
Thanks! I will be posting a format patch asap, I will keep you on Cc.
^ permalink raw reply
* Re: [PATCH net-next 2/3] ppp: unify two channel structs
From: Paolo Abeni @ 2026-05-05 11:16 UTC (permalink / raw)
To: Qingfang Deng, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Jiri Kosina, David Sterba, Greg Kroah-Hartman,
Jiri Slaby, Mitchell Blank Jr, Chas Williams, Simon Horman,
James Chapman, Kees Cook, Sebastian Andrzej Siewior, Taegu Ha,
Guillaume Nault, Eric Woudstra, Arnd Bergmann, Dawid Osuchowski,
Breno Leitao, linux-ppp, netdev, linux-kernel, linux-serial,
linux-atm-general
In-Reply-To: <20260430090532.244758-2-qingfang.deng@linux.dev>
On 4/30/26 11:05 AM, Qingfang Deng wrote:
> Historically, PPP maintained two separate structures for a channel:
> 'struct channel' was internal to ppp_generic.c, while 'struct ppp_channel'
> was the public interface that drivers were required to embed. This
> duplication was redundant and forced drivers to manage the lifecycle of
> the public structure.
>
> Unify these two structures into a single 'struct ppp_channel', which is
> now internal to ppp_generic.c. Drivers now use a 'ppp_channel_conf'
> structure to specify registration parameters and receive an opaque
> pointer to the allocated channel.
>
> Key changes:
> - ppp_register_channel() and ppp_register_net_channel() now return
> a 'struct ppp_channel *' instead of taking a pointer to a driver-
> embedded structure.
> - 'struct ppp_channel_ops' methods now take the driver's 'private'
> pointer directly as their first argument, simplifying driver logic.
> - ppp_unregister_channel() now takes the opaque pointer.
> - Multilink-specific fields are unified and handled via the new
> configuration structure.
>
> This cleanup simplifies the driver interface and makes the channel
> lifecycle management more robust by centralizing allocation in the PPP
> generic layer.
>
> Assisted-by: Gemini:gemini-3-flash
> Signed-off-by: Qingfang Deng <qingfang.deng@linux.dev>
> ---
> drivers/net/ppp/ppp_async.c | 51 +++++-----
> drivers/net/ppp/ppp_generic.c | 161 +++++++++++++++----------------
> drivers/net/ppp/ppp_synctty.c | 51 +++++-----
> drivers/net/ppp/pppoe.c | 34 ++++---
> drivers/net/ppp/pppox.c | 4 +-
> drivers/net/ppp/pptp.c | 40 ++++----
> drivers/tty/ipwireless/network.c | 30 +++---
> include/linux/if_pppox.h | 2 +-
> include/linux/ppp_channel.h | 49 ++++++----
> net/atm/pppoatm.c | 61 ++++++------
> net/l2tp/l2tp_ppp.c | 34 ++++---
> 11 files changed, 271 insertions(+), 246 deletions(-)
This patch is IMHO a bit too big and should be split. Also this kind of
refactor looks very invasive and potentially regression prone. I think
it should include a signficant self-test coverage increase.
> @@ -391,9 +396,9 @@ ppp_async_init(void)
> * The following routines provide the PPP channel interface.
> */
> static int
> -ppp_async_ioctl(struct ppp_channel *chan, unsigned int cmd, unsigned long arg)
> +ppp_async_ioctl(void *private, unsigned int cmd, unsigned long arg)
> {
> - struct asyncppp *ap = chan->private;
> + struct asyncppp *ap = private;
> void __user *argp = (void __user *)arg;
> int __user *p = argp;
> int err, val;
Minor nit: reverse christmas tree above
> @@ -2985,16 +2983,13 @@ char *ppp_dev_name(struct ppp_channel *chan)
> * This must be called in process context.
> */
> void
> -ppp_unregister_channel(struct ppp_channel *chan)
> +ppp_unregister_channel(struct ppp_channel *pch)
> {
> - struct channel *pch = chan->ppp;
> struct ppp_net *pn;
>
> if (!pch)
> return; /* should never happen */
>
> - chan->ppp = NULL;
> -
Sashiko says:
Could this specific ordering introduce a race condition that might lead
to a use-after-free?
If userspace has a file descriptor attached to this channel, it can
concurrently invoke the PPPIOCCONNECT ioctl. Because
ppp_disconnect_channel()
clears pch->ppp and removes the channel from its current unit before
pch->file.dead is set to 1, the concurrent ioctl could observe
pch->file.dead == 0.
This would allow ppp_connect_channel() to successfully attach the dying
channel to a new PPP unit. Once ppp_unregister_channel() completes and
frees the channel, the new PPP unit would retain a pointer to the freed
memory in its channels list, which might be accessed during a later
packet transmission via ppp_push().
> @@ -215,7 +210,8 @@ static void pppoatm_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
> !memcmp(skb->data, &pppllc[LLC_LEN],
> sizeof(pppllc) - LLC_LEN)) {
> pvcc->encaps = e_vc;
> - pvcc->chan.mtu += LLC_LEN;
> + ppp_channel_update_mtu(pvcc->chan,
> + atmvcc->qos.txtp.max_sdu - PPP_HDRLEN);
Does the above introduce a functional change? At very least some comment
needed. Also possibly better move the update_mtu wrapper to a pre-req patch.
> @@ -221,7 +221,7 @@ static void pppol2tp_recv(struct l2tp_session *session, struct sk_buff *skb, int
> struct pppox_sock *po;
>
> po = pppox_sk(sk);
> - ppp_input(&po->chan, skb);
> + ppp_input(po->chan, skb);
Sashiko says:
Does decoupling the channel lifetime from the driver structure introduce
a use-after-free when receiving packets?
Previously, the struct ppp_channel was embedded in struct pppox_sock,
meaning its lifecycle was safely tied to the socket's refcount. Now that
po->chan is dynamically allocated and freed during pppox_unbind_sock()
via ppp_unregister_channel(), it seems possible for pppol2tp_recv() to
access freed memory.
Since pppol2tp_recv() runs locklessly in softirq context while holding
only rcu_read_lock() and a socket reference, can it observe the
PPPOX_BOUND state and dereference po->chan just after it was freed on
another CPU?
/P
^ permalink raw reply
* [PATCH net-next 5/5] selftests: net: getsockopt_iter: address review nits
From: Breno Leitao @ 2026-05-05 11:12 UTC (permalink / raw)
To: Oliver Hartkopp, Marc Kleine-Budde, Robin van der Gracht,
Oleksij Rempel, kernel, Jeremy Kerr, Matt Johnston,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Shuah Khan
Cc: linux-can, linux-kernel, netdev, linux-kselftest, Breno Leitao,
kernel-team, Stanislav Fomichev, Bobby Eshleman
In-Reply-To: <20260505-getsock_two-v1-0-4cb0738950e0@debian.org>
Apply two cleanups suggested by Stanislav Fomichev on the original
selftest series:
- Reorder local variable declarations into reverse christmas-tree
order (longest line first). Because that ordering puts socklen_t
optlen before the variable whose size it stores, the
"optlen = sizeof(...)" initializer is moved out of the declaration
to a plain assignment in the test body, as Stanislav suggested.
- Add ASSERT_EQ(optlen, ...) on every error path so the value the
kernel writes back to the userspace optlen is pinned down even
when the syscall returns -1. With do_sock_getsockopt() now writing
opt->optlen back to userspace unconditionally, asserting that the
netlink/vsock error paths leave the original input length untouched
guards against future regressions.
Bobby Eshleman pointed out that
SO_VM_SOCKETS_CONNECT_TIMEOUT_NEW/OLD return a sock_timeval-shaped
payload (16 bytes on 64-bit), which is wider than the u64 case
already covered. Add four tests that exercise this path:
- connect_timeout_new_exact exact-size buffer
- connect_timeout_new_oversize_clamped oversize buffer, clamped
- connect_timeout_new_undersize undersize -> -EINVAL, optlen
untouched
- connect_timeout_old_exact exact-size buffer for OLD optname
Suggested-by: Stanislav Fomichev <sdf@fomichev.me>
Suggested-by: Bobby Eshleman <bobbyeshleman@meta.com>
Signed-off-by: Breno Leitao <leitao@debian.org>
---
tools/testing/selftests/net/getsockopt_iter.c | 109 +++++++++++++++++++++++---
1 file changed, 98 insertions(+), 11 deletions(-)
diff --git a/tools/testing/selftests/net/getsockopt_iter.c b/tools/testing/selftests/net/getsockopt_iter.c
index 179f9e84926fd..209569354d0e3 100644
--- a/tools/testing/selftests/net/getsockopt_iter.c
+++ b/tools/testing/selftests/net/getsockopt_iter.c
@@ -22,6 +22,7 @@
#include <unistd.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
+#include <linux/time_types.h>
#include <linux/vm_sockets.h>
#include <sys/socket.h>
#include "kselftest_harness.h"
@@ -61,8 +62,10 @@ FIXTURE_TEARDOWN(netlink)
TEST_F(netlink, pktinfo_exact)
{
+ socklen_t optlen;
int val = -1;
- socklen_t optlen = sizeof(val);
+
+ optlen = sizeof(val);
ASSERT_EQ(0, getsockopt(self->fd, SOL_NETLINK, NETLINK_PKTINFO,
&val, &optlen));
@@ -73,7 +76,9 @@ TEST_F(netlink, pktinfo_exact)
TEST_F(netlink, pktinfo_oversize_clamped)
{
char buf[16] = {};
- socklen_t optlen = sizeof(buf);
+ socklen_t optlen;
+
+ optlen = sizeof(buf);
ASSERT_EQ(0, getsockopt(self->fd, SOL_NETLINK, NETLINK_PKTINFO,
buf, &optlen));
@@ -83,11 +88,14 @@ TEST_F(netlink, pktinfo_oversize_clamped)
TEST_F(netlink, pktinfo_undersize)
{
char buf[2] = {};
- socklen_t optlen = sizeof(buf);
+ socklen_t optlen;
+
+ optlen = sizeof(buf);
ASSERT_EQ(-1, getsockopt(self->fd, SOL_NETLINK, NETLINK_PKTINFO,
buf, &optlen));
ASSERT_EQ(EINVAL, errno);
+ ASSERT_EQ(sizeof(buf), optlen);
}
TEST_F(netlink, list_memberships_size_discovery)
@@ -105,7 +113,9 @@ TEST_F(netlink, list_memberships_size_discovery)
TEST_F(netlink, list_memberships_full_read)
{
__u32 buf[64] = {};
- socklen_t optlen = sizeof(buf);
+ socklen_t optlen;
+
+ optlen = sizeof(buf);
ASSERT_EQ(0, getsockopt(self->fd, SOL_NETLINK,
NETLINK_LIST_MEMBERSHIPS,
@@ -117,22 +127,28 @@ TEST_F(netlink, list_memberships_full_read)
TEST_F(netlink, bad_level)
{
+ socklen_t optlen;
int val;
- socklen_t optlen = sizeof(val);
+
+ optlen = sizeof(val);
ASSERT_EQ(-1, getsockopt(self->fd, SOL_SOCKET + 1, NETLINK_PKTINFO,
&val, &optlen));
ASSERT_EQ(ENOPROTOOPT, errno);
+ ASSERT_EQ(sizeof(val), optlen);
}
TEST_F(netlink, bad_optname)
{
+ socklen_t optlen;
int val;
- socklen_t optlen = sizeof(val);
+
+ optlen = sizeof(val);
ASSERT_EQ(-1, getsockopt(self->fd, SOL_NETLINK, 0x7fff,
&val, &optlen));
ASSERT_EQ(ENOPROTOOPT, errno);
+ ASSERT_EQ(sizeof(val), optlen);
}
/* ---------- vsock ---------- */
@@ -157,8 +173,10 @@ FIXTURE_TEARDOWN(vsock)
TEST_F(vsock, buffer_size_exact)
{
+ socklen_t optlen;
uint64_t val = 0;
- socklen_t optlen = sizeof(val);
+
+ optlen = sizeof(val);
ASSERT_EQ(0, getsockopt(self->fd, AF_VSOCK,
SO_VM_SOCKETS_BUFFER_SIZE,
@@ -170,7 +188,9 @@ TEST_F(vsock, buffer_size_exact)
TEST_F(vsock, buffer_size_oversize_clamped)
{
char buf[16] = {};
- socklen_t optlen = sizeof(buf);
+ socklen_t optlen;
+
+ optlen = sizeof(buf);
ASSERT_EQ(0, getsockopt(self->fd, AF_VSOCK,
SO_VM_SOCKETS_BUFFER_SIZE,
@@ -181,33 +201,100 @@ TEST_F(vsock, buffer_size_oversize_clamped)
TEST_F(vsock, buffer_size_undersize)
{
char buf[4] = {};
- socklen_t optlen = sizeof(buf);
+ socklen_t optlen;
+
+ optlen = sizeof(buf);
ASSERT_EQ(-1, getsockopt(self->fd, AF_VSOCK,
SO_VM_SOCKETS_BUFFER_SIZE,
buf, &optlen));
ASSERT_EQ(EINVAL, errno);
+ ASSERT_EQ(sizeof(buf), optlen);
}
TEST_F(vsock, bad_level)
{
+ socklen_t optlen;
uint64_t val;
- socklen_t optlen = sizeof(val);
+
+ optlen = sizeof(val);
ASSERT_EQ(-1, getsockopt(self->fd, SOL_SOCKET + 1,
SO_VM_SOCKETS_BUFFER_SIZE,
&val, &optlen));
ASSERT_EQ(ENOPROTOOPT, errno);
+ ASSERT_EQ(sizeof(val), optlen);
}
TEST_F(vsock, bad_optname)
{
+ socklen_t optlen;
uint64_t val;
- socklen_t optlen = sizeof(val);
+
+ optlen = sizeof(val);
ASSERT_EQ(-1, getsockopt(self->fd, AF_VSOCK, 0x7fff,
&val, &optlen));
ASSERT_EQ(ENOPROTOOPT, errno);
+ ASSERT_EQ(sizeof(val), optlen);
+}
+
+/* SO_VM_SOCKETS_CONNECT_TIMEOUT_{NEW,OLD} return a sock_timeval-shaped
+ * payload, which is wider than u64 on 64-bit. They exercise the path
+ * where the protocol's reported lv (16 bytes) is larger than the
+ * common 8-byte u64 case covered above.
+ */
+TEST_F(vsock, connect_timeout_new_exact)
+{
+ struct __kernel_sock_timeval tv = {};
+ socklen_t optlen;
+
+ optlen = sizeof(tv);
+
+ ASSERT_EQ(0, getsockopt(self->fd, AF_VSOCK,
+ SO_VM_SOCKETS_CONNECT_TIMEOUT_NEW,
+ &tv, &optlen));
+ ASSERT_EQ(sizeof(tv), optlen);
+}
+
+TEST_F(vsock, connect_timeout_new_oversize_clamped)
+{
+ char buf[sizeof(struct __kernel_sock_timeval) * 2] = {};
+ socklen_t optlen;
+
+ optlen = sizeof(buf);
+
+ ASSERT_EQ(0, getsockopt(self->fd, AF_VSOCK,
+ SO_VM_SOCKETS_CONNECT_TIMEOUT_NEW,
+ buf, &optlen));
+ ASSERT_EQ(sizeof(struct __kernel_sock_timeval), optlen);
+}
+
+TEST_F(vsock, connect_timeout_new_undersize)
+{
+ socklen_t optlen;
+ uint64_t val;
+
+ optlen = sizeof(val);
+
+ ASSERT_EQ(-1, getsockopt(self->fd, AF_VSOCK,
+ SO_VM_SOCKETS_CONNECT_TIMEOUT_NEW,
+ &val, &optlen));
+ ASSERT_EQ(EINVAL, errno);
+ ASSERT_EQ(sizeof(val), optlen);
+}
+
+TEST_F(vsock, connect_timeout_old_exact)
+{
+ struct __kernel_old_timeval tv = {};
+ socklen_t optlen;
+
+ optlen = sizeof(tv);
+
+ ASSERT_EQ(0, getsockopt(self->fd, AF_VSOCK,
+ SO_VM_SOCKETS_CONNECT_TIMEOUT_OLD,
+ &tv, &optlen));
+ ASSERT_EQ(sizeof(tv), optlen);
}
TEST_HARNESS_MAIN
--
2.52.0
^ permalink raw reply related
* [PATCH net-next 4/5] llc: convert to getsockopt_iter
From: Breno Leitao @ 2026-05-05 11:12 UTC (permalink / raw)
To: Oliver Hartkopp, Marc Kleine-Budde, Robin van der Gracht,
Oleksij Rempel, kernel, Jeremy Kerr, Matt Johnston,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Shuah Khan
Cc: linux-can, linux-kernel, netdev, linux-kselftest, Breno Leitao,
kernel-team
In-Reply-To: <20260505-getsock_two-v1-0-4cb0738950e0@debian.org>
Convert LLC socket's getsockopt implementation to use the new
getsockopt_iter callback with sockopt_t.
Key changes:
- Replace (char __user *optval, int __user *optlen) with sockopt_t *opt
- Use opt->optlen for buffer length (input) and returned size (output)
- Use copy_to_iter() instead of put_user()/copy_to_user()
- Add linux/uio.h for copy_to_iter()
Signed-off-by: Breno Leitao <leitao@debian.org>
---
net/llc/af_llc.c | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
index 1b210db3119e8..7d723f0bd26c2 100644
--- a/net/llc/af_llc.c
+++ b/net/llc/af_llc.c
@@ -27,6 +27,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/sched/signal.h>
+#include <linux/uio.h>
#include <net/llc.h>
#include <net/llc_sap.h>
@@ -1172,19 +1173,16 @@ static int llc_ui_setsockopt(struct socket *sock, int level, int optname,
* Get connection specific socket information.
*/
static int llc_ui_getsockopt(struct socket *sock, int level, int optname,
- char __user *optval, int __user *optlen)
+ sockopt_t *opt)
{
struct sock *sk = sock->sk;
struct llc_sock *llc = llc_sk(sk);
- int val = 0, len = 0, rc = -EINVAL;
+ int val = 0, len, rc = -EINVAL;
lock_sock(sk);
if (unlikely(level != SOL_LLC))
goto out;
- rc = get_user(len, optlen);
- if (rc)
- goto out;
- rc = -EINVAL;
+ len = opt->optlen;
if (len != sizeof(int))
goto out;
switch (optname) {
@@ -1212,7 +1210,8 @@ static int llc_ui_getsockopt(struct socket *sock, int level, int optname,
goto out;
}
rc = 0;
- if (put_user(len, optlen) || copy_to_user(optval, &val, len))
+ opt->optlen = len;
+ if (copy_to_iter(&val, len, &opt->iter_out) != len)
rc = -EFAULT;
out:
release_sock(sk);
@@ -1239,7 +1238,7 @@ static const struct proto_ops llc_ui_ops = {
.listen = llc_ui_listen,
.shutdown = llc_ui_shutdown,
.setsockopt = llc_ui_setsockopt,
- .getsockopt = llc_ui_getsockopt,
+ .getsockopt_iter = llc_ui_getsockopt,
.sendmsg = llc_ui_sendmsg,
.recvmsg = llc_ui_recvmsg,
.mmap = sock_no_mmap,
--
2.52.0
^ permalink raw reply related
* [PATCH net-next 3/5] mctp: convert to getsockopt_iter
From: Breno Leitao @ 2026-05-05 11:12 UTC (permalink / raw)
To: Oliver Hartkopp, Marc Kleine-Budde, Robin van der Gracht,
Oleksij Rempel, kernel, Jeremy Kerr, Matt Johnston,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Shuah Khan
Cc: linux-can, linux-kernel, netdev, linux-kselftest, Breno Leitao,
kernel-team
In-Reply-To: <20260505-getsock_two-v1-0-4cb0738950e0@debian.org>
Convert MCTP socket's getsockopt implementation to use the new
getsockopt_iter callback with sockopt_t.
Key changes:
- Replace (char __user *optval, int __user *optlen) with sockopt_t *opt
- Use opt->optlen for buffer length (input)
- Use copy_to_iter() instead of copy_to_user()
- Add linux/uio.h for copy_to_iter()
Signed-off-by: Breno Leitao <leitao@debian.org>
---
net/mctp/af_mctp.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/net/mctp/af_mctp.c b/net/mctp/af_mctp.c
index 209a963112e3a..8af5e2b3c8d12 100644
--- a/net/mctp/af_mctp.c
+++ b/net/mctp/af_mctp.c
@@ -12,6 +12,7 @@
#include <linux/mctp.h>
#include <linux/module.h>
#include <linux/socket.h>
+#include <linux/uio.h>
#include <net/mctp.h>
#include <net/mctpdevice.h>
@@ -405,7 +406,7 @@ static int mctp_setsockopt(struct socket *sock, int level, int optname,
}
static int mctp_getsockopt(struct socket *sock, int level, int optname,
- char __user *optval, int __user *optlen)
+ sockopt_t *opt)
{
struct mctp_sock *msk = container_of(sock->sk, struct mctp_sock, sk);
int len, val;
@@ -413,14 +414,13 @@ static int mctp_getsockopt(struct socket *sock, int level, int optname,
if (level != SOL_MCTP)
return -EINVAL;
- if (get_user(len, optlen))
- return -EFAULT;
+ len = opt->optlen;
if (optname == MCTP_OPT_ADDR_EXT) {
if (len != sizeof(int))
return -EINVAL;
val = !!msk->addr_ext;
- if (copy_to_user(optval, &val, len))
+ if (copy_to_iter(&val, len, &opt->iter_out) != len)
return -EFAULT;
return 0;
}
@@ -639,7 +639,7 @@ static const struct proto_ops mctp_dgram_ops = {
.listen = sock_no_listen,
.shutdown = sock_no_shutdown,
.setsockopt = mctp_setsockopt,
- .getsockopt = mctp_getsockopt,
+ .getsockopt_iter = mctp_getsockopt,
.sendmsg = mctp_sendmsg,
.recvmsg = mctp_recvmsg,
.mmap = sock_no_mmap,
--
2.52.0
^ permalink raw reply related
* [PATCH net-next 0/5] net: convert four more protocols to getsockopt_iter
From: Breno Leitao @ 2026-05-05 11:12 UTC (permalink / raw)
To: Oliver Hartkopp, Marc Kleine-Budde, Robin van der Gracht,
Oleksij Rempel, kernel, Jeremy Kerr, Matt Johnston,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Shuah Khan
Cc: linux-can, linux-kernel, netdev, linux-kselftest, Breno Leitao,
kernel-team, Stanislav Fomichev, Bobby Eshleman
Continue the work to convert protocols to the new getsockopt_iter API.
Convert four additional getsockopt implementations to the new
sockopt_t/getsockopt_iter callback:
- CAN ISO-TP
- MCTP
- CAN J1939
- LLC
These are mechanical, ABI-preserving conversions following the same
pattern as the previously converted protocols (af_packet, can/raw,
af_netlink, af_vsock): the (char __user *optval, int __user *optlen)
pair is replaced with a single sockopt_t *opt that carries the buffer
length on input and the returned size on output, and exposes an iov_iter
for the copy-out path. put_user()/copy_to_user() pairs are replaced with
a single copy_to_iter() per option, and the wrapper in
do_sock_getsockopt() handles writing optlen back to userspace.
I picked these four because each is small and self-contained, with only
one getsockopt callback and a handful of options, so the conversions are
easy to audit individually.
NOTE: optlen is always updated (returned to userspace) even when optval
fails to copy. I.e, userspace will get the "new" optlen even when the
getsockop() fails. That seems wrong, but, this just preserve the
previous behaviour, not changing it.
Signed-off-by: Breno Leitao <leitao@debian.org>
---
Breno Leitao (5):
can: isotp: convert to getsockopt_iter
can: j1939: convert to getsockopt_iter
mctp: convert to getsockopt_iter
llc: convert to getsockopt_iter
selftests: net: getsockopt_iter: address review nits
net/can/isotp.c | 12 ++-
net/can/j1939/socket.c | 21 +++--
net/llc/af_llc.c | 15 ++--
net/mctp/af_mctp.c | 10 +--
tools/testing/selftests/net/getsockopt_iter.c | 109 +++++++++++++++++++++++---
5 files changed, 128 insertions(+), 39 deletions(-)
---
base-commit: c1e5127b577c6b88fa48e532616932ae978528d5
change-id: 20260505-getsock_two-abad19643336
Best regards,
--
Breno Leitao <leitao@debian.org>
^ permalink raw reply
* [PATCH net-next 2/5] can: j1939: convert to getsockopt_iter
From: Breno Leitao @ 2026-05-05 11:12 UTC (permalink / raw)
To: Oliver Hartkopp, Marc Kleine-Budde, Robin van der Gracht,
Oleksij Rempel, kernel, Jeremy Kerr, Matt Johnston,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Shuah Khan
Cc: linux-can, linux-kernel, netdev, linux-kselftest, Breno Leitao,
kernel-team
In-Reply-To: <20260505-getsock_two-v1-0-4cb0738950e0@debian.org>
Convert CAN J1939 socket's getsockopt implementation to use the new
getsockopt_iter callback with sockopt_t.
Key changes:
- Replace (char __user *optval, int __user *optlen) with sockopt_t *opt
- Use opt->optlen for buffer length (input) and returned size (output)
- Use copy_to_iter() instead of copy_to_user()
- Restructure the chained if/else if (which depended on put_user() being
an expression) into a nested if/else block now that opt->optlen = len
is a statement
- Add linux/uio.h for copy_to_iter()
Signed-off-by: Breno Leitao <leitao@debian.org>
---
net/can/j1939/socket.c | 21 +++++++++++++--------
1 file changed, 13 insertions(+), 8 deletions(-)
diff --git a/net/can/j1939/socket.c b/net/can/j1939/socket.c
index 50a598ef5fd4a..d0c6ce607b0dc 100644
--- a/net/can/j1939/socket.c
+++ b/net/can/j1939/socket.c
@@ -17,6 +17,7 @@
#include <linux/can/skb.h>
#include <linux/errqueue.h>
#include <linux/if_arp.h>
+#include <linux/uio.h>
#include <net/can.h>
#include "j1939-priv.h"
@@ -767,7 +768,7 @@ static int j1939_sk_setsockopt(struct socket *sock, int level, int optname,
}
static int j1939_sk_getsockopt(struct socket *sock, int level, int optname,
- char __user *optval, int __user *optlen)
+ sockopt_t *opt)
{
struct sock *sk = sock->sk;
struct j1939_sock *jsk = j1939_sk(sk);
@@ -779,8 +780,7 @@ static int j1939_sk_getsockopt(struct socket *sock, int level, int optname,
if (level != SOL_CAN_J1939)
return -EINVAL;
- if (get_user(ulen, optlen))
- return -EFAULT;
+ ulen = opt->optlen;
if (ulen < 0)
return -EINVAL;
@@ -804,11 +804,16 @@ static int j1939_sk_getsockopt(struct socket *sock, int level, int optname,
* but most sockopt's are 'int' properties, and have 'len' & 'val'
* left unchanged, but instead modified 'tmp'
*/
- if (len > ulen)
- ret = -EFAULT;
- else if (put_user(len, optlen))
+ if (len > ulen) {
ret = -EFAULT;
- else if (copy_to_user(optval, val, len))
+ goto no_copy;
+ }
+
+ opt->optlen = len;
+ /* Even if the copy below fails, we want to update optlen. This is
+ * a bit confusing, but, it preserves the original behaviour
+ */
+ if (copy_to_iter(val, len, &opt->iter_out) != len)
ret = -EFAULT;
else
ret = 0;
@@ -1385,7 +1390,7 @@ static const struct proto_ops j1939_ops = {
.listen = sock_no_listen,
.shutdown = sock_no_shutdown,
.setsockopt = j1939_sk_setsockopt,
- .getsockopt = j1939_sk_getsockopt,
+ .getsockopt_iter = j1939_sk_getsockopt,
.sendmsg = j1939_sk_sendmsg,
.recvmsg = j1939_sk_recvmsg,
.mmap = sock_no_mmap,
--
2.52.0
^ permalink raw reply related
* [PATCH net-next 1/5] can: isotp: convert to getsockopt_iter
From: Breno Leitao @ 2026-05-05 11:12 UTC (permalink / raw)
To: Oliver Hartkopp, Marc Kleine-Budde, Robin van der Gracht,
Oleksij Rempel, kernel, Jeremy Kerr, Matt Johnston,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Shuah Khan
Cc: linux-can, linux-kernel, netdev, linux-kselftest, Breno Leitao,
kernel-team
In-Reply-To: <20260505-getsock_two-v1-0-4cb0738950e0@debian.org>
Convert CAN ISO-TP socket's getsockopt implementation to use the new
getsockopt_iter callback with sockopt_t.
Key changes:
- Replace (char __user *optval, int __user *optlen) with sockopt_t *opt
- Use opt->optlen for buffer length (input) and returned size (output)
- Use copy_to_iter() instead of put_user()/copy_to_user()
Signed-off-by: Breno Leitao <leitao@debian.org>
---
net/can/isotp.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/net/can/isotp.c b/net/can/isotp.c
index c48b4a818297e..1c33f09fbd338 100644
--- a/net/can/isotp.c
+++ b/net/can/isotp.c
@@ -1500,7 +1500,7 @@ static int isotp_setsockopt(struct socket *sock, int level, int optname,
}
static int isotp_getsockopt(struct socket *sock, int level, int optname,
- char __user *optval, int __user *optlen)
+ sockopt_t *opt)
{
struct sock *sk = sock->sk;
struct isotp_sock *so = isotp_sk(sk);
@@ -1509,8 +1509,7 @@ static int isotp_getsockopt(struct socket *sock, int level, int optname,
if (level != SOL_CAN_ISOTP)
return -EINVAL;
- if (get_user(len, optlen))
- return -EFAULT;
+ len = opt->optlen;
if (len < 0)
return -EINVAL;
@@ -1544,9 +1543,8 @@ static int isotp_getsockopt(struct socket *sock, int level, int optname,
return -ENOPROTOOPT;
}
- if (put_user(len, optlen))
- return -EFAULT;
- if (copy_to_user(optval, val, len))
+ opt->optlen = len;
+ if (copy_to_iter(val, len, &opt->iter_out) != len)
return -EFAULT;
return 0;
}
@@ -1718,7 +1716,7 @@ static const struct proto_ops isotp_ops = {
.listen = sock_no_listen,
.shutdown = sock_no_shutdown,
.setsockopt = isotp_setsockopt,
- .getsockopt = isotp_getsockopt,
+ .getsockopt_iter = isotp_getsockopt,
.sendmsg = isotp_sendmsg,
.recvmsg = isotp_recvmsg,
.mmap = sock_no_mmap,
--
2.52.0
^ permalink raw reply related
* Re: [PATCH] fixup! net: dsa: microchip: implement KSZ87xx Module 3 low-loss cable errata
From: Marek Vasut @ 2026-05-05 11:07 UTC (permalink / raw)
To: Fidelio LAWSON, Sai Krishna Gajula, netdev@vger.kernel.org
Cc: Andrew Lunn, Woojung Huh, Fidelio Lawson
In-Reply-To: <18cfeb86-9879-4644-b2f8-ab7775287b1e@gmail.com>
On 4/17/26 6:30 PM, Fidelio LAWSON wrote:
> On 4/17/26 18:10, Sai Krishna Gajula wrote:
>>> -----Original Message-----
>>> From: Fidelio Lawson <lawson.fidelio@gmail.com>
>>> Sent: Friday, April 17, 2026 9:20 PM
>>> To: netdev@vger.kernel.org
>>> Cc: Marek Vasut <marex@nabladev.com>; Andrew Lunn <andrew@lunn.ch>;
>>> Woojung Huh <woojung.huh@microchip.com>; Fidelio Lawson
>>> <fidelio.lawson@exotec.com>
>>> Subject: [PATCH] fixup! net: dsa: microchip: implement KSZ87xx
>>> Module 3 low-loss cable errata
>>
>> Since this errata is a fix and pushed to "net", adding fixes tag may
>> be required.
>>
>
> Good point, thanks for spotting this.
> I’ll add an appropriate fixes tag referencing the commit that introduced
> the KSZ87xx support, and follow up with an updated fixup.
Could you maybe collect the fixes and send a V5 ?
Thank you !
^ permalink raw reply
* Re: [PATCH net 06/12] netfilter: nf_conntrack_expect: honor expectation helper field
From: Ilya Maximets @ 2026-05-05 11:01 UTC (permalink / raw)
To: Pablo Neira Ayuso
Cc: i.maximets, netfilter-devel, fw, davem, netdev, kuba, pabeni,
edumazet, horms, Eelco Chaudron, Aaron Conole
In-Reply-To: <afkuhbWieFXRTirN@chamomile>
On 5/5/26 1:40 AM, Pablo Neira Ayuso wrote:
> On Tue, May 05, 2026 at 01:16:05AM +0200, Pablo Neira Ayuso wrote:
>> Thanks for the detailed report. It seems I changed the semantics of
>> exp->helper, this used to be use to set a new helper for an expected
>> connection, which is the case for sip and h323.
>>
>> Would this patch help address the issue you are observing?
>
> Actually, this needs to set to NULL the new exp->assign_helper field,
> see new patch, untested.
I ran this through OVS system tests and all passed. So, this restores
the old behavior, at least for FTP (we do not support sip/h323). For
that part:
Tested-by: Ilya Maximets <i.maximets@ovn.org>
^ permalink raw reply
* Re: [PATCH net 06/12] netfilter: nf_conntrack_expect: honor expectation helper field
From: Ilya Maximets @ 2026-05-05 11:01 UTC (permalink / raw)
To: Pablo Neira Ayuso
Cc: i.maximets, netfilter-devel, fw, davem, netdev, kuba, pabeni,
edumazet, horms, Eelco Chaudron, Aaron Conole
In-Reply-To: <afkosr2fDEPA_jX9@chamomile>
On 5/5/26 1:16 AM, Pablo Neira Ayuso wrote:
> Hi Ilya,
>
> On Mon, May 04, 2026 at 02:19:20PM +0200, Ilya Maximets wrote:
>> On 5/1/26 12:37 PM, Pablo Neira Ayuso wrote:
>>> Hi Ilya,
>>>
>>> On Thu, Apr 30, 2026 at 10:58:38PM +0200, Ilya Maximets wrote:
>>>> On 3/26/26 1:51 PM, Pablo Neira Ayuso wrote:
>>>>> The expectation helper field is mostly unused. As a result, the
>>>>> netfilter codebase relies on accessing the helper through exp->master.
>>>>>
>>>>> Always set on the expectation helper field so it can be used to reach
>>>>> the helper.
>>>>>
>>>>> nf_ct_expect_init() is called from packet path where the skb owns
>>>>> the ct object, therefore accessing exp->master for the newly created
>>>>> expectation is safe. This saves a lot of updates in all callsites
>>>>> to pass the ct object as parameter to nf_ct_expect_init().
>>>>>
>>>>> This is a preparation patches for follow up fixes.
>>>>>
>>>>> Signed-off-by: Florian Westphal <fw@strlen.de>
>>>>> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
>>>>> ---
>>>>
>>>> Hi, Pablo and Florian.
>>>>
>>>> I was investigating FTP test failures in OVS with 7.0 kernel and bisected
>>>> the issue down to this commit. AFAIU, with this change all the related
>>>> connections over time gain their parents' helpers,. This is causing a change
>>>> visible to the userspace, because FTP data connections are now reported to
>>>> have helpers in the conntrack dump:
>>>>
>>>> # conntrack -L
>>>> tcp 6 119 TIME_WAIT src=10.1.1.1 dst=10.1.1.2 sport=59534 dport=21 \
>>>> src=10.1.1.2 dst=10.1.1.1 sport=21 dport=59534 \
>>>> [ASSURED] mark=0 helper=ftp use=2
>>>> tcp 6 119 TIME_WAIT src=10.1.1.2 dst=10.1.1.1 sport=52709 dport=52381 \
>>>> src=10.1.1.1 dst=10.1.1.2 sport=52381 dport=52709 \
>>>> [ASSURED] mark=0 helper=ftp use=1
>>>>
>>>> Before this commit only the control connection had helper=ftp reported in
>>>> the dump. The traffic seems to work fine, but our tests fail because we
>>>> do not expect the helper attached.
>>>>
>>>> AFAIU, it's generally not something that should be happening, as helpers
>>>> on data connections do not really make much sense. But I'm just trying to
>>>> figure out if you would consider this as a regression and fix in the kernel
>>>> or if we should adjust our userspace components for this new dump content,
>>>> which would not be very straightforward to do if we want to be able to run
>>>> tests on both old and the new versions.
>>>>
>>>> What do you think?
>>>
>>> It seems previous behaviour to 9c42bc9db90a was inconsistent, ie. only
>>> the h323 helper sets on exp->helper, then it shows helper= in expected
>>> connections via ctnetlink. I guess this is for debugging given that
>>> h323 is actually a family of helpers.
>>>
>>> To consistently skip dumping this for expected connections, probably
>>> this is the way to do:
>>>
>>> diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conn
>>> index eda5fe4a75c8..9491ae9e080e 100644
>>> --- a/net/netfilter/nf_conntrack_netlink.c
>>> +++ b/net/netfilter/nf_conntrack_netlink.c
>>> @@ -226,7 +226,7 @@ static int ctnetlink_dump_helpinfo(struct sk_buff *sk
>>> const struct nf_conn_help *help = nfct_help(ct);
>>> struct nf_conntrack_helper *helper;
>>>
>>> - if (!help)
>>> + if (!help || ct->status & IPS_EXPECTED)
>>> return 0;
>>>
>>> rcu_read_lock();
>>
>> I'm not sure. I tried this change and it fixed one case but broke another.
>> Looking at what we're testing, the old behavior (at least for FTP) was:
>> "if helper was committed - report it, if not - don't". i.e. it's not really
>> about the connection being expected it's about if the user committed the
>> helper for the connection or not.
>>
>> Let me explain a few scenarios that we have in the OVS system tests and what
>> I see with the old kernel (6.19), the new (7.0) and the patch above.
>>
>> A) The first scenario has the following OpenFlow rules (simplified):
>>
>> table=0,in_port=1,tcp,action=ct(alg=ftp,commit),2
>> table=0,in_port=2,tcp,action=ct(table=1)
>> table=1,in_port=2,tcp,ct_state=+trk+est,action=1
>> table=1,in_port=2,tcp,ct_state=+trk+rel,action=1
>>
>> This set of rule blindly commits every packet coming from port 1 with the
>> helper and sends to port 2. Packets from port 2 are passed through ct and
>> only related or established traffic is passed to port 1. This is a very
>> rudimentary setup that users can make to allow ftp from port 1 towards port 2,
>> but not in the opposite direction.
>>
>> For this scenario regardless of the kernel version or the patch above I see
>> that both the data and the control connections have a helper reported in the
>> ctnetlink dump.
>
> This ruleset then is attached the conntrack helper to data connection,
> that is, ALG is inspecting the FTP data connection but it will just
> find no patterns because it is only the FTP control connection that
> creates expectations?
Yes. It's just a "lazy" way to make the traffic work, we do not expect
the helper on the data connection to do anything useful in this scenario.
Best regards, Ilya Maximets.
^ permalink raw reply
* Re: [PATCH 0/6] SUNRPC: Address remaining cache_check_rcu() UAF in cache content files
From: Chuck Lever @ 2026-05-05 10:53 UTC (permalink / raw)
To: Calum Mackay, Misbah Anjum N, Jeff Layton, NeilBrown,
Olga Kornievskaia, Dai Ngo, Tom Talpey, Trond Myklebust,
Anna Schumaker, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Yang Erkun
Cc: linux-nfs, linux-kernel, netdev, Chuck Lever, alexandr.alexandrov
In-Reply-To: <daa6461b-d8d6-42ad-adac-ac0df58c3b6e@oracle.com>
On 5/5/26 12:49 PM, Calum Mackay wrote:
> On 01/05/2026 3:51 pm, Chuck Lever wrote:
>> Misbah Anjum reported a use-after-free in cache_check_rcu()
>> reached through e_show() while sosreport was reading
>> /proc/fs/nfsd/exports on ppc64le. Two fixes for that report
>> landed in v7.0:
>>
>> 48db892356d6 ("NFSD: Defer sub-object cleanup in export put
>> callbacks")
>> e7fcf179b82d ("NFSD: Hold net reference for the lifetime of /proc/
>> fs/nfs/exports fd")
>>
>> The original e_show() repro is now fixed. However, the same
>> sosreport workload still reproduces a closely related fault on
>> post-v7.0 mainline (Misbah, ppc64le) and on master.20260424
>> (internal report, aarch64). In both cases the fault is in
>> cache_check_rcu() reached through c_show() rather than e_show(),
>> and the cache_head pointer is plain garbage:
>>
>> pc : cache_check_rcu+0x40 [sunrpc]
>> lr : c_show+0x60 [sunrpc]
>> ...faulting on h->flags off h = 0x0000000200000000
>>
>> c_show() is the generic show callback used by
>> /proc/net/rpc/<cd>/content for every per-net cache_detail
>> (auth.unix.ip, auth.unix.gid, nfsd.fh, nfsd.export). Two
>> bugs combine in that path:
>>
>> 1. cache_unregister_net() / cache_destroy_net() free cd and
>> cd->hash_table synchronously when the namespace exits. The
>> /proc/net/rpc/.../content open path takes only a module
>> reference, so a fd kept open across a netns exit walks a
>> freed hash_table and returns garbage cache_head pointers.
>> This is the same hazard that e7fcf179b82d closed for the
>> /proc/fs/nfs/exports file alone.
>>
>> 2. ip_map_put() drops auth_domain_put() before kfree_rcu(), so
>> sub-objects can be freed before the RCU grace period -- the
>> same hazard that 48db892356d6 fixed for svc_export_put() and
>> expkey_put(). unix_gid_put() does not have this bug
>> structurally (its put_group_info() runs inside the call_rcu()
>> callback) but it uses a separate idiom from the other three
>> caches.
>>
>> This series replaces the v1 narrow fixes with shared
>> infrastructure that covers all four cache_detail .put paths
>> and all three per-cache file types:
>>
>> Patch 1 hoists nfsd_export_wq up to the sunrpc layer as
>> sunrpc_cache_wq, exposed through sunrpc_cache_queue_release()
>> and sunrpc_cache_drain() so all four put callbacks share one
>> workqueue and one drain primitive.
>>
>> Patch 2 converts ip_map_put() to the queue_rcu_work() pattern,
>> moving auth_domain_put() into a deferred ip_map_release() that
>> runs after the RCU grace period.
>>
>> Patch 3 unifies unix_gid_put() onto the same pattern for
>> consistency (not a bug fix on its own).
>>
>> Patch 4 takes a get_net(cd->net) in content_open(), cache_open(),
>> and open_flush() and drops it in the matching release helpers,
>> so cache_destroy_net() cannot run while a sunrpc cache fd is
>> open.
>>
>> Series has been compile-tested only.
>>
>> ---
>> Chuck Lever (6):
>> SUNRPC: Move cache_initialize() declaration to sunrpc-private
>> header
>> SUNRPC: Provide a shared workqueue for cache release callbacks
>> SUNRPC: Defer ip_map sub-object cleanup past RCU grace period
>> SUNRPC: Use shared release pattern for the unix_gid cache
>> SUNRPC: Hold cd->net for the lifetime of cache files
>> NFSD: Convert nfsd_export_shutdown() to sunrpc_cache_destroy_net()
>>
>> fs/nfsd/export.c | 45 ++--------------------
>> fs/nfsd/export.h | 2 -
>> fs/nfsd/nfsctl.c | 8 +---
>> include/linux/sunrpc/cache.h | 3 +-
>> net/sunrpc/cache.c | 90 ++++++++++++++++++++++++++++++++++
>> ++++++++--
>> net/sunrpc/sunrpc.h | 2 +
>> net/sunrpc/sunrpc_syms.c | 23 ++++++-----
>> net/sunrpc/svcauth_unix.c | 46 ++++++++++++----------
>> 8 files changed, 135 insertions(+), 84 deletions(-)
>> ---
>> base-commit: f3a313ecd1fdab1f5da119db355363b13af6fcac
>> change-id: 20260430-cache-uaf-fix-a13000f67c37
>>
>> Best regards,
>> --
>> Chuck Lever
>>
>>
>
> Looks good Chuck, thanks very much.
>
> With these patches, testing shows no crashes, sosreport no longer hangs,
> no seq_file errors.
>
> Tested-by: Alexandr Alexandrov <alexandr.alexandrov@oracle.com>
>
> cheers,
> c.
>
Excellent; pushed with Jeff's R-b and Alexandr's T-b.
--
Chuck Lever
^ permalink raw reply
* Re: [PATCH 0/6] SUNRPC: Address remaining cache_check_rcu() UAF in cache content files
From: Calum Mackay @ 2026-05-05 10:49 UTC (permalink / raw)
To: Chuck Lever, Misbah Anjum N, Jeff Layton, NeilBrown,
Olga Kornievskaia, Dai Ngo, Tom Talpey, Trond Myklebust,
Anna Schumaker, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Yang Erkun
Cc: Calum Mackay, linux-nfs, linux-kernel, netdev, Chuck Lever,
alexandr.alexandrov
In-Reply-To: <20260501-cache-uaf-fix-v1-0-a49928bf4817@oracle.com>
On 01/05/2026 3:51 pm, Chuck Lever wrote:
> Misbah Anjum reported a use-after-free in cache_check_rcu()
> reached through e_show() while sosreport was reading
> /proc/fs/nfsd/exports on ppc64le. Two fixes for that report
> landed in v7.0:
>
> 48db892356d6 ("NFSD: Defer sub-object cleanup in export put callbacks")
> e7fcf179b82d ("NFSD: Hold net reference for the lifetime of /proc/fs/nfs/exports fd")
>
> The original e_show() repro is now fixed. However, the same
> sosreport workload still reproduces a closely related fault on
> post-v7.0 mainline (Misbah, ppc64le) and on master.20260424
> (internal report, aarch64). In both cases the fault is in
> cache_check_rcu() reached through c_show() rather than e_show(),
> and the cache_head pointer is plain garbage:
>
> pc : cache_check_rcu+0x40 [sunrpc]
> lr : c_show+0x60 [sunrpc]
> ...faulting on h->flags off h = 0x0000000200000000
>
> c_show() is the generic show callback used by
> /proc/net/rpc/<cd>/content for every per-net cache_detail
> (auth.unix.ip, auth.unix.gid, nfsd.fh, nfsd.export). Two
> bugs combine in that path:
>
> 1. cache_unregister_net() / cache_destroy_net() free cd and
> cd->hash_table synchronously when the namespace exits. The
> /proc/net/rpc/.../content open path takes only a module
> reference, so a fd kept open across a netns exit walks a
> freed hash_table and returns garbage cache_head pointers.
> This is the same hazard that e7fcf179b82d closed for the
> /proc/fs/nfs/exports file alone.
>
> 2. ip_map_put() drops auth_domain_put() before kfree_rcu(), so
> sub-objects can be freed before the RCU grace period -- the
> same hazard that 48db892356d6 fixed for svc_export_put() and
> expkey_put(). unix_gid_put() does not have this bug
> structurally (its put_group_info() runs inside the call_rcu()
> callback) but it uses a separate idiom from the other three
> caches.
>
> This series replaces the v1 narrow fixes with shared
> infrastructure that covers all four cache_detail .put paths
> and all three per-cache file types:
>
> Patch 1 hoists nfsd_export_wq up to the sunrpc layer as
> sunrpc_cache_wq, exposed through sunrpc_cache_queue_release()
> and sunrpc_cache_drain() so all four put callbacks share one
> workqueue and one drain primitive.
>
> Patch 2 converts ip_map_put() to the queue_rcu_work() pattern,
> moving auth_domain_put() into a deferred ip_map_release() that
> runs after the RCU grace period.
>
> Patch 3 unifies unix_gid_put() onto the same pattern for
> consistency (not a bug fix on its own).
>
> Patch 4 takes a get_net(cd->net) in content_open(), cache_open(),
> and open_flush() and drops it in the matching release helpers,
> so cache_destroy_net() cannot run while a sunrpc cache fd is
> open.
>
> Series has been compile-tested only.
>
> ---
> Chuck Lever (6):
> SUNRPC: Move cache_initialize() declaration to sunrpc-private header
> SUNRPC: Provide a shared workqueue for cache release callbacks
> SUNRPC: Defer ip_map sub-object cleanup past RCU grace period
> SUNRPC: Use shared release pattern for the unix_gid cache
> SUNRPC: Hold cd->net for the lifetime of cache files
> NFSD: Convert nfsd_export_shutdown() to sunrpc_cache_destroy_net()
>
> fs/nfsd/export.c | 45 ++--------------------
> fs/nfsd/export.h | 2 -
> fs/nfsd/nfsctl.c | 8 +---
> include/linux/sunrpc/cache.h | 3 +-
> net/sunrpc/cache.c | 90 ++++++++++++++++++++++++++++++++++++++++++--
> net/sunrpc/sunrpc.h | 2 +
> net/sunrpc/sunrpc_syms.c | 23 ++++++-----
> net/sunrpc/svcauth_unix.c | 46 ++++++++++++----------
> 8 files changed, 135 insertions(+), 84 deletions(-)
> ---
> base-commit: f3a313ecd1fdab1f5da119db355363b13af6fcac
> change-id: 20260430-cache-uaf-fix-a13000f67c37
>
> Best regards,
> --
> Chuck Lever
>
>
Looks good Chuck, thanks very much.
With these patches, testing shows no crashes, sosreport no longer hangs,
no seq_file errors.
Tested-by: Alexandr Alexandrov <alexandr.alexandrov@oracle.com>
cheers,
c.
^ permalink raw reply
* [PATCH net 3/3] netdevsim: psp: rcu protect psp_dev reference
From: Daniel Zahka @ 2026-05-05 10:42 UTC (permalink / raw)
To: Jakub Kicinski, Andrew Lunn, David S. Miller, Eric Dumazet,
Paolo Abeni, Willem de Bruijn, Willem de Bruijn
Cc: netdev, linux-kernel
In-Reply-To: <20260505-psd-rcu-v1-0-a8f69ec1ab96@gmail.com>
There are two issues with the way psp_dev is used in nsim_do_psp():
1. There is no check for IS_ERR() on the peers psp_dev, before
dereferencing.
2. The refcount on this psp_dev can be dropped by
nsim_psp_rereg_write()
To fix this, we can make netdevsim's reference to its psp_dev an rcu
reference, and then nsim_do_psp() can read the fields it needs from an
rcu critical section.
Fixes: f857478d6206 ("netdevsim: a basic test PSP implementation")
Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com>
---
drivers/net/netdevsim/netdevsim.h | 2 +-
drivers/net/netdevsim/psp.c | 54 +++++++++++++++++++++++++--------------
2 files changed, 36 insertions(+), 20 deletions(-)
diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h
index e373ffc26b0c..d909c4160ea1 100644
--- a/drivers/net/netdevsim/netdevsim.h
+++ b/drivers/net/netdevsim/netdevsim.h
@@ -120,7 +120,7 @@ struct netdevsim {
u64_stats_t tx_packets;
u64_stats_t tx_bytes;
struct u64_stats_sync syncp;
- struct psp_dev *dev;
+ struct psp_dev __rcu *dev;
struct dentry *rereg;
struct mutex rereg_lock;
u32 spi;
diff --git a/drivers/net/netdevsim/psp.c b/drivers/net/netdevsim/psp.c
index 86d84b7e566b..6936ecb8173e 100644
--- a/drivers/net/netdevsim/psp.c
+++ b/drivers/net/netdevsim/psp.c
@@ -19,6 +19,7 @@ nsim_do_psp(struct sk_buff *skb, struct netdevsim *ns,
struct netdevsim *peer_ns, struct skb_ext **psp_ext)
{
enum skb_drop_reason rc = 0;
+ struct psp_dev *peer_psd;
struct psp_assoc *pas;
struct net *net;
void **ptr;
@@ -48,7 +49,8 @@ nsim_do_psp(struct sk_buff *skb, struct netdevsim *ns,
}
/* Now pretend we just received this frame */
- if (peer_ns->psp.dev->config.versions & (1 << pas->version)) {
+ peer_psd = rcu_dereference(peer_ns->psp.dev);
+ if (peer_psd && peer_psd->config.versions & (1 << pas->version)) {
bool strip_icv = false;
u8 generation;
@@ -61,8 +63,7 @@ nsim_do_psp(struct sk_buff *skb, struct netdevsim *ns,
skb_ext_reset(skb);
skb->mac_len = ETH_HLEN;
- if (psp_dev_rcv(skb, peer_ns->psp.dev->id, generation,
- strip_icv)) {
+ if (psp_dev_rcv(skb, peer_psd->id, generation, strip_icv)) {
rc = SKB_DROP_REASON_PSP_OUTPUT;
goto out_unlock;
}
@@ -209,10 +210,18 @@ static struct psp_dev_caps nsim_psp_caps = {
.assoc_drv_spc = sizeof(void *),
};
-static void __nsim_psp_uninit(struct netdevsim *ns)
+static void __nsim_psp_uninit(struct netdevsim *ns, bool teardown)
{
- if (!IS_ERR(ns->psp.dev))
- psp_dev_unregister(ns->psp.dev);
+ struct psp_dev *psd;
+
+ psd = rcu_dereference_protected(ns->psp.dev,
+ teardown ||
+ lockdep_is_held(&ns->psp.rereg_lock));
+ if (psd) {
+ rcu_assign_pointer(ns->psp.dev, NULL);
+ synchronize_rcu();
+ psp_dev_unregister(psd);
+ }
WARN_ON(ns->psp.assoc_cnt);
}
@@ -220,7 +229,7 @@ void nsim_psp_uninit(struct netdevsim *ns)
{
debugfs_remove(ns->psp.rereg);
mutex_destroy(&ns->psp.rereg_lock);
- __nsim_psp_uninit(ns);
+ __nsim_psp_uninit(ns, true);
}
static ssize_t
@@ -228,16 +237,23 @@ nsim_psp_rereg_write(struct file *file, const char __user *data, size_t count,
loff_t *ppos)
{
struct netdevsim *ns = file->private_data;
- int err;
+ struct psp_dev *psd;
+ ssize_t ret;
mutex_lock(&ns->psp.rereg_lock);
- __nsim_psp_uninit(ns);
+ __nsim_psp_uninit(ns, false);
+
+ psd = psp_dev_create(ns->netdev, &nsim_psp_ops, &nsim_psp_caps, ns);
+ if (IS_ERR(psd)) {
+ ret = PTR_ERR(psd);
+ goto out;
+ }
- ns->psp.dev = psp_dev_create(ns->netdev, &nsim_psp_ops,
- &nsim_psp_caps, ns);
- err = PTR_ERR_OR_ZERO(ns->psp.dev);
+ rcu_assign_pointer(ns->psp.dev, psd);
+ ret = count;
+out:
mutex_unlock(&ns->psp.rereg_lock);
- return err ?: count;
+ return ret;
}
static const struct file_operations nsim_psp_rereg_fops = {
@@ -250,13 +266,13 @@ static const struct file_operations nsim_psp_rereg_fops = {
int nsim_psp_init(struct netdevsim *ns)
{
struct dentry *ddir = ns->nsim_dev_port->ddir;
- int err;
+ struct psp_dev *psd;
+
+ psd = psp_dev_create(ns->netdev, &nsim_psp_ops, &nsim_psp_caps, ns);
+ if (IS_ERR(psd))
+ return PTR_ERR(psd);
- ns->psp.dev = psp_dev_create(ns->netdev, &nsim_psp_ops,
- &nsim_psp_caps, ns);
- err = PTR_ERR_OR_ZERO(ns->psp.dev);
- if (err)
- return err;
+ rcu_assign_pointer(ns->psp.dev, psd);
mutex_init(&ns->psp.rereg_lock);
ns->psp.rereg = debugfs_create_file("psp_rereg", 0200, ddir, ns,
--
2.52.0
^ permalink raw reply related
* [PATCH net 2/3] netdevsim: psp: serialize calls to nsim_psp_uninit()
From: Daniel Zahka @ 2026-05-05 10:42 UTC (permalink / raw)
To: Jakub Kicinski, Andrew Lunn, David S. Miller, Eric Dumazet,
Paolo Abeni, Willem de Bruijn, Willem de Bruijn
Cc: netdev, linux-kernel
In-Reply-To: <20260505-psd-rcu-v1-0-a8f69ec1ab96@gmail.com>
The debugfs write handler, nsim_psp_rereg_write(), can race against
nsim_destroy() and against itself, causing nsim_psp_uninit() to run
more than once concurrently. Two complementary changes serialize all
callers:
1. Delete the psp_rereg debugfs file from nsim_psp_uninit() before
doing the actual teardown. debugfs_remove() drains any in-flight
writers and prevents new ones from starting.
2. Add a mutex around the body of nsim_psp_rereg_write() so that two
concurrent userspace writers cannot both enter the teardown path
at once.
The teardown work itself is moved into a new __nsim_psp_uninit() that
the rereg handler calls under the mutex, while the public
nsim_psp_uninit() wraps it with the debugfs_remove()/mutex_destroy()
pair so nsim_destroy() doesn't have to know about the psp internals.
Fixes: f857478d6206 ("netdevsim: a basic test PSP implementation")
Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com>
---
drivers/net/netdevsim/netdevsim.h | 2 ++
drivers/net/netdevsim/psp.c | 17 ++++++++++++++---
2 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h
index 7e129dddbbe7..e373ffc26b0c 100644
--- a/drivers/net/netdevsim/netdevsim.h
+++ b/drivers/net/netdevsim/netdevsim.h
@@ -121,6 +121,8 @@ struct netdevsim {
u64_stats_t tx_bytes;
struct u64_stats_sync syncp;
struct psp_dev *dev;
+ struct dentry *rereg;
+ struct mutex rereg_lock;
u32 spi;
u32 assoc_cnt;
} psp;
diff --git a/drivers/net/netdevsim/psp.c b/drivers/net/netdevsim/psp.c
index 0b4d717253b0..86d84b7e566b 100644
--- a/drivers/net/netdevsim/psp.c
+++ b/drivers/net/netdevsim/psp.c
@@ -209,13 +209,20 @@ static struct psp_dev_caps nsim_psp_caps = {
.assoc_drv_spc = sizeof(void *),
};
-void nsim_psp_uninit(struct netdevsim *ns)
+static void __nsim_psp_uninit(struct netdevsim *ns)
{
if (!IS_ERR(ns->psp.dev))
psp_dev_unregister(ns->psp.dev);
WARN_ON(ns->psp.assoc_cnt);
}
+void nsim_psp_uninit(struct netdevsim *ns)
+{
+ debugfs_remove(ns->psp.rereg);
+ mutex_destroy(&ns->psp.rereg_lock);
+ __nsim_psp_uninit(ns);
+}
+
static ssize_t
nsim_psp_rereg_write(struct file *file, const char __user *data, size_t count,
loff_t *ppos)
@@ -223,11 +230,13 @@ nsim_psp_rereg_write(struct file *file, const char __user *data, size_t count,
struct netdevsim *ns = file->private_data;
int err;
- nsim_psp_uninit(ns);
+ mutex_lock(&ns->psp.rereg_lock);
+ __nsim_psp_uninit(ns);
ns->psp.dev = psp_dev_create(ns->netdev, &nsim_psp_ops,
&nsim_psp_caps, ns);
err = PTR_ERR_OR_ZERO(ns->psp.dev);
+ mutex_unlock(&ns->psp.rereg_lock);
return err ?: count;
}
@@ -249,6 +258,8 @@ int nsim_psp_init(struct netdevsim *ns)
if (err)
return err;
- debugfs_create_file("psp_rereg", 0200, ddir, ns, &nsim_psp_rereg_fops);
+ mutex_init(&ns->psp.rereg_lock);
+ ns->psp.rereg = debugfs_create_file("psp_rereg", 0200, ddir, ns,
+ &nsim_psp_rereg_fops);
return 0;
}
--
2.52.0
^ permalink raw reply related
* [PATCH net 1/3] netdevsim: psp: only call nsim_psp_uninit() on PFs
From: Daniel Zahka @ 2026-05-05 10:42 UTC (permalink / raw)
To: Jakub Kicinski, Andrew Lunn, David S. Miller, Eric Dumazet,
Paolo Abeni, Willem de Bruijn, Willem de Bruijn
Cc: netdev, linux-kernel
In-Reply-To: <20260505-psd-rcu-v1-0-a8f69ec1ab96@gmail.com>
VFs go through nsim_init_netdevsim_vf() which never calls
nsim_psp_init(), so ns->psp.dev stays NULL. nsim_psp_uninit() guards
with !IS_ERR(ns->psp.dev), so destroying a VF reaches
psp_dev_unregister(NULL) and dereferences NULL on the first
mutex_lock(&psd->lock):
BUG: kernel NULL pointer dereference, address: 0000000000000020
RIP: 0010:mutex_lock+0x1c/0x30
Call Trace:
psp_dev_unregister+0x2a/0x1a0
nsim_psp_uninit+0x1f/0x40 [netdevsim]
nsim_destroy+0x61/0x1e0 [netdevsim]
__nsim_dev_port_del+0x47/0x90 [netdevsim]
nsim_drv_configure_vfs+0xc9/0x130 [netdevsim]
nsim_bus_dev_numvfs_store+0x79/0xb0 [netdevsim]
Gate nsim_psp_uninit() on nsim_dev_port_is_pf(), matching the pattern
already used for nsim_exit_netdevsim() and the bpf/ipsec/macsec/queue
teardowns.
Reproducer:
modprobe netdevsim
echo "10 1" > /sys/bus/netdevsim/new_device
echo 1 > /sys/bus/netdevsim/devices/netdevsim10/sriov_numvfs
devlink dev eswitch set netdevsim/netdevsim10 mode switchdev
echo 0 > /sys/bus/netdevsim/devices/netdevsim10/sriov_numvfs
Fixes: f857478d6206 ("netdevsim: a basic test PSP implementation")
Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com>
---
drivers/net/netdevsim/netdev.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
index a05af192caf3..a750768912b5 100644
--- a/drivers/net/netdevsim/netdev.c
+++ b/drivers/net/netdevsim/netdev.c
@@ -1182,7 +1182,8 @@ void nsim_destroy(struct netdevsim *ns)
unregister_netdevice_notifier_dev_net(ns->netdev, &ns->nb,
&ns->nn);
- nsim_psp_uninit(ns);
+ if (nsim_dev_port_is_pf(ns->nsim_dev_port))
+ nsim_psp_uninit(ns);
rtnl_lock();
peer = rtnl_dereference(ns->peer);
--
2.52.0
^ permalink raw reply related
* [PATCH net 0/3] netdevsim: psp: fix init and uninit bugs
From: Daniel Zahka @ 2026-05-05 10:42 UTC (permalink / raw)
To: Jakub Kicinski, Andrew Lunn, David S. Miller, Eric Dumazet,
Paolo Abeni, Willem de Bruijn, Willem de Bruijn
Cc: netdev, linux-kernel
This series has three fixes. The first is a straightforward NULL
pointer dereference that is reachable by creating and destroying some
vfs on a kernel with INET_PSP enabled.
The last two patches deal with nsim_psp_rereg_write(), which is a
debugfs handler that reregisters netdevsim's psp_dev without
aquiescing and disabling tx/rx processing. This was added to enable
some tests in psp.py where a psp device is unregistered while it still
referenced by tcp socket state.
There are two issues with this code:
1. Calls to nsim_psp_uninit() are not properly serialized
2. netdevsim's psp_dev refcount can be released while nsim_do_psp() is
reading from it.
Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com>
---
Daniel Zahka (3):
netdevsim: psp: only call nsim_psp_uninit() on PFs
netdevsim: psp: serialize calls to nsim_psp_uninit()
netdevsim: psp: rcu protect psp_dev reference
drivers/net/netdevsim/netdev.c | 3 +-
drivers/net/netdevsim/netdevsim.h | 4 ++-
drivers/net/netdevsim/psp.c | 65 +++++++++++++++++++++++++++------------
3 files changed, 51 insertions(+), 21 deletions(-)
---
base-commit: 07d99587396024932e02474c3a5bede71d108454
change-id: 20260504-psd-rcu-aea28e0e2c14
Best regards,
--
Daniel Zahka <daniel.zahka@gmail.com>
^ permalink raw reply
* Re: [PATCH v4 3/3 omap] ARM: dts: omap2: add stlc4560 spi-wireless node
From: Linus Walleij @ 2026-05-05 10:41 UTC (permalink / raw)
To: Arnd Bergmann
Cc: netdev, Arnd Bergmann, Aaro Koskinen, Andreas Kemnade,
Bartosz Golaszewski, Benoît Cousson, David S. Miller,
Dmitry Torokhov, Eric Dumazet, Felipe Balbi, Jakub Kicinski,
Johannes Berg, Kevin Hilman, Krzysztof Kozlowski, Paolo Abeni,
Rob Herring, Roger Quadros, Tony Lindgren, linux-wireless,
devicetree, linux-kernel, linux-arm-kernel, linux-gpio,
linux-omap, Krzysztof Kozlowski
In-Reply-To: <20260430081242.3686993-4-arnd@kernel.org>
On Thu, Apr 30, 2026 at 10:13 AM Arnd Bergmann <arnd@kernel.org> wrote:
> From: Arnd Bergmann <arnd@arndb.de>
>
> Converted from the platform_device creation in board-n8x0.c.
>
> Link: https://lore.kernel.org/all/20230314163201.955689-1-arnd@kernel.org/
> Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Reviewed-by: Linus Walleij <linusw@kernel.org>
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH v4 2/3 net-next] p54spi: convert to devicetree
From: Linus Walleij @ 2026-05-05 10:37 UTC (permalink / raw)
To: Arnd Bergmann
Cc: netdev, Arnd Bergmann, Aaro Koskinen, Andreas Kemnade,
Bartosz Golaszewski, Benoît Cousson, David S. Miller,
Dmitry Torokhov, Eric Dumazet, Felipe Balbi, Jakub Kicinski,
Johannes Berg, Kevin Hilman, Krzysztof Kozlowski, Paolo Abeni,
Rob Herring, Roger Quadros, Tony Lindgren, linux-wireless,
devicetree, linux-kernel, linux-arm-kernel, linux-gpio,
linux-omap, Christian Lamparter
In-Reply-To: <20260430081242.3686993-3-arnd@kernel.org>
On Thu, Apr 30, 2026 at 10:13 AM Arnd Bergmann <arnd@kernel.org> wrote:
> From: Arnd Bergmann <arnd@arndb.de>
>
> The Prism54 SPI driver hardcodes GPIO numbers and expects users to
> pass them as module parameters, apparently a relic from its life as a
> staging driver. This works because there is only one user, the Nokia
> N8x0 tablet.
>
> Convert this to the gpio descriptor interface and DT based probing
> to improve this and simplify the code at the same time.
>
> Acked-by: Christian Lamparter <chunkeey@gmail.com>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Reviewed-by: Linus Walleij <linusw@kernel.org>
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH net] net: usb: asix: ax88772: re-add usbnet_link_change() in phylink callbacks
From: Baier, Markus @ 2026-05-05 10:33 UTC (permalink / raw)
To: patchwork-bot+netdevbpf@kernel.org
Cc: o.rempel@pengutronix.de, andrew+netdev@lunn.ch,
davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
pabeni@redhat.com, linux@armlinux.org.uk, enelsonmoore@gmail.com,
linmq006@gmail.com, linux-usb@vger.kernel.org,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <177794760791.1391894.7472938774024727243.git-patchwork-notify@kernel.org>
Hello,
for your information, the current version of the patch goes a bit too far,
as using the "usbnet_link_change" function in this context.
called from the "mac_link_up" or "mac_link_down" functions, works but
is not ideal.
With Oleksij's help, I have since been able to create a new patch
that specifically enables or disables only the RX URB submission.
I will submit the new patch as v2 of the current patch later today
or tomorrow at the latest.
I have completed testing of the new patch, and the results were positive.
PS: Sorry that I sent the first email in HTML format
Best regards
Markus
Von: patchwork-bot+netdevbpf@kernel.org <patchwork-bot+netdevbpf@kernel.org>
Gesendet: Dienstag, 5. Mai 2026 04:20:07
An: Baier, Markus
Cc: o.rempel@pengutronix.de; andrew+netdev@lunn.ch; davem@davemloft.net; edumazet@google.com; kuba@kernel.org; pabeni@redhat.com; linux@armlinux.org.uk; enelsonmoore@gmail.com; linmq006@gmail.com; linux-usb@vger.kernel.org; netdev@vger.kernel.org; linux-kernel@vger.kernel.org
Betreff: Re: [PATCH net] net: usb: asix: ax88772: re-add usbnet_link_change() in phylink callbacks
Hello:
This patch was applied to netdev/net.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Fri, 1 May 2026 18:39:41 +0200 you wrote:
> Commit e0bffe3e6894 ("net: asix: ax88772: migrate to phylink") replaced
> the asix_adjust_link() PHY callback with phylink's mac_link_up() and
> mac_link_down() handlers, but did not carry over the usbnet_link_change()
> notification that commit 805206e66fab ("net: asix: fix "can't send until
> first packet is send" issue") had added.
>
> As a result, the original symptom returns: when the link comes up,
> usbnet is never notified, so the RX URB submission stays dormant until
> some other event (e.g. a transmitted packet triggering the status
> endpoint interrupt) wakes it up.
>
> [...]
Here is the summary with links:
- [net] net: usb: asix: ax88772: re-add usbnet_link_change() in phylink callbacks
https://git.kernel.org/netdev/net/c/36bdc0e815b4
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply
* Re: [PATCH] vsock/virtio: fix vsockmon info leak in non-linear tap copy
From: Paolo Abeni @ 2026-05-05 10:26 UTC (permalink / raw)
To: sgarzare, stefanha
Cc: netdev, linux-kernel, mst, jasowang, xuanzhuo, eperezma, davem,
edumazet, kuba, horms, Yiqi Sun, kvm, virtualization
In-Reply-To: <20260430071110.380509-1-sunyiqixm@gmail.com>
On 4/30/26 9:11 AM, Yiqi Sun wrote:
> vsockmon mirrors packets through virtio_transport_build_skb(), which
> builds a new skb and copies the payload into it. For non-linear skbs,
> this goes through virtio_transport_copy_nonlinear_skb().
>
> Helper manually initializes a iov_iter, but leaves iov_iter.count unset.
> As a result, skb_copy_datagram_iter() sees zero writable bytes
> in the destination iterator and copies no payload data.
>
> This becomes an info leak because virtio_transport_build_skb() has
> already reserved payload_len bytes in the new skb with skb_put(). The
> skb is then returned to the tap path with that payload area still
> uninitialized, so userspace reading from a vsockmon device can observe
> heap contents and potentially kernel address.
>
> Fix it by initializing iov_iter.count to the number of bytes to copy.
>
> Fixes: 4b0bf10eb077 ("vsock/virtio: non-linear skb handling for tap")
> Signed-off-by: Yiqi Sun <sunyiqixm@gmail.com>
> ---
> net/vmw_vsock/virtio_transport_common.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c
> index 416d533f493d..6b26ee57ccab 100644
> --- a/net/vmw_vsock/virtio_transport_common.c
> +++ b/net/vmw_vsock/virtio_transport_common.c
> @@ -152,7 +152,7 @@ static void virtio_transport_copy_nonlinear_skb(const struct sk_buff *skb,
> iov_iter.nr_segs = 1;
>
> to_copy = min_t(size_t, len, skb->len);
> -
> + iov_iter.count = to_copy;
> skb_copy_datagram_iter(skb, VIRTIO_VSOCK_SKB_CB(skb)->offset,
> &iov_iter, to_copy);
@Stefano, @Stefan, the patch LGTM, but sashiko pointed out to a
pre-existing issue you should probably want to address:
> to_copy = min_t(size_t, len, skb->len);
Does this length calculation account for the offset when a packet is
split across multiple transmissions?
If a packet is requeued, VIRTIO_VSOCK_SKB_CB(skb)->offset is increased,
but to_copy still evaluates to the full length of the skb.
/P
^ permalink raw reply
* Re: [PATCH 0/3] net: mana: Fix mana_destroy_rxq() cleanup for partial RXQ init
From: patchwork-bot+netdevbpf @ 2026-05-05 10:20 UTC (permalink / raw)
To: Dipayaan Roy
Cc: kys, haiyangz, wei.liu, decui, andrew+netdev, davem, edumazet,
kuba, pabeni, leon, longli, kotaranov, horms, shradhagupta,
ssengar, ernis, shirazsaleem, linux-hyperv, netdev, linux-kernel,
linux-rdma, stephen, jacob.e.keller, dipayanroy, leitao, kees,
john.fastabend, hawk, bpf, daniel, ast, sdf, yury.norov
In-Reply-To: <20260430035935.1859220-1-dipayanroy@linux.microsoft.com>
Hello:
This series was applied to netdev/net.git (main)
by Paolo Abeni <pabeni@redhat.com>:
On Wed, 29 Apr 2026 20:57:51 -0700 you wrote:
> When mana_create_rxq() fails partway through initialization (e.g. the
> hardware rejects the WQ object creation), the error path calls
> mana_destroy_rxq() to tear down a partially-initialized RXQ.
> This exposed multiple issues in mana_destroy_rxq() path, as it assumed
> the RXQ was always fully initialized, leading to multiple issues:
>
> 1. xdp_rxq_info_unreg() was called on an unregistered xdp_rxq,
> triggering a WARN_ON ("Driver BUG") in net/core/xdp.c.
>
> [...]
Here is the summary with links:
- [1/3] net: mana: check xdp_rxq registration before unreg in mana_destroy_rxq()
https://git.kernel.org/netdev/net/c/e9e334f8063a
- [2/3] net: mana: Skip WQ object destruction for uninitialized RXQ
https://git.kernel.org/netdev/net/c/2a1c69118282
- [3/3] net: mana: remove double CQ cleanup in mana_create_rxq error path
https://git.kernel.org/netdev/net/c/3985c9a56da4
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox