mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/
synced 2026-11-13 07:31:07 +00:00
1,485,420 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
a90ee4305c | Linux 7.3-rc6 v7.3-rc6 | ||
|
|
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:
|
||
|
|
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> |
||
|
|
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:
|
||
|
|
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:
|
||
|
|
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:
|
||
|
|
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 |
||
|
|
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 |
||
|
|
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> |
||
|
|
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:
|
||
|
|
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:
|
||
|
|
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
|
||
|
|
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
|
||
|
|
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()
|
||
|
|
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
|
||
|
|
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> |
||
|
|
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> |
||
|
|
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:
|
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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:
|
||
|
|
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: |
||
|
|
caf16f9b4a |
nullfs: don't update the access time
There's no point in updating access times of the nullfs instance. Raise
S_IMMUTABLE.
Fixes:
|
||
|
|
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:
|
||
|
|
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:
|
||
|
|
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> |
||
|
|
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:
|
||
|
|
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:
|
||
|
|
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:
|
||
|
|
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:
|
||
|
|
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
|
||
|
|
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:
|
||
|
|
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> |
||
|
|
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> |
||
|
|
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
|
||
|
|
d3eea584b5 |
turbostat 2026.09.28
Signed-off-by: Len Brown <len.brown@intel.com> |
||
|
|
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:
|
||
|
|
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:
|
||
|
|
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:
|
||
|
|
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:
|
||
|
|
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> |
||
|
|
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> |
||
|
|
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:
|
||
|
|
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"
...
|