Commit graph

1,485,420 commits

Author SHA1 Message Date
Linus Torvalds
a90ee4305c Linux 7.3-rc6 v7.3-rc6 2026-10-04 13:45:25 -07:00
Haibo Chen
94b6df0504 spi: spi-nxp-fspi: exit stop mode before waiting for DLL lock
For 8D-8D-8D (octal DTR) mode the FlexSPI samples read data using
MCR0[RXCLKSRC] = 3 (flash-memory-provided read strobe on the DQS pad),
which requires the DLL to be locked. Per the i.MX95 Reference Manual
(FlexSPI chapter, "DLL configuration for sampling"), when the serial
root clock is above 100 MHz the DLL is enabled (DLLxCR[DLLEN] = 1,
OVRDEN = 0) and software must then wait for STS2[xREFLOCK] and
STS2[xSLVLOCK] to be asserted before starting a read or write. This DLL
lock is relative to the serial root clock.

While the module is in stop mode (MCR0[MDIS] = 1) the AHB and serial
clocks are gated off internally, so the serial root clock the DLL locks
against is not running. nxp_fspi_dll_calibration() both programs DLLxCR
and then polls STS2 for lock. When it runs entirely in stop mode the
STS2 REF/SLV lock bits never assert (observed as "DLL lock failed" with
STS2 = 0).

The MCR0 bit fields (RXCLKSRC) and the serial root clock rate still have
to be reconfigured in stop mode, so keep entering stop mode around that.
Only move the exit from stop mode (clearing MCR0[MDIS]) ahead of the DLL
calibration/override step, so that the serial root clock is running when
the DLL is calibrated and STS2 can report lock.

Fixes: b4bde5cfff ("spi: spi-nxp-fspi: enter stop mode before reconfiguring MCR0 and DLL")
Signed-off-by: Haibo Chen <haibo.chen@nxp.com>
Link: https://patch.msgid.link/20260928-fspi-fix-v1-1-a0f9288cd5c8@nxp.com
Signed-off-by: Mark Brown <broonie@kernel.org>
2026-10-04 22:20:44 +02:00
Christian Brauner
1514faf41f
Merge patch series "mount: more bugfixes, trapped in the Black Lodge edition"
Christian Brauner <brauner@kernel.org> says:

More bugfixes from work in this area:

- unhash a dentry before detaching the mounts on it to avoid leaking
  sensitive data
- don't reveal overmounted entries in refwalk
- refuse F_SET_RW_HINT on an immutable inode
- refuse an automount below a mount that is in no namespace
- handle mount locking for automounts correctly
- don't update the access time on nullfs
- never expire a locked mount
- keep the lock on a mount that a propagated copy is moved beneath
- decide the subtree check under mount_lock
- keep the private nullfs instance in knullfs
- nothing is mounted on or written through knullfs
- let a filesystem refuse fsnotify marks on its objects
- refuse file locks on nullfs
- refuse leases and delegations on nullfs
- take no inode lock on an immutable directory

* patches from https://patch.msgid.link/20261002-work-mount-fixes-4-v1-0-dd44b89d44ce@kernel.org:
  selftests/filesystems: check that reading the root of an empty mount namespace stalls nobody
  selftests/filesystems: add a helper that holds a readdir in a page fault
  readdir: take no inode lock on an immutable directory
  nullfs: refuse file locks
  fsnotify: let a filesystem refuse marks on its objects
  namespace: nothing is mounted on or written through knullfs
  namespace: keep the private nullfs instance in knullfs
  fhandle: decide the subtree check under mount_lock
  selftests/filesystems: check that an automount below an overlay layer is refused
  selftests/filesystems: check the atime of the empty mount namespace root
  selftests/filesystems: check that a lock lands on the right mount and stays
  namespace: keep the lock on a mount that a propagated copy is moved beneath
  namespace: never expire a locked mount
  nullfs: don't update the access time
  namespace: handle mount locking for automounts correctly
  namespace: refuse an automount below a mount that is in no namespace
  selftests/filesystems: check that an immutable inode takes no write hint
  fcntl: refuse F_SET_RW_HINT on an immutable inode
  namei: don't reveal overmounted entries in refwalk
  namespace: unhash a dentry before detaching the mounts on it

Link: https://patch.msgid.link/20261002-work-mount-fixes-4-v1-0-dd44b89d44ce@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-10-04 21:46:09 +02:00
성병찬
dd3ea3fcba KEYS: Fix add_key() race with keyring restriction
__key_create_or_update() snapshots keyring->restrict_link before taking
the destination keyring's semaphore.  keyring_restrict() installs a
restriction while holding that semaphore.

This allows a writer to observe no restriction, wait for the keyring
owner to install a reject-all restriction and return successfully, and
then link a key using the stale NULL snapshot.  The writer only needs
write permission on the destination keyring.

Move the restrict_link read after __key_link_lock() and
__key_link_begin().  The read and the subsequent restriction check are
then serialized with restriction installation by keyring->sem.

The race was reproduced on v7.2.8 in 19 executions where restriction
installation returned before the link completed.  All 19 linked the key
despite the reject-all restriction.  With this change, 312 executions
reached the same ordering and every add_key() call failed with -EPERM.

The issue was found by manual concurrency analysis assisted by AI-based
analysis and independently verified with a QEMU reproducer and kernel
instrumentation.

Fixes: 5ac7eace2d ("KEYS: Add a facility to restrict new links into a keyring")
Cc: stable@vger.kernel.org
Signed-off-by: 성병찬 <tjdqudcks0424@naver.com>
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
Link: https://lore.kernel.org/r/20260930041802.6114-1-tjdqudcks0424@naver.com
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
2026-10-04 21:09:32 +03:00
Karl Mehltretter
25bf14f817 keys: finalize persistent keyring timeout after link attempt
When no keyring exists for the requested UID, KEYCTL_GET_PERSISTENT
creates and registers one before linking it to the requested destination.
The configured timeout is set only after the destination link succeeds.

A destination restricted with KEYCTL_RESTRICT_KEYRING makes that link fail
with -EPERM. With persistent_keyring_expiry set to 60 seconds, /proc/keys
still reports the registered keyring's expiry as "perm".
The failed call therefore leaves a quota-exempt keyring in the namespace's
hidden register, where it may remain until namespace teardown.

Rename the write-locked helper to key_get_or_create_persistent() and return
the key reference through a result parameter. Return 0 when it creates a
keyring and 1 when the retry finds an existing one. Return a negative error
on failure. Another caller may create the keyring between the initial
read-locked lookup and the retry under the write lock.

Set the timeout after permission checking and linking. Do this on success,
or on failure if the call allocated the keyring. This leaves a new keyring
collectible after failure without starting its timeout while linking is
still in progress.

Cc: stable@vger.kernel.org # v5.10+
Fixes: f36f8c75ae ("KEYS: Add per-user_namespace registers for persistent per-UID kerberos caches")
Assisted-by: LLM
Signed-off-by: Karl Mehltretter <kmehltretter@gmail.com>
Link: https://lore.kernel.org/r/20260912095440.79864-1-kmehltretter@gmail.com
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
2026-10-04 21:09:32 +03:00
Alexey Charkov
5b4bd13e05 power: supply: core: prevent unregistering a power supply while a callback runs
Once a power supply is registered, its callbacks can immediately start
firing from other contexts, such as external_power_changed() triggered by
the TCPM stack. If a power supply is unregistered while the callback is
still running, the driver data can already be freed when the callback
tries to access it, leading to a use-after-free.

This happens e.g. when the hardware bus carrying the power supply device
malfunctions (e.g. I2C is hogged down by another malfunctioning device)
immediately after the power supply is registered, and thus the core is
still processing the callbacks which were queued up when the driver
starts the removal, leading in some cases to a kernel crash, e.g.:

