Netdev List
 help / color / mirror / Atom feed
* [PATCH net 1/3] nfc: llcp: add TLV length bounds checks in parse_gb_tlv and parse_connection_tlv
From: Lekë Hapçiu @ 2026-04-09 23:35 UTC (permalink / raw)
  To: netdev
  Cc: linux-nfc, stable, davem, edumazet, kuba, pabeni,
	Lekë Hapçiu, Simon Horman
In-Reply-To: <20260409233517.1891497-1-snowwlake@icloud.com>

v1 of this fix promoted `offset` from u8 to u16 in both TLV parsers,
preventing the infinite loop when a connection TLV array exceeds 255 bytes.
During review, Simon Horman identified two additional issues that the u16
promotion alone does not address.

Issue 1 - truncated TLV header:

  The loop guard `offset < tlv_array_len` is not sufficient to guarantee
  that reading tlv[0] (type) and tlv[1] (length) is safe.  When exactly
  one byte remains (offset == tlv_array_len - 1) the loop body reads
  tlv[1] one byte past the end of the array.

Issue 2 - peer-controlled `length` field:

  `length` is read from peer-supplied frame data and is not checked against
  the remaining array space before advancing `tlv` and `offset`:

    offset += length + 2;   /* always */
    tlv    += length + 2;   /* may now point past buffer end */

  A crafted `length` advances `tlv` past the array boundary; the following
  iteration reads tlv[0]/tlv[1] from adjacent kernel memory.

  For nfc_llcp_parse_gb_tlv() this is particularly impactful: its input is
  &local->remote_gb[3], a field within nfc_llcp_local.  A large `length`
  can walk `tlv` into adjacent struct fields including sdreq_timer and
  sdreq_timeout_work which contain kernel function pointers at approximately
  +176 and +216 bytes past remote_gb[].  The parsed `type` byte at those
  positions may match a recognized TLV type causing the parser to store
  bytes from the function pointer into local->remote_miu, which is
  subsequently readable via getsockopt().

Issue 3 - zero-length TLV value:

  The llcp_tlv8() and llcp_tlv16() accessor helpers read tlv[2] and
  tlv[2..3] respectively.  The outer guard guarantees `length` bytes of
  value are available past the two-byte header, but when length == 0 it
  only guarantees offset+2 <= tlv_array_len (non-strict), leaving tlv[2]
  out of bounds.  Per-type minimum-length checks are required before each
  accessor call.  Note: llcp_tlv8/16 additionally validate against the
  llcp_tlv_length[] table, providing a second safety layer; the per-type
  checks here make the rejection explicit and avoid silent zero-defaults.

Fix: add two loop-level guards inside each parsing loop:

  if (tlv_array_len - offset < 2)            /* need type + length */
      break;
  [read type, length]
  if (tlv_array_len - offset - 2 < length)   /* need length value bytes */
      break;

Both subtractions are safe: the loop condition guarantees offset <
tlv_array_len; the first guard then guarantees the difference is >= 2,
making the second subtraction non-negative.

Add per-type minimum-length checks before each accessor call:
  - tlv8-based (VERSION, LTO, OPT, RW): require length >= 1
  - tlv16-based (MIUX, WKS):            require length >= 2

Reachability: nfc_llcp_parse_connection_tlv() is reached on receipt of a
CONNECT or CC PDU before any connection is established.
nfc_llcp_parse_gb_tlv() is reached during ATR_RES processing.  Both are
triggerable from any NFC peer within ~4 cm with no authentication.

Reported-by: Simon Horman <horms@kernel.org>
Fixes: d646960f7986 ("NFC: Add LLCP sockets")
Cc: stable@vger.kernel.org
Signed-off-by: Lekë Hapçiu <snowwlake@icloud.com>
---
 net/nfc/llcp_commands.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/net/nfc/llcp_commands.c b/net/nfc/llcp_commands.c
