check_fwfile_format() reads each block header and trusts its data length
before proving that both fit in the firmware image. A truncated header or
oversized block can therefore pass malformed extents to the download path.
Require the remaining image to contain the complete header and payload
before accepting each block.
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Link: https://patch.msgid.link/20260830140420.26399-1-pengpeng@iscas.ac.cn
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
check_fwfile_format() reads each block header and trusts its data length
before proving that both fit in the firmware image. A truncated header or
oversized block can therefore pass malformed extents to the download path.
Require the remaining image to contain the complete header and payload
before accepting each block.
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Link: https://patch.msgid.link/20260830124810.97223-1-pengpeng@iscas.ac.cn
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
WRT3200ACM and WRT32x routers always report a fixed US regulatory domain
from the mwifiex ROM, which conflicts with the platform regulatory
configuration on units sold outside the US market. For example:
- phy0 mwlwifi 5 GHz, hard-coded region 98 EU mapped to FR
- phy1 mwlwifi 2.4 GHz, hard-coded region 98 EU mapped to FR
- phy2 mwifiex 2.4 and 5 GHz, hard-coded region US
When the system boots, it detects a conflict between the user selected
region and the radios, e.g. BG FR US, and applies extreme restrictions,
preventing phy0 from starting on any DFS channel. phy2 works.
Add a device-tree flag, which allows affected devices, where the radio
conflicts with the platform to ignore the incorrect regulatory hint in
the ROM of the radio, so the platform regulatory domain can be used.
This does not allow the user to change the regulatory configuration of
any radio. It only allows phy0 to start and operate according to its
certified configuration.
The change affects only platforms which explicitly define this flag, and
helps overcome the incorrect behaviour of proprietary radio firmware.
The change has been tested on OpenWrt and fixes the issue where
phy0 does not start on WRT3200ACM-EU when a DFS channel is used
[1] https://github.com/kaloz/mwlwifi/issues/173#issuecomment-307879699
[2] https://github.com/openwrt/openwrt/issues/9956
Signed-off-by: Georgi Valkov <gvalkov@gmail.com>
Link: https://patch.msgid.link/20260827175850.89395-2-gvalkov@gmail.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
WRT3200ACM and WRT32x routers always report a fixed US regulatory domain
from the mwifiex ROM, which conflicts with the platform regulatory
configuration on units sold outside the US market. For example:
- phy0 mwlwifi 5 GHz, hard-coded region 98 EU mapped to FR
- phy1 mwlwifi 2.4 GHz, hard-coded region 98 EU mapped to FR
- phy2 mwifiex 2.4 and 5 GHz, hard-coded region US
When the system boots, it detects a conflict between the user selected
region and the radios, e.g. BG FR US, and applies extreme restrictions,
preventing phy0 from starting on any DFS channel. phy2 works.
Add a device-tree flag, which allows affected devices, where the radio
conflicts with the platform to ignore the incorrect regulatory hint in
the ROM of the radio, so the platform regulatory domain can be used.
This does not allow the user to change the regulatory configuration of
any radio. It only allows phy0 to start and operate according to its
certified configuration.
[1] https://github.com/kaloz/mwlwifi/issues/173#issuecomment-307879699
[2] https://github.com/openwrt/openwrt/issues/9956
Signed-off-by: Georgi Valkov <gvalkov@gmail.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Link: https://patch.msgid.link/20260827175850.89395-1-gvalkov@gmail.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
The WFxxx device provides an SDIO interface. In addition to the usual
in-band SDIO IRQ, the device also supports an out-of-band IRQ line.
However, using the OOB IRQ with SDIO requires to poll the control
register during the device initialization. This polling is unreliable:
if an IRQ is raised while the host reads the control register, the
device is lost and only a reset allows to recover it.
There is no way to fix this in software. So, warn the user that this
setup should be reserved to debug.
Signed-off-by: Jérôme Pouiller <jerome.pouiller@silabs.com>
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Link: https://patch.msgid.link/20260901083548.113131-3-jerome.pouiller@silabs.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
The WFxxx device provides an SDIO interface. In addition to the usual
in-band SDIO IRQ, the device also supports out-of-band IRQ line. OOB IRQ
requires a specific initialization described in commit f00dc1d789
("staging: wfx: poll IRQ during init"):
When the chip starts in SDIO mode, the external IRQ (aka Out-Of-Band
IRQ) cannot be used before to configure it. Therefore, the first
exchanges with the chip have to be done without the OOB IRQ.
This patch allow to poll the data until the OOB IRQ is correctly
setup. In order to keep the code simpler, this patch also poll data
even if OOB IRQ is not used.
Commit 57aa557f11 ("staging: wfx: introduce a way to poll IRQ")
announce some limitation about the data polling mechanism:
This function [wfx_bh_poll_irq()] must used with care: if an IRQ
fires while the host reads control register, the IRQ can be lost.
However, with last analysis, it seems it does not only impact the IRQ.
When this condition happen the hardware is lost and won't reply the next
commands. The only way to recover the error is to pull the reset pin and
bind the device again.
Currently wfx_bh_poll_irq() is only used during the two first exchanges
with the hardware. Therefore, it has been reported to only happen after
a few hours of bind/rebind in a loop. This explain why it has not been
reported before.
Fortunately, wfx_bh_poll_irq() is only required for OOB IRQ, which is
probably very marginal. The In-Band IRQ case also uses this function,
but only to simplify the code.
This patch limits the use of wfx_bh_poll_irq() to the OOB IRQ. The bus
driver now tells wfx_probe() whether polling is necessary. When it is
not (in-band SDIO IRQ and SPI), the IRQ is subscribed before the first
exchange with the device and wfx_bh_poll_irq() is never called. When it
is (SDIO with OOB IRQ), the behavior is unchanged: the control register
is polled until the PDS file has configured the IRQ line.
To conclude, In-Band users are now safe. Users of OOB IRQ will be still
impacted by the bug, but there is nothing we can do (and nobody
complained during the last 6 years).
Fixes: f00dc1d789 ("staging: wfx: poll IRQ during init")
Reported-by: Gerard Salvatella <gerard.salvatella@siemens.com>
Reported-by: Lukas Stockmann <lukas.stockmann@siemens.com>
Signed-off-by: Jérôme Pouiller <jerome.pouiller@silabs.com>
Reviewed-by: Alexander Sverdlin <alexander.sverdlin@siemens.com>
Tested-by: Alexander Sverdlin <alexander.sverdlin@siemens.com>
Link: https://patch.msgid.link/20260901083548.113131-2-jerome.pouiller@silabs.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
The ack skb has to be stored while the frame is still in 802.3
format, since that is what is reported back to userspace. It's
currently done in ieee80211_build_hdr(), but that complicates
it a bit.
Thanks the the previous ieee80211_lookup_ra_sta() change, it's
now known whether or not the frame will be group addressed on
the air, which is needed for this condition.
Also simplify callers of ieee80211_store_ack_skb() by filling
the TX info directly and fix the free in ieee80211_build_hdr()
to use ieee80211_free_txskb(), reporting the drop to userspace
rather than being quiet about it.
This also lets use validate the link ID for control port TX in
that code itself, rather than interleaving it into build_hdr().
Link: https://patch.msgid.link/20260803141309.292711-16-johannes@sipsolutions.net
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
ieee80211_build_hdr() takes the info and control flags to use as
arguments, but that leads to some messy code and missed cleanup.
Fill them in the SKB before calling ieee80211_build_hdr().
Link: https://patch.msgid.link/20260803141309.292711-15-johannes@sipsolutions.net
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
ieee80211_lookup_ra_sta() returns ERR_PTR(-ENOENT) both when the
802.11 frame will be is group addressed and when it's going to
an unknown station.
Keep reporting an ERR_PTR() for group addressed but set to NULL
for individually addressed frames so the callers can use it to
distinguish later. This is already explicitly the case for all
interface types except mesh, and callers already tolerate (but
don't distinguish) both cases.
Also change the ieee80211_lookup_ra_sta() to be static.
Link: https://patch.msgid.link/20260803141309.292711-14-johannes@sipsolutions.net
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
ieee80211_build_hdr() unshares the skb halfway through, after it
has already looked at it but before it writes anything. That's not
a problem, but complicates the callers and requires passing the
flags to the function, etc.
Move the unsharing to the only caller that matters, the new one
from the previous patch has a fresh SKB and doesn't need it and
the TDLS callers via ieee80211_tdls_build_mgmt_packet_data() are
also fresh SKBs.
Link: https://patch.msgid.link/20260803141309.292711-13-johannes@sipsolutions.net
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
ieee80211_tx_control_port() already does most of the necessary work,
much of which is repeated by __ieee80211_subif_start_xmit(). Most
work in the latter function is completely unnecessary since these
are special frames we built directly here (long enough, etc.)
Call ieee80211_build_hdr() and ieee80211_xmit() directly instead.
It also means some errors can now be reported to userspace rather
than frames silently getting dropped, but that's a good thing.
Link: https://patch.msgid.link/20260803141309.292711-11-johannes@sipsolutions.net
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
In ieee80211_build_hdr(), IEEE80211_TX_CTL_REQ_TX_STATUS is checked
in ctrl_flags, which is wrong - IEEE80211_TX_CTL_REQ_TX_STATUS is in
info->flags, so the check is for IEEE80211_TX_CTRL_PORT_CTRL_PROTO
instead. This works out OK because the only place setting _that_ at
a point before this gets called is in fact ieee80211_tx_control_port()
which was intended here. This is actually needed for correctness, if
jt were checking info->flags instead, TDLS would fill/leak the status
frames created here.
However, we can just fix it by using the cookie instead, that'll be
set for PREAUTH frames via ieee80211_tx_control_port() as well, and
no other frames.
Additionally, the code also erroneously set it, but that just caused
preauth frames to get it set, since storing the ACK SKB will also set
the correct flag. Drop this assignment entirely.
Fixes: a7528198ad ("mac80211: support control port TX status reporting")
Link: https://patch.msgid.link/20260803141309.292711-10-johannes@sipsolutions.net
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This function isn't used by any driver, and we may want to
change it in the future. Don't expose it. Drivers may still
do the same determination based on the flags, but if we'd
ever change the encapsulation internally etc. (which I'm
considering) then the use in mac80211 may need to change,
or the function itself.
Link: https://patch.msgid.link/20260803135248.cd23ccac65d7.I1c238c6abe39f5a1ff1b11d8556599d01dd03ff0@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
For 802.11 frames, ieee80211_tx_h_select_key() drops a data frame
that ended up without a key if the station requires encryption, so
that traffic can never leak out unprotected. Encapsulation offload
erroneously didn't get this code path. Fix that.
Fixes: 50ff477a86 ("mac80211: add 802.11 encapsulation offloading support")
Link: https://patch.msgid.link/20260802085818.1336616-7-johannes@sipsolutions.net
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
ieee80211_tx_h_select_key() assumes the frame is in 802.11 format
for picking the key, at least when there's no pairwise TK for the
STA to transmit with.
For unicast this is likely not relevant because if there's no
pairwise TK for the STA there's probably not going to be any other
key either. But multicast encapsulation offload frames have no
STA, so it looks at the ethernet header as if it was 802.11. This
may not matter very much since multicast encapsulation offload is
likely to ignore the key selection, but it's still wrong.
Create a separate selection function that doesn't (need to) look
at the frame header - it's data anyway, so either unicast to a
station (with sta pointer) or multicast. For MLO, the driver has
to duplicate the frame and select the key anyway, so just skip
it in that case entirely.
Fixes: 50ff477a86 ("mac80211: add 802.11 encapsulation offloading support")
Link: https://patch.msgid.link/20260802105818.0feb7ad61047.Ia506ca211176a3c466bc60e4cc3e506df34a4a67@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
The check in ieee80211_tx_dequeue() reads frame_control, addr1 and
addr2 out of the skb, but for encapsulation offload that's just a
random part of the ethernet addresses, so dropping depends on bits
in the destination address. This is obviously wrong.
Refactor the check and short-circuit for ethernet format frames,
it only needs the port-control flag check since those are locally
generated and not forwarded frames.
Fixes: 50ff477a86 ("mac80211: add 802.11 encapsulation offloading support")
Link: https://patch.msgid.link/20260802105818.dd5da579813d.I51ed0121154bb652bebc97bb0597b1fae9ac978f@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Store the per-descriptor metadata in the DMA ring allocation instead of
allocating it separately.
This ties the metadata lifetime directly to the ring, removes a separate
allocation failure path, and keeps the descriptor count available for
__counted_by() bounds checking.
Assisted-by: Codex:GPT-5.5
Signed-off-by: Rosen Penev <rosenp@gmail.com>
Link: https://patch.msgid.link/20260511041934.378209-1-rosenp@gmail.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Embed the RX reorder pointer array in struct mwifiex_rx_reorder_tbl
instead of allocating it separately.
This ties the array to the reorder table lifetime and removes a
separate allocation and cleanup path.
Change the void pointer type to the proper one for clarity.
Assisted-by: Codex:GPT-5.5
Signed-off-by: Rosen Penev <rosenp@gmail.com>
Link: https://patch.msgid.link/20260727003035.118047-1-rosenp@gmail.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
When initialising the rate control system, ieee80211_s1g_sta_rate_init()
is called for S1G stations during association where it initialises a
last rate of type STA_STATS_RATE_TYPE_S1G but does not initialise
nss, mcs bw etc. Since the last_rate no longer has a value equivalent
to STA_STATS_RATE_INVALID, the invalid rate will be decoded and
the NL80211_STA_INFO_RX_BITRATE flag will be set.
As a result, there is a period during association before the first
data frame is rx'ed where the seeded value is overwritten by
ieee80211_rx_h_sta_process() while this invalid last_rate lives. If
the sta is desroyed during this process, nl80211_put_sta_rate() will
call into cfg80211_calculate_bitrate() and attempt to calculate
the bitrate using the invalid last_rate leading to a WARN:
4,336,675067400,-;------------[ cut here ]------------
4,337,675067524,-;WARNING: net/wireless/util.c:1960 at cfg80211_calculate_bitrate+0x4d8/0x8b0 [cfg80211], CPU#3: kworker/u16:3/874
4,338,675068176,-;invalid rate bw=0, mcs=0, nss=0
[snip loaded modules]
4,341,675068954,-;Hardware name: BCM2711
4,342,675068961,-;Workqueue: events_unbound cfg80211_wiphy_work [cfg80211]
4,343,675069386,-;Call trace:
4,344,675069392,-; unwind_backtrace from show_stack+0x10/0x14
4,345,675069440,-; show_stack from dump_stack_lvl+0xa8/0xb8
4,346,675069475,-; dump_stack_lvl from __warn+0x90/0x224
4,347,675069517,-; __warn from warn_slowpath_fmt+0x130/0x1a8
4,348,675069559,-; warn_slowpath_fmt from cfg80211_calculate_bitrate+0x4d8/0x8b0 [cfg80211]
4,349,675070005,-; cfg80211_calculate_bitrate [cfg80211] from nl80211_put_sta_rate+0x48/0x590 [cfg80211]
4,350,675070819,-; nl80211_put_sta_rate [cfg80211] from nl80211_put_sta_info_common+0x4f4/0xd50 [cfg80211]
4,351,675071616,-; nl80211_put_sta_info_common [cfg80211] from nl80211_send_station.constprop.0+0x114/0x424 [cfg80211]
4,352,675072427,-; nl80211_send_station.constprop.0 [cfg80211] from cfg80211_del_sta_sinfo+0xc4/0x368 [cfg80211]
4,353,675073222,-; cfg80211_del_sta_sinfo [cfg80211] from __sta_info_destroy_part2+0x108/0x2c0 [mac80211]
4,354,675074178,-; __sta_info_destroy_part2 [mac80211] from sta_info_destroy_addr+0x4c/0x88 [mac80211]
4,355,675075243,-; sta_info_destroy_addr [mac80211] from ieee80211_destroy_assoc_data+0x194/0x2d8 [mac80211]
4,356,675075920,-; ieee80211_destroy_assoc_data [mac80211] from ieee80211_rx_mgmt_assoc_resp+0x220/0x1d4c [mac80211]
4,357,675076558,-; ieee80211_rx_mgmt_assoc_resp [mac80211] from ieee80211_iface_work+0x1c0/0x5d0 [mac80211]
4,358,675077187,-; ieee80211_iface_work [mac80211] from cfg80211_wiphy_work+0x110/0x368 [cfg80211]
4,359,675077763,-; cfg80211_wiphy_work [cfg80211] from process_one_work+0x260/0x868
4,360,675078022,-; process_one_work from worker_thread+0x1bc/0x3ec
4,361,675078042,-; worker_thread from kthread+0x120/0x154
4,362,675078060,-; kthread from ret_from_fork+0x14/0x20
4,363,675078074,-;Exception stack(0xf0ac1fb0 to 0xf0ac1ff8)
4,364,675078081,-;1fa0: 00000000 00000000 00000000 00000000
4,365,675078088,-;1fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
4,366,675078093,-;1fe0: 00000000 00000000 00000000 00000000 00000013 00000000
4,367,675080226,-;irq event stamp: 15780967
4,368,675080287,-;hardirqs last enabled at (15780975): [<c050c154>] __up_console_sem+0x50/0x60
4,369,675080395,-;hardirqs last disabled at (15780982): [<c050c140>] __up_console_sem+0x3c/0x60
4,370,675080497,-;softirqs last enabled at (15780966): [<c0476f14>] handle_softirqs+0x398/0x650
4,371,675080608,-;softirqs last disabled at (15780939): [<c0477388>] __irq_exit_rcu+0x150/0x1f0
4,372,675080715,-;---[ end trace 0000000000000000 ]---
To fix, we can simply not seed this psuedo rate. It was originally
implemented to avoid errornous paths that S1G shouldn't take, but those
have since been fixed / cleaned up. While we are here, we also don't
need to initialise the tx side's last rate with
IEEE80211_TX_RC_S1G_MCS (which is equivalent to
IEEE80211_TX_RC_VHT_MCS). The entire tx reporting side does not
support S1G widths and is assumed to be handled by the driver so
we can just remove the entire function.
Fixes: 12bf8fad4c ("mac80211: initialize last_rate for S1G STAs")
Signed-off-by: Lachlan Hodges <lachlan.hodges@morsemicro.com>
Link: https://patch.msgid.link/20260827054456.254573-1-lachlan.hodges@morsemicro.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Previous releases - regressions:
- page_pool: keep frag_offset aligned for odd-sized requests
- sched: fix u32 duplicate handle when node ID pool is exhausted
- udp: create exceptions before socket matching
- igmp: convert struct ip_sf_list to RCU
- ip6_gre: check tunnel info before xmit in ip6gre_tunnel_xmit
- rds: acquire the fastpath locks in rds_conn_shutdown()
- tipc:
- protect node reset trace dump with node lock
- fix NULL deref in tipc_named_node_up() on empty publication list
- bluetooth:
L2CAP: fix out-of-bounds write in l2cap_ecred_connect
hci_core: fix race condition during device registration
- eth: mlx5e: prevent stale XSK buffer release on refill retries
- eth: bridge: don't truncate the port group walk on teardown
Previous releases - always broken:
- gro: fix nesting of TCP GSO SKBs in skb_gro_receive_list()
- sched: fix skb sizing and action leak on reoffload delete
- tcp: fix use-after-free in do_tcp_getsockopt()
- af_packet: don't cast tpacket_hdr.tp_len to int in tpacket_parse_header().
- sctp: fix soft lockup from unpadded ASCONF-ACK parameter iteration
- iptunnel: fix stale transport header during tunnel decapsulation
- eth: vxlan: fix use-after-free in vxlan_mdb_remote_src_del()
- eth: bonding: fix uninitialized transport header access in alb_determine_nd()
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
-----BEGIN PGP SIGNATURE-----
iQJGBAABCgAwFiEEg1AjqC77wbdLX2LbKSR5jcyPE6QFAmqZp4kSHHBhYmVuaUBy
ZWRoYXQuY29tAAoJECkkeY3MjxOkEjkQALMGg903vZ4TfGlzKayFzyhcd5ZC8G4F
R4M+UgTGRfNuas/1YwjpyOpvOYyFgGZ9xBmYNFdsW0YCzZwu8PxpXgu6WTZ+F4gu
sDtWoAbN5V6CfY3fdC7IbXTp8t4CX+shQAsVvEp39Y8SJF4AZeMn8N0+Lnu4DlD3
DAPo/lYSSfvv7RK/5Jvr9FWo7vyoEylfG+LekzGASmWGwhC3h7kWGB4RB4PhJmyq
vRIj2ZjnzdDxu4N7ZGh+EEu5SBCcLP0e/dIMCDg++HAghDqPJ+7pzbWC1kFtQ0ss
qOSyws/xMW3D0Rb68tkiikYWRwgvXUsfEL7Jdf2lhC1xDI8ZpxrrnPYYSZS4rsjb
hjeBwtzRZhv5R0PnNlaZyNpFICIW3XwqP0bYqH/Z/CgwwkKYd+Rp6Tm7hkLpafNx
Py607x2Ff/L2Aydp8csJEyqFP33QOHAfeW+X/YCo4jTc0zBTMSsOblG/EsPPBdNX
fvhVkx4NdqAvIdLYm65cdvhe5dZtIhOAhwAMcrGiMIia4vCIsXq3fWbAe6Phtu8T
KHpQ7Esg/if6blNPpflBuVPsoU+5N6mL7a+zsurqvilJBC5DgYaxwbMlgRSUmJzg
2rR6IlrOsb0FFITNUv+xgPEGzMGV1rL4wnaMSmVN0tjmFQvcu24XQ17D+ug27+eG
rD+E2lrX5rNn
=0sv8
-----END PGP SIGNATURE-----
Merge tag 'net-7.3-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Pull networking fixes from Paolo Abeni:
"Including fixes from bluetooth.
Previous releases - regressions:
- page_pool: keep frag_offset aligned for odd-sized requests
- sched: fix u32 duplicate handle when node ID pool is exhausted
- udp: create exceptions before socket matching
- igmp: convert struct ip_sf_list to RCU
- ip6_gre: check tunnel info before xmit in ip6gre_tunnel_xmit
- rds: acquire the fastpath locks in rds_conn_shutdown()
- tipc:
- protect node reset trace dump with node lock
- fix NULL deref in tipc_named_node_up() on empty publication
list
- bluetooth:
- L2CAP: fix out-of-bounds write in l2cap_ecred_connect
- hci_core: fix race condition during device registration
- eth:
- mlx5e: prevent stale XSK buffer release on refill retries
- bridge: don't truncate the port group walk on teardown
Previous releases - always broken:
- gro: fix nesting of TCP GSO SKBs in skb_gro_receive_list()
- sched: fix skb sizing and action leak on reoffload delete
- tcp: fix use-after-free in do_tcp_getsockopt()
- af_packet: don't cast tpacket_hdr.tp_len to int in
tpacket_parse_header()
- sctp: fix soft lockup from unpadded ASCONF-ACK parameter iteration
- iptunnel: fix stale transport header during tunnel decapsulation
- eth:
- vxlan: fix use-after-free in vxlan_mdb_remote_src_del()
- bonding: fix uninitialized transport header access in
alb_determine_nd()"
* tag 'net-7.3-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (83 commits)
net: gro: Fix nesting of TCP GSO SKBs in skb_gro_receive_list()
net: stmmac: reconfigure RX packet parser table in stmmac_hw_setup() after reset
net: airoha: enable RX_DONE interrupt for RX queue 31
net/rds: don't let rds_conn_shutdown() consume a concurrent drop
net/rds: acquire the fastpath locks in rds_conn_shutdown()
net/rds: acquire RDS_IN_XMIT in rds_tcp_reset_callbacks()
net/rds: tcp: don't force RDS_CONN_RESETTING over a concurrent shutdown
net/rds: clear cp_flags bits individually in rds_conn_path_reset()
net/rds: use clear_bit_unlock() in release_refill()
net/rds: use wq_has_sleeper() in release_in_xmit()
net: usb: qmi_wwan: add Compal EXM-G1x support
net: macb: exclude software FCS from TX byte statistics
net: Remove conflicting altnames for dying netns in __dev_change_net_namespace().
net: bridge: mcast: don't truncate the port group walk on teardown
bonding: do not clear curr_active_slave prematurely when releasing all slaves
net: qrtr: Send HELLO message on endpoint register
octeontx2-af: Fix limiting SRIOV VF count logic
bonding: alb: fix uninitialized transport header access in alb_determine_nd()
s390/ctcm: Prevent XID null dereference
net: psp: do not inherit the Rx association on clone
...
- dm-cache: fix rwsem being locked and unlocked from different processes
- dm-integrity: set the 'stable writes' flag
- dm-integrity: fix a buffer overflow introduced in this merge window
- dm-integrity: fix an infinite loop if tag size is greater than 64
- dm-cache: fix demotion statistics
- dm-integrity: fix NULL pointer dereference in the data-recovery mode
- dm-ebs: remove a bogus restriction on the starting sector offset
-----BEGIN PGP SIGNATURE-----
iIoEABYIADIWIQRnH8MwLyZDhyYfesYTAyx9YGnhbQUCapmHXxQcbXBhdG9ja2FA
cmVkaGF0LmNvbQAKCRATAyx9YGnhbXwlAP9TGvtNybtjhdQJmo3t528XRdwYrYuJ
TZTRcQ+KMXEAkgEAxG1l4vvECTwSkUhZXub2own7+IypiY8N5cFOWCkdVwc=
=hVzb
-----END PGP SIGNATURE-----
Merge tag 'for-7.3/dm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm
Pull device mapper fixes from Mikulas Patocka:
- fix a dm-crypt race condition that could make errors not being reported
- dm-cache:
- fix rwsem being locked and unlocked from different processes
- fix demotion statistics
- dm-integrity:
- set the 'stable writes' flag
- fix a buffer overflow introduced in this merge window
- fix an infinite loop if tag size is greater than 64
- fix NULL pointer dereference in dm-integrity data-recovery mode
- remove a bogus restriction on the dm-ebs starting sector offset
* tag 'for-7.3/dm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm:
dm-ebs: fix incorrect device offset check in ebs_ctr()
dm-integrity: fix NULL pointer dereference when the 'R' flag is used
dm cache: fix demotion stats in passthrough mode
dm-integrity: fix infinite loop on discard with large tag size
dm-integrity: fix buffer overflow with keyed discard
dm-integrity: require stable writes for internal hash modes
dm cache: fix issue with background work locking
dm-crypt: fix a tiny race condition in crypt_dec_pending
invalidate_lock, avoiding mmap failures during concurrent size changes
and exposure of uninitialized data during allocation.
- Correct fallocate signal and zeroing error handling.
- Fix FITRIM range alignment to prevent discard requests from extending
into allocated clusters.
- Fix free-cluster accounting when cluster-freeing rollback or bitmap
clearing fails.
- Keep volumes marked dirty when ntfs errors have been recorded.
- Compute bi_sector in 512-byte units, preventing silent corruption on
4Kn devices.
- Validate sectors_per_cluster values and prevent undefined shifts when
parsing MFT and index record sizes.
- Bound $AttrDef traversal to the loaded table size.
- Fix MFT record resizing, memmove overlap, and kmap_local cleanup issues.
- Improve error propagation across attribute, EA, and reparse operations,
including returning -ERANGE for undersized xattr buffers.
- Avoid modifying the HasEA flag when setxattr fails and return
DT_UNKNOWN when directory inode lookup fails.
- Reduce contention in WOF decompression by performing block reads outside
the decompression lock.
-----BEGIN PGP SIGNATURE-----
iQJKBAABCgA0FiEE6NzKS6Uv/XAAGHgyZwv7A1FEIQgFAmqZGasWHGxpbmtpbmpl
b25Aa2VybmVsLm9yZwAKCRBnC/sDUUQhCIdnD/9OEohX3GvIqwHT90GubLIGunJr
S2D1MSJz0AwNF0sNQhTawAc3fbjwI77B2H3mI/Xghkd4IvgtzcY/L/jYfaZ3M7sn
Grctto0BypHI5DuBbArfjTQdW/NkPR0IpXGyBLQ8sO6aYVUPGAG0lvL9tT1Zm52N
JQU1mtjEihE5ZpD79gx8PexuDJHIg0uuok4EANk9Vu+Ub68bDBsnl/Zyxm4spIEA
976QAdboGDvo+71IdpPSaMuSAMytOf7LDJqxECqZXN5aUOoz9wrJnjELVg+xRE6c
AFM9hHZ4tZ0zs5A0EpR835URaB/bxGWpbGdkCyDDBm+QMHiTGNp5nGFl/Sd/NO5B
NcSaj0Tc2+7DbcTLU2hk1FhUsEk8eTwBZK05gxE6OajAIfAyXqxTNeB1th5smLKG
PjKWjQh9F2okIB71D6jkdntAs/0RPyuu37bTl0EtJeuRoWYZooHkgeA+tV350BQz
vjOwQuVUnDoNRQ0z1egrqAZalgjoNG7xLu0fI+n7eXZ5a4XZvQpYlKWKsodXYVwX
TBwnQhst8zEx49fe5dIBGnLiZhhQMe2zxmh7lxAOu6VcVPE4Xv6jSwzcilyiPtQF
YrdZGOEgtByOLsD+m1PRYZvukvQDDpn+NX6w4dJ+YL3MjGB7X1e2c7imqonJJYM1
0hByGPAn3g+5XdGSig==
=gAcy
-----END PGP SIGNATURE-----
Merge tag 'ntfs-for-7.3-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/ntfs
Pull ntfs fixes from Namjae Jeon:
- Serialize truncate, fallocate, and mmap fault paths with
invalidate_lock, avoiding mmap failures during concurrent size
changes and exposure of uninitialized data during allocation
- Correct fallocate signal and zeroing error handling
- Fix FITRIM range alignment to prevent discard requests from extending
into allocated clusters
- Fix free-cluster accounting when cluster-freeing rollback or bitmap
clearing fails
- Keep volumes marked dirty when ntfs errors have been recorded
- Compute bi_sector in 512-byte units, preventing silent corruption on
4Kn devices
- Validate sectors_per_cluster values and prevent undefined shifts when
parsing MFT and index record sizes
- Bound $AttrDef traversal to the loaded table size
- Fix MFT record resizing, memmove overlap, and kmap_local cleanup
issues
- Improve error propagation across attribute, EA, and reparse
operations, including returning -ERANGE for undersized xattr buffers
- Avoid modifying the HasEA flag when setxattr fails and return
DT_UNKNOWN when directory inode lookup fails
- Reduce contention in WOF decompression by performing block reads
outside the decompression lock
* tag 'ntfs-for-7.3-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/ntfs: (23 commits)
ntfs: take invalidate_lock in ntfs_filemap_page_mkwrite()
ntfs: take invalidate_lock in ntfs_setattr_size()
ntfs: handle signal interruption in fallocate
ntfs: fix FITRIM range alignment
ntfs: read WOF chunks outside the decompression lock
ntfs: leave HasEA flag untouched on setxattr failure
ntfs: fix race between fallocate and mmap reads
ntfs: fix memmove overlap in ntfs_new_attr_flags
ntfs: compute bi_sector in 512-byte units
ntfs: reject invalid sectors_per_cluster in the boot sector
ntfs: bound $AttrDef table walk to the loaded table size
ntfs: fix undefined behavior in mft/index record size calculation
ntfs: treat any nonzero dio zero-range return as an error
ntfs: fix incorrect MFT record pointer passed to ntfs_attr_record_resize
ntfs: do not mark the volume clean in sync_fs when errors were recorded
ntfs: skip free cluster decrement when rollback fails
ntfs: only count successfully cleared runs when freeing clusters
ntfs: fix kmap_local leak in write_mft_record_nolock() error paths
ntfs: return real error from ntfs_non_resident_attr_record_add()
ntfs: preserve error code in ntfs_resident_attr_record_add()
...
The flags defined in `enum wx_pf_flags` and its terminator
`WX_PF_FLAGS_NBITS` were originally named with a "PF" (Physical Function)
prefix. However, these flags are not exclusive to PFs and are also
utilized by Virtual Functions (VFs).
Rename the enumeration to `enum wx_flags` and the bit count to
`WX_FLAGS_NBITS` to accurately reflect their shared usage across both PF
and VF drivers, and to prevent potential confusion.
Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
Reviewed-by: Breno Leitao <leitao@debian.org>
Link: https://patch.msgid.link/9479B0506F544556+20260901065659.41273-1-jiawenwu@trustnetic.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
vzalloc() returns zeroed memory, so the memset after the allocation is
redundant.
No functional change.
Signed-off-by: Sang-Heon Jeon <ekffu200098@gmail.com>
Reviewed-by: Xuanqiang Luo <luoxuanqiang@kylinos.cn>
Link: https://patch.msgid.link/20260901110913.977745-1-ekffu200098@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Register and handle the NIX LF error (NIX_LF_ERR_INT) and poison/RAS
(NIX_LF_RAS) interrupt vectors, The handlers acknowledge the interrupt
and log the status (ratelimited) to help debug NIX LF faults.
Signed-off-by: Nitin Shetty J <nshettyj@marvell.com>
Signed-off-by: Naveen Mamindlapalli <naveenm@marvell.com>
Link: https://patch.msgid.link/20260831062600.839203-1-nshettyj@marvell.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Fraglist GRO and hardware GRO can create an fraglist of
HW-GRO packets. This cannot be segmented back into
the original form on TCP tethering scenario.
Avoid constructing such a GSO packet, by flushing an already
built fraglist GRO packet if a hardware GRO packet arrives.
Scenario (Tethering/Forwarding):
1.Driver submits a single TCP packet, P1. P1 is kept in the
gro_list as the first packet.
2. The driver submits a TCP GSO skb, P2. P2 has already aggregated
multiple TCP packets by HW_GRO, and its non-linear data is stored in
frags[].
3. P1 and P2 match the GRO rules, and since there is no local socket,
they are aggregated by skb_gro_receive_list(). The resulting skb,
P3, has a frag_list entry that still contains frags[]:
P3: [ Linear Data ] -> frag_list -> [ Linear Data ]
[ frag[1] ]
[ frag[2] ]
...
4. Later, tcp4_gso_segment() or tcp6_gso_segment() calls
skb_segment_list() to segment P3. However, skb_segment_list() only
segments the entries in frag_list. It does not segment the frags[]
inside P2, so P3 is not restored to the original packets, which leads
to IP fragmentation or packet drop in the following path.
Check skb_is_gso(skb) and current GRO method, make sure fraglist GRO
applies to consecutive non-GSO skb, others adopt regular GRO path.
Fixes: 8d95dc474f ("net: add code for TCP fraglist GRO")
Signed-off-by: Zhaoping Shu <zhaoping.shu@mediatek.com>
Signed-off-by: HW He <hw.he@mediatek.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Link: https://patch.msgid.link/20260901082312.14596-1-zhaoping.shu@mediatek.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
stmmac_select_queue() forces every GSO frame (TCPv4/TCPv6/UDP-L4) onto
TX queue 0, relying on the legacy assumption that at least queue 0 is
always TSO/USO capable. This is no longer needed since
stmmac_features_check() already validates each GSO frame against the
capabilities of the queue it is mapped to, clearing the checksum and GSO
features for queues that cannot perform TSO (e.g. TBS queues or queues
without TX checksum offload support).
Remove stmmac_select_queue() so GSO frames are selected through the
regular queue selection path (XPS, flow hashing and priority mapping)
and can be spread across all TX queues. This also fixes the case where
queue 0 is not TSO-capable while other queues are, which previously
forced all TSO traffic into software GSO. Non-GSO traffic is unaffected,
since the core already falls back to netdev_pick_tx() when ndo_select_queue
is not set.
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@oss.qualcomm.com>
Link: https://patch.msgid.link/20260831-stmmac_select_queue-tso-fix-v3-1-d9c215fe7a85@oss.qualcomm.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
The PF and VF drivers warn and return -EPROBE_DEFER when the AF has
not programmed the RVUM revision or does not answer the mailbox READY
message. That is expected until rvu_af has finished initializing, so
the warning is repeated on every deferred retry.
Use dev_err_probe() instead of dev_warn() so the expected deferral is
not printed at warning level. -EPROBE_DEFER is logged at debug level
and the reason is recorded in devices_deferred.
Signed-off-by: Juuso Rinta <juuso.rinta@nokia.com>
Acked-by: Ratheesh Kannoth <rkannoth@marvell.com>
Link: https://patch.msgid.link/20260901-octeontx2-dev-err-probe-v1-1-1b5e1affb994@nokia.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
The core software reset issued in stmmac_init_dma_engine() during
ndo_open() callback clears the MTL RX packet parser registers, but
stmmac_rxp_config() is only invoked from the cls_u32 add/delete paths.
After an ifdown/ifup cycle the hardware therefore runs with the default
all-pass table while priv->tc_entries still reports the filters as
installed. Re-apply the RX packet parser table from priv->tc_entries in
stmmac_hw_setup(), right after the software reset, so the filters are
restored when the interface is brought up again.
Fixes: 4dbbe8dde8 ("net: stmmac: Add support for U32 TC filter using Flexible RX Parser")
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@oss.qualcomm.com>
Link: https://patch.msgid.link/20260831-stmmac_tc_cls32_reconfigure-v1-1-21cb459e64ae@oss.qualcomm.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
RX queue 31 has always been allocated and filled by airoha_qdma_init_rx()
since RX_DONE_INT_MASK spans queues 0-31, but none of the RX_IRQ*
_BANK_PIN_MASK values covered BIT(31). As a consequence the RX_DONE
interrupt for queue 31 was never enabled, airoha_qdma_rx_process() never
ran on that queue and its buffers were never reaped.
Route RX queue 31's RX_DONE interrupt to IRQ bank 1 so that the queue
is drained and its buffers returned to the page pool.
Fixes: f252493e18 ("net: airoha: Enable multiple IRQ lines support in airoha_eth driver.")
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20260830-airoha-rxdone-rxq31-v1-1-830a91503f2f@kernel.org
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Maxime Chevallier says:
====================
net: stmmac: dwmac4: Auto-discover UC filter size
Following my attempts to get clean ethtool selftests runs on stmmac [1],
several issues were found with the unicast filtering.
[1]: https://lore.kernel.org/netdev/20260827134004.45ffb57e@kernel.org/
This lead to the discovery that on dwmac4 platforms, the unicast filter
size is always falling back to the default value of 1 entry. On older
variants, the size comes from devicetree.
With a single-entry filter, we directly fallback to unicast promisc as
soon as any entry is added in the dev->uc list.
dwmac4 exposes through the HW_Features0 register the actual size of the
unicast filter, which is made of 3 banks (details in patch 2). Let's use
this feature to grab the filter size.
Results on actual hardware :
- imx8mp : goes from 1 entry to 64
- stm32mp1 : goes from 1 entry to 4
- jh7110 : goes from 1 entry to 9
- yt6801 : still 1 single entry, on extra implemented in HW
====================
Link: https://patch.msgid.link/20260831070121.349778-1-maxime.chevallier@bootlin.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Contrary to dwmac1000 that gets its number of perfect filter entries
through the 'snps,perfect-filter-entries' property, dwmac4 allows
reading the filter size from the HW features registers.
Perfect filter is used for Unicast filtering, and can contain up to 128
entries, each having its own set of registers to access it.
The registers are always at the same location in the map, regardless
whether or not the entry is implemented in hardware. Accessing a register
for an un-implemented entry just doesn't do anything.
The filter is made of one always-available entry, and 3 configurable
banks :
Entry 0 : Always implemented, stores the primary MAC address
Entry 1 \
... + -- Can contain between 0 and 31 entries. Number of available
Entry 31 / entries in HW_Features0[18:22].
Entry 32 \
... + -- Additional 32 entries, all or nothing. Availability is
Entry 63 / specified by HW_Features0[23]
Entry 64 \
... + - Additional 64 entries, all or nothing. Availability is
Entry 127 / specified by HW_Features0[24].
Each of the 3 configurable banks are independently selectable, meaning
we can have gaps in the register banks.
For instance, a setup with 50 addresses enabled will have 17 entries in
the first bank and the additional 32 bank enabled (50 = 32 + 17 + 1).
Another example with 70 addresses : 64 addr bank on, 5 addresses in the
first bank (70 = 64 + 5 + 1).
While I haven't seen HW with gaps in the banks, Synopsys confirmed this
is a real possibility.
Let's therefore introduce a dwmac4 helper to get the physical slot
number of a given entry, allowing to configure the correct bank when
populating the filter. As we need the HW feature-set to compute the
index, store the bank info in the mac_device_info struct.
The total number of available entries is computed based on the
discovered parameters, instead of using the default value of 1.
Results on HW that uses dwmac4 :
- imx8mp : goes from 1 entry to 64 (1 + 31 + 32)
- stm32mp1 : goes from 1 entry to 4 (1 + 3)
- jh7110 : goes from 1 entry to 9 (1 + 8)
- yt6801 : goes from 1 entry to hum, 1 entry (no extra addresses)
Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Reviewed-by: Nicolai Buchwitz <nb@tipi-net.de>
Link: https://patch.msgid.link/20260831070121.349778-3-maxime.chevallier@bootlin.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
dwmac4 has multiple banks of perfect filter entries, independently
configurable during IP integration.
The multi_addr bank reports a number between 0 and 31 corresponding to
the actual number of entries in that bank, while the 32 and 64 banks
are all-or-nothing.
Expose these caps over debugfs as well.
Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Reviewed-by: Nicolai Buchwitz <nb@tipi-net.de>
Link: https://patch.msgid.link/20260831070121.349778-2-maxime.chevallier@bootlin.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
David Yang says:
====================
net: dsa: motorcomm: Add LED support
LEDs can be described in the device tree using the standard LED node
notation. Currently, only parallel mode and strict 1:1 mapping (i.e. the
HW default) are supported.
====================
Link: https://patch.msgid.link/20260831044818.4103477-1-mmyangfl@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Add LEDs definition example for yt921x to describe how they should be
defined for a correct usage.
Signed-off-by: David Yang <mmyangfl@gmail.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Link: https://patch.msgid.link/20260831044818.4103477-6-mmyangfl@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Each port has at most 3 LEDs connected and can be declared using the
standard LEDs structure.
Currently, only parallel mode and strict 1:1 mapping (i.e. the HW
default) are supported.
Signed-off-by: David Yang <mmyangfl@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://patch.msgid.link/20260831044818.4103477-5-mmyangfl@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
SMI operations are going to be used across different modules. Minor
changes are applied to fix build errors.
Signed-off-by: David Yang <mmyangfl@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://patch.msgid.link/20260831044818.4103477-4-mmyangfl@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
yt921x is already the longest single-file DSA driver, so it's time to
split it into parts.
Signed-off-by: David Yang <mmyangfl@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://patch.msgid.link/20260831044818.4103477-3-mmyangfl@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
mutex_is_locked() was used to check the lock status. While it should not
be triggered unless a bug is introduced, it does not warn on lock being
held by another thread. Fix it with lockdep helpers.
Fixes: 186623f4aa ("net: dsa: yt921x: Add support for Motorcomm YT921x")
Signed-off-by: David Yang <mmyangfl@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://patch.msgid.link/20260831044818.4103477-2-mmyangfl@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Allison Henderson says:
====================
net/rds: own the fastpath locks across connection teardown
This is v5 of the follow-up set to "net/rds: Bug fix ports, part 2"
[1] (v1 at [2], v2 at [3], v3 at [4], v4 at [5]). During review of part 2,
the later half of that series needed more work than a respin, so it was
split off into this set together with the companion fixes identified
along the way. As discussed on the v2 thread, it is targeted at net.
RDS connection teardown quiesces the transmit and receive-refill fast
paths by waiting for the RDS_IN_XMIT/RDS_RECV_REFILL bits to be
sampled clear. Sampling a bit clear is not owning it: the fast path
can re-take its bit right after the wait returns and then run
concurrently with the transport shutdown and the send-state reset.
Oracle UEK closed this by making teardown acquire the bits as locks
("rds: Make sure transmit path and connection tear-down does not run
concurrently"); patches 5 and 6 do the same for the two
rds_send_path_reset() call sites upstream.
Making teardown block on the bits as locks promotes several latent
ordering bugs from rare to load-bearing, so they are fixed first:
Patches 1 and 2 fix the release side of the two bit locks.
release_in_xmit() and release_refill() both clear their bit and then
test for waiters, but the barrier is on the wrong side of the clear
to order the critical section's stores before the release, and the
waiter check does not order against the clear. Once teardown blocks
on these bits as locks (uninterruptible and untimed), a lost wake-up
or a store observed out of order stops mattering only in theory.
Use clear_bit_unlock() and wq_has_sleeper(), the pattern already
half-present in release_in_xmit().
Patch 3: rds_conn_path_reset() wipes the whole cp_flags word with a
plain store. Once teardown owns bits in that word across the reset,
a blanket store would end lock ownership early - and it already
races atomic RMWs on the same word today. Clear the bits the reset
is responsible for individually, as Oracle UEK also does.
Patch 4: rds_tcp_reset_callbacks() stores RDS_CONN_RESETTING
unconditionally, which can overwrite the RDS_CONN_ERROR or
RDS_CONN_DISCONNECTING of a shutdown already in progress on the same
path and send that shutdown through an extra drop cycle. Once the
accept path can park for the duration of a teardown (patch 6) that
window widens, so make the transition conditional first, as Oracle
UEK does.
With those in place, patch 5 converts rds_tcp_reset_callbacks() from
waiting on RDS_IN_XMIT to acquiring it, holding it across the socket
swap and rds_send_path_reset(), and patch 6 has rds_conn_shutdown()
hold both bit locks across the transport shutdown and path reset.
Patch 7 fixes a pre-existing teardown-state hole that this series
makes easier to hit but did not introduce. Since commit
e97656d03c the final transition in rds_conn_shutdown() accepts
RDS_CONN_ERROR as well as RDS_CONN_DISCONNECTING, so that a FIN
processed during the teardown does not derail the shutdown. But
consuming that RDS_CONN_ERROR also consumes the shutdown pass that a
concurrent rds_conn_path_drop() queued along with it. For a FIN that
is harmless; for rds_tcp_accept_one() it is not. A drop can race the
accept's DOWN -> CONNECTING path claim, the accept then installs the
freshly accepted socket while the drop's teardown - which sampled
tc->t_sock before that socket existed - is still running,
rds_connect_path_complete() fails and drops the path again, and if the
in-flight shutdown's final transition then swallows that
RDS_CONN_ERROR, the pass that should reap the just-installed socket
finds the path already RDS_CONN_DOWN and does nothing. The socket is
leaked with its callbacks armed and its rds_tcp_connection still on
rds_tcp_tc_list, the peer sees an established connection that nothing
reads, and the path wedges in RDS_CONN_DOWN. Make the final
transition DISCONNECTING -> DOWN only and leave a racing drop's
RDS_CONN_ERROR alone, so the pass it queued runs and tears down
whatever attached to the path; the branch quiesces the reconnect
timer itself, since a pending destroy can suppress that pass (see the
changes below).
This surfaced while re-reviewing v3: whether the
release-then-transition ordering in patch 6 could let a woken waiter
install a socket that the teardown then strands. Chasing that down,
the reachable form of the leak turned out to be the accept-vs-drop
race above rather than the parked-waiter path (a path mid-teardown is
never handed to rds_tcp_reset_callbacks(): rds_tcp_accept_one_path()
only claims a path it can move DOWN -> CONNECTING), and it predates
this series. It reproduces on an instrumented kernel - a test-only
drop injected into the accept window plus a widened teardown-to-tail
window - as an ESTABLISHED socket with an ever-growing receive queue
on a path stuck down; the same kernel runs clean with patch 7.
The set was built per-commit, run through the rds selftests (tcp and
rdma/rxe), and exercised with a connection/netns churn load and
module load/unload cycles; the patch 7 destroy-window fix was
additionally verified against an instrumented kernel that reproduces
the timer-left-armed WARN deterministically (fires on every destroyed
path unfixed, silent with the fix).
====================
Link: https://patch.msgid.link/20260828223921.202913-1-achender@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
rds_conn_shutdown() finishes by moving the path from
RDS_CONN_DISCONNECTING to RDS_CONN_DOWN, and also accepts
RDS_CONN_ERROR as the starting state of that final transition, so that
a FIN processed in softirq context during the teardown does not derail
the shutdown into a noisy error path.
But consuming that RDS_CONN_ERROR also consumes the shutdown pass that
came with it: rds_conn_path_drop() sets RDS_CONN_ERROR and then queues
cp_down_w, and a pass that starts on a path already in RDS_CONN_DOWN
is a no-op. For the FIN case that is harmless - the socket the FIN
arrived on is the very socket the teardown just released. It is not
harmless for a dropper that attached something to the path first.
rds_tcp_accept_one() is such a dropper. Its path claim in
rds_tcp_accept_one_path() transitions RDS_CONN_DOWN ->
RDS_CONN_CONNECTING, and a concurrent drop - a FIN on a previous
socket in softirq context, an administrative reset - can put the path
into RDS_CONN_ERROR between that claim and the state check that
follows, which accepts RDS_CONN_ERROR. The accept then installs the
freshly accepted socket with rds_tcp_set_callbacks() while the queued
teardown - which sampled tc->t_sock before this socket existed - is
still running. rds_connect_path_complete() fails its transition to
RDS_CONN_UP and drops the path again, queueing the pass that should
reap the socket it just installed. If the in-flight shutdown's final
transition consumes that drop's RDS_CONN_ERROR, the queued pass finds
the path in RDS_CONN_DOWN and does nothing. The installed socket is
never torn down: it sits established with its callbacks armed and its
rds_tcp_connection on rds_tcp_tc_list, the peer sees a connection that
nothing ever reads, and the path is wedged in RDS_CONN_DOWN until some
later event drops it again. Reproduced with widened race windows as
an ever-growing receive queue on a socket owned by a path stuck in
RDS_CONN_DOWN, with the peer's send path wedged behind it.
Make the final transition only DISCONNECTING -> DOWN. If it fails
because the path is in RDS_CONN_ERROR, a drop raced the teardown:
cancel the reconnect timer and clear RDS_RECONNECT_PENDING - the one
piece of the skipped tail that must not be left behind - and return,
letting the pass the drop queued finish the job: it tears down
whatever attached to the path in the meantime, completes the
transition to RDS_CONN_DOWN, and re-arms the reconnect from its own
tail.
The timer quiesce in that branch matters because the racing drop does
not always queue that pass: rds_conn_path_drop() returns without
queueing when a destroy is pending - exactly the situation during a
netns teardown or module unload, when a FIN on the dying socket is
processed while rds_conn_path_destroy() flushes cp_down_w. If the
flushed pass is the one that takes this return, no later pass exists,
and rds_conn_path_destroy() would find cp_conn_w still armed
(WARN_ON) and then free a path whose reconnect timer can still fire.
With the cancel in the branch, every exit of a shutdown pass leaves
the timer quiesced no matter which pass completes the transition.
The FIN case keeps making progress, one pass later and still without
noisy logging. Any other state keeps today's rds_conn_path_error()
handling; no current cp_state writer can leave a DISCONNECTING path
in anything but RDS_CONN_ERROR (every other writer is a cmpxchg from
a non-DISCONNECTING state), so that branch is defensive.
On kernels without the preceding patches the same hazard exists with
the sample-based quiesce; the fix applies there equally.
Fixes: e97656d03c ("rds: tcp: allow progress of rds_conn_shutdown if the rds_connection is marked ERROR by an intervening FIN")
Signed-off-by: Allison Henderson <achender@kernel.org>
Link: https://patch.msgid.link/20260828223921.202913-8-achender@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
rds_conn_shutdown() quiesces the transmit and receive-refill paths by
waiting for RDS_IN_XMIT and RDS_RECV_REFILL to be sampled clear, and
then runs the transport shutdown and rds_conn_path_reset(). Sampling
the bits clear is not the same as owning them: the moment after the
wait_event() returns, rds_send_xmit() can re-acquire RDS_IN_XMIT (or
rds_ib_recv_refill() can re-acquire RDS_RECV_REFILL) and run
concurrently with the teardown.
The sender does recheck the connection state after taking the lock,
but that recheck is a classic store-buffering pattern: teardown writes
the state and reads the bit while the sender writes the bit and reads
the state. acquire_in_xmit() is only an acquire operation, so on
weakly ordered architectures both sides can miss each other's write,
and the transmit path then runs while the transport zeroes its rings
(e.g. rds_ib_ring_init()) and rds_send_path_reset() rewrites the
transmit state under it.
Oracle UEK fixed the same class of crashes - a 14-year tail of
BUG_ON()s in rds_ib_sub_signaled(), unexpected op-codes and NULL
dereferences in rds_ib_send_cqe_handler() during failover testing -
by making the teardown path *acquire* the fastpath bit locks instead
of testing them ("rds: Make sure transmit path and connection
tear-down does not run concurrently"). Ownership of a single word is
decided by RMW atomicity, so no cross-variable ordering is needed.
Do the same here: take both locks before calling the transport
shutdown, hold them across rds_conn_path_reset(), and release them
explicitly with a wake-up afterwards. Both are released with
clear_bit_unlock(), so that the ring re-initialization done by the
transport shutdown and the transmit state rewritten by
rds_send_path_reset() are ordered before either bit is seen clear by
the next acquire_in_xmit() or acquire_refill().
The fastpath users of these bits - rds_send_xmit() and
rds_ib_recv_refill() - are trylock style and back off while teardown
owns the locks, so no new lock dependency is introduced for them.
rds_tcp_reset_callbacks() is different: since the previous patch it
acquires RDS_IN_XMIT as well, and it blocks doing so, so its wait now
spans the teardown instead of at most one send batch. That waiter
runs from rds_tcp_accept_one() on the single-threaded krdsd workqueue
and holds rds_tcp_accept_lock and t_conn_path_lock while it waits, so
a duelling SYN accepted while its path is being torn down parks
accept processing for the duration of the teardown - for TCP bounded
by the (up to 5 s) drain loop in rds_tcp_conn_path_shutdown(). An IB
path's drain in rds_ib_conn_path_shutdown() has no round cap, but no
blocking waiter either: rds_tcp_reset_callbacks() is the only blocking
acquirer of these bits and waits only on its own TCP path, and the
fastpaths are trylock-and-back-off on both transports, so a long IB
drain lengthens only that path's own quiesce. The
window is narrow: the accept-side state check has to pass before the
teardown moves the path to RDS_CONN_DISCONNECTING.
Because krdsd is a single global workqueue, everything else queued
there - accept processing for other connections and network
namespaces, and the flush_workqueue(rds_wq) in rds_tcp_listen_stop()
during namespace teardown - waits behind the parked accept worker for
that time. It cannot deadlock, although the waits do point at each
other: the teardown blocks until the bit's holder releases it, and
the holder may be that krdsd accept worker. The holder finishes
without needing anything the teardown owns: the sync cancels
rds_tcp_reset_callbacks() issues target cp_send_w and cp_recv_w on
the path's ordered cp_wq, whose only execution slot is occupied by
the blocked cp_down_w itself, so they are pending at most and cancel
without flushing - a reliance on cp_wq being ordered that is now
noted next to those cancels (on the allocation-failure fallback where
a path shares rds_wq, the work items simply serialize).
Nor is the blocking wait itself new: rds_tcp_reset_callbacks() has
waited on RDS_IN_XMIT from the krdsd work item since
commit 335b48d980 ("RDS: TCP: Add/use rds_tcp_reset_callbacks to
reset tcp socket safely"); this patch stretches its worst case from
a sender's batch to the teardown's drain. The alternative to parking
is the accept path racing the teardown, which is what these patches
close; making the teardown itself non-blocking is a separate item.
One observable side effect: the SENDING flag reported by rds-info has
always mirrored RDS_IN_XMIT, so it now also covers the window where
teardown owns the bit.
The comments that describe the old sample-based handshake or name
rds_send_xmit() as the only other holder of these bits - in
rds_send_xmit(), above rds_conn_path_reset(), in rds_ib_recv_refill()
and in rds_tcp_reset_callbacks() - are updated to match.
For anyone backporting this patch standalone: it depends on
"net/rds: clear cp_flags bits individually in rds_conn_path_reset()"
and "net/rds: acquire RDS_IN_XMIT in rds_tcp_reset_callbacks()"
earlier in this series. Without the former, the blanket cp_flags
clear in rds_conn_path_reset() would drop both held bits in the middle
of the teardown; without the latter, rds_tcp_reset_callbacks() would
still sample t_sock without owning RDS_IN_XMIT. "net/rds: use
clear_bit_unlock() in release_refill()" is needed for the refill
side's release to pair with the acquire added here, and the follow-up
"net/rds: don't let rds_conn_shutdown() consume a concurrent drop"
completes the teardown-state handling for the waiter this patch
parks; a backport should carry all four.
Fixes: 0f4b1c7e89 ("rds: fix rds_send_xmit() serialization")
Signed-off-by: Håkon Bugge <haakon.bugge@oracle.com>
[achender: reimplement for net-next shutdown path: acquire the existing
RDS_IN_XMIT/RDS_RECV_REFILL bit locks in rds_conn_shutdown() and release
after teardown; update comments and commit message]
Signed-off-by: Allison Henderson <achender@kernel.org>
Link: https://patch.msgid.link/20260828223921.202913-7-achender@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>