[   11.645942] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000005
[   11.646751] Mem abort info:
[   11.647006]   ESR = 0x0000000096000004
[   11.647338]   EC = 0x25: DABT (current EL), IL = 32 bits
[   11.647806]   SET = 0, FnV = 0
[   11.648077]   EA = 0, S1PTW = 0
[   11.648356]   FSC = 0x04: level 0 translation fault
[   11.648785] Data abort info:
[   11.649041]   ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000
[   11.649524]   CM = 0, WnR = 0, TnD = 0, TagAccess = 0
[   11.649981]   GCS = 0, Overlay = 0, DirtyBit = 0
[   11.650390] [0000000000000005] user address but active_mm is swapper
[   11.650955] Internal error: Oops: 0000000096000004 [#1]  SMP
[   11.651460] Modules linked in:
[   11.651742] CPU: 1 UID: 0 PID: 144 Comm: kworker/1:2 Not tainted 7.2.0-rc6-g62a9297af2cd #1 PREEMPT
[   11.652553] Hardware name: Flipper One rev. F0B1C2 (DT)
[   11.653024] Workqueue: events power_supply_changed_work
[   11.653511] pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[   11.654135] pc : __power_supply_is_supplied_by+0x18/0x100
[   11.654624] lr : __power_supply_am_i_supplied+0x40/0xb8
[   11.655098] sp : ffff80008192bb30
[   11.655399] x29: ffff80008192bb30 x28: 0000000000000000 x27: 0000000000000000
[   11.656049] x26: 0000000000000000 x25: 0000000000000000 x24: 0000000000000000
[   11.656695] x23: ffff0000c19f4200 x22: ffffdb2232ba4ea8 x21: ffff80008192bc28
[   11.657344] x20: ffff0000c1eef000 x19: ffff80008192bc18 x18: 00000000a0886e62
[   11.657991] x17: 000000040044ffff x16: 04500072b5503510 x15: 0000000000000000
[   11.658639] x14: 0000000000000000 x13: 0000000000000220 x12: 0000000000000000
[   11.659286] x11: 0000000000000000 x10: ffff0000c1fdb2b0 x9 : ffffdb2232ba5590
[   11.659934] x8 : 00000000e5b906e6 x7 : ffff0000c2502778 x6 : ffffdb22339793d0
[   11.660581] x5 : ffff80008192bc18 x4 : ffff0000c19cbca0 x3 : 0000000000000000
[   11.661228] x2 : ffff0000c1fdaf40 x1 : ffffffffffffffed x0 : ffff0000c1eef000
[   11.661878] Call trace:
[   11.662103]  __power_supply_is_supplied_by+0x18/0x100 (P)
[   11.662596]  __power_supply_am_i_supplied+0x40/0xb8
[   11.663040]  psy_for_each_psy_cb+0x20/0x40
[   11.663416]  class_for_each_device+0x110/0x150
[   11.663825]  power_supply_am_i_supplied+0x68/0x100
[   11.664262]  bq257xx_external_power_changed+0x58/0x140
[   11.664733]  __power_supply_changed_work+0x60/0x80
[   11.665170]  psy_for_each_psy_cb+0x20/0x40
[   11.665545]  class_for_each_device+0x110/0x150
[   11.665953]  power_supply_changed_work+0x98/0x1b8
[   11.666382]  process_one_work+0x164/0x4c0
[   11.666758]  worker_thread+0x19c/0x320
[   11.667104]  kthread+0x138/0x150
[   11.667408]  ret_from_fork+0x10/0x20
[   11.667744] Code: d503233f a9bd7bfd 910003fd a90153f3 (f9400c34)
[   11.668294] ---[ end trace 0000000000000000 ]---

Add a read-write semaphore between external_power_changed() and
power_supply_unregister() to prevent the latter from returning (and thus
the driver from freeing its data) while the callback is still running.

Fixes: bc1540561c ("power_supply: Add API for safe access of power supply function attrs")
Signed-off-by: Alexey Charkov <alchark@flipper.net>
Link: https://patch.msgid.link/20260910-bq257xx-init-v3-1-4e219a1a04a5@flipper.net
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
2026-10-04 18:49:02 +02:00
Linus Torvalds
7704c4c5bb i2c-fixes for v7.3-rc6
Three patches in xiic for fixing the block reads and a single
 cleanup in the error path.
 
 - at91: also release DMA channels when deferring probe
 
 - xiic: fix SMBus block reads with PEC
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQScDfrjQa34uOld1VLaeAVmJtMtbgUCasIP0gAKCRDaeAVmJtMt
 bplRAP94u1e4hKXK0XeiC2WtZ7vfBYtwjeHgalyruKgnL3sK3wEAutT0bEOxpk1p
 cx+8y8eF0L7wOKSRU4+cHrW65YWxIQU=
 =x4Aw
 -----END PGP SIGNATURE-----

Merge tag 'i2c-fixes-7.3-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/andi.shyti/linux

Pull i2c fixes from Andi Shyti:
 "Three patches in xiic for fixing the block reads and a single cleanup
  in the at91 error path:

   - at91: also release DMA channels when deferring probe

   - xiic: fix SMBus block reads with PEC"

* tag 'i2c-fixes-7.3-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/andi.shyti/linux:
  i2c: at91: release DMA channels when probe defers
  i2c: xiic: don't clobber msg->len to signal block-read completion
  i2c: xiic: defer RX_FULL until all trailing bytes are in FIFO
  i2c: xiic: preserve PEC byte length in SMBus block read setup
2026-10-04 09:38:11 -07:00
Mark Brown
5a26d7d96a regulator: of: Fixes to of_regulator_bulk_get_all()
Alexey Charkov <alchark@flipper.net> says:

of_regulator_bulk_get_all() only fills in the .consumer part of the
struct regulator_bulk_data for the regulators it gets, leaving .supply as
garbage, while the rest of the regulator core expects a meaningful name
there (e.g. for error prints), causing uninitialized memory access in any
failure paths in the core.

It also allocates the supplies array and hands it to callers, but never
says the callers need to free it (which they don't currently), causing
leaks.

Fix the former and document the latter in the kerneldoc to help any new
users avoid the leak.

Link: https://patch.msgid.link/20260930-regulator-get-all-v2-0-ca82070d22f2@flipper.net
2026-10-04 18:29:13 +02:00
Alexey Charkov
b35ff7bd7d regulator: of: state who owns the array from of_regulator_bulk_get_all()
of_regulator_bulk_get_all() allocates the consumer array and hands it to
the caller, but never said so. Its own error path frees the array, while
regulator_bulk_free() only puts the regulators, so both callers release
the regulators and leak the array.

Spell the contract out in the kerneldoc.

Signed-off-by: Alexey Charkov <alchark@flipper.net>
Link: https://patch.msgid.link/20260930-regulator-get-all-v2-2-ca82070d22f2@flipper.net
Signed-off-by: Mark Brown <broonie@kernel.org>
2026-10-04 18:29:12 +02:00
Alexey Charkov
e2151c29ce regulator: of: fill in supply names in of_regulator_bulk_get_all()
of_regulator_bulk_get_all() returns an array it allocated itself, and
fills in only the consumer of each entry. Every other way of getting a
bulk array has the supply name set, because the caller provides it, and
the core expects it to be there: regulator_bulk_enable() prints it when
a supply fails to enable, so a caller that hands such an array to it
dereferences uninitialised memory on that path.

Copy each name into the array's own allocation, right behind the
entries, so that it shares the array's lifetime and callers still have
nothing extra to free. That also retires the fixed 64 byte stack buffer
the names were assembled in, which is_supply_name() never bounded the
copy against.

Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/patchset/20260928-b4-rk3576-reboot-mode-v1-0-65486b03bd41@flipper.net?part=3
Fixes: 27b9ecc7a9 ("regulator: Add of_regulator_bulk_get_all")
Signed-off-by: Alexey Charkov <alchark@flipper.net>
Link: https://patch.msgid.link/20260930-regulator-get-all-v2-1-ca82070d22f2@flipper.net
Signed-off-by: Mark Brown <broonie@kernel.org>
2026-10-04 18:29:12 +02:00
Svyatoslav Ryhel
6bca94e642 power: supply: generic-adc-battery: Fix temperature IIO channel conversion
Temperature IIO channel data is provided in milli-degrees, while
POWER_SUPPLY_PROP_TEMP is expected to be in deci-degrees. Adjust the
existing logic to reflect this conversion properly.

Fixes: 33088c0513 ("power: supply: generic-adc-battery: add temperature support")
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
Link: https://patch.msgid.link/20260926142905.206215-2-clamor95@gmail.com
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
2026-10-04 18:01:20 +02:00
Linus Torvalds
06ac073129 x86 architecture fixes [with an UM fix included]:
- Don't apply va_align to hugetlb mappings on AMD F15h systems
    that have custom va_align.bits values (Laurent Wandrebeck)
 
  - Fix PMD teardown handling regression flagged by lockdep
    (Mikhail Gavrilov)
 
  - Hide ptrace header register offset macros behind __ASSEMBLER__ or
    __FRAME_OFFSETS, to fix user-space build errors that may trigger
    if they happen to shadow these short and generic macro names
    (Nick Desaulniers)
 
 Signed-off-by: Ingo Molnar <mingo@kernel.org>
 -----BEGIN PGP SIGNATURE-----
 
 iQJFBAABCgAvFiEEBpT5eoXrXCwVQwEKEnMQ0APhK1gFAmrCBfsRHG1pbmdvQGtl
 cm5lbC5vcmcACgkQEnMQ0APhK1hhvxAAiRvv7gz6K9VIJ7S24PdQOf8VuiuLT4De
 JUxTb6tUJ3VQ9+qk0xKSAg10z603PKn2Ow01znUNV5wTrRcumpkKTk39ut+x9Yl5
 qLDeLVTI/NFAkrYajtjPq3OrwZKnLcAYoZaM9cWtZIoIVCBVIDAsJgS7lIJbUjQ8
 FVvI4UUFaToM79jBMvAA89QOK5FrwO26/ENZLbRyceHzHnPrw/pYObaWpUhUs3S6
 r0OS2NRUacDid3s3SrVJqkJ9siZvS1OdVQZZwSSKz7oNPsk3yH5aqkFrLrCZJNsa
 VG3gCtb7ZLe3omFDmW9RzCYo5afbaUNbdHDOtameVoAT4h71cPoBr3mzAWDJiNEq
 NFu7ICAt7XP9Kvfoa4k0n4HhbYNxH1VAyoXOAiquqpPtsU+ZtG2HhqwZknrqGxM4
 9S127eCrAyGN9CLrYgcnZlALd1HUJ/nGHqdaSVxyxhaJxgxu9e717YmgsxXVl79p
 uCASyox64F4JrKr1n7Yp08UwfPvsquc8ViTyxsfHCuHj59hLnLfxPefr6N86Ztdc
 97yQhb7tDq7z8S8IUQTJuOtcDuqIUdm/VRg6+8SP+hVZquCW2zo0lla24Yi/cS1+
 om89Mfy4l9v+VzkBy2TvNU0cLy0ClK1BQTquHALWFuCDDEmJ4vftc7eWV4VQ+Idh
 lQDDgs0Q66g=
 =j39M
 -----END PGP SIGNATURE-----

Merge tag 'x86-urgent-2026-10-04' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 fixes from Ingo Molnar:

 - Don't apply va_align to hugetlb mappings on AMD F15h systems
   that have custom va_align.bits values (Laurent Wandrebeck)

 - Fix PMD teardown handling regression flagged by lockdep
   (Mikhail Gavrilov)

 - Hide ptrace header register offset macros behind __ASSEMBLER__ or
   __FRAME_OFFSETS, to fix user-space build errors that may trigger
   if they happen to shadow these short and generic macro names
   (Nick Desaulniers)

* tag 'x86-urgent-2026-10-04' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  {x86,um}/uapi/ptrace: Guard register offset macros with __ASSEMBLER__ or __FRAME_OFFSETS
  x86/mm: Drop unnecessary PMD page copy when freeing
  x86/mm: Don't apply va_align to hugetlb mappings on AMD F15h
2026-10-04 08:59:22 -07:00
Linus Torvalds
942e4a0e46 Timer fix:
- Fix task work flags management regression in the hrtimer
    rearming code that can leave task work items unprocessed
    (Karl Mehltretter)
 
 Signed-off-by: Ingo Molnar <mingo@kernel.org>
 -----BEGIN PGP SIGNATURE-----
 
 iQJFBAABCgAvFiEEBpT5eoXrXCwVQwEKEnMQ0APhK1gFAmrCA2cRHG1pbmdvQGtl
 cm5lbC5vcmcACgkQEnMQ0APhK1i79Q/9FjK0/gpSQMMiMYMqId0884UXMtLexmlT
 bMWqLE8OOIx484g0Shelgqjvy335ur9l8FqlV1GXmfUNmA+tTUV7wfonGTCbsZ9z
 7WHtBHkRySItwu9Pg/KBOUuit6+ohX73K8WmPpVazvp3vQR2fIOJ4SsflSsjAFRU
 /kg1996BwfBnvQs9WoULJi28/rTzmNcnCmZjV2kh780LNwlbzFYEAZPihTQl9HYL
 Eg2qoTeRw3b8qb3oAFJtjHk/jT5Um0Fu58Z9WB6/ElRPvZ2Y4Fynvu0FBv++1OwB
 IILT5M0ogKdj4BfhJZf3MWdRGeMqzBvfXydPETS2ctck3DMjN1F2e7ldk3Z/wkqF
 QXesbDn3FubsA7jaIKaxVdg4hSNAhhM7OcNwRTn1u9UW1zc1rolL69Y01pYeZ8iw
 kBJ0AN/Bou/GHKTlCwmhyLHSLgqAPQ0NTVo0d8cEfkmu61hxTp64ECxI7no/Eb4U
 U+i2UHVmnG6FzPSFXAy0QU87mtNWABF5RpS8GQtIxfvt3UjiiziMzb8hjOjMkDwD
 CcACRw7UtoXQ2kILFuqu3X0uYgIGD61T290v+RKY+5Ox1scX/7u7D+HnLp9pk5id
 Kimw8UAEZWEaytLh2f6ONMNL6voY5+e22jmfh2PH0cLPRGxj6uu9f8dogy4O+/GL
 0vir6C41CGQ=
 =IUqa
 -----END PGP SIGNATURE-----

Merge tag 'timers-urgent-2026-10-04' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull timer fix from Ingo Molnar:

 - Fix task work flags management regression in the hrtimer
   rearming code that can leave task work items unprocessed
   (Karl Mehltretter)

* tag 'timers-urgent-2026-10-04' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  hrtimer: Use the mask to clear TIF_HRTIMER_REARM from the exit work
2026-10-04 08:39:26 -07:00
Linus Torvalds
a27611f899 Perf events fixes:
- Fix race between perf_event_exit_task() and perf_pending_task()
    (Luo Gengkun)
 
  - Fix perf header output management regressions (Ian Rogers)
 
  - Require kernel access for text poke events (Zhengchuan Liang)
 
 Signed-off-by: Ingo Molnar <mingo@kernel.org>
 -----BEGIN PGP SIGNATURE-----
 
 iQJFBAABCgAvFiEEBpT5eoXrXCwVQwEKEnMQ0APhK1gFAmrCAjwRHG1pbmdvQGtl
 cm5lbC5vcmcACgkQEnMQ0APhK1hTzw/+IJzVOLjNe2TaHJF20uYtuFVp80FGckH3
 qGMQcSSxEsdH2zWgA196UWYCuxcNtq9gRVkBw90u30Tka8F/C57r9fWf2Mx6iUBy
 zRrf70Lp4RsACAnM7kscX5ieJvesflYK5Vdr1je7DtQGE9P40Hq/45zquZt1B0uJ
 IqMVeDnqR46QIdAc/xNkn6G6FmI4CTJ1znwE1ZUm2HoDJ7Ya3zy0Gm9HNvdTaUN5
 IU5HWgNSEyL1id+2hwrv4/f+TPgmFSkJUf/t2hn/Rvzf1eOmRHuB/d8ZEBOEBDxk
 H5qeq/CGStzGMZsJprfQ65BGj/8QlXWNI8a6bzTnpAL2Ss9VKFvLvwmWDXmGo+B6
 n4+MOevA9LWDuZoSxRWzM00nBFp3h8YxyjSLYScZpoA3t0n45ckA+saK/ZDFBjYZ
 meWQX5mVVbktUX39hA/BeR2ps1KuHO8l2hq7BTlyK5nJfC69ptpM3OT2q0Jx/jD2
 kWKlhBLBhSObe3PX2uZiHDwXdEzuiMK0VKSYfz7gr0UDFoBbwe0AETOFIN9qhEXC
 4Lwln4vBpZTPGcGZYmBiWLS0uesy0mUa+FKzD8pZn7DKh8QY210Z9mr3+Tja3gsV
 pVjTs+7cpT9dsfX9z4PuSSnw8VGPfoM6iwGON5byva6Ylss+uL5iCCSQ3+heQFOz
 9aDZYLimUj4=
 =58mT
 -----END PGP SIGNATURE-----

Merge tag 'perf-urgent-2026-10-04' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull perf events fixes from Ingo Molnar:

 - Fix race between perf_event_exit_task() and perf_pending_task()
   (Luo Gengkun)

 - Fix perf header output management regressions (Ian Rogers)

 - Require kernel access for text poke events (Zhengchuan Liang)

* tag 'perf-urgent-2026-10-04' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  perf: Require kernel access for text poke events
  perf: Replace perf_event_header__init_id with full header init
  perf: Fix race between perf_event_exit_task() and perf_pending_task()
2026-10-04 08:35:29 -07:00
Linus Torvalds
1c915d6007 Locking fixes:
- Don't run refcount kunit self-test when !CONFIG_KUNIT_ALL_TESTS
    (Kuan-Wei Chiu)
 
  - Fix futex private hash use-after-free on resize (Chris Mason)
 
 Signed-off-by: Ingo Molnar <mingo@kernel.org>
 -----BEGIN PGP SIGNATURE-----
 
 iQJFBAABCgAvFiEEBpT5eoXrXCwVQwEKEnMQ0APhK1gFAmrCASARHG1pbmdvQGtl
 cm5lbC5vcmcACgkQEnMQ0APhK1g8/hAAsD+KLKE+WBSVX1CTqwKyflGbV5R8fMH+
 NabxcUzawNKwI3YTNSE+02cDKqDMMgmRMKPu9+hwxouVeXfWh/IU+vOWsUmGzIvd
 +pXYbKt6UInGA+4BVlSc++vAskPh/s/5MySOKIH++mMINbNYsXrvfvJL+KcYUkFr
 2vijeqCfdE7BTYzujYwoOlT0Dy2cTIr3ExjGe7/DE6YUT9ajahwoS4r7AaAto9YD
 NzPrYBMUB/4wkx6rznZn7Pn6Di7zj9/jAUXJXsLlgM7I1+PoARP7vg12tLMUnlRp
 WEk8D6ipOfSbNgEMCa41jcT9OjcIu9uny7W/lNVI9IJ9X4Irg55pMlgMUXRrsVn9
 8PlYrnVxtWerxsKMhbm7g37SvD7r/7wo3FXw97N85ZPNpJrKcZS3EY6bcDCJq9ME
 DWsGAFGgUpXTivjcq/pmWOCxVgLsuwyJWtzNMU3CwQ+cOADs8jMBb97qT9U1mwMi
 4gB299hViUAunGTf8lIWP1NFoBmh50xQtyJ3V9jAJxVHHQvUYpuANgaLguvEWWND
 aFwyoIYwUyRmRp24Gpmwb4aDhr6JK21mA97o8IJ4w5He/zuoz5DtNPacnFqObq6Y
 T+I+oIFNtrZ6iVy7/yRTFqe5irmEQoA//714/VWrvaR0qorX0Elhq7JZJa95dnvC
 JZ/J+oYi9jw=
 =M+J3
 -----END PGP SIGNATURE-----

Merge tag 'locking-urgent-2026-10-04' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull locking fixes from Ingo Molnar:

 - Don't run refcount kunit self-test when !CONFIG_KUNIT_ALL_TESTS
   (Kuan-Wei Chiu)

 - Fix futex private hash use-after-free on resize (Chris Mason)

* tag 'locking-urgent-2026-10-04' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  futex: Fix private hash use-after-free on resize
  irq: Make refcount_interrupt kunit test selectable
2026-10-04 08:29:27 -07:00
Christian Brauner
098bf3be6c selftests/filesystems: check that reading the root of an empty mount namespace stalls nobody
A readdir of the root of an empty mount namespace stuck in the page
fault of its buffer must stall neither a create nor a lookup in that
directory. The test needs userfaultfd and skips without it.

Link: https://patch.msgid.link/20261002-work-mount-fixes-4-v1-21-dd44b89d44ce@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-10-04 12:36:15 +02:00
Christian Brauner
fa15a241f0 selftests/filesystems: add a helper that holds a readdir in a page fault
A getdents64() whose buffer is a page registered with userfaultfd sits
in handle_userfault() with whatever iterate_dir() took before it copied
the entries. Add readdir_hold.h for tests that want to know what that
blocks: it opens the userfaultfd before the test enters a user
namespace, the fault happens in the kernel and needs CAP_SYS_PTRACE in
the initial one, starts the readdir in a thread, waits until that
thread is stuck, queues a create behind it and waits for it to settle,
then probes a lookup with a watchdog and says whether it came back.
The page is released afterwards so that everything drains on a kernel
that still holds the lock across the copy.

The two users follow.

Link: https://patch.msgid.link/20261002-work-mount-fixes-4-v1-20-dd44b89d44ce@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-10-04 12:36:14 +02:00
Christian Brauner
e08f57a7dc readdir: take no inode lock on an immutable directory
iterate_dir() takes the directory's i_rwsem shared and holds it across
->iterate_shared(). For a directory that never has an entry and is
never removed the lock keeps nothing still, it only orders every reader
and every writer of that inode behind each other.

For the directory of a nullfs instance that matters. The instance of
the initial mount namespace is the root of every empty mount namespace
and the private instance is the root of every kernel thread, so one
inode is shared across users who have nothing else in common. And a
reader can hold the lock for as long as it likes: back the getdents()
buffer with a mapping of a file on a FUSE mount of your own, let the
copy of "." and ".." fault and let the server wait. Queue an exclusive
taker behind it, a mkdir() in that directory goes through start_dirop()
before the read-only mount is reported, and from then on every lookup
that misses the dcache in that directory, every create and every mount
on it waits until the server answers. One user of an empty mount
namespace stalls all the others.

Add FOP_IMMUTABLE for the file operations of a directory that never
changes and is never removed and let iterate_dir() skip the lock for
it. The flag never changes for a file, ->f_pos is protected by
f_pos_lock since directories are FMODE_ATOMIC_POS, IS_DEADDIR can't be
set on such a directory and neither touch_atime() nor fsnotify take
i_rwsem. Set it on the nullfs directory. The placeholder directories of
libfs never have an entry either but their owners remove them, so they
keep the lock.

Fixes: 9d4e752a24 ("namespace: allow creating empty mount namespaces")
Cc: stable@vger.kernel.org # v7.1+
Link: https://patch.msgid.link/20261002-work-mount-fixes-4-v1-19-dd44b89d44ce@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-10-04 12:36:13 +02:00
Christian Brauner
31a1fb9062
nullfs: refuse file locks
Refuse flock() and POSIX locks on nullfs. Its one inode is the root of
every kernel thread and the following patches make it the directory
that stands in for an unmounted mount, so a lock taken through one such
directory would block the locks of every other holder and F_GETLK would
tell them the pid of the holder. Give the directory file operations of
its own: what libfs gives an empty directory plus ->lock and ->flock
that fail with ENOLCK, the way a filesystem without lock support does.

Link: https://patch.msgid.link/20261002-work-mount-fixes-4-v1-17-dd44b89d44ce@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-10-04 12:31:40 +02:00
Christian Brauner
c9ec8607b4
fsnotify: let a filesystem refuse marks on its objects
Don't let nullfs be watched. fanotify refuses mount and filesystem marks
on SB_NOUSER superblocks but inode marks of inotify, fanotify and
dnotify go through. The one inode of knullfs is the root of every
kernel thread and the following patches make it reachable from
userspace as the directory that stands in for an unmounted mount. A
watch placed through one such directory would report the opens through
all the others, across users.

Add FS_DISALLOW_NOTIFY next to FS_DISALLOW_NOTIFY_PERM, refuse a mark on
any object of such a filesystem in fsnotify_add_mark_list() where every
backend ends up and set it for nullfs. There's nothing to watch on a
permanently empty and immutable filesystem.

Link: https://patch.msgid.link/20261002-work-mount-fixes-4-v1-16-dd44b89d44ce@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-10-04 12:31:40 +02:00
Christian Brauner
e22e69c2ad
namespace: nothing is mounted on or written through knullfs
Mark the root of knullfs with dont_mount(). Nothing is ever mounted on
the root of a kernel thread and the following patches make that root
reachable from userspace, so say it on the dentry where it doesn't
depend on the mount being in no namespace. Let do_lock_mount() refuse
such a target before it takes the inode lock and namespace_sem. The
flag is sticky so the check needs no lock. The one under the locks
stays for a mountpoint that is being removed.

Make the mount read-only as well. Its one inode is immutable so nothing
could be changed through it anyway, but MNT_READONLY makes that visible
the usual way: EROFS instead of EPERM and ST_RDONLY in statvfs().

Link: https://patch.msgid.link/20261002-work-mount-fixes-4-v1-15-dd44b89d44ce@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-10-04 12:31:40 +02:00
Christian Brauner
4209cd7f54
namespace: keep the private nullfs instance in knullfs
The private nullfs instance that kernel threads are confined to is only
ever reachable through init_task's root and pwd. The following patches
point mounts at it as well, so keep it in a global.

No functional changes.

Link: https://patch.msgid.link/20261002-work-mount-fixes-4-v1-14-dd44b89d44ce@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-10-04 12:31:40 +02:00
Christian Brauner
67b69b8a6e
fhandle: decide the subtree check under mount_lock
may_decode_fh() lets a caller who is privileged over the mount
namespace of @root decode handles below @root->dentry as long as the
mount is mounted and no locked child covers something below it. The
three parts are read one after the other without a lock: is_mounted()
and capable_wrt_mount() read ->mnt_ns and has_locked_children() walks
->mnt_mounts under a mount_lock of its own.

Today the gaps are harmless. A lazy umount in between clears ->mnt_ns,
but the locked children stay attached to their unmounted parent, so the
walk still finds them and the decode is refused either way. The
following patches detach every unmounted mount from its parent. Then
an umount between is_mounted() and the walk makes the walk come back
empty and the caller decodes into what a locked child covered.

So take mount_lock once and answer all three questions under it.
is_mounted() is stable there, umount_tree() clears ->mnt_ns on the
write side, and a mounted mount still has its locked children on its
list. ns_capable() under the spinlock is fine, generic_permission()
calls it in RCU walk already. has_locked_children() loses its locking
wrapper, its other callers hold namespace_sem or mount_lock anyway.

Link: https://patch.msgid.link/20261002-work-mount-fixes-4-v1-13-dd44b89d44ce@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-10-04 12:31:40 +02:00
Christian Brauner
39796254f4
selftests/filesystems: check that an automount below an overlay layer is refused
Make sure that we don't automount on top of internal things.

Link: https://patch.msgid.link/20261002-work-mount-fixes-4-v1-12-dd44b89d44ce@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-10-04 12:31:40 +02:00
Christian Brauner
2244ca5662
selftests/filesystems: check the atime of the empty mount namespace root
No access time updates for immutable nullfs.

Link: https://patch.msgid.link/20261002-work-mount-fixes-4-v1-11-dd44b89d44ce@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-10-04 12:31:40 +02:00
Christian Brauner
921c14fd00
selftests/filesystems: check that a lock lands on the right mount and stays
Check MNT_LOCKED:

- A child in a user namespace of its own triggers the tracefs automount
  through a directory descriptor on the host's debugfs mount. The copy
  in the child's namespace has to be locked and the host's mount unlocked.

- A child moves a bind of that automount beneath a locked covering mount,
  unmounts the covering mount and asks for the umount of an unlocked
  ancestor. This must not expire the mount which holds the lock now.

- The host mounts and unmounts on a directory that a locked mount covers
  in a user namespace further down the propagation chain. That cover has
  to be locked afterwards as it was before.

Link: https://patch.msgid.link/20261002-work-mount-fixes-4-v1-10-dd44b89d44ce@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-10-04 12:31:39 +02:00
Christian Brauner
d74d66aa70
namespace: keep the lock on a mount that a propagated copy is moved beneath
attach_recursive_mnt() transfers MNT_LOCKED from the top mount to the
mount that is moved beneath it with MOVE_MOUNT_BENEATH. This allows the
owner of a user namespace to replace its locked /proc or its root. The
mount beneath takes on the job of covering the underlying mountpoint
allowing the top mount to be unmounted.

Consider two mount namespaces:

(H) The host H has a shared mount P with a secret in P/d
(Z) Z is a user namespace made from M. Its copy of P receives
    propagation from the host's P and its copy of M's cover on P/d is
    locked Z's owner must not get to see P/d.

Now (H) mounts X on P/d. This propagates into (Z). The copy of X lands
beneath (Z)'s locked cover. The locked property is transfered from (Z)'s
cover to the copy of X propagated beneath it. The cover is now unlocked.

Now (H) unmounts X again. The copy of X in (Z) gets unmounted and the
covering mount is left unlocked on top of P/d. (Z) can now unmount it:

    Z: umount2(P/d)             = EINVAL            /* the cover is locked */
    H: mount X on P/d, umount X                     /* both propagate into Z /*
    Z: umount2(P/d)             = 0                 /* the cover is now unlocked */
    Z: read P/d/secret          = "covered-by-root" /* secret revealed */

So only transfer the locked property to the mount beneath for mounts the
caller has placed. A propagated copy that lands beneath a locked mount
is locked as well so that the mount at the bottom of the stack carries a
lock the way every check expects. The mount on top of it remains locked
to ensure that it keeps covering even if the propagated mount is
unmounted again.

Fixes: c62a476693 ("move_mount: transfer MNT_LOCKED")
Cc: stable@vger.kernel.org # v7.1+
Link: https://patch.msgid.link/20261002-work-mount-fixes-4-v1-9-dd44b89d44ce@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-10-04 12:31:39 +02:00
Christian Brauner
f78ddcc872
namespace: never expire a locked mount
Locked mounts are special. They protect the underlying files and
directories from being revealed. do_umount() refuses to unmount locked
mounts but shrink_submounts() doesn't.

A shrinkable mount can become locked once the owner of a user namespace
puts it beneath a locked mount with MOVE_MOUNT_BENEATH. The locked
property now moves to the mount at the bottom making it possible to
unmount the top mount.

So umount() of an unlocked ancestor now expires the bottom mount first
and the covered directory is revealed:

  move_mount(c -> x/hidden, MOVE_MOUNT_BENEATH) = 0
  the cover after the lock moved:  umount2(x/hidden) = 0
  the holder of the lock:          umount2(x/hidden) = EINVAL
  the root of the copy, busy:      umount2(x) = EBUSY
  reads x/hidden/secret: "covered-by-root"

So leave a locked mount alone as it dies together with its parent. A
plain umount() of an unlocked mount with a locked one below it is EBUSY
from now on. It's the same for any other locked child. A lazy umount
still takes the whole tree.

mark_mounts_for_expiry() never sees a locked mount. lock_mnt_tree()
leaves a mount on an expiry list alone and nothing else puts a locked
one on such a list. Add an assert for this.

Fixes: 5ff9d8a65c ("vfs: Lock in place mounts from more privileged users")
Fixes: c62a476693 ("move_mount: transfer MNT_LOCKED")
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20261002-work-mount-fixes-4-v1-8-dd44b89d44ce@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-10-04 12:31:39 +02:00
Christian Brauner
caf16f9b4a
nullfs: don't update the access time
There's no point in updating access times of the nullfs instance. Raise
S_IMMUTABLE.

Fixes: 9d4e752a24 ("namespace: allow creating empty mount namespaces")
Cc: stable@vger.kernel.org # v7.1+
Link: https://patch.msgid.link/20261002-work-mount-fixes-4-v1-7-dd44b89d44ce@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-10-04 12:31:39 +02:00
Christian Brauner
33aadc7c72
namespace: handle mount locking for automounts correctly
If mounts are propagated across user namespaces, attach_recursive_mnt()
locks every copy of the source mount to protect overmounts from
vanishing and revealing the underlying files or directories.

The user namespace is taken from the caller's mount namespaces since
this is where the mounts end up. Except, that's not always true.
Automounts may legitimately get popped in by tasks located in a
different mount and user namespace during path lookup.

Then check doesn't make sense at that point. The copy in the namespace
of the parent - which may be the host's - is now locked and the host
cannot change the flags of its own mounts anymore.

Here's the reproducer:

- host has debugfs mounted nosuid,nodev,noexec and shared
- tracefs automount below it is not yet active
- hand a child process a directory descriptor on that mount
- child process enters auser and mount namespace
- child process' namespace now holds a locked copy of the host's debugfs
  mount that receives propagation from it
- child process stats "tracing/." through the descriptor
- lookup runs on the host's mount so the automount lands below the host's mount
- propagation puts a copy below the child's copy
- both try to clear the flags on the mount they got, with a bind remount:

    host, on its own automount:            MS_REMOUNT|MS_BIND = EPERM
    child, on the copy in its namespace:   MS_REMOUNT|MS_BIND = 0

So the lock landed on the host's mount instead of the child's copy.
Congrats. So we need to compare with the owner of the namespace the
mount actually gets mounted on. For all regular cases that is the
caller's mount namespace and so nothing changes.

Detached trees in anonymous mount namespaces by be handed over via
SCM_RIGHTS or inherited in other ways on purpose so the attaching task's
mount namespace is authoritative, not the creator of the detached tree.

Fixes: 132c94e31b ("vfs: Carefully propogate mounts across user namespaces")
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20261002-work-mount-fixes-4-v1-6-dd44b89d44ce@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-10-04 12:31:39 +02:00
Christian Brauner
ba985ce084
namespace: refuse an automount below a mount that is in no namespace
It's possible to add autmounts even when the parent mount isn't in the
mount namespace of the caller. The only requirement we have is that the
parent mount namespace must not be NULL, i.e., unmounted.

Problem is that clone_private_mount() has MNT_NS_INTERNAL which makes
that trivially true. So that passes the test and attach_recursive_mnt()
accepts that as a mount point and funny enough, count_mounts()
dereferences MNT_NS_INTERNAL. The problem is it is an error pointer...

So we can reach this in userspace via fanotify. A filesystem mark on the
lower filesystem of an overlay reports paths on the layer clone and
reading the event hands out a descriptor on it. For example with debugfs
as the lower layer it goes kaboom:

  openat(evfd, "tracing", O_DIRECTORY)

  Oops: general protection fault
  KASAN: null-ptr-deref in range [0x1d0-0x1d7]
  RIP: 0010:count_mounts+0x35/0x200
   attach_recursive_mnt
   finish_automount

And since that sleeping beauty happens under namespace_sem held for
writing every mount operation on the system blocks from then on.
Congrats.

Use is_mounted() instead which rejects unmounted and internal mounts
alike. The open fails with EINVAL just as it did before
clone_private_mount() used MNT_NS_INTERNAL.

Fixes: df820f8de4 ("ovl: make private mounts longterm")
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20261002-work-mount-fixes-4-v1-5-dd44b89d44ce@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-10-04 12:31:39 +02:00
Christian Brauner
66cda7ec9a
selftests/filesystems: check that an immutable inode takes no write hint
Check that an immutable inode takes no write hint.

Link: https://patch.msgid.link/20261002-work-mount-fixes-4-v1-4-dd44b89d44ce@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-10-04 12:31:39 +02:00
Christian Brauner
b0d1022b9b
fcntl: refuse F_SET_RW_HINT on an immutable inode
An immutable inode is never written to so write hints are pointless.
Refuse the hint on an immutable inode the way setattr(), fallocate() and
etxattr() refuse their changes.

Fixes: c75b1d9421 ("fs: add fcntl() interface for setting/getting write life time hints")
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20261002-work-mount-fixes-4-v1-3-dd44b89d44ce@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-10-04 12:31:38 +02:00
Christian Brauner
8189ab688f
namei: don't reveal overmounted entries in refwalk
In rcuwalk the dentry is validated before it is accepted. step_into()
step_into() rechecks d_seq and __follow_mount_rcu() rechecks mount_lock.
An entry that gets unlinked in between causes the lookup to retry and
miss.

A refwalk doesn't do this. lookup_fast() takes a reference on the hashed
dentry and simply accepts it. So an unlink that happens after the
reference was taken isn't seen by refwalk. That's fine for a simple
file. We just happened to open it before it was unlinked, no problem.

For a mountpoint and specifically a locked mountpoint it very much
isn't. The unlink detaches all mounts and then removes the name. Any
refwalk that hasn't traversed the mounts yet simply reveals the
underlying entry. It's a very narrow window but it can be hit:

  reads of a covered file in 60 s, 3 walkers, ~15000 unlinks
    no widening            27
    that step + 200 us   3741

See the appended patch for a more reliable reproducer.

So check the entry after step_into(). unlink(), rmdir() and rename()
mark the dentry with dont_mount() before they detach the mounts and
remove the dentry.

So a dentry that is marked with DCACHE_CANT_MOUNT and is unhashed by the
time its mounts were looked at is a name that was unlinked under the
refwalk. DCACHE_CANT_MOUNT is read after the mounts were looked up and
it is set before they are detached by detach_mounts(). A refwalk that
missed the mounts will see DCACHE_CANT_MOUNT.

Plain d_unlinked() is fine. A rename takes the dentry off its hash chain
but ___d_drop() leaves d_hash.pprev set. So only __d_drop() and a rename
over the dentry unhash it. The only move that flips IS_ROOT splices in a
disconnected alias. That doesn't have DCACHE_CANT_MOUNT set.

Add the to step_into_slowpath(). ".." and LOOKUP_DOWN may legitimately
land on an unhashed directory. A refwalk that crossed onto a mount has
path.mnt different from nd->path.mnt. A dentry that a filesystem dropped
on its own (d_invalidate(), d_drop()) doesn't have the flag set and is
treated as before.

  // SPDX-License-Identifier: GPL-2.0
  /*
   * unlink_covered: unlink a file that is a mountpoint in a detached copy of
   * its mount, against walkers that open it through that copy.
   *
   * A is a tmpfs with the file f1 (content SECRET_F) and the plain file
   * MARK_A. A' is an open_tree(OPEN_TREE_CLONE) copy of A with MARK_A bound
   * on A'/f1, held through an O_PATH fd on its root once the tree fd is
   * closed. Walkers open f1 through that fd while the driver unlinks A/f1,
   * where nothing is mounted on it. A walker may read MARK_A or get ENOENT.
   * A read of SECRET_F is a hit: the name was found after its mount was
   * gone. The lockless walks use openat2(RESOLVE_CACHED).
   *
   * usage: unlink_covered [-t seconds] [-w walkers]
   */
  #ifndef _GNU_SOURCE
  #define _GNU_SOURCE
  #endif
  #include <errno.h>
  #include <fcntl.h>
  #include <pthread.h>
  #include <stdatomic.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include <unistd.h>
  #include <sys/mount.h>
  #include <sys/stat.h>
  #include <sys/syscall.h>
  #include <linux/openat2.h>

  #ifndef __NR_open_tree
  #define __NR_open_tree 428
  #endif
  #ifndef __NR_move_mount
  #define __NR_move_mount 429
  #endif
  #ifndef __NR_openat2
  #define __NR_openat2 437
  #endif
  #ifndef OPEN_TREE_CLONE
  #define OPEN_TREE_CLONE 1
  #endif
  #ifndef OPEN_TREE_CLOEXEC
  #define OPEN_TREE_CLOEXEC O_CLOEXEC
  #endif
  #ifndef MOVE_MOUNT_F_EMPTY_PATH
  #define MOVE_MOUNT_F_EMPTY_PATH 0x00000004
  #endif

  #define WORK "/tmp/uc"
  #define ADIR WORK "/A"

  static int duration = 60, nwalkers = 3;
  static atomic_int stop, writer_waiting;
  static pthread_rwlock_t cur_lock = PTHREAD_RWLOCK_INITIALIZER;
  static int cur_fd = -1;		/* the root of A', -1 while there is none */
  static atomic_long n_unlink, n_walk, n_mark, n_enoent, n_other, n_secret,
  		   n_secret_cached;

  static void die(const char *what)
  {
  	fprintf(stderr, "FATAL %s: %s\n", what, strerror(errno));
  	exit(2);
  }

  static void put_file(int dfd, const char *name, const char *content)
  {
  	int fd = openat(dfd, name, O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC,
  			0644);

  	if (fd < 0 || write(fd, content, strlen(content)) < 0)
  		die(name);
  	close(fd);
  }

  /* "plain/../" @n times, then f1: a longer walk that checks nothing on its way */
  static char *longpath(int n)
  {
  	char *p = malloc(n * 9 + 3), *q = p;

  	for (int i = 0; i < n; i++, q += 9)
  		memcpy(q, "plain/../", 9);
  	strcpy(q, "f1");
  	return p;
  }

  static void try_read(int dfd, const char *path, int cached)
  {
  	struct open_how how = { .flags = O_RDONLY | O_CLOEXEC,
  				.resolve = RESOLVE_CACHED };
  	char buf[32] = "";
  	long n;
  	int fd;

  	if (cached)
  		fd = syscall(__NR_openat2, dfd, path, &how, sizeof(how));
  	else
  		fd = openat(dfd, path, O_RDONLY | O_CLOEXEC);
  	atomic_fetch_add(&n_walk, 1);
  	if (fd < 0) {
  		if (errno == ENOENT)
  			atomic_fetch_add(&n_enoent, 1);
  		else if (!cached || errno != EAGAIN)
  			atomic_fetch_add(&n_other, 1);
  		return;
  	}
  	n = read(fd, buf, sizeof(buf) - 1);
  	close(fd);
  	if (n >= 6 && !strncmp(buf, "SECRET", 6)) {
  		if (cached)
  			atomic_fetch_add(&n_secret_cached, 1);
  		if (!atomic_fetch_add(&n_secret, 1))
  			printf("HIT: read \"%s\" through %s (%s walk)\n", buf,
  			       path, cached ? "lockless" : "any");
  	} else {
  		atomic_fetch_add(&n_mark, 1);
  	}
  }

  static void *walker(void *arg)
  {
  	unsigned int r = (long)arg * 2654435761u;

  	while (!atomic_load(&stop)) {
  		char *p_long, *p_short;
  		int dfd;

  		while (atomic_load(&writer_waiting) && !atomic_load(&stop))
  			usleep(20);
  		pthread_rwlock_rdlock(&cur_lock);
  		dfd = cur_fd;
  		if (dfd < 0) {
  			pthread_rwlock_unlock(&cur_lock);
  			usleep(100);
  			continue;
  		}
  		r = r * 1103515245u + 12345u;
  		p_long = longpath(1 + (r >> 8) % 400);
  		p_short = longpath(0);
  		try_read(dfd, p_long, 0);
  		try_read(dfd, p_short, 0);
  		try_read(dfd, p_long, 1);
  		pthread_rwlock_unlock(&cur_lock);
  		free(p_long);
  		free(p_short);
  	}
  	return NULL;
  }

  /* hand the walkers a new A' (or none), close the old one */
  static void publish(int fd)
  {
  	int old;

  	atomic_fetch_add(&writer_waiting, 1);
  	pthread_rwlock_wrlock(&cur_lock);
  	old = cur_fd;
  	cur_fd = fd;
  	pthread_rwlock_unlock(&cur_lock);
  	atomic_fetch_sub(&writer_waiting, 1);
  	if (old >= 0)
  		close(old);
  }

  static void *driver(void *arg __attribute__((unused)))
  {
  	int a;

  	if (mkdir(ADIR, 0755) && errno != EEXIST)
  		die("mkdir A");
  	if (mount("A", ADIR, "tmpfs", 0, "size=4M"))
  		die("mount A");
  	a = open(ADIR, O_PATH | O_DIRECTORY | O_CLOEXEC);
  	if (a < 0 || mkdirat(a, "plain", 0755))
  		die("A/plain");
  	put_file(a, "MARK_A", "MARK_A");
  	while (!atomic_load(&stop)) {
  		int t, m, fd_a;

  		put_file(a, "f1", "SECRET_F");
  		t = syscall(__NR_open_tree, a, "",
  			    OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC | AT_EMPTY_PATH);
  		if (t < 0)
  			die("open_tree A");
  		m = syscall(__NR_open_tree, a, "MARK_A",
  			    OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC);
  		if (m < 0)
  			die("open_tree MARK_A");
  		if (syscall(__NR_move_mount, m, "", t, "f1",
  			    MOVE_MOUNT_F_EMPTY_PATH))
  			die("move_mount");
  		close(m);
  		fd_a = openat(t, ".", O_PATH | O_DIRECTORY | O_CLOEXEC);
  		if (fd_a < 0)
  			die("open A'");
  		publish(fd_a);
  		usleep(200 + rand() % 1000);
  		close(t);			/* A' is unmounted, fd_a holds it */
  		usleep(200 + rand() % 1000);
  		if (unlinkat(a, "f1", 0))	/* through A, a plain file there */
  			die("unlink f1");
  		atomic_fetch_add(&n_unlink, 1);
  		usleep(rand() % 300);
  		publish(-1);
  	}
  	close(a);
  	umount2(ADIR, MNT_DETACH);
  	return NULL;
  }

  int main(int argc, char **argv)
  {
  	pthread_t d, *w;
  	int c, i;

  	setvbuf(stdout, NULL, _IOLBF, 0);
  	while ((c = getopt(argc, argv, "t:w:")) != -1) {
  		switch (c) {
  		case 't':
  			duration = atoi(optarg);
  			break;
  		case 'w':
  			nwalkers = atoi(optarg);
  			break;
  		default:
  			fprintf(stderr, "usage: unlink_covered [-t seconds] [-w walkers]\n");
  			return 2;
  		}
  	}
  	if (unshare(CLONE_NEWNS) ||
  	    mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL))
  		die("unshare");
  	if (mkdir(WORK, 0755) && errno != EEXIST)
  		die("mkdir");
  	w = calloc(nwalkers, sizeof(*w));
  	for (i = 0; i < nwalkers; i++)
  		if (pthread_create(&w[i], NULL, walker, (void *)(long)i))
  			die("pthread_create");
  	if (pthread_create(&d, NULL, driver, NULL))
  		die("pthread_create");
  	sleep(duration);
  	atomic_store(&stop, 1);
  	pthread_join(d, NULL);
  	for (i = 0; i < nwalkers; i++)
  		pthread_join(w[i], NULL);
  	printf("unlink_covered: %d s, %d walkers: unlinks %ld walks %ld mark %ld enoent %ld other %ld SECRET %ld (lockless %ld)\n",
  	       duration, nwalkers, atomic_load(&n_unlink), atomic_load(&n_walk),
  	       atomic_load(&n_mark), atomic_load(&n_enoent),
  	       atomic_load(&n_other), atomic_load(&n_secret),
  	       atomic_load(&n_secret_cached));
  	return atomic_load(&n_secret) ? 1 : 0;
  }

  diff --git a/fs/namei.c b/fs/namei.c
  --- a/fs/namei.c
  +++ b/fs/namei.c
  @@ -35,6 +35,7 @@
   #include <linux/fcntl.h>
   #include <linux/device_cgroup.h>
   #include <linux/fs_struct.h>
  +#include <linux/delay.h>
   #include <linux/posix_acl.h>
   #include <linux/hash.h>
   #include <linux/bitops.h>
  @@ -1205,9 +1206,26 @@ static int sysctl_protected_symlinks __read_mostly;
   static int sysctl_protected_hardlinks __read_mostly;
   static int sysctl_protected_fifos __read_mostly;
   static int sysctl_protected_regular __read_mostly;
  +/* debug: widen the two windows of the detach_mounts() race */
  +static int sysctl_detach_race_walk_us __read_mostly;
  +static int sysctl_detach_race_unlink_us __read_mostly;

   #ifdef CONFIG_SYSCTL
   static const struct ctl_table namei_sysctls[] = {
  +	{
  +		.procname	= "detach_race_walk_us",
  +		.data		= &sysctl_detach_race_walk_us,
  +		.maxlen		= sizeof(int),
  +		.mode		= 0644,
  +		.proc_handler	= proc_dointvec,
  +	},
  +	{
  +		.procname	= "detach_race_unlink_us",
  +		.data		= &sysctl_detach_race_unlink_us,
  +		.maxlen		= sizeof(int),
  +		.mode		= 0644,
  +		.proc_handler	= proc_dointvec,
  +	},
   	{
   		.procname	= "protected_symlinks",
   		.data		= &sysctl_protected_symlinks,
  @@ -1878,6 +1896,10 @@ static struct dentry *lookup_fast(struct nameidata *nd)
   		dentry = __d_lookup(parent, &nd->last);
   		if (unlikely(!dentry))
   			return NULL;
  +		/* debug: between finding a mountpoint and crossing its mounts */
  +		if (unlikely(sysctl_detach_race_walk_us) && d_mountpoint(dentry))
  +			usleep_range(sysctl_detach_race_walk_us,
  +				     sysctl_detach_race_walk_us + 10);
   		status = d_revalidate(nd->inode, &nd->last, dentry, nd->flags);
   	}
   	if (unlikely(status <= 0)) {
  @@ -5693,6 +5715,10 @@ int vfs_unlink(struct mnt_idmap *idmap, struct inode *dir,
   			if (!error) {
   				dont_mount(dentry);
   				detach_mounts(dentry);
  +				/* debug: the mounts are gone, d_delete() is still to come */
  +				if (unlikely(sysctl_detach_race_unlink_us))
  +					usleep_range(sysctl_detach_race_unlink_us,
  +						     sysctl_detach_race_unlink_us + 10);
   			}
   		}
   	}

Fixes: 8ed936b567 ("vfs: Lazily remove mounts on unlinked files and directories.")
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20261002-work-mount-fixes-4-v1-2-dd44b89d44ce@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-10-04 12:31:38 +02:00
Christian Brauner
528b383dc3
namespace: unhash a dentry before detaching the mounts on it
unlink(), rmdir() and rename() remove the entry from the filesystem,
call detach_mounts() on the entry with the inode locked and then call
d_delete() once the inode is unlocked.

The thing is that between detach_mounts() and d_delete() the dentry is
still hashed and positive. But after detach_mounts() nothing covers the
dentry anymore. A lookup that finds this dentry in the dcache can
uncover what the mounts hid.

That's a problem when unlinking files or directories that are
mountpoints in other mount namespaces. Everybody who had the underlying
entry covered can race the detach_mount() call until d_delete() has run.

The race window isn't all that small. It encompasses namespace_unlock()
with a full synchronize_rcu_expedited() grace period and the
inode_unlock() of the entry.

In my experiments three walkers that kept trying read an overmounted
file in 11938 of the 16140 unlinks that removed its mountpoint from a
bind mount of the filesystem within a minute.

Fun fact, d_invalidate() has the same ordering problem but gets it
right. It unhashes the dentry first and detaches the mounts afterwards.
Let's do the same in __detach_mounts():

- A lookup that hasn't found the dentry yet misses it in the dcache and
  waits for the directory lock that the caller holds until the name is
  gone for good.

- A lockless lookup that found it already fails the mount_lock check
  while the dentry still counts as a mountpoint and the d_seq check once
  it doesn't, and retries.

This fixes the lockless path. We still need to fix the reference count
lookup in a follow-up patch.

So d_drop() the dentry. The dentry stays positive and held but can't be
found anymore. Then proceed with the detach and unlink.

Reproducer:

The reads were counted with the program below, three walkers for 60 s
in a VM with 4 CPUs. The race window is stretched with the debug patch
pasted here. fs.detach_race_walk_us sleeps in lookup_fast() once it
found a mountpoint dentry and before its mounts are crossed.
fs.detach_race_unlink_us sleeps in vfs_unlink() between detach_mounts()
and d_delete().

  // SPDX-License-Identifier: GPL-2.0
  /*
   * unlink_covered: unlink a file that is a mountpoint in a detached copy of
   * its mount, against lookups that open it through that copy.
   *
   * A is a tmpfs with the file f1 (content SECRET_F) and the plain file
   * MARK_A. A' is an open_tree(OPEN_TREE_CLONE) copy of A with MARK_A bound
   * on A'/f1, held through an O_PATH fd on its root once the tree fd is
   * closed. Walkers open f1 through that fd while the driver unlinks A/f1,
   * where nothing is mounted on it. A walker may read MARK_A or get ENOENT.
   * A read of SECRET_F is a hit: the name was found after its mount was
   * gone. The lockless walks use openat2(RESOLVE_CACHED).
   *
   * usage: unlink_covered [-t seconds] [-w walkers]
   */
  #ifndef _GNU_SOURCE
  #define _GNU_SOURCE
  #endif
  #include <errno.h>
  #include <fcntl.h>
  #include <pthread.h>
  #include <stdatomic.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include <unistd.h>
  #include <sys/mount.h>
  #include <sys/stat.h>
  #include <sys/syscall.h>
  #include <linux/openat2.h>

  #ifndef __NR_open_tree
  #define __NR_open_tree 428
  #endif
  #ifndef __NR_move_mount
  #define __NR_move_mount 429
  #endif
  #ifndef __NR_openat2
  #define __NR_openat2 437
  #endif
  #ifndef OPEN_TREE_CLONE
  #define OPEN_TREE_CLONE 1
  #endif
  #ifndef OPEN_TREE_CLOEXEC
  #define OPEN_TREE_CLOEXEC O_CLOEXEC
  #endif
  #ifndef MOVE_MOUNT_F_EMPTY_PATH
  #define MOVE_MOUNT_F_EMPTY_PATH 0x00000004
  #endif

  #define WORK "/tmp/uc"
  #define ADIR WORK "/A"

  static int duration = 60, nwalkers = 3;
  static atomic_int stop, writer_waiting;
  static pthread_rwlock_t cur_lock = PTHREAD_RWLOCK_INITIALIZER;
  static int cur_fd = -1;		/* the root of A', -1 while there is none */
  static atomic_long n_unlink, n_walk, n_mark, n_enoent, n_other, n_secret,
  		   n_secret_cached;

  static void die(const char *what)
  {
  	fprintf(stderr, "FATAL %s: %s\n", what, strerror(errno));
  	exit(2);
  }

  static void put_file(int dfd, const char *name, const char *content)
  {
  	int fd = openat(dfd, name, O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC,
  			0644);

  	if (fd < 0 || write(fd, content, strlen(content)) < 0)
  		die(name);
  	close(fd);
  }

  /* "plain/../" @n times, then f1: a longer walk that checks nothing on its way */
  static char *longpath(int n)
  {
  	char *p = malloc(n * 9 + 3), *q = p;

  	for (int i = 0; i < n; i++, q += 9)
  		memcpy(q, "plain/../", 9);
  	strcpy(q, "f1");
  	return p;
  }

  static void try_read(int dfd, const char *path, int cached)
  {
  	struct open_how how = { .flags = O_RDONLY | O_CLOEXEC,
  				.resolve = RESOLVE_CACHED };
  	char buf[32] = "";
  	long n;
  	int fd;

  	if (cached)
  		fd = syscall(__NR_openat2, dfd, path, &how, sizeof(how));
  	else
  		fd = openat(dfd, path, O_RDONLY | O_CLOEXEC);
  	atomic_fetch_add(&n_walk, 1);
  	if (fd < 0) {
  		if (errno == ENOENT)
  			atomic_fetch_add(&n_enoent, 1);
  		else if (!cached || errno != EAGAIN)
  			atomic_fetch_add(&n_other, 1);
  		return;
  	}
  	n = read(fd, buf, sizeof(buf) - 1);
  	close(fd);
  	if (n >= 6 && !strncmp(buf, "SECRET", 6)) {
  		if (cached)
  			atomic_fetch_add(&n_secret_cached, 1);
  		if (!atomic_fetch_add(&n_secret, 1))
  			printf("HIT: read \"%s\" through %s (%s walk)\n", buf,
  			       path, cached ? "lockless" : "any");
  	} else {
  		atomic_fetch_add(&n_mark, 1);
  	}
  }

  static void *walker(void *arg)
  {
  	unsigned int r = (long)arg * 2654435761u;

  	while (!atomic_load(&stop)) {
  		char *p_long, *p_short;
  		int dfd;

  		while (atomic_load(&writer_waiting) && !atomic_load(&stop))
  			usleep(20);
  		pthread_rwlock_rdlock(&cur_lock);
  		dfd = cur_fd;
  		if (dfd < 0) {
  			pthread_rwlock_unlock(&cur_lock);
  			usleep(100);
  			continue;
  		}
  		r = r * 1103515245u + 12345u;
  		p_long = longpath(1 + (r >> 8) % 400);
  		p_short = longpath(0);
  		try_read(dfd, p_long, 0);
  		try_read(dfd, p_short, 0);
  		try_read(dfd, p_long, 1);
  		pthread_rwlock_unlock(&cur_lock);
  		free(p_long);
  		free(p_short);
  	}
  	return NULL;
  }

  /* hand the walkers a new A' (or none), close the old one */
  static void publish(int fd)
  {
  	int old;

  	atomic_fetch_add(&writer_waiting, 1);
  	pthread_rwlock_wrlock(&cur_lock);
  	old = cur_fd;
  	cur_fd = fd;
  	pthread_rwlock_unlock(&cur_lock);
  	atomic_fetch_sub(&writer_waiting, 1);
  	if (old >= 0)
  		close(old);
  }

  static void *driver(void *arg __attribute__((unused)))
  {
  	int a;

  	if (mkdir(ADIR, 0755) && errno != EEXIST)
  		die("mkdir A");
  	if (mount("A", ADIR, "tmpfs", 0, "size=4M"))
  		die("mount A");
  	a = open(ADIR, O_PATH | O_DIRECTORY | O_CLOEXEC);
  	if (a < 0 || mkdirat(a, "plain", 0755))
  		die("A/plain");
  	put_file(a, "MARK_A", "MARK_A");
  	while (!atomic_load(&stop)) {
  		int t, m, fd_a;

  		put_file(a, "f1", "SECRET_F");
  		t = syscall(__NR_open_tree, a, "",
  			    OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC | AT_EMPTY_PATH);
  		if (t < 0)
  			die("open_tree A");
  		m = syscall(__NR_open_tree, a, "MARK_A",
  			    OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC);
  		if (m < 0)
  			die("open_tree MARK_A");
  		if (syscall(__NR_move_mount, m, "", t, "f1",
  			    MOVE_MOUNT_F_EMPTY_PATH))
  			die("move_mount");
  		close(m);
  		fd_a = openat(t, ".", O_PATH | O_DIRECTORY | O_CLOEXEC);
  		if (fd_a < 0)
  			die("open A'");
  		publish(fd_a);
  		usleep(200 + rand() % 1000);
  		close(t);			/* A' is unmounted, fd_a holds it */
  		usleep(200 + rand() % 1000);
  		if (unlinkat(a, "f1", 0))	/* through A, a plain file there */
  			die("unlink f1");
  		atomic_fetch_add(&n_unlink, 1);
  		usleep(rand() % 300);
  		publish(-1);
  	}
  	close(a);
  	umount2(ADIR, MNT_DETACH);
  	return NULL;
  }

  int main(int argc, char **argv)
  {
  	pthread_t d, *w;
  	int c, i;

  	setvbuf(stdout, NULL, _IOLBF, 0);
  	while ((c = getopt(argc, argv, "t:w:")) != -1) {
  		switch (c) {
  		case 't':
  			duration = atoi(optarg);
  			break;
  		case 'w':
  			nwalkers = atoi(optarg);
  			break;
  		default:
  			fprintf(stderr, "usage: unlink_covered [-t seconds] [-w walkers]\n");
  			return 2;
  		}
  	}
  	if (unshare(CLONE_NEWNS) ||
  	    mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL))
  		die("unshare");
  	if (mkdir(WORK, 0755) && errno != EEXIST)
  		die("mkdir");
  	w = calloc(nwalkers, sizeof(*w));
  	for (i = 0; i < nwalkers; i++)
  		if (pthread_create(&w[i], NULL, walker, (void *)(long)i))
  			die("pthread_create");
  	if (pthread_create(&d, NULL, driver, NULL))
  		die("pthread_create");
  	sleep(duration);
  	atomic_store(&stop, 1);
  	pthread_join(d, NULL);
  	for (i = 0; i < nwalkers; i++)
  		pthread_join(w[i], NULL);
  	printf("unlink_covered: %d s, %d walkers: unlinks %ld walks %ld mark %ld enoent %ld other %ld SECRET %ld (lockless %ld)\n",
  	       duration, nwalkers, atomic_load(&n_unlink), atomic_load(&n_walk),
  	       atomic_load(&n_mark), atomic_load(&n_enoent),
  	       atomic_load(&n_other), atomic_load(&n_secret),
  	       atomic_load(&n_secret_cached));
  	return atomic_load(&n_secret) ? 1 : 0;
  }

  diff --git a/fs/namei.c b/fs/namei.c
  --- a/fs/namei.c
  +++ b/fs/namei.c
  @@ -35,6 +35,7 @@
   #include <linux/fcntl.h>
   #include <linux/device_cgroup.h>
   #include <linux/fs_struct.h>
  +#include <linux/delay.h>
   #include <linux/posix_acl.h>
   #include <linux/hash.h>
   #include <linux/bitops.h>
  @@ -1205,9 +1206,26 @@ static int sysctl_protected_symlinks __read_mostly;
   static int sysctl_protected_hardlinks __read_mostly;
   static int sysctl_protected_fifos __read_mostly;
   static int sysctl_protected_regular __read_mostly;
  +/* debug: widen the two windows of the detach_mounts() race */
  +static int sysctl_detach_race_walk_us __read_mostly;
  +static int sysctl_detach_race_unlink_us __read_mostly;

   #ifdef CONFIG_SYSCTL
   static const struct ctl_table namei_sysctls[] = {
  +	{
  +		.procname	= "detach_race_walk_us",
  +		.data		= &sysctl_detach_race_walk_us,
  +		.maxlen		= sizeof(int),
  +		.mode		= 0644,
  +		.proc_handler	= proc_dointvec,
  +	},
  +	{
  +		.procname	= "detach_race_unlink_us",
  +		.data		= &sysctl_detach_race_unlink_us,
  +		.maxlen		= sizeof(int),
  +		.mode		= 0644,
  +		.proc_handler	= proc_dointvec,
  +	},
   	{
   		.procname	= "protected_symlinks",
   		.data		= &sysctl_protected_symlinks,
  @@ -1878,6 +1896,10 @@ static struct dentry *lookup_fast(struct nameidata *nd)
   		dentry = __d_lookup(parent, &nd->last);
   		if (unlikely(!dentry))
   			return NULL;
  +		/* debug: between finding a mountpoint and crossing its mounts */
  +		if (unlikely(sysctl_detach_race_walk_us) && d_mountpoint(dentry))
  +			usleep_range(sysctl_detach_race_walk_us,
  +				     sysctl_detach_race_walk_us + 10);
   		status = d_revalidate(nd->inode, &nd->last, dentry, nd->flags);
   	}
   	if (unlikely(status <= 0)) {
  @@ -5693,6 +5715,10 @@ int vfs_unlink(struct mnt_idmap *idmap, struct inode *dir,
   			if (!error) {
   				dont_mount(dentry);
   				detach_mounts(dentry);
  +				/* debug: the mounts are gone, d_delete() is still to come */
  +				if (unlikely(sysctl_detach_race_unlink_us))
  +					usleep_range(sysctl_detach_race_unlink_us,
  +						     sysctl_detach_race_unlink_us + 10);
   			}
   		}
   	}

Fixes: 8ed936b567 ("vfs: Lazily remove mounts on unlinked files and directories.")
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20261002-work-mount-fixes-4-v1-1-dd44b89d44ce@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-10-04 12:31:38 +02:00
Fuad Tabba
b52ef45013 arm64/boot: Don't set PMUv3p9 FGT2 bits without PMUv3
On a CPU with FGT2 and an IMPLEMENTATION DEFINED PMU (PMUVer 0b1111),
__init_el2_fgt2 sets the PMUv3p9 bits in HDFGRTR2_EL2 and HDFGWTR2_EL2,
which are RES0 there. The macro only checks that PMUVer is at least
PMUv3p9, and 0b1111 passes.

Exclude 0b1111 before the compare, as __init_el2_debug does.

Fixes: 858c7bfcb3 ("arm64/boot: Enable EL2 requirements for FEAT_PMUv3p9")
Signed-off-by: Fuad Tabba <fuad.tabba@linux.dev>
Reviewed-by: Bradley Morgan <brads@mainlining.org>
Reviewed-by: Anshuman Khandual <anshuman.khandual@arm.com>
Signed-off-by: Will Deacon <will@kernel.org>
2026-10-04 09:14:20 +00:00
Linus Torvalds
6addb4f385 - In versalnet_edac, properly release a remote processor reference which was
acquired at probe time, on memory controller instance remove
 
 - A handful of Altera EDAC driver fixes:
 
   - Fix device node reference leaks covering both the success path and the
     various error paths, and route the single-bit setup function through the
     common exit label
 
   - Fix a use-after-free by releasing the devres group before freeing the
     control info structure in the error paths, since managed IRQ handlers
     could reference the freed dci struct if they fire at just the right time
 
   - Fix a memory leak by freeing the allocated control info structure when the
     devres group open fails in the Altera SDMMC setup path
 
   - Remove the __init marking from the Altera Arria10 setup paths and their
     helpers so they remain safely callable at runtime, including after
     deferred or re-triggered probing
 
   - Prevent the Altera driver from being unbound by removing their ->remove
     callbacks and marking them to suppress bind/unbind sysfs attributes, since
     unbinding could erase active system memory
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEzv7L6UO9uDPlPSfHEsHwGGHeVUoFAmrBzj0ACgkQEsHwGGHe
 VUpYCw/+PunHfO7n2E+jDTzJZh74NA6gcjVl9izDghf2MF2RBOMmS1o9swH1FAsJ
 IwOxBkT79xmKBoaSeJ3Ompjm+/aIDZO4INHP1QiSq0f6p/7ilT+QLJwgIGvW9C6l
 ipdYqjPJI1MoOGRQokGPGDkGsANTrO1IlSbI4KI8NQZf67QkKn7SPsf6RlF0DP4O
 XvJL2xLtIVvcRIMcwWUwmkvxrTgyVc9uxKUWdhLhRR6u7ZYMNLHH3BEaVKxr2mo5
 my+eW12hUJIrcSLKR0NOCQYgfiC0gS3hPZRMB3hWMD3YVVxLOzvx3UIF2PIj0PKZ
 xRoGnQXjRd7yHtY1t8Un7OGCnmCcEFuQbP4jDw6HrsrwJlZ8N3R+jciSuhk88FFr
 GKdrvUSAaBoJXpgDVxba7KBkxO/5pi3iSf5yAjbWob/+U6Lm02/7V9GQzk7b802R
 sK7lJo1gqKXA6Yyh7DjT7yWDjAQNDH/Y5gp0EpN67meR9MScTV/3Pe0ZCRYJ81F2
 hrSKS+WuJdBQBxR++QZBEan3PbTKwfdWntQxGwEsf2swyiG4WUn0AwH+P85NUGtx
 EM9HNCHR2PR3jaNP539TDx4YEw186yIKLn1DyCQ6JaUvtRE/eZ/uuSfr5/4aGBVQ
 3gGF+i+xXxGr0UJ6OIZe3vocEt0tU/ecRuA5hNy+7LiFOgaQ0Wg=
 =2r1p
 -----END PGP SIGNATURE-----

Merge tag 'edac_urgent_for_v7.3_rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/ras/ras

Pull EDAC fixes from Borislav Petkov:
 "This is more of the new normal of LLM-induced fixes of error paths. Oh
  well, they should be done eventually and hopefully we'll be back to
  normal soon-ish... one would hope... :-P

  AMD Versal NET:

   - Properly release a remote processor reference which was acquired at
     probe time, on memory controller instance remove

  A handful of Altera EDAC driver fixes:

   - Fix device node reference leaks covering both the success path and
     the various error paths, and route the single-bit setup function
     through the common exit label

   - Fix a use-after-free by releasing the devres group before freeing
     the control info structure in the error paths, since managed IRQ
     handlers could reference the freed dci struct if they fire at just
     the right time

   - Fix a memory leak by freeing the allocated control info structure
     when the devres group open fails in the Altera SDMMC setup path

   - Remove the __init marking from the Altera Arria10 setup paths and
     their helpers so they remain safely callable at runtime, including
     after deferred or re-triggered probing

   - Prevent the Altera driver from being unbound by removing their
     ->remove callbacks and marking them to suppress bind/unbind sysfs
     attributes, since unbinding could erase active system memory"

* tag 'edac_urgent_for_v7.3_rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/ras/ras:
  EDAC/versalnet: Drop remote processor handle refcount on driver removal
  EDAC/altera: Fix device node reference leaks in the SDMMC ECC setup
  EDAC/altera: Fix use-after-free in error paths
  EDAC/altera: Fix memory leak on dci allocation failure
  EDAC/altera: Drop __init from ECC setup paths for re-probe safety
  EDAC/altera: Do not allow driver unbinding
2026-10-03 21:14:25 -07:00
Kuba Piecuch
e6ac89b8b1 sched_ext: Generate qseq from a per-task counter
finish_dispatch() uses the qseq embedded in p->scx.ops_state to tell
whether the QUEUED instance of a task it's about to claim is the one
scx_bpf_dsq_insert() saw. qseq is generated from rq->scx.ops_qseq, but
the counters of different rqs are independent, so if a task is dequeued
and re-enqueued on a different rq between scx_bpf_dsq_insert() and
finish_dispatch(), the new QUEUED instance can end up with the same
qseq as the old one:

  CPU X                          CPU Z
  -----                          -----
                                 enqueue p on rq A, qseq = N
  ops.dispatch()
    scx_bpf_dsq_insert(p)
      records qseq N
                                 sched_setaffinity(p)
                                   dequeue p from rq A
                                   enqueue p on rq B, qseq = N
  finish_dispatch(p, N)
    qseq matches, p is claimed

The claim itself is still atomic so the core stays consistent, but an
insert issued for a previous QUEUED instance gets applied to a new one
which the BPF scheduler has just received through ops.enqueue(). This
breaks the guarantee that dispatches targeting a stale instance are
ignored.

Generate qseq from a per-task counter, p->scx.ops_qseq, instead so that
consecutive QUEUED instances of a task never share a qseq regardless of
which rq they're on. The counter is only updated in
scx_do_enqueue_task() with the task's rq locked, so no additional
synchronization is needed, and it fits in an existing hole in struct
sched_ext_entity on 64bit. Remove the now unused rq->scx.ops_qseq.

Never generate qseq 0. NONE and DISPATCHING don't carry a qseq, so
scx_bpf_dsq_insert() on a task in either state records 0. With a
per-task counter, every task's first QUEUED instance would otherwise get
qseq 0 and could be claimed by such an insert. Wrap the counter where
the QSEQ field wraps so that it can't reach a value that shifts to 0 on
32bit either.

Fixes: f0e1a0643a ("sched_ext: Implement BPF extensible scheduler class")
Cc: stable@vger.kernel.org # v6.12+
Assisted-by: Claude:claude-opus-5.5
Signed-off-by: Kuba Piecuch <jpiecuch@google.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
2026-10-03 13:23:31 -10:00
Arnd Bergmann
1fc2d80928 Reject zero-sized allocations in tee_dyn_shm_alloc_helper()
-----BEGIN PGP SIGNATURE-----
 
 iQJUBAABCgA+FiEE0qerISgy2SKkqO79Wr/6JGat8H4FAmrBEqsgHGplbnMud2lr
 bGFuZGVyQG9zcy5xdWFsY29tbS5jb20ACgkQWr/6JGat8H5j+w/9EOjO/CnsBN1W
 8NCjEdmKOQzJ/T92pqmGJnyX70b1ZyMOpdc1tvBNfU69ELAWxDGQLTw5gw+PHaww
 pSwRRyZeWHMZUx37Po8wZeBKvp6CE42kT4H4KpAagr2aLPGEqR7bKlKo3W+fXrmj
 U+W9J6TuaAjWeUaA5n0AFxoa0U7OQ9lJ4LA98vk5xUCmcTg4zeGhkXU/GSAs1tZT
 H34+LJuiRzoO6LnDaR2BJ8Y/qxZ0Bqgror1u1pCZKWB8eOBPiFniUf5InNRzwJmf
 3iwNrnHFMh8YG4cdsEiOkE2w1EH7wQY/FzQJ1QjDok+tZ4OhE3U1D4XmIgvN+P3a
 xGH8n2V0qjy/8GOKRiwCA2wrCHK2XR/HTePXLPHIcwhRqgCSl3l+f1mQIHan5w2d
 WZg2ocfARe+ezuSVjkqRF2flLSn1uLSmqvZ/9X2Z31/CrFhlCa277KwkOmEZfniB
 2sXVb+GglwZxeAvlt81dfyTrtofqxJJXhvB02gWKsvqpXKIK15dDp2KiGb4Rd0YC
 S7kFx6F8zu+WtXML6uKSPvqv7zcHzEpoNatxhPXrmotAEUlhZexY9UQiSrZBI6ei
 LM4nebnQvd0UU3aiXl2Cwa9xhcq1q5/QIKMsyeI7I7TEEkI3mVN9vHAOvr9g1hyF
 EyCgFacUa+9063NFdWkZ1UJga59Ko0A=
 =/w8l
 -----END PGP SIGNATURE-----
gpgsig -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEo6/YBQwIrVS28WGKmmx57+YAGNkFAmrBdJgACgkQmmx57+YA
 GNlLnA/+P6zcvRua5h+dtOwu7yciltcGe6dH1OJHs8erfQGuG6Y3vdebbeCgIpmY
 sDSFUDDawbR2bAi2wwNT55ggHHknXr7b5Mna/6/IqM/gfb8WwRsOCPCmqBaJl46B
 QSJdd3TGtCizI0h8jAw8kUwEKk8PUqh5IHqsUJpJyGp/J0Ux3lrVfdNhMaI/FeuB
 n8x66UD6do7MCI/N+3W02mj0GqVma5jHKnpAwYAbVVMo6KVXRE5JcdZ9w4OfpEGO
 VrFqurGEe3GHhlp5LEbziqzUXq/1/TUZhBj5PNUdPZ/Vp43/TE7Zj6YkuDA/UgXO
 vgHV/oDIkgF3SRamLCC+muA1vIiQsLbaMl/ue3X0z/ua+x8gntnz0D+CAXtPOPTM
 Lvyd4TS2sexo+394ior5uQNDwTILuBnigSxhoSGtrocOYGihMRpVLUw5/QqKl75S
 0yMkRA9CsSTqDb27oVnWTVGaWe9dBGre1GRxe1xFCkTPBNTfoDINkiHnazKBZF2p
 IZRu5VJu9ysfmEE/CGRW03/NtC2pz0H+KI/xUVq1mZtw/Y0OS9n0hFbBYFDCvY9F
 j1+a69paLw2qixLrs0OupUlej3qKmOy5QCUV/xO9e2+JUuahOMuBFdy+DNzE4it+
 HeYV0CTEeaG99UOU4ItCuCRTgXausEVWNezxfZrhTI2t4bvyMGs=
 =/Oc5
 -----END PGP SIGNATURE-----

Merge tag 'tee-fix-for-v7.3' of git://git.kernel.org/pub/scm/linux/kernel/git/jenswi/linux-tee into arm/fixes

Reject zero-sized allocations in tee_dyn_shm_alloc_helper()

* tag 'tee-fix-for-v7.3' of git://git.kernel.org/pub/scm/linux/kernel/git/jenswi/linux-tee:
  tee: shm: reject zero-sized allocations in tee_dyn_shm_alloc_helper()

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
2026-10-03 23:33:02 +02:00
Arnd Bergmann
67c050583f Fix kernel-doc warnings
-----BEGIN PGP SIGNATURE-----
 
 iQJUBAABCgA+FiEE0qerISgy2SKkqO79Wr/6JGat8H4FAmrBEIAgHGplbnMud2lr
 bGFuZGVyQG9zcy5xdWFsY29tbS5jb20ACgkQWr/6JGat8H42UBAAzlnYCD3zohQp
 5H5MVA/3TCey4q7ww2GahM7e5lAueN1B/73pWIdjsB7ySNrbB8FPnN8+95d+hTev
 q4i7xabadOVPkE4h5BYMGFkYBYmdkzSb0nDCAW3GkypBdGehwYneK1fbMqMOATDz
 6YHO4TLSgWcRQt0y1SHwP9w5ald+MYePVNbW3fIeZWnixMG7XSNYWQJbi7JTdOdr
 zkK30YyvwIGuzogug3vYCaSoryyto7rZWWVPz2y0GT6L3KReCTQXFG/ZA7D0a1PG
 1/+bRTlvuEdz3cGesgW8f3hrwuCTm8m1+4P7yc0aDH8I2ghnL+ks/q80hG5W4Dq5
 qgX0XYQe2Xek5mgq1KpkCP3QkJ+5ofctcLYBsOl3OBYi7Ap97F6f9hLbE157Oe4i
 1lv+N/HpgfzicSbo75ORgIapBFdS0MjjaOPjO6uBX6qGC1YFnTeG2p8FWlr95sny
 mhovfL9Y3QYQ96kJXKwpPQBqP1QAP3MP8IqkHZhpzIUo32+nNqjDwUIIp66s0J5e
 n0xlhiuUJ6wJy8kY9Uryi+puN1JGF9UFiSJmS0bu8VRqsemDOpdQUEtv2CrZTnbk
 VdD9WDVLZcKjRRS3wHUJFIef72kDE0EDyDaLz4D/kX5wjhuZ2uVmQGIyr2JbMavj
 Qxd0ftaTFmwQAllqwwShETMS0dPkWqw=
 =PBha
 -----END PGP SIGNATURE-----
gpgsig -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEo6/YBQwIrVS28WGKmmx57+YAGNkFAmrBa9AACgkQmmx57+YA
 GNmtYhAAhmL/k87jNgEiZdGkkXabyXzI2vYa6MYY3bQTzg2IME3gBOSluEiPK7Ge
 T8xwkiBoZdeoH4vN7lpXH3FktepcJ+UpuR/SeP0CF02QepYNevcB2hqSQcCKzakr
 pVERb+NvEkvLSxfEFe/VvZvG56o753C6Yv7E0WJEWttEnnAAUeRZlj/PbNhUasRq
 8b8MF4p7RFAMbEccEz0+PGuCHRtMUPQ2kBB23dcB09Ljh8UunOOjCDjDVa2ckYuH
 qM1qbCQ+EFcP82fUbRsgZwloc57Gp7vtmx/uF6lG8XgqNphPf+B/0zYEyV/QcQZt
 AbKSj5RLHRm/mcR5qWJG1z98DpdPKdBXv7WTYPGlWXmICiiMqWixiOQyVSSnFKgk
 43/oG3w5fqZJYLLdMJ+HRgEK/KD+TC3/gEOKXMkgx9Zoa4OuDkryOwPsotih1Fil
 fi5yGWZLW4VzbxLXn84NRtMZizyc7FL5/joA8DFQenfwtCAGYHUhMddVdCmW9W+c
 O7o4HErRS/M5EKo1CVI/NUvlGthNoeobZxYOyVsSurr9pEmDl7M1gapgKIJY8Dbc
 RK3eLdDckRuNo2cvYZilIUA+iJha2cQmJB7S2wKSk2E3Bb4uLoMipObcmQs5oCJG
 OxxzKvZHt5koFM2mE1kvK0zMgP4MOA0X5mK5HYeNYWvc2gqHMHY=
 =E1wW
 -----END PGP SIGNATURE-----

Merge tag 'qcomtee-fix-for-v7.3' of git://git.kernel.org/pub/scm/linux/kernel/git/jenswi/linux-tee into arm/fixes

Fix kernel-doc warnings

* tag 'qcomtee-fix-for-v7.3' of git://git.kernel.org/pub/scm/linux/kernel/git/jenswi/linux-tee:
  tee: qcomtee: fix kernel-doc warnings

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
2026-10-03 22:55:39 +02:00
Linus Torvalds
a74306e2e6 Two small clk driver fixes:
- spacemit: k3: Fix an issue that will trigger a system hang due to
   unavailable frequency.
 - ti: composite: Reverts a commit that breaks OMAP3.
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQSkbTJwWGWqPd7cKQS30t0nXX7AhwUCasE5PAAKCRC30t0nXX7A
 h53bAQDDZT2927gpHwGA2v7Die+Zim3kTz/V51BE1ilzSXc8cwD/WTndQx2y6V7x
 31zCbTEkPX/nRl3Gt1qw+uscGwO7/AA=
 =5SHU
 -----END PGP SIGNATURE-----

Merge tag 'clk-fixes-for-linus-v7.3' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux

Pull clk fixes from Brian Masney:
 "Two small clk driver fixes:

   - spacemit: k3: Fix an issue that will trigger a system hang due to
     unavailable frequency

   - ti: composite: Reverts a commit that breaks OMAP3"

* tag 'clk-fixes-for-linus-v7.3' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux:
  clk: spacemit: k3: add CPU PLL rate tables
  clk: ti: composite: resolve parent clocks by name again
2026-10-03 10:57:47 -07:00
Len Brown
d3eea584b5 turbostat 2026.09.28
Signed-off-by: Len Brown <len.brown@intel.com>
2026-10-03 13:02:41 -04:00
Len Brown
154b96dab8 tools/power turbostat: Fix add_counter issue if > 24 counters.
We allocate space for added counters ahead of time,
and we arbitrarily chose 24 added counters of each type.
If a future code flow hits this limit and continues,
and then removes counters, we do a phantom increment
and lose track of the number of added counters.

Increment the count only if there is no error.

Fixes: 388e9c8134 ("tools/power turbostat: Make extensible via the --add parameter")
Assisted-by: Claude: Claude Sonnet 4.6
Signed-off-by: Len Brown <len.brown@intel.com>
2026-10-03 13:02:30 -04:00
Len Brown
11741cc90f tools/power turbostat: Fix PMT error path fd handling
It is possible to leak a file descriptor if a diretory
open succeeds, but the scan fails.  Close the fd on error.

Also, on cleanup, check for NULL fd.

Assisted-by: Claude: Claude Sonnet 4.6
Fixes: 4265a86582 ("tools/power turbostat: Add PMT directory iterator helper")
Signed-off-by: Len Brown <len.brown@intel.com>
2026-10-03 13:01:42 -04:00
Len Brown
5e940dd96b tools/power turbostat: Fix CWF PMT off-by-one
Fix off-by-one error causing last CPU on CWF
to never get a pmt counter allocated.

Fixes: 5ce1e9bbb2 ("tools/power turbostat: Add CPU%c1e BIC for CWF")
Assisted-by: GitHub Copilot (claude-sonnet-4.6)
Signed-off-by: Len Brown <len.brown@intel.com>
2026-10-03 13:00:55 -04:00
Len Brown
767c64414c tools/power turbostat: Fix fd_perf leak on reset
When turbostat notices a topology change,
it frees perf file descriptors for each CPU
to prepare to re-initialize.

Fix an off-by-one error in that per-cpu loop that
resulted in a file descriptor leak of the file for
the highest numbered CPU in the system.

Fixes: 67bab430f4 ("tools/power turbostat: Group SMI counter with APERF and MPERF")
Assisted-by: GitHub Copilot (claude-sonnet-4.6)
Signed-off-by: Len Brown <len.brown@intel.com>
2026-10-03 13:00:55 -04:00
Len Brown
485c599728 tools/power turbostat: Sanity check GFX%rc6 and SAM%mc6 percentages
When measuring over a suspend cycle, GRX%rc6 and SAM%mc6
are observed to print as numbers much greater than 100%.

Those numbers are not useful, and they mess up the columns.
Detect when they are out of range, and print them as NaN.

Signed-off-by: Len Brown <len.brown@intel.com>
2026-10-03 13:00:55 -04:00
longlong yan
148aefa949 tools/power turbostat: add NULL check after calloc()
Three calloc() calls in turbostat lack NULL return checks, leading to
potential NULL pointer dereferences on allocation failure:

1. rapl_perf_init(): the allocated `domain_visited` is used later via
   memset(domain_visited, 0, ...) without checking for NULL.

2. added_perf_counters_init_(): the allocated `domain_visited` is used
   later via memset() and domain_visited[next_domain] without checking
   for NULL.

3. pmt_add_counter(): the allocated `pcounter` is dereferenced
   immediately via strncpy(pcounter->name, ...) without checking for
   NULL.

Add NULL checks after each calloc(), using the same error handling
style already present in each function: err(-1, ...) for rapl_perf_init(),
errx(1, ...) for added_perf_counters_init_(), and return 1 for
pmt_add_counter().

Signed-off-by: longlong yan <yanlonglong@kylinos.cn>
Signed-off-by: Len Brown <len.brown@intel.com>
2026-10-03 13:00:54 -04:00
Len Brown
1de8307e86 tools/power turbostat: Warn, but don't Err on out-dated perf systems
Some systems in the field have perf enabled,
but their kernel perf support lacks the latest L2 stats.
Warn, but don't Err on those systems, and suggest how to avoid the Warn.

Fixes: dd23bfe4c3 ("tools/power turbostat: Add L2 cache statistics")
Reported-by: David Arcari <darcari@redhat.com>
Signed-off-by: Len Brown <len.brown@intel.com>
2026-10-03 13:00:44 -04:00
Linus Torvalds
25d576ed11 Char/Misc/IIO fixes for 7.3-rc6
Here is a set of char/misc/iio and other small driver subsystem fixes
 for 7.3-rc6 that resolve a number of reported issues.  Included in here
 are:
   - lots of small iio driver fixes for reported problems.
   - interconnect driver revert to resolve a regression
   - nitro_enclaves driver fix for a use-after-free
   - binder driver fixes for reported problems (in both the rust and C
     versions)
 
 All of these have been in linux-next with no reported issues
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 
 iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCasDiSA8cZ3JlZ0Brcm9h
 aC5jb20ACgkQMUfUDdst+yl3dQCdH7FcKA2Tw8/IlsWz6uprAdiwFVsAoLHwDHjt
 ryfPUaZkAvaZL4oPR4Dq
 =KRVz
 -----END PGP SIGNATURE-----

Merge tag 'char-misc-7.3-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc

Pull char/misc/IIO fixes from Greg KH:
 "Here is a set of char/misc/iio and other small driver subsystem fixes
  for 7.3-rc6 that resolve a number of reported issues. Included in here
  are:

   - lots of small iio driver fixes for reported problems

   - interconnect driver revert to resolve a regression

   - nitro_enclaves driver fix for a use-after-free

   - binder driver fixes for reported problems (in both the rust and C
     versions)

  All of these have been in linux-next with no reported issues"

* tag 'char-misc-7.3-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (63 commits)
  iio: adc: ad_sigma_delta: fix use-after-free on unbind
  iio: accel: kxcjk-1013: reject duplicate event disable
  iio: buffer: serialize buffer teardown with mode claims
  iio: cdc: ad7150: fix OF matching and publish module aliases
  iio: adc: ade9000: fix NULL pointer dereference in clkout registration
  iio: adc: ad4030: fix invalid oversampling_ratio validation
  iio: adc: ad7173: Fix digital filter configuration
  iio: adc: stm32-adc: fix possible division by zero in processed channel
  iio: adc: stm32-adc: fix check on internal channel availability
  iio: proximity: isl29501: Fix return type of isl29501_register_write
  iio: imu: inv_icm42607: restore runtime PM on system resume errors
  iio: imu: inv_icm42607: propagate runtime suspend errors
  iio: adc: pac1934: check ACPI label duplication
  rust_binderfs: add transaction_report feature entry
  rust_binder: reschedule node refcount update on thread exit
  rust_binder: cancel deferred work items in thread exit
  binderfs: fix UAF write in binder_add_device
  binder: fix is_failure flag for superseded transaction cleanup
  binder: fix leaked fd fixups on TF_UPDATE_TXN supersede
  Revert "interconnect: qcom: x1e80100: enable QoS configuration"
  ...
2026-10-03 09:05:47 -07:00