index 6937dcb3b..7cc237a6d 100644
--- a/net/nfc/llcp_commands.c
+++ b/net/nfc/llcp_commands.c
@@ -202,25 +202,39 @@ int nfc_llcp_parse_gb_tlv(struct nfc_llcp_local *local,
 		return -ENODEV;
 
 	while (offset < tlv_array_len) {
+		if (tlv_array_len - offset < 2)
+			break;
 		type = tlv[0];
 		length = tlv[1];
+		if (tlv_array_len - offset - 2 < length)
+			break;
 
 		pr_debug("type 0x%x length %d\n", type, length);
 
 		switch (type) {
 		case LLCP_TLV_VERSION:
+			if (length < 1)
+				break;
 			local->remote_version = llcp_tlv_version(tlv);
 			break;
 		case LLCP_TLV_MIUX:
+			if (length < 2)
+				break;
 			local->remote_miu = llcp_tlv_miux(tlv) + 128;
 			break;
 		case LLCP_TLV_WKS:
+			if (length < 2)
+				break;
 			local->remote_wks = llcp_tlv_wks(tlv);
 			break;
 		case LLCP_TLV_LTO:
+			if (length < 1)
+				break;
 			local->remote_lto = llcp_tlv_lto(tlv) * 10;
 			break;
 		case LLCP_TLV_OPT:
+			if (length < 1)
+				break;
 			local->remote_opt = llcp_tlv_opt(tlv);
 			break;
 		default:
@@ -253,16 +267,24 @@ int nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock,
 		return -ENOTCONN;
 
 	while (offset < tlv_array_len) {
+		if (tlv_array_len - offset < 2)
+			break;
 		type = tlv[0];
 		length = tlv[1];
+		if (tlv_array_len - offset - 2 < length)
+			break;
 
 		pr_debug("type 0x%x length %d\n", type, length);
 
 		switch (type) {
 		case LLCP_TLV_MIUX:
+			if (length < 2)
+				break;
 			sock->remote_miu = llcp_tlv_miux(tlv) + 128;
 			break;
 		case LLCP_TLV_RW:
+			if (length < 1)
+				break;
 			sock->remote_rw = llcp_tlv_rw(tlv);
 			break;
 		case LLCP_TLV_SN:
-- 
2.51.0


^ permalink raw reply related

* [PATCH net 0/3] nfc: llcp: fix OOB reads in TLV parsers and PDU handlers
From: Lekë Hapçiu @ 2026-04-09 23:35 UTC (permalink / raw)
  To: netdev
  Cc: linux-nfc, stable, davem, edumazet, kuba, pabeni,
	Lekë Hapçiu

This series fixes three out-of-bounds read vulnerabilities in the NFC
LLCP layer, all reachable from RF without prior pairing or session
establishment.

Patch 1 adds missing TLV length bounds checks in nfc_llcp_parse_gb_tlv()
and nfc_llcp_parse_connection_tlv() — a crafted CONNECT or SNL PDU
containing a short TLV value field can read beyond the skb tail.

Patch 2 fixes nfc_llcp_recv_snl(), which accessed TLV fields and
performed arithmetic on an uncapped length byte before any bounds
check, enabling a 1-byte heap OOB read and a u8 wrap-around.

Patch 3 fixes nfc_llcp_recv_dm(), which read the DM reason byte at
skb->data[2] without verifying the frame is at least 3 bytes long.
A 2-byte DM PDU (header only) from a rogue peer triggers a 1-byte
OOB heap read.

All three bugs are independently triggered via RF (AV:A, AC:L, no
authentication required).

Lekë Hapçiu (3):
  nfc: llcp: add TLV length bounds checks in parse_gb_tlv and
    parse_connection_tlv
  nfc: llcp: fix TLV parsing OOB and length underflow in
    nfc_llcp_recv_snl
  nfc: llcp: fix OOB read of DM reason byte in nfc_llcp_recv_dm()

 net/nfc/llcp_commands.c |  9 ++++++++-
 net/nfc/llcp_core.c     | 22 ++++++++++++++++++++++
 2 files changed, 30 insertions(+), 1 deletion(-)

--
2.34.1

^ permalink raw reply

* Re: [PATCH RFC net-next 02/10] net: stmmac: rename dev_id to userver
From: Jitendra Vegiraju @ 2026-04-09 23:07 UTC (permalink / raw)
  To: Russell King (Oracle)
  Cc: Andrew Lunn, Alexandre Torgue, Andrew Lunn, Chen-Yu Tsai,
	David S. Miller, Eric Dumazet, Jakub Kicinski, linux-arm-kernel,
	linux-stm32, linux-sunxi, netdev, Paolo Abeni, Samuel Holland
In-Reply-To: <E1wAPBR-0000000F7ju-1fD9@rmk-PC.armlinux.org.uk>

[-- Attachment #1: Type: text/plain, Size: 4607 bytes --]

Hi Russell,

On Wed, Apr 8, 2026 at 2:27 AM Russell King (Oracle)
<rmk+kernel@armlinux.org.uk> wrote:
>
> The Synopsys Databook and several implementation TRMs identify bits
> 15:8 of the version register in dwmac v3.xx and v4.xx as "userver".
> We even print its value with "User ID". Rather than using "dev_id",
> use "userver" instead.
>
> Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
> ---
>  drivers/net/ethernet/stmicro/stmmac/hwif.c | 18 +++++++++---------
>  1 file changed, 9 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c
> index 3774af66db48..830ff816ab4f 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/hwif.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c
> @@ -15,7 +15,7 @@
>
>  struct stmmac_version {
>         u8 snpsver;
> -       u8 dev_id;
> +       u8 userver;
>  };
From the XGMAC databook that I have access to bits(15:8) identify the
DEVID field of MAC_version register.
The userver field is from bits(23:16) of the same register. This is a
customer defined field (configured with coreConsultant).
Currently stmmac doesn't care about bits(23:16).

I think the confusion is coming from macro name in common.h
#define DWMAC_USERVER   GENMASK_U32(15, 8)
This should be named
#define DWMAC_DEVID   GENMASK_U32(15, 8)
Hope someone with access to another databook can confirm this.

>
>  static void stmmac_get_version(struct stmmac_priv *priv,
> @@ -26,7 +26,7 @@ static void stmmac_get_version(struct stmmac_priv *priv,
>         u32 version;
>
>         ver->snpsver = 0;
> -       ver->dev_id = 0;
> +       ver->userver = 0;
>
>         if (core_type == DWMAC_CORE_MAC100)
>                 return;
> @@ -48,7 +48,7 @@ static void stmmac_get_version(struct stmmac_priv *priv,
>
>         ver->snpsver = FIELD_GET(DWMAC_SNPSVER, version);
>         if (core_type == DWMAC_CORE_XGMAC)
> -               ver->dev_id = FIELD_GET(DWMAC_USERVER, version);
> +               ver->userver = FIELD_GET(DWMAC_USERVER, version);
>  }
>
>  static void stmmac_dwmac_mode_quirk(struct stmmac_priv *priv)
> @@ -111,7 +111,7 @@ int stmmac_reset(struct stmmac_priv *priv)
>  static const struct stmmac_hwif_entry {
>         enum dwmac_core_type core_type;
>         u32 min_snpsver;
> -       u32 dev_id;
> +       u32 userver;
>         const struct stmmac_regs_off regs;
>         const void *desc;
>         const void *dma;
> @@ -247,7 +247,7 @@ static const struct stmmac_hwif_entry {
>         }, {
>                 .core_type = DWMAC_CORE_XGMAC,
>                 .min_snpsver = DWXGMAC_CORE_2_10,
> -               .dev_id = DWXGMAC_ID,
> +               .userver = DWXGMAC_ID,
>                 .regs = {
>                         .ptp_off = PTP_XGMAC_OFFSET,
>                         .mmc_off = MMC_XGMAC_OFFSET,
> @@ -269,7 +269,7 @@ static const struct stmmac_hwif_entry {
>         }, {
>                 .core_type = DWMAC_CORE_XGMAC,
>                 .min_snpsver = DWXLGMAC_CORE_2_00,
> -               .dev_id = DWXLGMAC_ID,
> +               .userver = DWXLGMAC_ID,
>                 .regs = {
>                         .ptp_off = PTP_XGMAC_OFFSET,
>                         .mmc_off = MMC_XGMAC_OFFSET,
> @@ -291,7 +291,7 @@ static const struct stmmac_hwif_entry {
>  };
>
>  static const struct stmmac_hwif_entry *
> -stmmac_hwif_find(enum dwmac_core_type core_type, u8 snpsver, u8 dev_id)
> +stmmac_hwif_find(enum dwmac_core_type core_type, u8 snpsver, u8 userver)
>  {
>         const struct stmmac_hwif_entry *entry;
>         int i;
> @@ -305,7 +305,7 @@ stmmac_hwif_find(enum dwmac_core_type core_type, u8 snpsver, u8 dev_id)
>                 if (snpsver < entry->min_snpsver)
>                         continue;
>                 if (core_type == DWMAC_CORE_XGMAC &&
> -                   dev_id != entry->dev_id)
> +                   userver != entry->userver)
>                         continue;
>
>                 return entry;
> @@ -358,7 +358,7 @@ int stmmac_hwif_init(struct stmmac_priv *priv)
>         /* Fallback to generic HW */
>
>         /* Use synopsys_id var because some setups can override this */
> -       entry = stmmac_hwif_find(core_type, priv->synopsys_id, version.dev_id);
> +       entry = stmmac_hwif_find(core_type, priv->synopsys_id, version.userver);
>         if (!entry) {
>                 dev_err(priv->device,
>                         "Failed to find HW IF (id=0x%x, gmac=%d/%d)\n",
> --
> 2.47.3
>

[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 5435 bytes --]

^ permalink raw reply

* [PATCH net] selftests: netfilter: nft_tproxy.sh: adjust to socat changes
From: Florian Westphal @ 2026-04-09 22:45 UTC (permalink / raw)
  To: netdev; +Cc: Florian Westphal, Jakub Kicinski

Like e65d8b6f3092 ("selftests: drv-net: adjust to socat changes") we
need to add shut-none for this test too.

The extra 0-packet can trigger a second (unexpected) reply from the server.

Fixes: 7e37e0eacd22 ("selftests: netfilter: nft_tproxy.sh: add tcp tests")
Reported-by: Jakub Kicinski <kuba@kernel.org>
Closes: https://lore.kernel.org/netdev/20260408152432.24b8ad0d@kernel.org/
Suggested-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Florian Westphal <fw@strlen.de>
---
 I'll leave it up to netdev maintainers to apply this to net-next
 instead.

 .../selftests/net/netfilter/nft_tproxy_udp.sh      | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/tools/testing/selftests/net/netfilter/nft_tproxy_udp.sh b/tools/testing/selftests/net/netfilter/nft_tproxy_udp.sh
index d16de13fe5a7..1dc7b0450145 100755
--- a/tools/testing/selftests/net/netfilter/nft_tproxy_udp.sh
+++ b/tools/testing/selftests/net/netfilter/nft_tproxy_udp.sh
@@ -190,13 +190,13 @@ table inet filter {
 }
 EOF
 
-	timeout "$timeout" ip netns exec "$nsrouter" socat -u "$socat_ipproto" udp-listen:12345,fork,ip-transparent,reuseport udp:"$ns1_ip_port",ip-transparent,reuseport,bind="$ns2_ip_port" 2>/dev/null &
+	timeout "$timeout" ip netns exec "$nsrouter" socat -u "$socat_ipproto" udp-listen:12345,fork,ip-transparent,reuseport,shut-none udp:"$ns1_ip_port",ip-transparent,reuseport,bind="$ns2_ip_port",shut-none 2>/dev/null &
 	local tproxy_pid=$!
 
-	timeout "$timeout" ip netns exec "$ns2" socat "$socat_ipproto" udp-listen:8080,fork SYSTEM:"echo PONG_NS2" 2>/dev/null &
+	timeout "$timeout" ip netns exec "$ns2" socat "$socat_ipproto" udp-listen:8080,fork,shut-none SYSTEM:"echo PONG_NS2" 2>/dev/null &
 	local server2_pid=$!
 
-	timeout "$timeout" ip netns exec "$ns3" socat "$socat_ipproto" udp-listen:8080,fork SYSTEM:"echo PONG_NS3" 2>/dev/null &
+	timeout "$timeout" ip netns exec "$ns3" socat "$socat_ipproto" udp-listen:8080,fork,shut-none SYSTEM:"echo PONG_NS3" 2>/dev/null &
 	local server3_pid=$!
 
 	busywait "$BUSYWAIT_TIMEOUT" listener_ready "$nsrouter" 12345 "-u"
@@ -205,7 +205,7 @@ EOF
 
 	local result
 	# request from ns1 to ns2 (forwarded traffic)
-	result=$(echo I_M_PROXIED | ip netns exec "$ns1" socat -t 2 -T 2 STDIO udp:"$ns2_ip_port",sourceport=18888)
+	result=$(echo I_M_PROXIED | ip netns exec "$ns1" socat -t 2 -T 2 STDIO udp:"$ns2_ip_port",sourceport=18888,shut-none)
 	if [ "$result" == "$expect_ns1_ns2" ] ;then
 		echo "PASS: tproxy test $testname: ns1 got reply \"$result\" connecting to ns2"
 	else
@@ -214,7 +214,7 @@ EOF
 	fi
 
 	# request from ns1 to ns3 (forwarded traffic)
-	result=$(echo I_M_PROXIED | ip netns exec "$ns1" socat -t 2 -T 2 STDIO udp:"$ns3_ip_port")
+	result=$(echo I_M_PROXIED | ip netns exec "$ns1" socat -t 2 -T 2 STDIO udp:"$ns3_ip_port",shut-none)
 	if [ "$result" = "$expect_ns1_ns3" ] ;then
 		echo "PASS: tproxy test $testname: ns1 got reply \"$result\" connecting to ns3"
 	else
@@ -223,7 +223,7 @@ EOF
 	fi
 
 	# request from nsrouter to ns2 (localy originated traffic)
-	result=$(echo I_M_PROXIED | ip netns exec "$nsrouter" socat -t 2 -T 2 STDIO udp:"$ns2_ip_port")
+	result=$(echo I_M_PROXIED | ip netns exec "$nsrouter" socat -t 2 -T 2 STDIO udp:"$ns2_ip_port",shut-none)
 	if [ "$result" == "$expect_nsrouter_ns2" ] ;then
 		echo "PASS: tproxy test $testname: nsrouter got reply \"$result\" connecting to ns2"
 	else
@@ -232,7 +232,7 @@ EOF
 	fi
 
 	# request from nsrouter to ns3 (localy originated traffic)
-	result=$(echo I_M_PROXIED | ip netns exec "$nsrouter" socat -t 2 -T 2 STDIO udp:"$ns3_ip_port")
+	result=$(echo I_M_PROXIED | ip netns exec "$nsrouter" socat -t 2 -T 2 STDIO udp:"$ns3_ip_port",shut-none)
 	if [ "$result" = "$expect_nsrouter_ns3" ] ;then
 		echo "PASS: tproxy test $testname: nsrouter got reply \"$result\" connecting to ns3"
 	else
-- 
2.52.0


^ permalink raw reply related

* Re: [PATCH v2 1/2] drm/drm_ras: Add clear-error-counter netlink command to drm_ras
From: Zack McKevitt @ 2026-04-09 23:01 UTC (permalink / raw)
  To: Tauro, Riana, intel-xe, dri-devel, netdev, rodrigo.vivi,
	joonas.lahtinen, aravind.iddamsetty
  Cc: anshuman.gupta, simona.vetter, airlied, pratik.bari,
	joshua.santosh.ranjan, ashwin.kumar.kulkarni, shubham.kumar,
	ravi.kishore.koppuravuri, raag.jadav, anvesh.bakwad,
	maarten.lankhorst, Jakub Kicinski, Lijo Lazar, Hawking Zhang,
	David S. Miller, Paolo Abeni, Eric Dumazet
In-Reply-To: <e7978696-eff6-4c1f-ab0f-047dccb18b59@intel.com>


On 4/9/2026 1:21 AM, Tauro, Riana wrote:
> Hi Zack
> 
> Could you please take a look at this patch if applicable to your 
> usecase. Please let me know if any
> changes are required
> 

 From a quick glance, I think this looks good from our end.

Thanks,
Zack

> @Rodrigo This is already reviewed by Jakub and Raag.
> If there are no opens, can this be merged via drm_misc
> 
> Thanks
> Riana
> 
> On 4/9/2026 1:03 PM, Riana Tauro wrote:
>> Introduce a new 'clear-error-counter' drm_ras command to reset the 
>> counter
>> value for a specific error counter of a given node.
>>
>> The command is a 'do' netlink request with 'node-id' and 'error-id'
>> as parameters with no response payload.
>>
>> Usage:
>>
>> $ sudo ynl --family drm_ras  --do clear-error-counter --json \
>> '{"node-id":1, "error-id":1}'
>> None
>>
>> Cc: Jakub Kicinski <kuba@kernel.org>
>> Cc: Zack McKevitt <zachary.mckevitt@oss.qualcomm.com>
>> Cc: Lijo Lazar <lijo.lazar@amd.com>
>> Cc: Hawking Zhang <Hawking.Zhang@amd.com>
>> Cc: David S. Miller <davem@davemloft.net>
>> Cc: Paolo Abeni <pabeni@redhat.com>
>> Cc: Eric Dumazet <edumazet@google.com>
>> Signed-off-by: Riana Tauro <riana.tauro@intel.com>
>> Reviewed-by: Jakub Kicinski <kuba@kernel.org>
>> Reviewed-by: Raag Jadav <raag.jadav@intel.com>
>> ---
>>   Documentation/gpu/drm-ras.rst            |  8 +++++
>>   Documentation/netlink/specs/drm_ras.yaml | 13 ++++++-
>>   drivers/gpu/drm/drm_ras.c                | 43 +++++++++++++++++++++++-
>>   drivers/gpu/drm/drm_ras_nl.c             | 13 +++++++
>>   drivers/gpu/drm/drm_ras_nl.h             |  2 ++
>>   include/drm/drm_ras.h                    | 11 ++++++
>>   include/uapi/drm/drm_ras.h               |  1 +
>>   7 files changed, 89 insertions(+), 2 deletions(-)
>>
>> diff --git a/Documentation/gpu/drm-ras.rst b/Documentation/gpu/drm- 
>> ras.rst
>> index 70b246a78fc8..4636e68f5678 100644
>> --- a/Documentation/gpu/drm-ras.rst
>> +++ b/Documentation/gpu/drm-ras.rst
>> @@ -52,6 +52,8 @@ User space tools can:
>>     as a parameter.
>>   * Query specific error counter values with the ``get-error-counter`` 
>> command, using both
>>     ``node-id`` and ``error-id`` as parameters.
>> +* Clear specific error counters with the ``clear-error-counter`` 
>> command, using both
>> +  ``node-id`` and ``error-id`` as parameters.
>>   YAML-based Interface
>>   --------------------
>> @@ -101,3 +103,9 @@ Example: Query an error counter for a given node
>>       sudo ynl --family drm_ras --do get-error-counter --json '{"node- 
>> id":0, "error-id":1}'
>>       {'error-id': 1, 'error-name': 'error_name1', 'error-value': 0}
>> +Example: Clear an error counter for a given node
>> +
>> +.. code-block:: bash
>> +
>> +    sudo ynl --family drm_ras --do clear-error-counter --json 
>> '{"node-id":0, "error-id":1}'
>> +    None
>> diff --git a/Documentation/netlink/specs/drm_ras.yaml b/Documentation/ 
>> netlink/specs/drm_ras.yaml
>> index 79af25dac3c5..e113056f8c01 100644
>> --- a/Documentation/netlink/specs/drm_ras.yaml
>> +++ b/Documentation/netlink/specs/drm_ras.yaml
>> @@ -99,7 +99,7 @@ operations:
>>         flags: [admin-perm]
>>         do:
>>           request:
>> -          attributes:
>> +          attributes: &id-attrs
>>               - node-id
>>               - error-id
>>           reply:
>> @@ -113,3 +113,14 @@ operations:
>>               - node-id
>>           reply:
>>             attributes: *errorinfo
>> +    -
>> +      name: clear-error-counter
>> +      doc: >-
>> +           Clear error counter for a given node.
>> +           The request includes the error-id and node-id of the
>> +           counter to be cleared.
>> +      attribute-set: error-counter-attrs
>> +      flags: [admin-perm]
>> +      do:
>> +        request:
>> +          attributes: *id-attrs
>> diff --git a/drivers/gpu/drm/drm_ras.c b/drivers/gpu/drm/drm_ras.c
>> index b2fa5ab86d87..d6eab29a1394 100644
>> --- a/drivers/gpu/drm/drm_ras.c
>> +++ b/drivers/gpu/drm/drm_ras.c
>> @@ -26,7 +26,7 @@
>>    * efficient lookup by ID. Nodes can be registered or unregistered
>>    * dynamically at runtime.
>>    *
>> - * A Generic Netlink family `drm_ras` exposes two main operations to
>> + * A Generic Netlink family `drm_ras` exposes the below operations to
>>    * userspace:
>>    *
>>    * 1. LIST_NODES: Dump all currently registered RAS nodes.
>> @@ -37,6 +37,10 @@
>>    *    Returns all counters of a node if only Node ID is provided or 
>> specific
>>    *    error counters.
>>    *
>> + * 3. CLEAR_ERROR_COUNTER: Clear error counter of a given node.
>> + *    Userspace must provide Node ID, Error ID.
>> + *    Clears specific error counter of a node if supported.
>> + *
>>    * Node registration:
>>    *
>>    * - drm_ras_node_register(): Registers a new node and assigns
>> @@ -66,6 +70,8 @@
>>    *   operation, fetching all counters from a specific node.
>>    * - drm_ras_nl_get_error_counter_doit(): Implements the 
>> GET_ERROR_COUNTER doit
>>    *   operation, fetching a counter value from a specific node.
>> + * - drm_ras_nl_clear_error_counter_doit(): Implements the 
>> CLEAR_ERROR_COUNTER doit
>> + *   operation, clearing a counter value from a specific node.
>>    */
>>   static DEFINE_XARRAY_ALLOC(drm_ras_xa);
>> @@ -314,6 +320,41 @@ int drm_ras_nl_get_error_counter_doit(struct 
>> sk_buff *skb,
>>       return doit_reply_value(info, node_id, error_id);
>>   }
>> +/**
>> + * drm_ras_nl_clear_error_counter_doit() - Clear an error counter of 
>> a node
>> + * @skb: Netlink message buffer
>> + * @info: Generic Netlink info containing attributes of the request
>> + *
>> + * Extracts the node ID and error ID from the netlink attributes and
>> + * clears the current value.
>> + *
>> + * Return: 0 on success, or negative errno on failure.
>> + */
>> +int drm_ras_nl_clear_error_counter_doit(struct sk_buff *skb,
>> +                    struct genl_info *info)
>> +{
>> +    struct drm_ras_node *node;
>> +    u32 node_id, error_id;
>> +
>> +    if (!info->attrs ||
>> +        GENL_REQ_ATTR_CHECK(info, 
>> DRM_RAS_A_ERROR_COUNTER_ATTRS_NODE_ID) ||
>> +        GENL_REQ_ATTR_CHECK(info, 
>> DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_ID))
>> +        return -EINVAL;
>> +
>> +    node_id = nla_get_u32(info- 
>> >attrs[DRM_RAS_A_ERROR_COUNTER_ATTRS_NODE_ID]);
>> +    error_id = nla_get_u32(info- 
>> >attrs[DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_ID]);
>> +
>> +    node = xa_load(&drm_ras_xa, node_id);
>> +    if (!node || !node->clear_error_counter)
>> +        return -ENOENT;
>> +
>> +    if (error_id < node->error_counter_range.first ||
>> +        error_id > node->error_counter_range.last)
>> +        return -EINVAL;
>> +
>> +    return node->clear_error_counter(node, error_id);
>> +}
>> +
>>   /**
>>    * drm_ras_node_register() - Register a new RAS node
>>    * @node: Node structure to register
>> diff --git a/drivers/gpu/drm/drm_ras_nl.c b/drivers/gpu/drm/drm_ras_nl.c
>> index 16803d0c4a44..dea1c1b2494e 100644
>> --- a/drivers/gpu/drm/drm_ras_nl.c
>> +++ b/drivers/gpu/drm/drm_ras_nl.c
>> @@ -22,6 +22,12 @@ static const struct nla_policy 
>> drm_ras_get_error_counter_dump_nl_policy[DRM_RAS_
>>       [DRM_RAS_A_ERROR_COUNTER_ATTRS_NODE_ID] = { .type = NLA_U32, },
>>   };
>> +/* DRM_RAS_CMD_CLEAR_ERROR_COUNTER - do */
>> +static const struct nla_policy 
>> drm_ras_clear_error_counter_nl_policy[DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_ID + 1] = {
>> +    [DRM_RAS_A_ERROR_COUNTER_ATTRS_NODE_ID] = { .type = NLA_U32, },
>> +    [DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_ID] = { .type = NLA_U32, },
>> +};
>> +
>>   /* Ops table for drm_ras */
>>   static const struct genl_split_ops drm_ras_nl_ops[] = {
>>       {
>> @@ -43,6 +49,13 @@ static const struct genl_split_ops drm_ras_nl_ops[] 
>> = {
>>           .maxattr    = DRM_RAS_A_ERROR_COUNTER_ATTRS_NODE_ID,
>>           .flags        = GENL_ADMIN_PERM | GENL_CMD_CAP_DUMP,
>>       },
>> +    {
>> +        .cmd        = DRM_RAS_CMD_CLEAR_ERROR_COUNTER,
>> +        .doit        = drm_ras_nl_clear_error_counter_doit,
>> +        .policy        = drm_ras_clear_error_counter_nl_policy,
>> +        .maxattr    = DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_ID,
>> +        .flags        = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
>> +    },
>>   };
>>   struct genl_family drm_ras_nl_family __ro_after_init = {
>> diff --git a/drivers/gpu/drm/drm_ras_nl.h b/drivers/gpu/drm/drm_ras_nl.h
>> index 06ccd9342773..a398643572a5 100644
>> --- a/drivers/gpu/drm/drm_ras_nl.h
>> +++ b/drivers/gpu/drm/drm_ras_nl.h
>> @@ -18,6 +18,8 @@ int drm_ras_nl_get_error_counter_doit(struct sk_buff 
>> *skb,
>>                         struct genl_info *info);
>>   int drm_ras_nl_get_error_counter_dumpit(struct sk_buff *skb,
>>                       struct netlink_callback *cb);
>> +int drm_ras_nl_clear_error_counter_doit(struct sk_buff *skb,
>> +                    struct genl_info *info);
>>   extern struct genl_family drm_ras_nl_family;
>> diff --git a/include/drm/drm_ras.h b/include/drm/drm_ras.h
>> index 5d50209e51db..f2a787bc4f64 100644
>> --- a/include/drm/drm_ras.h
>> +++ b/include/drm/drm_ras.h
>> @@ -58,6 +58,17 @@ struct drm_ras_node {
>>       int (*query_error_counter)(struct drm_ras_node *node, u32 error_id,
>>                      const char **name, u32 *val);
>> +    /**
>> +     * @clear_error_counter:
>> +     *
>> +     * This callback is used by drm_ras to clear a specific error 
>> counter.
>> +     * Driver should implement this callback to support clearing 
>> error counters
>> +     * of a node.
>> +     *
>> +     * Returns: 0 on success, negative error code on failure.
>> +     */
>> +    int (*clear_error_counter)(struct drm_ras_node *node, u32 error_id);
>> +
>>       /** @priv: Driver private data */
>>       void *priv;
>>   };
>> diff --git a/include/uapi/drm/drm_ras.h b/include/uapi/drm/drm_ras.h
>> index 5f40fa5b869d..218a3ee86805 100644
>> --- a/include/uapi/drm/drm_ras.h
>> +++ b/include/uapi/drm/drm_ras.h
>> @@ -41,6 +41,7 @@ enum {
>>   enum {
>>       DRM_RAS_CMD_LIST_NODES = 1,
>>       DRM_RAS_CMD_GET_ERROR_COUNTER,
>> +    DRM_RAS_CMD_CLEAR_ERROR_COUNTER,
>>       __DRM_RAS_CMD_MAX,
>>       DRM_RAS_CMD_MAX = (__DRM_RAS_CMD_MAX - 1)


^ permalink raw reply

* [PATCH net-next v2 2/2] KEYS: annotate struct user_key_payload with __counted_by
From: Thorsten Blum @ 2026-04-09 22:57 UTC (permalink / raw)
  To: David Howells, Jarkko Sakkinen, Kees Cook, Gustavo A. R. Silva
  Cc: Thorsten Blum, netdev, keyrings, linux-kernel, linux-hardening
In-Reply-To: <20260409225703.158552-4-thorsten.blum@linux.dev>

Add the __counted_by() compiler attribute to the flexible array member
'data' to improve access bounds-checking via CONFIG_UBSAN_BOUNDS and
CONFIG_FORTIFY_SOURCE.

Signed-off-by: Thorsten Blum <thorsten.blum@linux.dev>
---
Changes in v2:
- Use __aligned(8) as suggested by David
- v1: https://lore.kernel.org/lkml/20260409073711.57020-6-thorsten.blum@linux.dev/

Cc: netdev@vger.kernel.org
---
 include/keys/user-type.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/include/keys/user-type.h b/include/keys/user-type.h
index 386c31432789..c29ed9f5d300 100644
--- a/include/keys/user-type.h
+++ b/include/keys/user-type.h
@@ -27,7 +27,8 @@
 struct user_key_payload {
 	struct rcu_head	rcu;		/* RCU destructor */
 	unsigned short	datalen;	/* length of this data */
-	char		data[] __aligned(__alignof__(u64)); /* actual data */
+	char		data[]		/* actual data */
+			__aligned(8) __counted_by(datalen);
 };
 
 extern struct key_type key_type_user;

^ permalink raw reply related

* [PATCH net-next v2 1/2] keys, dns: drop unused upayload->data NUL terminator
From: Thorsten Blum @ 2026-04-09 22:57 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Thorsten Blum, Tim Bird
  Cc: netdev, linux-kernel

In dns_resolver_preparse(), do not NUL-terminate ->data and allocate one
byte less. The NUL terminator is never used and only ->datalen bytes are
accessed.

Signed-off-by: Thorsten Blum <thorsten.blum@linux.dev>
---
No changes in patch 1/2.
---
 net/dns_resolver/dns_key.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c
index c3c8c3240ef9..451247864a63 100644
--- a/net/dns_resolver/dns_key.c
+++ b/net/dns_resolver/dns_key.c
@@ -203,7 +203,7 @@ dns_resolver_preparse(struct key_preparsed_payload *prep)
 	kdebug("store result");
 	prep->quotalen = result_len;
 
-	upayload = kmalloc_flex(*upayload, data, result_len + 1);
+	upayload = kmalloc_flex(*upayload, data, result_len);
 	if (!upayload) {
 		kleave(" = -ENOMEM");
 		return -ENOMEM;
@@ -211,7 +211,6 @@ dns_resolver_preparse(struct key_preparsed_payload *prep)
 
 	upayload->datalen = result_len;
 	memcpy(upayload->data, data, result_len);
-	upayload->data[result_len] = '\0';
 
 	prep->payload.data[dns_key_data] = upayload;
 	kleave(" = 0");

^ permalink raw reply related

* Re: [PATCH] udp: Force compute_score to always inline
From: Gabriel Krisman Bertazi @ 2026-04-09 22:50 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: willemdebruijn.kernel, davem, dsahern, kuba, pabeni, kuniyu,
	horms, netdev
In-Reply-To: <CANn89iKQhLOdtn-_viyDN8ytjJtR-4p0gteXL6gGSHoUYZp5Hw@mail.gmail.com>

Eric Dumazet <edumazet@google.com> writes:

> On Thu, Apr 9, 2026 at 3:16 PM Gabriel Krisman Bertazi <krisman@suse.de> wrote:
>
>>
>> Back in 2024 I reported a 7-12% regression on an iperf3 UDP loopback
>> thoughput test that we traced to the extra overhead of calling
>> compute_score on two places, introduced by commit f0ea27e7bfe1 ("udp:
>> re-score reuseport groups when connected sockets are present").  At the
>> time, I pointed out the overhead was caused by the multiple calls,
>> associated with cpu-specific mitigations, and merged commit
>> 50aee97d1511 ("udp: Avoid call to compute_score on multiple sites") to
>> jump back explicitly, to force the rescore call in a single place.
>>
>> Recently though, we got another regression report against a newer distro
>> version, which a team colleague traced back to the same root-cause.
>> Turns out that once we updated to gcc-13, the compiler got smart enough
>> to unroll the loop, undoing my previous mitigation.  Let's bite the
>> bullet and __always_inline compute_score on both ipv4 and ipv6 to
>> prevent gcc from de-optimizing it again in the future.  These functions
>> are only called in two places each, udpX_lib_lookup1 and
>> udpX_lib_lookup2, so the extra size shouldn't be a problem and it is hot
>> enough to be very visible in profilings.  In fact, with gcc13, forcing
>> the inline will prevent gcc from unrolling the fix from commit
>> 50aee97d1511, so we don't end up increasing udpX_lib_lookup2 at all.
>>
>> I haven't recollected the results myself, as I don't have access to the
>> machine at the moment.  But the same colleague reported 4.67%
>> inprovement with this patch in the loopback benchmark, solving the
>> regression report within noise margins.
>
> You could include scripts/bloat-o-meter results, so that we can sense
> the cost of such a change.
>
> $ scripts/bloat-o-meter -t vmlinux.old vmlinux.new
> add/remove: 0/2 grow/shrink: 6/1 up/down: 622/-410 (212)
> Function                                     old     new   delta
> __udp6_lib_lookup                            797    1007    +210
> __udp4_lib_lookup                            838     984    +146
> udp6_lib_lookup2                             404     536    +132
> udp4_lib_lookup2                             396     498    +102
> udpv6_rcv                                   3018    3034     +16
> udp_init_sock                                244     260     +16
> bpf_iter_udp_batch                           953     937     -16
> __pfx_compute_score                           32       -     -32
> compute_score                                362       -    -362
> Total: Before=30269687, After=30269899, chg +0.00%
>
> No change for clang.
>
> Reviewed-by: Eric Dumazet <edumazet@google.com>

Apologies, I wasn't aware of that tool. I did some calculations by hand
and found something like 200 bytes extra in udp6_lib_lookup2.

For gcc-13:

scripts/bloat-o-meter vmlinux vmlinux-inline
add/remove: 0/2 grow/shrink: 4/0 up/down: 616/-416 (200)
Function                                     old     new   delta
udp6_lib_lookup2                             762     949    +187
__udp6_lib_lookup                            810     975    +165
udp4_lib_lookup2                             757     906    +149
__udp4_lib_lookup                            871     986    +115
__pfx_compute_score                           32       -     -32
compute_score                                384       -    -384
Total: Before=35011784, After=35011984, chg +0.00%



-- 
Gabriel Krisman Bertazi

^ permalink raw reply

* Re: [PATCH] udp: Force compute_score to always inline
From: Eric Dumazet @ 2026-04-09 22:36 UTC (permalink / raw)
  To: Gabriel Krisman Bertazi
  Cc: willemdebruijn.kernel, davem, dsahern, kuba, pabeni, kuniyu,
	horms, netdev
In-Reply-To: <20260409221532.69090-1-krisman@suse.de>

On Thu, Apr 9, 2026 at 3:16 PM Gabriel Krisman Bertazi <krisman@suse.de> wrote:
>
> Back in 2024 I reported a 7-12% regression on an iperf3 UDP loopback
> thoughput test that we traced to the extra overhead of calling
> compute_score on two places, introduced by commit f0ea27e7bfe1 ("udp:
> re-score reuseport groups when connected sockets are present").  At the
> time, I pointed out the overhead was caused by the multiple calls,
> associated with cpu-specific mitigations, and merged commit
> 50aee97d1511 ("udp: Avoid call to compute_score on multiple sites") to
> jump back explicitly, to force the rescore call in a single place.
>
> Recently though, we got another regression report against a newer distro
> version, which a team colleague traced back to the same root-cause.
> Turns out that once we updated to gcc-13, the compiler got smart enough
> to unroll the loop, undoing my previous mitigation.  Let's bite the
> bullet and __always_inline compute_score on both ipv4 and ipv6 to
> prevent gcc from de-optimizing it again in the future.  These functions
> are only called in two places each, udpX_lib_lookup1 and
> udpX_lib_lookup2, so the extra size shouldn't be a problem and it is hot
> enough to be very visible in profilings.  In fact, with gcc13, forcing
> the inline will prevent gcc from unrolling the fix from commit
> 50aee97d1511, so we don't end up increasing udpX_lib_lookup2 at all.
>
> I haven't recollected the results myself, as I don't have access to the
> machine at the moment.  But the same colleague reported 4.67%
> inprovement with this patch in the loopback benchmark, solving the
> regression report within noise margins.

You could include scripts/bloat-o-meter results, so that we can sense
the cost of such a change.

$ scripts/bloat-o-meter -t vmlinux.old vmlinux.new
add/remove: 0/2 grow/shrink: 6/1 up/down: 622/-410 (212)
Function                                     old     new   delta
__udp6_lib_lookup                            797    1007    +210
__udp4_lib_lookup                            838     984    +146
udp6_lib_lookup2                             404     536    +132
udp4_lib_lookup2                             396     498    +102
udpv6_rcv                                   3018    3034     +16
udp_init_sock                                244     260     +16
bpf_iter_udp_batch                           953     937     -16
__pfx_compute_score                           32       -     -32
compute_score                                362       -    -362
Total: Before=30269687, After=30269899, chg +0.00%

No change for clang.

Reviewed-by: Eric Dumazet <edumazet@google.com>

^ permalink raw reply

* [PATCH v3][next] netfilter: x_tables: Avoid a couple -Wflex-array-member-not-at-end warnings
From: Gustavo A. R. Silva @ 2026-04-09 22:34 UTC (permalink / raw)
  To: Pablo Neira Ayuso, Florian Westphal, Phil Sutter, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman
  Cc: netfilter-devel, coreteam, netdev, linux-kernel,
	Gustavo A. R. Silva, linux-hardening, Kees Cook

-Wflex-array-member-not-at-end was introduced in GCC-14, and we are
getting ready to enable it, globally.

Use the TRAILING_OVERLAP() helper to fix the following warnings:

1 net/netfilter/x_tables.c:816:39: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
1 net/netfilter/x_tables.c:811:39: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]

This helper creates a union between a flexible-array member (FAM)
and a set of members that would otherwise follow it. This overlays
the trailing members onto the FAM while preserving the original
memory layout.

Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
---
Changes in v3:
 - Use the TRAILING_OVERLAP() helper.
  - Update changelog text.

Changes in v2:
 - Update verdict after (compat_uint_t *)st->data;
 - Link: https://lore.kernel.org/linux-hardening/adgL5wPm9VpaV3MO@kspp/

v1:
 - Link: https://lore.kernel.org/linux-hardening/adbIKC0cZcK7VcCF@kspp/

 net/netfilter/x_tables.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index b39017c80548..9f837fb5ceb4 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -819,13 +819,17 @@ EXPORT_SYMBOL_GPL(xt_compat_match_to_user);
 
 /* non-compat version may have padding after verdict */
 struct compat_xt_standard_target {
-	struct compat_xt_entry_target t;
-	compat_uint_t verdict;
+	/* Must be last as it ends in a flexible-array member. */
+	TRAILING_OVERLAP(struct compat_xt_entry_target, t, data,
+		compat_uint_t verdict;
+	);
 };
 
 struct compat_xt_error_target {
-	struct compat_xt_entry_target t;
-	char errorname[XT_FUNCTION_MAXNAMELEN];
+	/* Must be last as it ends in a flexible-array member. */
+	TRAILING_OVERLAP(struct compat_xt_entry_target, t, data,
+		char errorname[XT_FUNCTION_MAXNAMELEN];
+	);
 };
 
 int xt_compat_check_entry_offsets(const void *base, const char *elems,
-- 
2.43.0


^ permalink raw reply related

* [PATCH net 4/4] nfc: digital: Fix OOB read of DID byte in digital_tg_recv_dep_req()
From: Lekë Hapçiu @ 2026-04-09 22:34 UTC (permalink / raw)
  To: netdev; +Cc: linux-wireless, stable, krzysztof.kozlowski,
	Lekë Hapçiu
In-Reply-To: <20260409223436.1887988-1-snowwlake@icloud.com>

digital_tg_recv_dep_req() guards against short frames with:

  if (resp->len < size ...)   /* size = sizeof(struct digital_dep_req_res) = 3 */

This guarantees resp->len >= 3 (dir + cmd + pfb).  However, when the
DID bit is set in pfb, the code immediately accesses resp->data[3] — the
DID byte — which is one byte past the guaranteed minimum:

  if (DIGITAL_NFC_DEP_DID_BIT_SET(pfb)) {
      if (ddev->did && (ddev->did == resp->data[3])) {

A remote NFC-DEP initiator can trigger this with a 3-byte DEP_REQ frame
that has the DID bit set in the PFB field, causing a 1-byte
out-of-bounds read of kernel heap memory.

Increment the minimum required length to 4 when the DID bit is present
before accessing resp->data[3], mirroring the pattern used for the
size++ / check at the end of the DID block.

Fixes: 7d0911c07b44 ("NFC Digital: Implement NFC-DEP target TX and RX")
Cc: stable@vger.kernel.org
Signed-off-by: Lekë Hapçiu <snowwlake@icloud.com>
---
 net/nfc/digital_dep.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/net/nfc/digital_dep.c b/net/nfc/digital_dep.c
index XXXXXXX..XXXXXXX 100644
--- a/net/nfc/digital_dep.c
+++ b/net/nfc/digital_dep.c
@@ -1117,6 +1117,11 @@ static int digital_tg_recv_dep_req(struct nfc_digital_dev *ddev, void *arg,
 	pfb = dep_req->pfb;

 	if (DIGITAL_NFC_DEP_DID_BIT_SET(pfb)) {
+		if (resp->len < size + 1) {
+			rc = -EIO;
+			goto exit;
+		}
+
 		if (ddev->did && (ddev->did == resp->data[3])) {
 			size++;
 		} else {
--
2.34.1

^ permalink raw reply

* [PATCH net 3/4] nfc: digital: Fix OOB read of RTOX byte in digital_in_recv_dep_res()
From: Lekë Hapçiu @ 2026-04-09 22:34 UTC (permalink / raw)
  To: netdev; +Cc: linux-wireless, stable, krzysztof.kozlowski,
	Lekë Hapçiu
In-Reply-To: <20260409223436.1887988-1-snowwlake@icloud.com>

In the SUPERVISOR_PDU / timeout (RTOX) branch of digital_in_recv_dep_res(),
the RTOX value byte is read from resp->data[0] after skb_pull() has
stripped the 3-byte DEP_RES header:

  skb_pull(resp, size);   /* size = sizeof(struct digital_dep_req_res) = 3 */
  ...
  case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU:
      ...
      rtox = DIGITAL_NFC_DEP_RTOX_VALUE(resp->data[0]);

If the remote device sends a DEP_RES frame that is exactly the minimum
length (3 bytes -- dir + cmd + pfb only, no payload), the skb_pull leaves
resp->len == 0 and the read of resp->data[0] is a 1-byte out-of-bounds
read of kernel heap memory beyond the socket buffer.

The I-PDU and ACK/NACK branches are not affected because they either
pass resp directly to upper layers or perform a separate minimum-length
check before accessing payload bytes.  Only the RTOX branch is missing
its guard.

Add a resp->len >= 1 check before the RTOX value read.

Fixes: 4b60cfce7aba ("NFC Digital: Implement NFC-DEP initiator TX and RX")
Cc: stable@vger.kernel.org
Signed-off-by: Lekë Hapçiu <snowwlake@icloud.com>
---
 net/nfc/digital_dep.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/net/nfc/digital_dep.c b/net/nfc/digital_dep.c
index XXXXXXX..XXXXXXX 100644
--- a/net/nfc/digital_dep.c
+++ b/net/nfc/digital_dep.c
@@ -866,6 +866,12 @@
 			goto error;
 		}
 
+		if (!resp->len) {
+			PROTOCOL_ERR("14.8.4.1");
+			rc = -EIO;
+			goto error;
+		}
+
 		rtox = DIGITAL_NFC_DEP_RTOX_VALUE(resp->data[0]);
 		if (!rtox || rtox > DIGITAL_NFC_DEP_RTOX_MAX) {
 			PROTOCOL_ERR("14.8.4.1");

--
2.34.1

^ permalink raw reply

* [PATCH net 2/4] nfc: digital: Fix check-after-read in digital_tg_recv_sens_req()
From: Lekë Hapçiu @ 2026-04-09 22:34 UTC (permalink / raw)
  To: netdev; +Cc: linux-wireless, stable, krzysztof.kozlowski,
	Lekë Hapçiu
In-Reply-To: <20260409223436.1887988-1-snowwlake@icloud.com>

digital_tg_recv_sens_req() reads resp->data[0] into sens_req at line
1092 before the !resp->len guard fires at line 1094.  A zero-length
frame causes an unconditional 1-byte out-of-bounds read before any
length check has taken place.

The root cause is that the assignment and the length check are split
across two statements: resp->data[0] is read unconditionally into
sens_req, and only then is resp->len tested as part of a compound
condition.  Even though the || operator correctly short-circuits, the
read on the previous line is already done.

Move the length guard before the data access by splitting the combined
condition into an early resp->len check followed by the data read and
the command comparison.

Fixes: 2e7a3e7ee80d ("NFC Digital: Add target mode for NFC-A/ISO14443A")
Cc: stable@vger.kernel.org
Signed-off-by: Lekë Hapçiu <snowwlake@icloud.com>
---
 net/nfc/digital_technology.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/net/nfc/digital_technology.c b/net/nfc/digital_technology.c
index XXXXXXX..XXXXXXX 100644
--- a/net/nfc/digital_technology.c
+++ b/net/nfc/digital_technology.c
@@ -1090,11 +1090,14 @@ void digital_tg_recv_sens_req(struct nfc_digital_dev *ddev, void *arg,
 	}

-	sens_req = resp->data[0];
-
-	if (!resp->len || (sens_req != DIGITAL_CMD_SENS_REQ &&
-	    sens_req != DIGITAL_CMD_ALL_REQ)) {
+	if (!resp->len) {
 		rc = -EINVAL;
 		goto exit;
 	}
+
+	sens_req = resp->data[0];
+	if (sens_req != DIGITAL_CMD_SENS_REQ && sens_req != DIGITAL_CMD_ALL_REQ) {
+		rc = -EINVAL;
+		goto exit;
+	}

 	rc = digital_tg_send_sens_res(ddev);
--
2.34.1

^ permalink raw reply

* [PATCH net 1/4] nfc: digital: Fix stack buffer overflow in digital_in_recv_sensf_res()
From: Lekë Hapçiu @ 2026-04-09 22:34 UTC (permalink / raw)
  To: netdev; +Cc: linux-wireless, stable, krzysztof.kozlowski,
	Lekë Hapçiu
In-Reply-To: <20260409223436.1887988-1-snowwlake@icloud.com>

The function digital_in_recv_sensf_res() validates that the incoming
SENSF_RES frame is at least DIGITAL_SENSF_RES_MIN_LENGTH (17) bytes,
but does not check that it is at most NFC_SENSF_RES_MAXSIZE (18) bytes
before copying into the 18-byte target.sensf_res stack buffer.

After skb_pull(resp, 1) removes the framing byte, resp->len can range
from 16 up to 253 — an NFC-F frame carries a 1-byte length field with
maximum value 255, from which the driver status byte (pulled here) and
the protocol length byte are subtracted.  The memcpy() at line 775 then
writes up to 235 bytes past the end of target.sensf_res, overflowing
into adjacent stack data including saved registers and the return address.

A device in NFC-F polling mode can trigger this condition without any
prior pairing or authentication by responding to a SENSF_REQ with an
oversized frame.  No user interaction is required on the victim device
while NFC discovery is active.

The NCI code path handles this correctly; nci/ntf.c line 508:
  nfcf_poll->sensf_res_len = min_t(__u8, *data++, NFC_SENSF_RES_MAXSIZE);

Apply the equivalent upper-bound check to the digital protocol path by
rejecting frames whose post-strip length exceeds NFC_SENSF_RES_MAXSIZE.

Fixes: 8c0695e4998d ("NFC Digital: Add NFC-F technology support")
Cc: stable@vger.kernel.org
Signed-off-by: Lekë Hapçiu <snowwlake@icloud.com>
---
 net/nfc/digital_technology.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/net/nfc/digital_technology.c b/net/nfc/digital_technology.c
index XXXXXXX..XXXXXXX 100644
--- a/net/nfc/digital_technology.c
+++ b/net/nfc/digital_technology.c
@@ -768,6 +768,11 @@ static void digital_in_recv_sensf_res(struct nfc_digital_dev *ddev, void *arg,

 	skb_pull(resp, 1);

+	if (resp->len > NFC_SENSF_RES_MAXSIZE) {
+		rc = -EIO;
+		goto exit;
+	}
+
 	memset(&target, 0, sizeof(struct nfc_target));

 	sensf_res = (struct digital_sensf_res *)resp->data;
--
2.34.1

^ permalink raw reply

* [PATCH net 0/4] nfc: digital: Fix missing and misplaced length checks
From: Lekë Hapçiu @ 2026-04-09 22:34 UTC (permalink / raw)
  To: netdev; +Cc: linux-wireless, stable, krzysztof.kozlowski,
	Lekë Hapçiu

This series fixes four length-check bugs in the NFC Digital Protocol stack.
All are reachable from RF without authentication:

  - Patch 1: Missing upper-bound check before memcpy into target.sensf_res
    in the NFC-F initiator polling path.  An oversized SENSF_RES overflows
    an 18-byte stack buffer by up to 235 bytes.  CVSS 8.1.

  - Patch 2: Check-after-read in the NFC-A target receive path.
    resp->data[0] is read before the resp->len != 0 guard fires.
    A zero-length frame triggers a 1-byte OOB read.

  - Patch 3: Missing post-pull length check in the RTOX handler inside
    digital_in_recv_dep_res().  After skb_pull strips the 3-byte DEP
    header, resp->data[0] is read with no guarantee that any payload byte
    remains.

  - Patch 4: DID byte accessed at resp->data[3] after only a
    sizeof(struct digital_dep_req_res) == 3 byte guard in
    digital_tg_recv_dep_req().  An attacker with DID bit set and a 3-byte
    frame triggers a 1-byte OOB read.

Patches 1-4 are independent and can be applied in any order.

Security Research (4):
  nfc: digital: Fix stack buffer overflow in digital_in_recv_sensf_res()
  nfc: digital: Fix check-after-read in digital_tg_recv_sens_req()
  nfc: digital: Fix OOB read of RTOX byte in digital_in_recv_dep_res()
  nfc: digital: Fix OOB read of DID byte in digital_tg_recv_dep_req()

 net/nfc/digital_dep.c        | 10 ++++++++--
 net/nfc/digital_technology.c | 13 ++++++++-----
 2 files changed, 16 insertions(+), 7 deletions(-)

^ permalink raw reply

* Re: [PATCH v2][next] netfilter: x_tables: Avoid a couple -Wflex-array-member-not-at-end warnings
From: Gustavo A. R. Silva @ 2026-04-09 22:23 UTC (permalink / raw)
  To: Florian Westphal
  Cc: Gustavo A. R. Silva, Pablo Neira Ayuso, Phil Sutter,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Kees Cook, netfilter-devel, coreteam, netdev,
	linux-kernel, linux-hardening
In-Reply-To: <adglrthId0L5__9w@strlen.de>



On 4/9/26 16:18, Florian Westphal wrote:
> Gustavo A. R. Silva <gustavo@embeddedor.com> wrote:
>> diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
>> index b39017c80548..9dd5957d9ed4 100644
>> --- a/net/netfilter/x_tables.c
>> +++ b/net/netfilter/x_tables.c
>> @@ -819,13 +819,15 @@ EXPORT_SYMBOL_GPL(xt_compat_match_to_user);
>>
>>    /* non-compat version may have padding after verdict */
>>    struct compat_xt_standard_target {
>> -       struct compat_xt_entry_target t;
>> -       compat_uint_t verdict;
>> +       TRAILING_OVERLAP(struct compat_xt_entry_target, t, data,
>> +               compat_uint_t verdict;
>> +       );
>>    };
>>
>>    struct compat_xt_error_target {
>> -       struct compat_xt_entry_target t;
>> -       char errorname[XT_FUNCTION_MAXNAMELEN];
>> +       TRAILING_OVERLAP(struct compat_xt_entry_target, t, data,
>> +               char errorname[XT_FUNCTION_MAXNAMELEN];
>> +       );
>>    };
>>
>> You tell me what you prefer.
> 
> I have no strong opinion. This compat code is needed to run 32bit
> iptables binaries on a 64 bit host, not many users these days I think.
> I still hope we can remove this eventually.
> 
> But as the above diff is smaller I would prefer it.

Okay; I'll submit this as v3 then.

Thanks for the feedback,
-Gustavo


^ permalink raw reply

* Re: [PATCH v2][next] netfilter: x_tables: Avoid a couple -Wflex-array-member-not-at-end warnings
From: Florian Westphal @ 2026-04-09 22:18 UTC (permalink / raw)
  To: Gustavo A. R. Silva
  Cc: Gustavo A. R. Silva, Pablo Neira Ayuso, Phil Sutter,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Kees Cook, netfilter-devel, coreteam, netdev,
	linux-kernel, linux-hardening
In-Reply-To: <96b116e4-d91d-456a-9a08-fb3de4822a62@embeddedor.com>

Gustavo A. R. Silva <gustavo@embeddedor.com> wrote:
> diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
> index b39017c80548..9dd5957d9ed4 100644
> --- a/net/netfilter/x_tables.c
> +++ b/net/netfilter/x_tables.c
> @@ -819,13 +819,15 @@ EXPORT_SYMBOL_GPL(xt_compat_match_to_user);
> 
>   /* non-compat version may have padding after verdict */
>   struct compat_xt_standard_target {
> -       struct compat_xt_entry_target t;
> -       compat_uint_t verdict;
> +       TRAILING_OVERLAP(struct compat_xt_entry_target, t, data,
> +               compat_uint_t verdict;
> +       );
>   };
> 
>   struct compat_xt_error_target {
> -       struct compat_xt_entry_target t;
> -       char errorname[XT_FUNCTION_MAXNAMELEN];
> +       TRAILING_OVERLAP(struct compat_xt_entry_target, t, data,
> +               char errorname[XT_FUNCTION_MAXNAMELEN];
> +       );
>   };
> 
> You tell me what you prefer.

I have no strong opinion. This compat code is needed to run 32bit
iptables binaries on a 64 bit host, not many users these days I think.
I still hope we can remove this eventually.

But as the above diff is smaller I would prefer it.

^ permalink raw reply

* [PATCH] udp: Force compute_score to always inline
From: Gabriel Krisman Bertazi @ 2026-04-09 22:15 UTC (permalink / raw)
  To: willemdebruijn.kernel, davem, dsahern, edumazet, kuba, pabeni,
	kuniyu
  Cc: horms, netdev, Gabriel Krisman Bertazi

Back in 2024 I reported a 7-12% regression on an iperf3 UDP loopback
thoughput test that we traced to the extra overhead of calling
compute_score on two places, introduced by commit f0ea27e7bfe1 ("udp:
re-score reuseport groups when connected sockets are present").  At the
time, I pointed out the overhead was caused by the multiple calls,
associated with cpu-specific mitigations, and merged commit
50aee97d1511 ("udp: Avoid call to compute_score on multiple sites") to
jump back explicitly, to force the rescore call in a single place.

Recently though, we got another regression report against a newer distro
version, which a team colleague traced back to the same root-cause.
Turns out that once we updated to gcc-13, the compiler got smart enough
to unroll the loop, undoing my previous mitigation.  Let's bite the
bullet and __always_inline compute_score on both ipv4 and ipv6 to
prevent gcc from de-optimizing it again in the future.  These functions
are only called in two places each, udpX_lib_lookup1 and
udpX_lib_lookup2, so the extra size shouldn't be a problem and it is hot
enough to be very visible in profilings.  In fact, with gcc13, forcing
the inline will prevent gcc from unrolling the fix from commit
50aee97d1511, so we don't end up increasing udpX_lib_lookup2 at all.

I haven't recollected the results myself, as I don't have access to the
machine at the moment.  But the same colleague reported 4.67%
inprovement with this patch in the loopback benchmark, solving the
regression report within noise margins.

Fixes: 50aee97d1511 ("udp: Avoid call to compute_score on multiple sites")
Signed-off-by: Gabriel Krisman Bertazi <krisman@suse.de>
---
 net/ipv4/udp.c | 8 ++++----
 net/ipv6/udp.c | 9 +++++----
 2 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 6c6b68a66dcd..e591e2ab0d7d 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -365,10 +365,10 @@ int udp_v4_get_port(struct sock *sk, unsigned short snum)
 	return udp_lib_get_port(sk, snum, hash2_nulladdr);
 }
 
-static int compute_score(struct sock *sk, const struct net *net,
-			 __be32 saddr, __be16 sport,
-			 __be32 daddr, unsigned short hnum,
-			 int dif, int sdif)
+static __always_inline int
+compute_score(struct sock *sk, const struct net *net,
+	      __be32 saddr, __be16 sport, __be32 daddr,
+	      unsigned short hnum, int dif, int sdif)
 {
 	int score;
 	struct inet_sock *inet;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 010b909275dd..889d229aad61 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -127,10 +127,11 @@ void udp_v6_rehash(struct sock *sk)
 	udp_lib_rehash(sk, new_hash, new_hash4);
 }
 
-static int compute_score(struct sock *sk, const struct net *net,
-			 const struct in6_addr *saddr, __be16 sport,
-			 const struct in6_addr *daddr, unsigned short hnum,
-			 int dif, int sdif)
+static __always_inline int
+compute_score(struct sock *sk, const struct net *net,
+	      const struct in6_addr *saddr, __be16 sport,
+	      const struct in6_addr *daddr, unsigned short hnum,
+	      int dif, int sdif)
 {
 	int bound_dev_if, score;
 	struct inet_sock *inet;
-- 
2.52.0


^ permalink raw reply related

* Re: [PATCH net-next v9 1/4] net: stmmac: Add DW25GMAC support in stmmac core driver
From: Jitendra Vegiraju @ 2026-04-09 22:14 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: netdev, alexandre.torgue, davem, edumazet, pabeni,
	mcoquelin.stm32, bcm-kernel-feedback-list, richardcochran, ast,
	daniel, hawk, john.fastabend, rmk+kernel, rohan.g.thomas,
	linux-kernel, linux-stm32, linux-arm-kernel, bpf, andrew+netdev,
	horms, sdf, siyanteng, prabhakar.mahadev-lad.rj, weishangjuan,
	wens, vladimir.oltean, lizhi2, boon.khai.ng, maxime.chevallier,
	chenchuangyu, yangtiezhu, ovidiu.panait.rb, chenhuacai,
	florian.fainelli, quic_abchauha
In-Reply-To: <20260407020954.3674529-1-kuba@kernel.org>

[-- Attachment #1: Type: text/plain, Size: 3227 bytes --]

On Mon, Apr 6, 2026 at 7:09 PM Jakub Kicinski <kuba@kernel.org> wrote:
>
> This is an AI-generated review of your patch. The human sending this
> email has considered the AI review valid, or at least plausible.
> ---
> Subject: net: stmmac: Add DW25GMAC support in stmmac core driver
>
> This commit introduces support for the DW25GMAC hardware in the stmmac
> core driver, which uses a new Hyper-DMA (HDMA) architecture. It adds a
> new DMA ops instance mapping virtual DMA channels to physical DMA
> channels and sets up the basic device configurations.
>
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/dw25gmac.c b/drivers/net/ethernet/stmicro/stmmac/dw25gmac.c
> > new file mode 100644
> > index 0000000000000..82eb22bff73e0
> > --- /dev/null
> > +++ b/drivers/net/ethernet/stmicro/stmmac/dw25gmac.c
>
> [ ... ]
>
> > +static int rd_dma_ch_ind(void __iomem *ioaddr, u8 mode, u32 channel)
> > +{
> > +     u32 reg_val = 0;
> > +
> > +     reg_val |= FIELD_PREP(XXVGMAC_MODE_SELECT, mode);
> > +     reg_val |= FIELD_PREP(XXVGMAC_ADDR_OFFSET, channel);
> > +     reg_val |= XXVGMAC_CMD_TYPE | XXVGMAC_OB;
> > +     writel(reg_val, ioaddr + XXVGMAC_DMA_CH_IND_CONTROL);
> > +     return readl(ioaddr + XXVGMAC_DMA_CH_IND_DATA);
> > +}
>
> Does this readl() need to wait for the hardware to clear the XXVGMAC_OB
> (Operation Busy) bit? Returning immediately might read uninitialized or
> stale data if the hardware hasn't finished the fetch.
>
This is an issue. We will fix it.
> > +
> > +static void wr_dma_ch_ind(void __iomem *ioaddr, u8 mode, u32 channel, u32 val)
> > +{
> > +     u32 reg_val = 0;
> > +
> > +     writel(val, ioaddr + XXVGMAC_DMA_CH_IND_DATA);
> > +     reg_val |= FIELD_PREP(XXVGMAC_MODE_SELECT, mode);
> > +     reg_val |= FIELD_PREP(XXVGMAC_ADDR_OFFSET, channel);
> > +     reg_val |= XGMAC_OB;
>
> This isn't a bug, but should this use the XXVGMAC_OB macro instead of
> XGMAC_OB here for consistency?
>
> > +     writel(reg_val, ioaddr + XXVGMAC_DMA_CH_IND_CONTROL);
> > +}
>
> Similarly, does this function need to poll for the busy bit to clear after
> the writel()? If back-to-back operations occur, the next indirect write
> might overwrite the control and data registers while the hardware is still
> processing this request.
>
Agreed. This is bug, we will fix it.
> [ ... ]
>
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
> > index f02b434bbd505..64c38de294da2 100644
> > --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
> > +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
>
> [ ... ]
>
> > -int dwxgmac2_setup(struct stmmac_priv *priv)
> > +static void dwxgmac2_common_setup(struct stmmac_priv *priv, char *mac_name)
> >  {
>
> This isn't a bug, but should mac_name be declared as const char * since it
> is passed string literals like "XGMAC2" and "DW25GMAC"? This avoids
> discarded-qualifiers compiler warnings.
>
> >       struct mac_device_info *mac = priv->hw;
> >
> > -     dev_info(priv->device, "\tXGMAC2\n");
> > +     dev_info(priv->device, "\t%s\n", mac_name);
>
Ack
> [ ... ]
> --
> pw-bot: cr

[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 5435 bytes --]

^ permalink raw reply

* Re: [PATCH v2][next] netfilter: x_tables: Avoid a couple -Wflex-array-member-not-at-end warnings
From: Gustavo A. R. Silva @ 2026-04-09 22:09 UTC (permalink / raw)
  To: Gustavo A. R. Silva, Pablo Neira Ayuso, Florian Westphal,
	Phil Sutter, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Simon Horman, Kees Cook
  Cc: netfilter-devel, coreteam, netdev, linux-kernel, linux-hardening
In-Reply-To: <adgL5wPm9VpaV3MO@kspp>

BTW folks,

We can use the TRAILING_OVERLAP() helper and address these warnings with
the following patch instead:

diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index b39017c80548..9dd5957d9ed4 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -819,13 +819,15 @@ EXPORT_SYMBOL_GPL(xt_compat_match_to_user);

  /* non-compat version may have padding after verdict */
  struct compat_xt_standard_target {
-       struct compat_xt_entry_target t;
-       compat_uint_t verdict;
+       TRAILING_OVERLAP(struct compat_xt_entry_target, t, data,
+               compat_uint_t verdict;
+       );
  };

  struct compat_xt_error_target {
-       struct compat_xt_entry_target t;
-       char errorname[XT_FUNCTION_MAXNAMELEN];
+       TRAILING_OVERLAP(struct compat_xt_entry_target, t, data,
+               char errorname[XT_FUNCTION_MAXNAMELEN];
+       );
  };


This helper creates a union between a flexible-array member (FAM)
and a set of members that would otherwise follow it. This overlays
the trailing members onto the FAM while preserving the original
memory layout. It was created to address exactly these sorts of
issues where flexible-array members end up embedded in the middle
of structs.

You tell me what you prefer.

Thanks
-Gustavo

On 4/9/26 14:28, Gustavo A. R. Silva wrote:
> -Wflex-array-member-not-at-end was introduced in GCC-14, and we are
> getting ready to enable it, globally.
> 
> struct compat_xt_standard_target and struct compat_xt_error_target are
> only used in xt_compat_check_entry_offsets(). Remove these structs and
> instead define the same memory layout on the stack via flexible struct
> compat_xt_entry_target and DEFINE_RAW_FLEX(). Adjust the rest of the
> code accordingly.
> 
> With these changes, fix the following warnings:
> 
> 1 net/netfilter/x_tables.c:816:39: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
> 1 net/netfilter/x_tables.c:811:39: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
> 
> Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
> ---
> Changes in v2:
>   - Update verdict after (compat_uint_t *)st->data;
> 
> v1:
>   - Link: https://lore.kernel.org/linux-hardening/adbIKC0cZcK7VcCF@kspp/
> 
>   net/netfilter/x_tables.c | 31 ++++++++++++++-----------------
>   1 file changed, 14 insertions(+), 17 deletions(-)
> 
> diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
> index b39017c80548..746012196d83 100644
> --- a/net/netfilter/x_tables.c
> +++ b/net/netfilter/x_tables.c
> @@ -817,17 +817,6 @@ int xt_compat_match_to_user(const struct xt_entry_match *m,
>   }
>   EXPORT_SYMBOL_GPL(xt_compat_match_to_user);
>   
> -/* non-compat version may have padding after verdict */
> -struct compat_xt_standard_target {
> -	struct compat_xt_entry_target t;
> -	compat_uint_t verdict;
> -};
> -
> -struct compat_xt_error_target {
> -	struct compat_xt_entry_target t;
> -	char errorname[XT_FUNCTION_MAXNAMELEN];
> -};
> -
>   int xt_compat_check_entry_offsets(const void *base, const char *elems,
>   				  unsigned int target_offset,
>   				  unsigned int next_offset)
> @@ -850,18 +839,26 @@ int xt_compat_check_entry_offsets(const void *base, const char *elems,
>   		return -EINVAL;
>   
>   	if (strcmp(t->u.user.name, XT_STANDARD_TARGET) == 0) {
> -		const struct compat_xt_standard_target *st = (const void *)t;
> +		DEFINE_RAW_FLEX(const struct compat_xt_entry_target, st, data,
> +				sizeof(compat_uint_t));
> +		compat_uint_t *verdict;
>   
> -		if (COMPAT_XT_ALIGN(target_offset + sizeof(*st)) != next_offset)
> +		st = (const void *)t;
> +		verdict = (compat_uint_t *)st->data;
> +
> +		if (COMPAT_XT_ALIGN(target_offset + __struct_size(st)) !=
> +				next_offset)
>   			return -EINVAL;
>   
> -		if (!verdict_ok(st->verdict))
> +		if (!verdict_ok(*verdict))
>   			return -EINVAL;
>   	} else if (strcmp(t->u.user.name, XT_ERROR_TARGET) == 0) {
> -		const struct compat_xt_error_target *et = (const void *)t;
> +		DEFINE_RAW_FLEX(const struct compat_xt_entry_target, et, data,
> +				XT_FUNCTION_MAXNAMELEN);
> +		et = (const void *)t;
>   
> -		if (!error_tg_ok(t->u.target_size, sizeof(*et),
> -				 et->errorname, sizeof(et->errorname)))
> +		if (!error_tg_ok(t->u.target_size, __struct_size(et),
> +				 et->data, __member_size(et->data)))
>   			return -EINVAL;
>   	}
>   


^ permalink raw reply related

* Re: [PATCH net-next v9 0/4] net: stmmac: Add PCI driver support for BCM8958x
From: Jitendra Vegiraju @ 2026-04-09 22:08 UTC (permalink / raw)
  To: Russell King (Oracle)
  Cc: netdev, alexandre.torgue, davem, edumazet, kuba, pabeni,
	mcoquelin.stm32, bcm-kernel-feedback-list, richardcochran, ast,
	daniel, hawk, john.fastabend, rohan.g.thomas, linux-kernel,
	linux-stm32, linux-arm-kernel, bpf, andrew+netdev, horms, sdf,
	siyanteng, prabhakar.mahadev-lad.rj, weishangjuan, wens,
	vladimir.oltean, lizhi2, boon.khai.ng, maxime.chevallier,
	chenchuangyu, yangtiezhu, ovidiu.panait.rb, chenhuacai,
	florian.fainelli, quic_abchauha
In-Reply-To: <adSxQpAE0nY0ulfU@shell.armlinux.org.uk>

[-- Attachment #1: Type: text/plain, Size: 1145 bytes --]

Hi Russell,

On Tue, Apr 7, 2026 at 12:25 AM Russell King (Oracle)
<linux@armlinux.org.uk> wrote:
>
> On Thu, Apr 02, 2026 at 02:36:25PM -0700, Jitendra Vegiraju wrote:
> > From: Jitendra Vegiraju <jitendra.vegiraju@broadcom.com>
> >
> > This patchset adds basic PCI ethernet device driver support for Broadcom
> > BCM8958x Automotive Ethernet switch SoC devices.
> >
> > The MAC block on BCM8958x is based on Synopsis XGMAC 4.00a core. This
> > MAC IP introduces new DMA architecture called Hyper-DMA for virtualization
> > scalability.
> >
> > Driver functionality specific to new MAC (DW25GMAC) is implemented in
> > new file dw25gmac.c.
>
> Sorry for suggesting this rather late, but I recently came across
> another stmmac driver in the kernel - drivers/net/ethernet/synopsys.
> This is for XLGMAC, but I wonder whether it may be a better bet for
> this core. Have you looked at it?
>
I wasn't aware of this driver earlier. We are looking into this driver now.
Thanks
> --
> RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
> FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!

[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 5435 bytes --]

^ permalink raw reply

* Re: [RFC net PATCH v1] net: pcs: pcs-mtk-lynxi: fix bpi-r3 serdes configuration
From: Vladimir Oltean @ 2026-04-09 21:55 UTC (permalink / raw)
  To: Frank Wunderlich
  Cc: Alexander Couzens, Daniel Golle, Andrew Lunn, Heiner Kallweit,
	Russell King, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Matthias Brugger, AngeloGioacchino Del Regno,
	Frank Wunderlich, netdev, linux-kernel, linux-arm-kernel,
	linux-mediatek
In-Reply-To: <20260409133344.129620-1-linux@fw-web.de>

On Thu, Apr 09, 2026 at 03:33:42PM +0200, Frank Wunderlich wrote:
> From: Frank Wunderlich <frank-w@public-files.de>
> 
> Commit 8871389da151 introduces common pcs dts properties which writes
> rx=normal,tx=normal polarity to register SGMSYS_QPHY_WRAP_CTRL of switch.
> This is initialized with tx-bit set and so change inverts polarity
> compared to before.
> 
> It looks like mt7531 has tx polarity inverted in hardware and set tx-bit
> by default to restore the normal polarity.
> 
> Till this patch the register write was only called when mediatek,pnswap
> property was set which cannot be done for switch because the fw-node param
> was always NULL from switch driver in the mtk_pcs_lynxi_create call.
> 
> Do not configure switch side like it's done before.
> 
> Fixes: 8871389da151 ("net: pcs: pcs-mtk-lynxi: deprecate "mediatek,pnswap"")
> Signed-off-by: Frank Wunderlich <frank-w@public-files.de>
> ---

Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>

^ permalink raw reply

* Re: [RFC net PATCH v1] net: pcs: pcs-mtk-lynxi: fix bpi-r3 serdes configuration
From: Vladimir Oltean @ 2026-04-09 21:52 UTC (permalink / raw)
  To: Daniel Golle
  Cc: Frank Wunderlich, Chester A. Unal, Felix Fietkau,
	Alexander Couzens, Andrew Lunn, Heiner Kallweit, Russell King,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Matthias Brugger, AngeloGioacchino Del Regno, Frank Wunderlich,
	netdev, linux-kernel, linux-arm-kernel, linux-mediatek
In-Reply-To: <adgSXDUn-oL6V_TK@makrotopia.org>

On Thu, Apr 09, 2026 at 09:55:56PM +0100, Daniel Golle wrote:
> On Thu, Apr 09, 2026 at 07:49:42PM +0300, Vladimir Oltean wrote:
> > I notice Arınc, listed by ./scripts/get_maintainer.pl drivers/net/dsa/mt7530.c,
> > and Felix, listed by ./scripts/get_maintainer.pl drivers/net/ethernet/mediatek/mtk_eth_soc.c,
> > are not on CC. Maybe they have more info.
> > 
> > Only the switch port has a chance of having a non-zero default polarity
> > setting? (coming from the efuse, if I understood this discussion properly)
> > https://lore.kernel.org/netdev/C59EED96-3973-4074-A4D8-C264949D447E@linux.dev/
> > The GMAC doesn't?
> 
> Yes, vendor SDK uses DT mediatek,pnswap{,-rx,-tx} properties only for the
> SoC GMACs. For MT7531 there are **no** strap pins deciding the SerDes
> polarity, and also no software-way to override the defaults in the vendor
> SDK.
> 
> However, the MT7531 datasheet quite clearly states:
> Register 000050EC QPHY_WRAP_CTRL -- QPHY wrapper control
> Reset value: 0x00000501
> 
> BIT 1 RX_BIT_POLARITY -- RX bit polarity control
>  1'b0: normal
>  1'b1: inverted
> 
> BIT 0 TX_BIT_POLARITY -- TX bit polarity control (TX default inversed in MT7531)
>  1'b0: normal
>  1'b1: inverted
> 
> Hence the best would be to just assume the documented default in the driver
> as well.
> 
> A quick register dump using the BPi-R3 confirms that this applies to *both*
> SerDes PCS on MT7531A (port 5 and port 6) equally, both read 0x00000501
> after reset.

OK. Excepting the DSA driver for MT7531 from polarity configuration
based on lack of a fwnode for the PCS should be fine (for now, to
address the regression).

^ permalink raw reply

* Re: [PATCH v2 1/4] rust: netlink: add raw netlink abstraction
From: Andrew Lunn @ 2026-04-09 21:50 UTC (permalink / raw)
  To: Alice Ryhl
  Cc: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Trevor Gross, Danilo Krummrich,
	Donald Hunter, Jakub Kicinski, David S. Miller, Eric Dumazet,
	Paolo Abeni, Simon Horman, Greg Kroah-Hartman,
	Arve Hjønnevåg, Todd Kjos, Christian Brauner,
	Carlos Llamas, linux-kernel, rust-for-linux, netdev
In-Reply-To: <20260408-binder-netlink-v2-1-c0d327d15435@google.com>

> +__rust_helper void rust_helper_genlmsg_cancel(struct sk_buff *skb, void *hdr)
> +{
> +	return genlmsg_cancel(skb, hdr);
> +}
> +
> +__rust_helper void rust_helper_genlmsg_end(struct sk_buff *skb, void *hdr)
> +{
> +	return genlmsg_end(skb, hdr);
> +}
> +
> +__rust_helper void rust_helper_nlmsg_free(struct sk_buff *skb)
> +{
> +	return nlmsg_free(skb);
> +}

It is a bit odd for a void function to call return like this,
especially when the functions they are calling are also void
functions.

	Andrew

^ permalink raw reply

* [PATCH v2 net-next 15/15] net/sched: taprio: prepare taprio_dump() for RTNL removal
From: Eric Dumazet @ 2026-04-09 21:49 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Jamal Hadi Salim, Jiri Pirko, Kuniyuki Iwashima,
	netdev, eric.dumazet, Eric Dumazet
In-Reply-To: <20260409214914.3072827-1-edumazet@google.com>

We soon will no longer hold RTNL in qdisc dumps.

Add READ_ONCE()/WRITE_ONCE() annoations.

Note taprio already uses RCU to protect most of its fields.

Signed-off-by: Eric Dumazet <edumazet@google.com>
---
 net/sched/sch_taprio.c | 42 ++++++++++++++++++++++++------------------
 1 file changed, 24 insertions(+), 18 deletions(-)

diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c
index 885a9bc859166dfb6d20aa0dfbb8f11194e02ba9..75030a834840cde3480722cc4214431625a7c7ee 100644
--- a/net/sched/sch_taprio.c
+++ b/net/sched/sch_taprio.c
@@ -308,10 +308,10 @@ static void taprio_update_queue_max_sdu(struct taprio_sched *q,
 
 		if (max_sdu != U32_MAX) {
 			sched->max_frm_len[tc] = max_sdu + dev->hard_header_len;
-			sched->max_sdu[tc] = max_sdu;
+			WRITE_ONCE(sched->max_sdu[tc], max_sdu);
 		} else {
 			sched->max_frm_len[tc] = U32_MAX; /* never oversized */
-			sched->max_sdu[tc] = 0;
+			WRITE_ONCE(sched->max_sdu[tc], 0);
 		}
 	}
 }
@@ -1770,8 +1770,8 @@ static int taprio_parse_tc_entries(struct Qdisc *sch,
 	}
 
 	for (tc = 0; tc < TC_QOPT_MAX_QUEUE; tc++) {
-		q->max_sdu[tc] = max_sdu[tc];
-		q->fp[tc] = fp[tc];
+		WRITE_ONCE(q->max_sdu[tc], max_sdu[tc]);
+		WRITE_ONCE(q->fp[tc], fp[tc]);
 		if (fp[tc] != TC_FP_EXPRESS)
 			have_preemption = true;
 	}
@@ -1851,12 +1851,14 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
 		return -EINVAL;
 	}
 
-	if (q->flags != TAPRIO_FLAGS_INVALID && q->flags != taprio_flags) {
-		NL_SET_ERR_MSG_MOD(extack,
-				   "Changing 'flags' of a running schedule is not supported");
-		return -EOPNOTSUPP;
+	if (q->flags != taprio_flags) {
+		if (q->flags != TAPRIO_FLAGS_INVALID) {
+			NL_SET_ERR_MSG_MOD(extack,
+					   "Changing 'flags' of a running schedule is not supported");
+			return -EOPNOTSUPP;
+		}
+		q->flags = taprio_flags;
 	}
-	q->flags = taprio_flags;
 
 	/* Needed for length_to_duration() during netlink attribute parsing */
 	taprio_set_picos_per_byte(dev, q, extack);
@@ -1939,7 +1941,8 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
 			goto unlock;
 		}
 
-		q->txtime_delay = nla_get_u32(tb[TCA_TAPRIO_ATTR_TXTIME_DELAY]);
+		WRITE_ONCE(q->txtime_delay,
+			   nla_get_u32(tb[TCA_TAPRIO_ATTR_TXTIME_DELAY]));
 	}
 
 	if (!TXTIME_ASSIST_IS_ENABLED(q->flags) &&
@@ -2279,8 +2282,8 @@ static int dump_schedule(struct sk_buff *msg,
 }
 
 static int taprio_dump_tc_entries(struct sk_buff *skb,
-				  struct taprio_sched *q,
-				  struct sched_gate_list *sched)
+				  const struct taprio_sched *q,
+				  const struct sched_gate_list *sched)
 {
 	struct nlattr *n;
 	int tc;
@@ -2294,10 +2297,11 @@ static int taprio_dump_tc_entries(struct sk_buff *skb,
 			goto nla_put_failure;
 
 		if (nla_put_u32(skb, TCA_TAPRIO_TC_ENTRY_MAX_SDU,
-				sched->max_sdu[tc]))
+				READ_ONCE(sched->max_sdu[tc])))
 			goto nla_put_failure;
 
-		if (nla_put_u32(skb, TCA_TAPRIO_TC_ENTRY_FP, q->fp[tc]))
+		if (nla_put_u32(skb, TCA_TAPRIO_TC_ENTRY_FP,
+				READ_ONCE(q->fp[tc])))
 			goto nla_put_failure;
 
 		nla_nest_end(skb, n);
@@ -2383,6 +2387,7 @@ static int taprio_dump(struct Qdisc *sch, struct sk_buff *skb)
 	struct sched_gate_list *oper, *admin;
 	struct tc_mqprio_qopt opt = { 0 };
 	struct nlattr *nest, *sched_nest;
+	u32 txtime_delay;
 
 	mqprio_qopt_reconstruct(dev, &opt);
 
@@ -2400,14 +2405,15 @@ static int taprio_dump(struct Qdisc *sch, struct sk_buff *skb)
 	if (q->flags && nla_put_u32(skb, TCA_TAPRIO_ATTR_FLAGS, q->flags))
 		goto options_error;
 
-	if (q->txtime_delay &&
-	    nla_put_u32(skb, TCA_TAPRIO_ATTR_TXTIME_DELAY, q->txtime_delay))
+	txtime_delay = READ_ONCE(q->txtime_delay);
+	if (txtime_delay &&
+	    nla_put_u32(skb, TCA_TAPRIO_ATTR_TXTIME_DELAY, txtime_delay))
 		goto options_error;
 
 	rcu_read_lock();
 
-	oper = rtnl_dereference(q->oper_sched);
-	admin = rtnl_dereference(q->admin_sched);
+	oper = rcu_dereference(q->oper_sched);
+	admin = rcu_dereference(q->admin_sched);
 
 	if (oper && taprio_dump_tc_entries(skb, q, oper))
 		goto options_error_rcu;
-- 
2.53.0.1213.gd9a14994de-goog


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox