summaryrefslogtreecommitdiff
AgeCommit message (Collapse)Author
2026-10-10ALSA: hda/realtek: Enable all four speaker amps on Lenovo ThinkBook X G2 IAHEvgeny Akhtimirov
The Lenovo ThinkBook X G2 IAH (MTM 21TU) has an ALC287 codec with four CS35L41 amplifiers on I2C (CSC3551). It reports codec SSID 17aa:3929, which it shares with the ThinkBook 13x Gen 5, and PCI SSID 17aa:3842. Since PCI SSID 17aa:3842 has no quirk entry, the codec SSID matches ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD. That fixup binds only two amps (cs35l41-hda.0 and .1), while the CS35L41 configuration table describes four for 17AA3929. Amps .2 and .3 probe and load firmware, but they are never bound to the codec, so half of the speakers stay silent. Add a ThinkPad-style fixup chain that binds four I2C amps, and match the laptop by its PCI SSID so the ThinkBook 13x Gen 5 is not affected. Tested with hda_model=1028:0c4d (alias to ALC287_FIXUP_CS35L41_I2C_4): all four amps bind, apply their calibration and are runtime-active during playback. Cc: stable@vger.kernel.org Signed-off-by: Evgeny Akhtimirov <evgeny@devduty.com> Link: https://patch.msgid.link/20261009-thinkbook-x-g2-iah-v1-1-56012188aee0@devduty.com Signed-off-by: Takashi Iwai <tiwai@suse.de>
2026-10-10ALSA: hda: Add NULL check for the driver pointer at unsol event workTakashi Iwai
snd_hdac_bus_process_unsol_events() assumes that the codec driver is always set when it's accessible from the codec table. It's true in general, but in a sheer timing, it might have been already NULLified at the driver unbinding. Although the codec removal should have been done properly by the previous fixes, just for more safety, let's add a NULL check before dereferencing and calling the driver's unsol_event callback. Fixes: e7255c00b10e ("ALSA: hda: Skip event processing for unregistered codecs") Link: https://patch.msgid.link/20261009133341.440917-6-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
2026-10-10ALSA: hda: Stop unsol event and jack polling at hda-ext device removal, tooTakashi Iwai
In the recent commit f3607b6952ca ("ALSA: hda: Stop unsol events and jack polling before codec unbind"), we applied the workaround to stop pending works at the hda codec driver removal, but it was applied after the bypass for hda-ext ops hdev_detach. Basically the same issue is seen for hda-ext stuff, so it's safer to apply the workaround at the beginning of hda_codec_driver_remove(). Along with it, the clearance of unsol_disabled flag is moved to the beginning of hda_codec_driver_probe(), too; otherwise hda-ext hdev_attach() might miss the unsol event handling when the code gets re-bound. Fixes: f3607b6952ca ("ALSA: hda: Stop unsol events and jack polling before codec unbind") Link: https://patch.msgid.link/20261009133341.440917-5-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
2026-10-10ALSA: hda: Add lock around codec->registered flag manipulationsTakashi Iwai
Currently the places setting or clearing codec->registered flag have no locking, while its reference in the unsol handling work snd_hdac_bus_process_unsol_events() takes the bus->reg_lock lock. Let's add the same bus->reg_lock at the places where codec->registered is set and cleared for avoiding the races. Link: https://patch.msgid.link/20261009133341.440917-4-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
2026-10-10ALSA: hda: Disable unsol event handling at error and shutdown pathsTakashi Iwai
When the HD-audio controller driver probe fails, it still leaves the unsolicited event handling and jackpoll work active, hence if they are pending, they might fire up later after the resource gets released, which may lead to a UAF. A similar problem may be seen at shutdown, too. Add the recently added helper to disable unsol events and the cancel of jackpoll_work at the appropriate places. We need the workaround in the error path before driver->ops->remove, too. As unsol events and jack polling may have been already enabled during the probe callback, the driver->ops->remove call is done (more) conditionally now. Fixes: c3ec8ac82105 ("ASoC: hdac_hda: fix memleak on module unload") Reported-by: Sashiko <sashiko-bot@kernel.org> Link: https://patch.msgid.link/20261009133341.440917-3-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
2026-10-10Merge tag 'mm81x-next-2026-10-09' of ↵Johannes Berg
https://github.com/MorseMicroLabs/linux-wireless Lachlan Hodges says: ==================== mm81x 7.4 PR #2 - monitor mode support - rx improvements - fix persistent NO_IR flag bug - misc minor LLM fixes ==================== Signed-off-by: Johannes Berg <johannes.berg@intel.com>
2026-10-09Input: mms114 - fix touch slot corruption in suspendDmitry Torokhov
In mms114_suspend, the driver synthesizes touch release events for all slots and calls input_sync before disabling the hardware interrupt via mms114_stop. Because the threaded interrupt handler runs independently and does not share a lock with this early part of the suspend path, an incoming hardware interrupt can fire after input_sync completes but before disable_irq is invoked. If a touch event arrives during this window, the interrupt handler reports the touch slot as active again, overwriting the synthetic release event right before the system goes to sleep. Upon resume, lifting the finger does not generate a release interrupt, potentially leaving userspace with a stuck active touch slot. Fix this race by calling mms114_stop, which disables the IRQ and synchronizes with any executing interrupt handler, before synthesizing the touch release events. Also ensure that we only synthesize touch release events if the input device is enabled, keeping the entire suspend sequence protected by input_dev->mutex. Reported-by: sashiko-bot@kernel.org Assisted-by: Antigravity:gemini-3.6-flash Link: https://patch.msgid.link/anKxGkyRRu5A92Q_@google.com Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
2026-10-09fs/resctrl: Ensure default group reports tasks on monitor-only systemsTony Luck
resctrl can be mounted on a system that supports monitoring but not allocation. On such a system reading the "tasks" file in the default group reports no tasks, even when there are tasks assigned to the default group. This problem occurs because the check for whether a task belongs to a CTRL_MON group is gated by a check for whether the system supports allocation. The resctrl_arch_alloc_capable() check in is_closid_match() breaks task reporting for the default group on monitor-only systems so remove this check. On systems that support allocation the check is redundant. Fixes: e6b2fac36fcc ("x86/resctrl: Use is_closid_match() in more places") Closes: https://sashiko.dev/#/patchset/20260831174421.13921-1-tony.luck%40intel.com?part=9 Reported-by: Sashiko <sashiko-bot@kernel.org> Signed-off-by: Tony Luck <tony.luck@intel.com> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Reviewed-by: Reinette Chatre <reinette.chatre@intel.com> Link: https://patch.msgid.link/20261009193923.15498-1-tony.luck@intel.com
2026-10-09drm/nouveau: prevent NULL deref of gr in GETPARAM_GRAPH_UNITSZhenhao Wan
nouveau_abi16_ioctl_getparam() fetches the graphics engine with gr = nvxx_gr(drm) (i.e. drm->nvkm->gr) and, for the NOUVEAU_GETPARAM_GRAPH_UNITS parameter, passes it straight to nvkm_gr_units(), which dereferences gr->func with no NULL check. When graphics-engine construction returns -ENODEV, NVKM treats it as an optional absent engine: the NVKM_LAYOUT_ONCE device constructor deletes the subdevice, leaves device->gr == NULL and continues probing, and Nouveau still registers a render node. An unprivileged client holding a /dev/dri/renderD* fd can then issue DRM_IOCTL_NOUVEAU_GETPARAM with NOUVEAU_GETPARAM_GRAPH_UNITS and oops the kernel on the NULL gr. Report 0 units when gr is absent. This matches nvkm_gr_units() itself, which already returns 0 when the engine exposes no units callback. Reported-by: Yuhao Jiang <danisjiang@gmail.com> Assisted-by: LLM Signed-off-by: Zhenhao Wan <whi4ed0g@gmail.com> Reviewed-by: Lyude Paul <lyude@redhat.com> Signed-off-by: Lyude Paul <lyude@redhat.com> Link: https://patch.msgid.link/20260812-nouveau-nvkm-absent-subdev-null-deref-v1-2-7e057f6aeba0@gmail.com
2026-10-10Merge tag 'pci-v7.3-fixes-4' of ↵Linus Torvalds
git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci Pull PCI fix from Bjorn Helgaas: "This fixes some GPU initialization regressions caused by eddba19b8b5f ("PCI/AER: Support Advisory Non-Fatal Errors"), which appeared in v7.3-rc1. That commit also caused a MacBookPro16,1 spontaneous power-off regression; I expect a fix for that next week" * tag 'pci-v7.3-fixes-4' of git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci: PCI/AER: Skip error recovery on false alarms
2026-10-10Merge tag 'mmc-v7.3-rc1-2' of ↵Linus Torvalds
git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc Pull MMC/MEMSTICK fixes from Ulf Hansson: "MMC host: - cavium-octeon|thunderx: Destroy slot platform devices on remove - mtk-sd: Cancel request timeout work on remove - sdhci-sprd: Disable runtime PM on remove MEMSTICK: - Wait for request completion before freeing card - rtsx_usb_ms: Complete requests after eject instead of dropping them" * tag 'mmc-v7.3-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc: memstick: rtsx_usb_ms: complete requests after eject instead of dropping them memstick: core: wait for request completion before freeing card mmc: cavium-thunderx: destroy slot platform devices on remove mmc: cavium-octeon: destroy slot platform devices on remove mmc: sdhci-sprd: disable runtime PM on remove mmc: mtk-sd: Cancel request timeout work on remove
2026-10-10Merge tag 'media/v7.3-3' of ↵Linus Torvalds
git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media Pull media fix from Mauro Carvalho Chehab: "A fix for em28xx unregister code affecting devices with FM radio support" * tag 'media/v7.3-3' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: media: em28xx: use video_unregister_device for radio_dev
2026-10-10Merge tag 'sound-7.3-rc7' of ↵Linus Torvalds
git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound Pull sound fixes from Takashi Iwai: "A dozen of small fixes. All device-specific quirks or fixes, and nothing exciting is expected. - USB-audio and HD-audio quirks - HD-audio TAS2781 codec fix - ctxfi driver memory leak fix - ASoC AMD quirks - ASoC cs35l56 and adau1372 codec fixes" * tag 'sound-7.3-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: ASoC: amd: acp: Add more ACP7.0 match entries for Cirrus Logic parts ASoC: amd: acp: Add DMI override for ASUS EXPERTBOOK AM7406CKA ASoC: sdw_utils: Switch CS35L56/57/62/63 to use OT25 DAI ASoC: cs35l56: Add DAI for SDCA OT25 stream ASoC: samsung: i2s: enable op_clk in probe to balance runtime PM ASoC: adau1372: fix invalid default state of output ASRC and DAC muxes ASoC: adau1372: allow sleepy powerdown GPIOs ASoC: amd: yc: Add DMI quirk for Acer Aspire Go 15 (AG15-21P) ALSA: hda/realtek: Add mute LED quirk for HP Pavilion 15-eg3xxx (103c:8bfd) ALSA: hda/tas2781: Accept V1 calibration data without CRC ALSA: ctxfi: Fix memory leakage when clearing DAO input mappers ALSA: hda/realtek: Add quirk for ASRock NUC BOX-358H ALSA: usb-audio: Add native DSD support for Cambridge Audio streamers
2026-10-10Merge tag 'pmdomain-v7.3-rc2' of ↵Linus Torvalds
git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/linux-pm Pull pmdomain provider fixes from Ulf Hansson: - imx: Serialize power on/off across sibling domains for imx8m-blk-ctrl - rockchip: Fix a couple of errors during probe * tag 'pmdomain-v7.3-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/linux-pm: pmdomain: rockchip: don't ignore clock lookup errors on attach pmdomain: rockchip: fix clock leak on domain probe failure pmdomain: rockchip: propagate subdomain add errors pmdomain: imx8m-blk-ctrl: Serialize power on/off across sibling domains
2026-10-10Merge tag 'dma-mapping-7.3-2026-10-09' of ↵Linus Torvalds
git://git.kernel.org/pub/scm/linux/kernel/git/mszyprowski/linux Pull dma-mapping fixes from Marek Szyprowski: "Two more fixes for the corner cases in the DMA-mapping SWIOTLB code (Peng Fan and Marek Szyprowski)" * tag 'dma-mapping-7.3-2026-10-09' of git://git.kernel.org/pub/scm/linux/kernel/git/mszyprowski/linux: swiotlb: fix default_swiotlb_limit() for non-growable default pool iommu/dma: skip swiotlb bounce for DMA_ATTR_MMIO in iommu_dma_map_phys
2026-10-10Merge tag 'fsverity-for-linus' of git://git.kernel.org/pub/scm/fs/fsverity/linuxLinus Torvalds
Pull fsverity fix from Eric Biggers: "Fix a regression from commit f77f281b6118 ("fsverity: use a hashtable to find the fsverity_info")" * tag 'fsverity-for-linus' of git://git.kernel.org/pub/scm/fs/fsverity/linux: fsverity: RCU-delay the freeing of struct fsverity_info
2026-10-09sched_ext: scx_qmap: Reset a child's cpuperf targets once its PERF revoke ↵Tejun Heo
takes effect A child that ran a cid at a low cpuperf target leaves the target there when PERF is revoked, since the kernel resets targets only at root enable. Reset the target from ops.sub_child_ecaps_updated() once the revoke is in effect. A detach reports nothing, so ops.sub_detach() resets the child's cids, and the pool unless another child holds it. Count the deliveries in the hier stats. v2: Reset from ops.sub_detach() for a detaching child's cids. v3: Skip the pool at detach while another child holds it (Andrea Righi). Signed-off-by: Tejun Heo <tj@kernel.org> Reviewed-by: Andrea Righi <arighi@nvidia.com>
2026-10-09Merge tag 'vfs-7.3-rc7.fixes' of ↵Linus Torvalds
git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs Pull vfs fixes from Christian Brauner: "This contains fixes for the current development cycle. All of them came out of a review of the mount code that started with a bug report. The review modeled the corner cases of mount propagation, unmounting and mount reference counting and turned up a lot of bugs. Most of them years old. Most fixes come with a selftest. - Rework connected mounts. A mount that is unmounted together with its parent can stay attached to the parent to keep its mountpoint covered. That happens when the mountpoint is removed with rmdir(), unlink() or rename(), when a detached tree is dissolved, and for locked mounts in any umount that isn't synchronous, including the teardown of their mount namespace. The parent then owns the child and drops it on its own final mntput(). So any reference from the child's superblock back to one of its ancestors becomes a cycle that is never freed. A loop device backed by an image on a tmpfs and mounted on that same tmpfs is enough. Remove the directory the tmpfs is mounted on from the host, let the container's mount namespace exit, and the loop device, the tmpfs and the filesystem on the loop device are leaked for good. The same works with autofs, zram, ecryptfs, binfmt_misc, fuse passthrough, zloop, a mass storage gadget and md, and the selftests have reproducers for them. This has been possible since v4.1. It is also why "put_mnt_ns(): leave mounts connected" was reverted in -rc5. Keeping every mount of a dying mount namespace connected made these cycles trivial to create. Every unmounted mount is now detached from its parent. Where the mountpoint has to stay covered the mount leaves a cover on the parent instead, allocated together with the mount. A lookup on the unmounted parent that hits a cover finds an empty immutable directory or file on the private nullfs instance. Nothing leads from a cover to another mount, so no unmounted mount owns another one and no cycle can form. This is visible to userspace. A formerly connected mount can no longer be reached through its unmounted parent and ".." inside it leads nowhere, as for every other lazily unmounted mount. With that the private nullfs instance becomes reachable from userspace, so it now refuses mounts on top, is mounted read-only, and refuses fsnotify marks and file locks. Its inodes are shared by every holder and a watch or a lock would otherwise reach across users. may_decode_fh() now also decides its subtree check under a single mount_lock hold, as a racing umount could otherwise let it decode into what a locked child covered. - umount: * Don't silently unmount busy mounts. Since v4.13 propagate_umount() takes down propagated copies of the victim with children as long as each child is an overmount or another copy of the victim, but propagate_mount_busy() only ever checked copies without children or with just an overmount. A container that moved a tree beneath its copy of a host mount lost that tree from under its open file descriptor to a plain umount() on the host. propagate_mount_busy() now applies the same rules, walking each chain of copies once. * Don't let a migrating task hide its reference from umount(). mnt_get_count() sums the per-cpu counters under mount_lock but the mntget() and mntput() fast paths don't take it. A task that takes a reference on a cpu the sum has already passed and drops it after migrating to one the sum hasn't reached yet hides the reference it held to begin with, and umount() succeeds with the file still open. Gets and puts now live in separate per-cpu counters and all puts are summed before all gets with a full barrier in between, the way srcu_readers_active_idx_check() does it. mntget() is unchanged and mntput() gains an smp_wmb(). * Check each submount for references right before unmounting it. shrink_submounts() and mark_mounts_for_expiry() checked all their victims up front. Unmounting the first could move a busy overmount to where the next victim's propagated copy is looked up and it was then unmounted without a check. * Never expire a locked mount. A shrinkable mount moved beneath a locked mount with MOVE_MOUNT_BENEATH takes over the lock, and umount() of an unlocked ancestor expired it and revealed what it covered. That umount() now fails with EBUSY as it does for any other locked child. A lazy umount still takes the whole tree. - Overmounts and locked mounts: * Unhash a dentry before detaching the mounts on it. unlink(), rmdir() and rename() detach the mounts on the victim but only d_delete() it once its inode is unlocked, a window that includes an expedited RCU grace period. In between, a lookup from a mount namespace in which the dentry is a mountpoint found it hashed, positive and uncovered. Drop the dentry first, as d_invalidate() already does. * Don't reveal overmounted entries in refwalk. A refwalk that had grabbed the dentry before the unlink never rechecked it the way rcuwalk does with d_seq and mount_lock. Without any artificial widening three walkers read the covered file 27 times in a minute. step_into() now fails an unhashed dentry marked DCACHE_CANT_MOUNT with -ESTALE and the walk is retried. * Keep covered mounts covered in OPEN_TREE_NAMESPACE. Creating such a mount namespace only takes a user namespace and the copy followed bind mount rules: no children without AT_RECURSIVE and no unbindable mounts with it. An unprivileged user could see what mounts covered in the source, such as the parts of /proc and /sys that container runtimes mask. If the caller doesn't own the source mount namespace a non-recursive copy of a mount with something mounted below the requested directory is now refused and a recursive copy includes unbindable mounts, the way unshare() copies. * Keep the lock on a mount that a propagated copy is moved beneath. MNT_LOCKED moved to any mount that ended up beneath a locked mount, propagated copies included. A host mount and umount on a directory covered by a locked mount in a less privileged mount namespace left that cover unlocked for the namespace's owner to remove. Only mounts the caller places beneath take over the lock now. * Handle mount locking for automounts correctly. Which copies to lock was decided by the mount namespace of the task that triggered the automount. A task in a user namespace that triggered one on a host mount through a file descriptor got the host's own automount locked while its own copy stayed unlocked and could have nosuid, nodev and noexec cleared. Use the owner of the mount namespace the mount lands in. - Use-after-free and crashes: * Refuse an automount below a mount that is in no namespace. The private clones overlayfs uses for its layers have the MNT_NS_INTERNAL error pointer as their namespace, which finish_automount() let through and count_mounts() dereferenced. A fanotify filesystem mark on an overlayfs lower layer hands out file descriptors on such a clone. With debugfs as the lower layer opening "tracing" oopses with namespace_sem held for writing and every mount operation on the system blocks from then on. * Reset the old parent's ->overmount in mnt_change_mountpoint(). When propagate_umount() moved an overmount off a mount that a file descriptor kept alive, MOVE_MOUNT_BENEATH through that descriptor later followed the stale pointer into the freed overmount. * statmount() with STATMOUNT_BY_FD and pivot_root() read the parent of a mount that may be unmounted and only held by a file descriptor, while the parent's final mntput() can free it. statmount() now reads it under mount_lock and pivot_root() first checks that both mounts are in the caller's mount namespace. * Queue a mount only once for mount notifications. A mount reparented by one umount_tree() and taken down by the next under the same namespace_sem hold, as in shrink_submounts(), was queued twice. That cut the mounts queued in between out of notify_list while it still pointed at them, and once they were freed every later mount operation walked freed memory. * Don't let a pseudo dentry become the root of a mount. A bind mount of a bpf token file did that with a DCACHE_NORCU dentry, which is freed without an RCU grace period while lockless path walks may still look at it. Refuse to clone such a mount. * Don't inherit MNT_UMOUNT in clone_mnt(). A bind mount of a lazily unmounted nsfs or pidfs mount through its file descriptor started out flagged as unmounted. Among other things __detach_mounts() then dropped the namespace's reference on it, the mount outlived its namespace and mount_setattr() through the descriptor read the freed namespace. A recursive bind mount of such a mount also copied the unmounted stack still attached to it. That now fails with EINVAL, copying the mount itself still works. * Remove the fsnotify marks of a mount namespace in free_mnt_ns() instead of the RCU callback that frees the namespace, where taking the group mutexes meant sleeping in softirq context. - Propagation and copies: * Keep a copied mount unbindable. Since v6.17 clone_mnt() didn't copy the unbindable flag, so every mount namespace created with CLONE_NEWNS had bindable copies of all unbindable mounts. This had been fixed once before. * Refuse MOVE_MOUNT_SET_GROUP on an unbindable mount. It made the mount an unbindable slave, a state nothing else can produce, or silently dropped the unbindable flag. CRIU applies MS_UNBINDABLE after restoring sharing and isn't affected. * Check a recursive bind mount for mount namespace loops. Recursively bind mounting a tree from another mount namespace could put a mount of a namespace's file inside that same namespace, which then pins itself and all its mounts. Repeating it leaks without limit, the reproducer took Shmem from 380 kB to 65916 kB. The copy is now checked with check_for_nsfs_mounts() before it is grafted, as move_mount() does. * Look at the topmost mount for a mount namespace file. attach_recursive_mnt() never looked at the topmost mount of the source's chain of overmounts. If that was the chain's only mount namespace file an existing mount at a propagated destination got buried below the root of the nsfs file where no path walk reaches it. * Don't put a mountpoint on a dentry that's being removed. attach_recursive_mnt() makes a mountpoint of the source's root without its inode lock, so a racing rmdir() of that directory could leave a mount on it that nothing ever detaches. d_set_mounted() now checks cant_mount() as well. - nullfs: * Take no inode lock for readdir of an immutable directory. The root of every empty mount namespace is the same nullfs directory and iterate_dir() held its i_rwsem across ->iterate_shared(). A reader whose buffer faults on a FUSE mount of its own holds it for as long as its server wants, and with an exclusive locker queued behind it every lookup that misses the dcache, every create and every mount in that directory waits. One user of an empty mount namespace stalls all others. Directories with the new FOP_IMMUTABLE flag skip the lock. * Refuse to reconfigure internal superblocks through fspick(), MS_REMOUNT or the read-only remount that a synchronous umount() of the root does. For nullfs only root in the initial user namespace could do it, but the superblock is shared by every mount namespace and the flags showed up in statfs() for all of them. * Don't update the access time on nullfs and refuse F_SET_RW_HINT on an immutable inode. - unshare: Free an nsproxy that was never installed with nsproxy_free() when set_cred_ucounts() fails. put_nsproxy() dropped active references that were never taken, which triggered a warning and hid the caller's own namespaces from listns(). - Smaller changes: mount_setattr() checks the target before it walks the tree to allocate peer group ids, unshare() puts the old fs_struct before the old namespaces, dissolve_on_fput() drops the file's reference to the tree itself, disconnect_mount() is simplified and the documentation of the propagated unmount rule is brought up to date" * tag 'vfs-7.3-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: (58 commits) namespace: simplify disconnect_mount() selftests/filesystems: test covered mounts namespace: rework connected mounts nullfs: add an empty immutable regular file 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 ...
2026-10-09sched_ext: Add ops.sub_child_ecaps_updated() to report a child's effective ↵Tejun Heo
cap changes A grant or revoke only records the target caps. They take effect on a cid at its next dispatch, and nothing tells the parent when. Without that the parent cannot act on a revoke: a child that ran a cid at a low cpuperf target leaves the target there when PERF is revoked, as the kernel resets targets only at root enable. Nor can the parent tell when it may schedule on the cid again. Add ops.sub_child_ecaps_updated(), delivered to the direct parent right after the child's own ops.sub_ecaps_updated() with the child's cgroup id and the same before and after caps, in the same dispatch context. Both deliveries are suppressed while the child is bypassing and replayed together afterwards. A disabled child reports nothing: ops.sub_detach() is where the parent restores what it had delegated. A sub is now bypassed before it is linked, so that the grants queued for it from ops.sub_attach() are consumed while it is bypassed and replayed to it and the parent once it is enabled. Otherwise a sync consumed before the sub's ops are registered would reach the parent but never the sub. v2: Drop the disable report with its sleep lock and nested-dispatch gate, the parent restores from ops.sub_detach() instead. Signed-off-by: Tejun Heo <tj@kernel.org> Reviewed-by: Andrea Righi <arighi@nvidia.com>
2026-10-09Merge tag 'arm64-fixes' of ↵Linus Torvalds
git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux Pull arm64 fixes from Will Deacon: "It finally seems to have calmed down on the arm64 fixes front, so please pull these two straightforward fixes for -rc7. One fixes the EL2 trap configuration for implementation-defined CPU PMU hardware during boot and the other fixes a kcov selftest failure by excluding our softirq early entry code: - Fix PMU EL2 trap configuration for CPUs with an IMPDEF PMU - Fix kcov boot selftest failure by excluding our early IRQ entry code" * tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux: arm64: irq: exclude the softirq stack switch from KCOV arm64/boot: Don't set PMUv3p9 FGT2 bits without PMUv3
2026-10-09Merge branch 'for-7.4/cxl-fixes' into cxl-for-nextDave Jiang
perf coordinates fixes: cxl/acpi: Convert QTG _DSM latencies to picoseconds cxl: Account for link width in latency calculation cxl/port: Convert PCIe link latency to nanoseconds GPF path fixes: cxl/pci: Update only the Port GPF timeout fields cxl/pci: Program the Port GPF timeouts before caching the DVSEC cxl/pci: Use the Device GPF DVSEC for restricted endpoints dport fixes: cxl/port: Attach endpoints to a dport under the lock that pins it cxl/core: Hold the dport host lock across dport lookup and use cxl/port: Clear cached dport pointers when a dport is removed
2026-10-09cxl/acpi: Convert QTG _DSM latencies to picosecondsKoichiro Den
The QTG _DSM expects read and write latencies in picoseconds, as specified in CXL 3.0, Table 9-30. The code base originally kept the latencies passed to the QTG _DSM in picoseconds in effect. Commit 51293c565cf4 ("cxl: Fix incorrect region perf data calculation") normalized CDAT and host bridge latencies to nanoseconds, but did not add a conversion back to picoseconds when constructing the _DSM input. Firmware can therefore select QTG IDs using understated latencies. Convert the latencies to picoseconds when constructing the _DSM input package. Multiply in 64 bits and reject latencies that cannot fit in the DWORD inputs defined by the specification. Fixes: 51293c565cf4 ("cxl: Fix incorrect region perf data calculation") Cc: stable@vger.kernel.org Signed-off-by: Koichiro Den <den@valinux.co.jp> Reviewed-by: Alison Schofield <alison.schofield@intel.com> Reviewed-by: Dave Jiang <dave.jiang@intel.com> Link: https://patch.msgid.link/20261009045452.1107921-4-den@valinux.co.jp Signed-off-by: Dave Jiang <dave.jiang@intel.com>
2026-10-09cxl: Account for link width in latency calculationKoichiro Den
cxl_pci_get_latency() derives bandwidth from the per-lane speed returned by pcie_link_speed_mbps(), ignoring the negotiated link width. This overestimates the FlitLatency contribution for multi-lane links. Sections 2.11.3 and 2.11.4 of the Intel CXL Memory Device Software Guide describe the link bandwidth as the product of the negotiated speed and width. Replace pcie_link_speed_mbps() with pcie_link_bandwidth_mbps() and migrate both CXL callers (the only users of the API). The new helper obtains speed and width from a single Link Status read. The CXL bandwidth calculation no longer needs a separate width read and multiplication. While at it, make error handling more robust by converting PCI config read errors to negative errno values and checking for zero bandwidth before calculating latency. Fixes: 4d07a05397c8 ("cxl: Calculate and store PCI link latency for the downstream ports") Cc: stable@vger.kernel.org Signed-off-by: Koichiro Den <den@valinux.co.jp> Reviewed-by: Alison Schofield <alison.schofield@intel.com> Acked-by: Bjorn Helgaas <bhelgaas@google.com> # pci/pci.c Reviewed-by: Dave Jiang <dave.jiang@intel.com> Link: https://patch.msgid.link/20261009045452.1107921-3-den@valinux.co.jp Signed-off-by: Dave Jiang <dave.jiang@intel.com>
2026-10-09cxl/port: Convert PCIe link latency to nanosecondsKoichiro Den
Commit 51293c565cf4 ("cxl: Fix incorrect region perf data calculation") converted CDAT latencies to nanoseconds and removed the conversion in cxl_region_perf_data_calculate(), but left PCIe link latencies in picoseconds. This inflates the FlitLatency contribution to region and node latencies by a factor of 1000, exposing incorrect values in sysfs. The resulting abstract distances can incorrectly reverse the memory tier ordering of nodes. Convert the FlitLatency contribution to nanoseconds before adding it to the access coordinates, rounding up as cdat_normalize() does. Fixes: 51293c565cf4 ("cxl: Fix incorrect region perf data calculation") Cc: stable@vger.kernel.org Signed-off-by: Koichiro Den <den@valinux.co.jp> Reviewed-by: Alison Schofield <alison.schofield@intel.com> Reviewed-by: Dave Jiang <dave.jiang@intel.com> Link: https://patch.msgid.link/20261009045452.1107921-2-den@valinux.co.jp Signed-off-by: Dave Jiang <dave.jiang@intel.com>
2026-10-09cxl/pci: Update only the Port GPF timeout fieldsGuixin Liu
update_gpf_port_dvsec() rebuilds the phase control register from just the timeout base and scale, so the rest of the register is cleared by the write. The other bits are reserved today and nothing is lost, but the full-register rewrite would clobber any field the spec defines there later. Read-modify-write the register and change only the two timeout fields. Fixes: a52b6a2c1c99 ("cxl/pci: Support Global Persistent Flush (GPF)") Assisted-by: LLM Signed-off-by: Guixin Liu <kanie@linux.alibaba.com> Reviewed-by: Dave Jiang <dave.jiang@intel.com> Reviewed-by: Alison Schofield <alison.schofield@intel.com> Link: https://patch.msgid.link/20261008034619.28059-4-kanie@linux.alibaba.com Signed-off-by: Dave Jiang <dave.jiang@intel.com>
2026-10-09cxl/pci: Program the Port GPF timeouts before caching the DVSECGuixin Liu
cxl_gpf_port_setup() caches the Port GPF DVSEC offset in the dport before programming the phase timeouts, and ignores the return value of both update_gpf_port_dvsec() calls: the function always reports success. A failing config write is therefore not only silent, it is also permanent: the timeouts stay at the hardware defaults instead of the maximum flush window the kernel is asking for, and the cached offset keeps any later endpoint attach from retrying the update. Propagate the errors and cache the offset only after both phases are programmed, so the next endpoint attach retries the setup. Fixes: 6af941db6a60 ("cxl/pci: Update Port GPF timeout only when the first EP attaching") Cc: stable@vger.kernel.org Assisted-by: LLM Signed-off-by: Guixin Liu <kanie@linux.alibaba.com> Reviewed-by: Jonathan Cameron <jonathan.cameron@oss.qualcomm.com> Reviewed-by: Dave Jiang <dave.jiang@intel.com> Reviewed-by: Alison Schofield <alison.schofield@intel.com> Link: https://patch.msgid.link/20261008034619.28059-3-kanie@linux.alibaba.com Signed-off-by: Dave Jiang <dave.jiang@intel.com>
2026-10-09cxl/pci: Use the Device GPF DVSEC for restricted endpointsGuixin Liu
cxl_gpf_get_dvsec() picks between the Port and the Device GPF DVSEC from the PCIe type of the given device, and only a plain endpoint counts as a device. A restricted CXL device is an endpoint too, but it falls into the port case and is probed for the Port GPF DVSEC instead of the Device GPF DVSEC. On an RCD, dirty shutdown tracking therefore never arms: the DVSEC lookup in cxl_nvdimm_arm_dirty_shutdown_tracking() fails, the dirty shutdown count stays invalid, and the warning complains about a missing Port GPF DVSEC on a device. Treat restricted endpoints as devices. Fixes: 36aace15d9bd ("cxl/pci: Drop the parameter is_port of cxl_gpf_get_dvsec()") Cc: stable@vger.kernel.org Assisted-by: LLM Signed-off-by: Guixin Liu <kanie@linux.alibaba.com> Reviewed-by: Jonathan Cameron <jonathan.cameron@oss.qualcomm.com> Reviewed-by: Dave Jiang <dave.jiang@intel.com> Reviewed-by: Alison Schofield <alison.schofield@intel.com> Link: https://patch.msgid.link/20261008034619.28059-2-kanie@linux.alibaba.com Signed-off-by: Dave Jiang <dave.jiang@intel.com>
2026-10-09cxl/port: Attach endpoints to a dport under the lock that pins itDave Jiang
devm_cxl_enumerate_ports() and add_port_attach_ep() look up or create a dport under its port's device lock, drop the lock, then pass the dport to cxl_add_ep(). add_ep() reads dport->port before taking the lock, and cxl_gpf_port_setup() reads and writes the dport with no lock held. A concurrent cxl_detach_ep() for another memdev below the same port can free the dport in that window: it calls del_dports() under the port lock when the last endpoint leaves. The enumerating memdev then dereferences freed memory. Attach the endpoint and set up GPF while the port lock from the lookup is still held. Make add_ep() assert that lock instead of taking it. Under the lock, a dport found in port->dports is still live, since removal erases it from the xarray before freeing it. [ dj: Added kdoc update from Alison. ] Fixes: de516b40116e ("cxl/port: Record dport in endpoint references") Reported-by: Li Ming <ming.li@zohomail.com> Closes: https://lore.kernel.org/linux-cxl/0c68324c-cfc7-46b2-9344-24ae40e88923@zohomail.com/ Assisted-by: LLM Reviewed-by: Li Ming <ming.li@zohomail.com> Reviewed-by: Alison Schofield <alison.schofield@intel.com> Link: https://patch.msgid.link/20261001154744.1095902-4-dave.jiang@intel.com Signed-off-by: Dave Jiang <dave.jiang@intel.com>
2026-10-09cxl/core: Hold the dport host lock across dport lookup and useDave Jiang
Callers of cxl_pci_find_port() and cxl_mem_find_port() can be handed a 'struct cxl_dport' that is already freed, and all four dereference it without the lock that would prevent that. A dport is kzalloc()'d into a devres group on its host device, so it dies when that host unbinds. The host is &port->dev for a switch port and port->uport_dev for the root port. Both helpers return the dport through an output parameter. The caller's port reference pins struct cxl_port, not the dport allocation, and the lookup itself is a bare xa_load() under no lock. Add cxl_port_dport_host() to name the device that pins a dport, and cxl_pci_find_dport() / cxl_mem_find_dport() to look one up with that device's lock held and asserted. Convert the four callers to use them and bail if the dport is gone. cxl_port_add_dport() already follows this rule. cxl_mem_probe() chose its endpoint devm host from dport->rch, which meant dereferencing the dport before taking any lock. Use cxl_port_dport_host(): rch dports only ever land on the root port, so it selects the same device without needing the dport. With every caller converted, the dport output parameter of cxl_pci_find_port() and cxl_mem_find_port() is unused. Drop it. Fixes: 733b57f262b0 ("cxl/pci: Early setup RCH dport component registers from RCRB") Assisted-by: LLM Reviewed-by: Li Ming <ming.li@zohomail.com> Reviewed-by: Alison Schofield <alison.schofield@intel.com> Link: https://patch.msgid.link/20261001154744.1095902-3-dave.jiang@intel.com Signed-off-by: Dave Jiang <dave.jiang@intel.com>
2026-10-09cxl/port: Clear cached dport pointers when a dport is removedDave Jiang
Switch decoders cache dport pointers in cxlsd->target[], and nothing clears them when a dport is freed. Readers then dereference freed memory. KASAN caught it under a cxl_test load/unload loop with concurrent sysfs reads (abbreviated). Clear the matching slots from cxl_dport_remove(), walking the port's decoders the way cxl_port_update_decoder_targets() does on the add side. Scan all nr_targets slots, the target[] allocation size, and clear every hit. Fixes: 8330671c57c7 ("cxl: Add helper to delete dport") Cc: stable@vger.kernel.org Assisted-by: LLM Reviewed-by: Jonathan Cameron <jonathan.cameron@oss.qualcomm.com> Reviewed-by: Li Ming <ming.li@zohomail.com> Reviewed-by: Gregory Price (Meta) <gourry@gourry.net> Reviewed-by: Alison Schofield <alison.schofield@intel.com> Link: https://patch.msgid.link/20261001154744.1095902-2-dave.jiang@intel.com Signed-off-by: Dave Jiang <dave.jiang@intel.com>
2026-10-09drm/panthor: Fix TOCTOU race between GROUP_REGISTERED check and eraseOsama Abdelkader
panthor_group_destroy() checks the GROUP_REGISTERED mark and then calls xa_erase() without holding the xarray lock across both. If the handle is destroyed by another thread in between, and a concurrent GROUP_CREATE reuses the freed ID, the first destroy erases and releases the new, still-initializing group, leading to a use-after-free in panthor_group_create(). Do the mark check and erase atomically under xa_lock(). Fixes: eec7e23d848d ("drm/panthor: Prevent potential UAF in group creation") Assisted-by: Claude:claude-opus-5.5 Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com> Reviewed-by: Liviu Dudau <liviu.dudau@arm.com> Cc: stable@vger.kernel.org Signed-off-by: Osama Abdelkader <osama.abdelkader@gmail.com> Reviewed-by: Steven Price <steven.price@arm.com> Signed-off-by: Liviu Dudau <liviu.dudau@arm.com> Link: https://patch.msgid.link/20261008100935.3059587-1-osama.abdelkader@gmail.com
2026-10-09scripts/make_fit: Ignore schema checks when decomposing DTBsTing-Han Hou
With CHECK_DTBS enabled, Kbuild appends a schema validation command to the fdtoverlay command saved in a composite DTB's .cmd file. When DTB decomposition is requested, process_dtb() treats every word after -i as an input file, including the semicolon and the validator arguments. FIT generation then fails with FileNotFoundError while opening or checking the size of those words as files. Limit the input list to the fdtoverlay command before extracting its arguments. This preserves the base DTB and overlay order and ignores the subsequent schema validation command. Fixes: 17c31aded9a1 ("scripts/make_fit: Support decomposing DTBs") Assisted-by: LLM Signed-off-by: Ting-Han Hou <ue081723@gmail.com> Reviewed-by: Simon Glass <sjg@chromium.org> Link: https://patch.msgid.link/CA+NtrhQBK8uW32qO3dXxVxO1GSN-0EJfyJ16tnyx0o52T17WtQ@mail.gmail.com Signed-off-by: Nathan Chancellor <nathan@kernel.org>
2026-10-09clang-tools: Import os for broken pipe handlingTing-Han Hou
The BrokenPipeError handler in run-clang-tools.py calls os.open() and os.dup2() without importing os. If this handler is reached, it raises NameError instead of redirecting stdout and exiting with status 1. Import os so the handler can work as intended. Fixes: 87c7ee67deb7 ("scripts: handle BrokenPipeError for python scripts") Assisted-by: LLM Signed-off-by: Ting-Han Hou <ue081723@gmail.com> Link: https://patch.msgid.link/20261009175836.2277-1-ue081723@gmail.com Signed-off-by: Nathan Chancellor <nathan@kernel.org>
2026-10-09kconfig: use the value argument in sym_get_near_range_bound()Leizhen Zhang
sym_get_near_range_bound() is meant to check whether the given value is outside of the active range of an int/hex symbol, and is called with the symbol's current value from sym_calc_value() and with the default value from sym_get_string_default(). Since commit 9b8719973ee2 ("kconfig: use unsigned integers for hex range checks") it ignores its value argument and uses the current value of the symbol (via sym_get_range_val()) instead. As a result, an out-of-range default is no longer clamped in sym_get_string_default(), and savedefconfig writes out values that are equal to the effective default again, for example CONFIG_A=4 for: config A int "a" range 1 4 default 8 The existing savedefconfig_range test did not catch this because it only covers symbols without a prompt. Parse the value argument again, and add a test case for a symbol with a prompt. Found while fuzzing Kconfig input with ASan/UBSan. Fixes: 9b8719973ee2 ("kconfig: use unsigned integers for hex range checks") Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Leizhen Zhang <lzsx618@gmail.com> Tested-by: Julian Braha <julianbraha@gmail.com> Reviewed-by: Julian Braha <julianbraha@gmail.com> Link: https://patch.msgid.link/20261008164540.3686383-1-lzsx618@gmail.com Signed-off-by: Nathan Chancellor <nathan@kernel.org>
2026-10-09kconfig: fix infinite loop in conf_choice() when no choice value is visibleLeizhen Zhang
If a choice is visible but none of its choice values is, conf_choice() counts cnt == 0 visible values and finds no default. When the choice has to be asked, e.g. because a new symbol was added to the same menu (oldconfig, syncconfig) or because stdin is at EOF (oldaskconfig), the loop that maps the answer to a menu entry never finds one and the while (1) loop repeats forever, printing "choice[1-0?]: 0" each time. This happens in the tree for s390 when the compiler supports none of the -march=z* options (e.g. a non-s390 host compiler), so that all values of the "Processor type" choice are invisible: $ make ARCH=s390 defconfig $ sed -i '/^CONFIG_NR_CPUS=/d' .config $ make ARCH=s390 oldconfig # hangs Before the removal of tristate choice support, conf_choice() returned early in this case. Do the same when there is no visible choice value. Found by fuzzing Kconfig input with ASan/UBSan. Fixes: fde192511bdb ("kconfig: remove tristate choice support") Assisted-by: Claude:claude-opus-5-5 libFuzzer Signed-off-by: Leizhen Zhang <lzsx618@gmail.com> Reviewed-by: Julian Braha <julianbraha@gmail.com> Tested-by: Julian Braha <julianbraha@gmail.com> Link: https://patch.msgid.link/20261008164521.3684735-1-lzsx618@gmail.com Signed-off-by: Nathan Chancellor <nathan@kernel.org>
2026-10-09kconfig: cleanup stale comment about 'keys' arrayJulian Braha
'keys' was removed from 'dialog_textbox' in: commit e14f1242a8be ("kconfig: menuconfig: simplify global jump key assignment") but the comment referencing it was never removed. Let's cleanup this stale comment. Signed-off-by: Julian Braha <julianbraha@gmail.com> Reviewed-by: Nicolas Schier <n.schier@fritz.com> Link: https://patch.msgid.link/20261009094617.17322-1-julianbraha@gmail.com Signed-off-by: Nathan Chancellor <nathan@kernel.org>
2026-10-09Merge branch 'bpf-use-scalar-evolution-to-widen-bounded-loops'Alexei Starovoitov
Eduard Zingerman says: ==================== bpf: use scalar evolution to widen bounded loops This series implements the scalar evolution (SCEV) technique for verification of loops. Scalar evolution is a static analysis technique that infers algebraic expressions describing how variables change within a loop body. These expressions can then be used to estimate the number of loop body executions. This estimate can be used to represent induction variables as ranges instead of enumerating each possible value. For example, the following loop: for (r0 = 0; r0 < 10; r0++) { ... } would now be verified with the assumption that r0 is a scalar value in the range [0..9] within its body. See the following patches for a more technical overview: - "bpf: compute scalar evolution expressions for loops" - "bpf: use SCEV to widen bounded loops" The series can be viewed as consisting of the following parts: - Preparatory patches fixing and extending liveness analysis and adding utility functions. The liveness changes collect stack access effects and register dependencies, including: - "bpf: fix arg_track_xfer() for atomic stack spills and fills" - "bpf: derive global subprog stack liveness from BTF signatures" - "bpf: compute parameters liveness in bpf_compute_live_registers()" - Patches relaxing the verifier's current restrictions on accessing memory via varying offset pointers, specifically: - "bpf: allow subrange relations for PTR_TO_STACK in regsafe()" - "bpf: representation for intervals with steps" - "bpf: varying offset access support for PTR_TO_BTF_ID pointers" - Patches to compute the immediate dominator tree and loop hierarchy. - Patches implementing scalar evolution and integrating it with the main verification pass: - "bpf: allow precision backtracking between overlapping checkpoints" - "bpf: compute scalar evolution expressions for loops" - "bpf: use SCEV to widen bounded loops" - "bpf: avoid widening registers that hinder exact stack-slot tracking" - Tests and test harness updates. Literature ========== - "Symbolic Evaluation of Chains of Recurrences for Loop Optimization" Robert A. van Engelen, 2000 - "The CR# Algebra and its Application in Loop Analysis and Optimization" Robert A. van Engelen, 2004 Supported patterns ================== As scalar evolution analysis attempts to infer recurring relationships from algebraic expressions describing loop variables, there are some limitations on what can be expressed. Below is a list of patterns that are expected to work with the current implementation. The examples are pseudo-code for the indicated BPF instruction shapes. Loop widening currently requires allow_uninit_stack, the verifier mode that permits reading uninitialized stack bytes. This requirement applies even to loops that use only registers. Without it, the verifier uses its existing iteration-by-iteration checking. 1. Counted loops, including decreasing counters: u64 i = 0; do { i += 1; } while (i < 10); u64 j = 3; do { j += -1; } while (j != 0); Header ranges are i in [0,9] and j in [1,3]. Pre-condition loops, such as while (i < 10) { i += 1; }, are also supported. The counter can reside in a register or a fixed 8-byte frame-pointer spill. 2. Strided accesses into a map value: /* bytes is a map-value array with at least 16 bytes. */ u64 i = 0, off = 0; do { bytes[off] = 1; i += 1; off += 2; } while (i < 8); At the header, off is in [0,14] with step 2. The byte store stays within the map value even though i and off are tracked separately. 3. A nonconstant entry value with a separate counted induction variable: u64 x = bpf_get_prandom_u32() & 6; // {0,2,4,6} u64 i = 0; do { x += 6; i += 1; } while (i < 3); The counter i supplies the bound. At the header, x widens to [0,18] with step 2, retaining the alignment common to its entry values and its slope; x itself need not start at a constant. 4. Conditional assignment from an invariant value: u64 x = 5; for (u64 i = 0; i < 3; i += 1) if (i == 1) x = 10; return x; Widening joins the pre-loop value 5 with the assigned value 10, giving x in [5,10] both inside and after the loop. 5. Early exits in addition to the counted backedge: u64 i = 0; do { if (bpf_get_prandom_u32() == 0) break; i += 1; } while (i != 3); The counter still bounds the loop. An additional exit reduces the available lower-bound information; it does not by itself prevent widening. 6. Array accesses through different memory types: Bounded varying offsets are supported for arrays in BTF-typed objects, stack memory, map values and keys, packet data and metadata, and memory buffers. The usual bounds, alignment and access restrictions still apply. For stack arrays indexed by a widened loop counter, only byte and half-word accesses are supported; see limitation 5 below. For an array in a BTF-typed object: struct inner { int a, b; }; struct object { struct inner arr[8]; }; /* o points to a live, non-NULL BTF-typed struct object. */ u64 i = bpf_get_prandom_u32() & 7; value = o->arr[i].b; The 4-byte load has offsets 4 + 8*i, i in [0,7]. Bounds keep accesses within arr; base and step 8 ensure that each possible offset selects member b. Such accesses also work without a loop. 7. Nested loops with separate counters: u64 i = 0; do { u64 j = 0; do { /* body */ j += 1; } while (j < 3); i += 1; } while (i < 4); Both loops can be widened: i is in [0,3] at the outer header, and j is in [0,2] at the inner header. The inner counter is reset on each outer iteration; i is unchanged by the inner loop. 8. Incrementing and comparing a pointer directly: /* bytes is a map-value array with at least 8 bytes. */ u8 *p = bytes, *end = bytes + 8; do { *p = 1; p++; } while (p != end); The initial pointer and fixed end pointer give eight iterations, without a separate integer counter. At the loop header, p ranges from bytes to bytes + 7, so each byte store stays within the array. Deriving the iteration count requires the compared pointers to have a provable common memory origin. 9. A loop bounded by an exit other than the latch: u64 i = 0, len = 14; do { if (i == len) break; use(i); i += 1; } while (i != 64); Every exit condition dominating the latch bounds the iteration count; the smallest bound wins. Here i is in [0,14] at the header, not [0,63], so use(i) sees the range established by the break. Limitations =========== Patterns that lose precision after widening ------------------------------------------- Widening can lose information that the verifier gets by checking each iteration separately. For example: r7 = 5; for (r6 = 0; r6 < 3; r6++) if (r6 == 1) r7 = 10; if (r7 != 10) invalid_stack_read(); R7 is always 10 at the real exit, but is represented as [5, 10] at loop entry and after the loop. The verifier therefore cannot exclude the invalid read and rejects this otherwise safe program. It would be hard to avoid this limitation. The same issue affects correlated linear counters at loop exit: u64 i = 0, off = 0; while (i < 8) { i++; off += 2; } if (off != 16) invalid_stack_read(); Enumeration establishes off == 16. Widening tracks i and off independently, and the exit check on i does not reconstruct off's exact final value. This can be lifted after analysis adjustments. Patterns not widened yet ------------------------ If one of the variables modified in the loop cannot be widened, the verifier checks each iteration instead. Examples include: 1. 32-bit recurrences and comparisons: for (u32 i = 0; i < 8; i++) // ALU32 / JMP32 use(i); Only 64-bit arithmetic and comparisons are supported. This limitation will be lifted. 2. Non-linear updates: for (u64 i = 1; i < 16; i *= 2) // non-linear recurrence use(i); Recognition is currently limited to simple additive recurrences. Literature describes a way to represent this, but it is not considered a priority at the moment. 3. A controlling counter or bound that is not constant at loop entry: u64 limit = unknown_in_range(1, 8); for (u64 i = 0; i < limit; i++) use(i); u64 i = unknown_in_range(0, 7); while (i < 8) i++; Both loops have finite bounds, but iteration-count evaluation currently requires concrete entry values. Other induction variables may have nonconstant entry ranges once a separate counter establishes the iteration bound. This limitation can be lifted eventually. 4. Alternative values referring to another evolving register: r7 = 0; for (r6 = 0; r6 < 4; r6++) if (condition) r7 = r6; use(r7); R6 changes on each iteration. Widening currently supports conditional assignments only from constants or values that do not change in the loop. This limitation can be lifted. 5. Stack addresses whose widening would lose precise slot tracking: u64 slots[4]; for (u64 i = 0; i < 4; i++) slots[i] = i; struct bpf_dynptr dptrs[4]; for (u64 i = 0; i < 4; i++) bpf_dynptr_from_xdp(ctx, 0, &dptrs[i]); Keep such indices concrete for 4- and 8-byte stack loads/stores and calls requiring fixed-offset stack objects. Dependencies inside nested loops also constrain the outer loop. It would be hard to lift this limitation. 6. Values modified by a nested loop do not get a closed-form summary for the enclosing loop: u64 sum = 0; for (u64 i = 0; i < 4; i++) for (u64 j = 0; j < 4; j++) sum++; use(sum); The inner loop may widen, but the outer analysis forgets values modified by it rather than deriving the combined recurrence. This limitation can be lifted. 7. Multiple backedges and irreducible control flow: i = 0; H: if (i >= 8) goto done; if (condition) { i++; goto H; } // first backedge i++; goto H; // second backedge done: i = 0; if (condition) goto body; // second entry into the loop H: i++; body: if (i < 8) goto H; Widening requires a reducible loop with one backedge and a supported dominating exit condition. Multiple exits are supported, but their early-exit paths reduce what can be inferred about iteration counts. It is unclear whether this can be lifted at the moment. 8. Large slopes and unsupported iteration bounds: for (u64 i = 0, x = 0; i < 4; i++) { use(x); x += 65536; // slope outside signed 16 bits } Slopes used for linear widening must be nonzero signed-16-bit constants. The inferred number of header executions must be finite and less than U32_MAX. Counter wraparound must be ruled out while deriving the bound. 9. Incompatible pointer alternatives or comparison operands: p = &map_a[0]; q = &map_b[0]; for (u64 i = 0; i < 10; i++) { if (i == 5) p = q; use(*p); } At the loop header, p has SCEV ANY(p_entry, q). The alternatives point into different maps, so their offsets cannot be joined while retaining one map's metadata. Joining invariant pointer alternatives requires compatible pointer metadata, including type, origin IDs, frame number. 10. Some hard-coded constant limits: - Programs with more than 16 nested loops in one function are rejected. - Loops with more than 256 exits exceed the metadata limits and are not analyzed for widening. - At most 4 exit conditions dominating the latch are consulted for the iteration count of a loop. - Expression traversal is limited to depth 8. Only a small fixed number of alternative values can be joined. Veristat changes ================ The main impact of the series is a 23% reduction in number of processed instructions on a subset of Meta BPF programs. Verdict changes --------------- Two programs flip succes->failure, both selftests whose expectations are updated by the series: - verifier_gotox/gotox_edges_at_limit: test's CFG is a nest of ~1000 irreducible loops, deeper than the per-function loop stack (16), the program is rejected with "Too many nested loops". - verifier_scev/conditional_assignment_on_second_iteration: a value assigned on the second iteration is checked after the loop with its widened range, so a stack read guarded by that check is rejected. No program from the production corpora changes verdict. Regressions ----------- 20 programs regress by 30-33% and 6 more by 10-21%, all from an appliction objects sharing one unwinder library. All programs share a common reason for regression: - a big outer loop contains several smaller nested loops; - nested loops are now widened and coverge, their convergence adds backedges to the outer loop's SCC, thus flipping checkpoint comparisons with the outer loop to RANGE_WITHIN mode. Support for 32-bit recurrences and comparisons widens these loops too and removes the regression. This would be handled in a followup. Statistics ---------- A: master; B: scev-minimal-v3. Corpora: cilium, meta, scx, selftests. Insns counts verifier-processed instructions, not program size. Object exclusions: verifier_scev.bpf.o. Histogram: selected programs, without the table filters. Total progs: 7952 Old success: 5637 New success: 5646 total_insns diff min: -99.84% total_insns diff max: 61.90% 0 -> value: 0 value -> 0: 0 total_insns abs max old: 837,487 total_insns abs max new: 837,487 -100 .. -95 %: 15 -95 .. -90 %: 12 -90 .. -85 %: 10 -85 .. -75 %: 8 -75 .. -70 %: 6 -70 .. -65 %: 14 -65 .. -60 %: 38 -60 .. -55 %: 10 -55 .. -50 %: 17 -50 .. -45 %: 36 -45 .. -40 %: 9 -40 .. -35 %: 25 -35 .. -25 %: 10 -25 .. -15 %: 11 -15 .. -10 %: 48 -10 .. -5 %: 47 -5 .. 0 %: 111 0 .. 5 %: 7488 5 .. 15 %: 3 15 .. 25 %: 5 30 .. 35 %: 20 35 .. 40 %: 7 40 .. 50 %: 1 60 .. 65 %: 1 Tables: success in both runs; baseline Insns >= 5,000. Ranked by percentage change, then instruction-count change, file, program. Meta names are anonymized; numbered objects are distinct files. Top wins (50) ------------- File Program Insns (A) Insns (B) Insns (DIFF) ---------------------------------- --------------------------------- --------- --------- ----------------- verifier_bounds.bpf.o crossing_64_bit_signed_boundary_2 12330 20 -12310 (-99.84%) verifier_iterating_callbacks.bpf.o test1 7004 12 -6992 (-99.83%) bpf_iter_tasks.bpf.o dump_task_sleepable 85522 556 -84966 (-99.35%) bpf_iter_task_stack.bpf.o dump_task_stack 7209 65 -7144 (-99.10%) profiler-10.bpf.o hhvm_stack 23828 347 -23481 (-98.54%) bpf_iter_unix.bpf.o dump_unix 9026 226 -8800 (-97.50%) meta-app-22.bpf.o program-03 8705 319 -8386 (-96.34%) meta-app-22.bpf.o program-06 8948 328 -8620 (-96.33%) security-sandbox-10.bpf.o fork 30760 1249 -29511 (-95.94%) profiler-02.bpf.o on_py_event 79064 3864 -75200 (-95.11%) profiler-03.bpf.o on_py_event 79064 3864 -75200 (-95.11%) profiler-05.bpf.o on_py_event 79064 3864 -75200 (-95.11%) security-monitor-66.bpf.o mac_sysctl_write 7333 448 -6885 (-93.89%) profiler-04.bpf.o get_task_stacks 73176 6050 -67126 (-91.73%) security-monitor-65.bpf.o lsm_bprm_creds_for_exec 17538 1701 -15837 (-90.30%) security-monitor-65.bpf.o lsm_task_alloc 5674 565 -5109 (-90.04%) security-monitor-65.bpf.o lsm_fo_task_update 11399 1181 -10218 (-89.64%) security-sandbox-29.bpf.o test_glob_match 47257 5477 -41780 (-88.41%) load-balancer-17.bpf.o edgeloom_tc 24854 2984 -21870 (-87.99%) profiler-13.bpf.o handle_aten_op_call_start 7183 976 -6207 (-86.41%) security-monitor-65.bpf.o lsm_file_open 154412 21168 -133244 (-86.29%) security-monitor-17.bpf.o test_execve 293300 46071 -247229 (-84.29%) security-sandbox-13.bpf.o kvm_die 36514 5807 -30707 (-84.10%) security-monitor-97.bpf.o child_iter 41266 8182 -33084 (-80.17%) scheduler-30.bpf.o lavd_dispatch 290915 66359 -224556 (-77.19%) security-monitor-25.bpf.o syscalls_kill 98038 27912 -70126 (-71.53%) security-sandbox-14.bpf.o kernel_module_request 7880 2357 -5523 (-70.09%) security-sandbox-14.bpf.o kernel_load_data 7881 2358 -5523 (-70.08%) security-sandbox-14.bpf.o kernel_read_file 7882 2359 -5523 (-70.07%) xdp_lb_bench.bpf.o xdp_lb_bench 27126 9208 -17918 (-66.05%) firewall-05.bpf.o ingress 54034 18584 -35450 (-65.61%) firewall-05.bpf.o tc_in 54034 18584 -35450 (-65.61%) firewall-07.bpf.o ingress 54034 18584 -35450 (-65.61%) firewall-07.bpf.o tc_in 54034 18584 -35450 (-65.61%) security-sandbox-01.bpf.o bpf 30692 10586 -20106 (-65.51%) security-monitor-34.bpf.o syscall_setresuid 122200 43305 -78895 (-64.56%) security-monitor-34.bpf.o syscalls_setfsgid 122200 43305 -78895 (-64.56%) security-monitor-34.bpf.o syscalls_setfsuid 122200 43305 -78895 (-64.56%) security-monitor-34.bpf.o syscalls_setgid 122200 43305 -78895 (-64.56%) security-monitor-34.bpf.o syscalls_setregid 122200 43305 -78895 (-64.56%) security-monitor-34.bpf.o syscalls_setreuid 122200 43305 -78895 (-64.56%) security-monitor-34.bpf.o syscalls_setuid 122200 43305 -78895 (-64.56%) security-monitor-15.bpf.o cve_2021_4034 122481 43629 -78852 (-64.38%) security-monitor-16.bpf.o test 122517 43665 -78852 (-64.36%) security-sandbox-10.bpf.o exec 12908 4626 -8282 (-64.16%) security-monitor-12.bpf.o connect_security_socket_connect 216252 78013 -138239 (-63.92%) security-monitor-19.bpf.o kernel_modules_do_init 92980 33776 -59204 (-63.67%) security-monitor-23.bpf.o enter_pivot_root 93518 34311 -59207 (-63.31%) security-monitor-08.bpf.o bpf_prog_detect 93384 34494 -58890 (-63.06%) firewall-05.bpf.o egress 58436 21951 -36485 (-62.44%) Top losses (38) --------------- File Program Insns (A) Insns (B) Insns (DIFF) -------------------------------- ----------------------------- --------- --------- ---------------- profiler-26.bpf.o handle_cu_mem_address_reserve 34326 45724 +11398 (+33.21%) profiler-26.bpf.o handle_cu_mem_create 34326 45724 +11398 (+33.21%) profiler-26.bpf.o handle_malloc 34326 45724 +11398 (+33.21%) profiler-26.bpf.o handle_cu_mem_map 34524 45922 +11398 (+33.01%) profiler-19.bpf.o sched_waking 17454 23153 +5699 (+32.65%) profiler-27.bpf.o handle_cuda_launch_exc 17477 23176 +5699 (+32.61%) profiler-27.bpf.o handle_cuda_launch 17490 23189 +5699 (+32.58%) profiler-12.bpf.o on_custom_event_begin 17697 23396 +5699 (+32.20%) profiler-12.bpf.o on_custom_event_end 17701 23400 +5699 (+32.20%) profiler-26.bpf.o handle_mtia_cached_alloc 35494 46892 +11398 (+32.11%) profiler-26.bpf.o handle_mtia_allocate_enter 35555 46953 +11398 (+32.06%) profiler-26.bpf.o handle_pytorch_malloc 35847 47245 +11398 (+31.80%) profiler-19.bpf.o oncpu 17990 23689 +5699 (+31.68%) profiler-12.bpf.o on_task_enqueued 18035 23734 +5699 (+31.60%) profiler-12.bpf.o sched_waking 18070 23769 +5699 (+31.54%) profiler-12.bpf.o on_task_dequeued 18210 23909 +5699 (+31.30%) profiler-12.bpf.o on_request_context_event 18301 24000 +5699 (+31.14%) profiler-12.bpf.o on_pytorch_event 18302 24001 +5699 (+31.14%) profiler-12.bpf.o on_task_stats 18384 24083 +5699 (+31.00%) profiler-12.bpf.o oncpu 18488 24187 +5699 (+30.83%) profiler-19.bpf.o sched_switch_offcpu 64726 78210 +13484 (+20.83%) profiler-12.bpf.o sched_switch 33515 40257 +6742 (+20.12%) profiler-09.bpf.o on_custom_event_start 38281 45973 +7692 (+20.09%) profiler-09.bpf.o trace_func_entry 38281 45973 +7692 (+20.09%) profiler-12.bpf.o get_crochet_walltime_stacks 43473 50215 +6742 (+15.51%) profiler-24.bpf.o get_task_stacks 94740 103742 +9002 (+9.50%) test_cls_redirect_subprogs.bpf.o cls_redirect 72052 73682 +1630 (+2.26%) security-sandbox-20.bpf.o redirect_socket_connect 72423 73913 +1490 (+2.06%) scheduler-28.bpf.o arena_alloc_mask 27159 27175 +16 (+0.06%) scheduler-30.bpf.o arena_alloc_mask 27159 27175 +16 (+0.06%) scx_cake.bpf.o arena_alloc_mask 28721 28737 +16 (+0.06%) scx_arena.bpf.o arena_alloc_mask 28734 28750 +16 (+0.06%) scx_arena_selftests.bpf.o arena_alloc_mask 28734 28750 +16 (+0.06%) scx_chaos.bpf.o arena_alloc_mask 28734 28750 +16 (+0.06%) scx_p2dq.bpf.o arena_alloc_mask 28734 28750 +16 (+0.06%) scx_cake.bpf.o cake_init_task 28758 28774 +16 (+0.06%) scheduler-01.bpf.o arena_alloc_mask 29197 29208 +11 (+0.04%) scheduler-03.bpf.o arena_alloc_mask 29197 29208 +11 (+0.04%) Changelog ========= v2 -> v3: TLDR: another bunch of major correctness fixes, plus several improvements to avoid veristat-meta failure identified for v2. - Widen only when allow_uninit_stack is set. - Mark scalar registers and stack spills used by the selected bounding condition's base, step and bound expressions precise before widening. - Join alternative values only for registers with compatible pointer metadata. Include the loop-entry value when a register is assigned an invariant in the body, including unconditional assignments. - Consider up to four exit conditions dominating the backedge and use the tightest available iteration bound. Match the induction variable in either operand of the comparison. - Require full spills for linear stack recurrences. Treat partially spilled and unallocated stack slots as unknown scalars and all-zero slots as zero. Materialize writable stack values safely, growing the stack when needed. - Keep base/step in sync with the bounds as the last step of reg_bounds_sync(). Preserve the register state when sign extension leaves all possible values unchanged. Check that step is nonzero and base is smaller than step. - Handle latch comparison polarity correctly when the continuing branch enters a nested loop. Compute SCEVs only for exits owned by the loop, fixing a verifier bug for irreducible inner loops. - Exclude BPF_F_INNER_MAP single-element arrays from the separate-lookup shortcut in bpf_same_memory_origin(). - Fix stack-pointer tracking through load-acquire/store-release and atomic exchange/fetch/cmpxchg operations, so accesses through recovered stack pointers are included in liveness analysis. - Derive global subprogram stack effects from BTF argument types, so freplace cannot invalidate a loop termination proof based on the original callee body. - Compute argument liveness from callee reads for static subprograms and from BTF-declared arguments for globals. Prepare argument metadata before liveness analysis, avoiding unnecessarily live registers that prevented widening. - Treat already-unbounded scalars as already widened, allowing unknown SCEVs such as stack outputs of probe-read helpers called through a subprogram. - Widen to an unbounded range when computing an induction variable's range overflows signed 64-bit arithmetic, retaining the power-of-two alignment common to the entry value and slope. - Fix dominator computation for subprograms whose entry is a loop header: initialize the entry as its own dominator during the fixed-point computation and skip updates to it. Use overflow-checked predecessor allocations. - Replace the private worklist heap with the kernel min-heap and limit expression rewriting to 32 passes before falling back to unknown. - Add regression coverage for the liveness, stack, pointer, iteration bound and widening changes. Fix __msg_next validation when an expected message is missing. v1 -> v2: TLDR: a bunch of major correctness fixes. - Introduce arg_access_info to distinguish read, may-write and must-write effects of helper/kfunc stack accesses. Handle map-specific argument semantics and writes through unknown callbacks. - Fix base/step tracking across signed overflow, truncation, sign/zero extension and linked-register updates. - Rework iteration-count calculation for signed/unsigned increasing and decreasing counters, including counter overflow checks. Evaluate the full latch base expression and consistently count header executions. - Substitute all registers in instantiate_header_scevs(). - Track pointer origins when evaluating latch expressions. Require compatible operands before deriving iteration bounds. - Preserve the correct congruence base when widening nonconstant entry values, assign fresh IDs to widened packet pointers, and exclude nullable pointers from widening. - Account for values modified on nested-loop exit paths when computing invariants. Do not use an inner loop's latch to bound an outer loop. - Restrict pruning against in-progress SCEV states to terminating innermost loops sharing the same entry checkpoint, preventing inner-loop pruning from hiding a nonterminating outer loop. - Rework loop entry/exit handling on the main verification pass. - Extend fixed-stack-offset widening suppression to ANY expressions and all dynptr arguments described by helper/kfunc prototypes. - Fix BTF array handling: retain bounds checks for fixed arrays inside flexible-array elements and preserve array type IDs when element types contain typedefs. - Fix SCEV handling of endian conversions and narrow fills on big-endian systems. - Grow expression storage geometrically and scale the expression hash table with program size. Add cancellation/rescheduling checks to dominator computation and fix the postorder-number allocation leak. - Pack bpf_reg_state/bpf_func_state for latter to fit back into the 1 KiB allocation bucket, measured SCEV memory consumption overhead is 3% now. - Major additions in the selftests. v1: https://lore.kernel.org/bpf/20260926-scev-minimal-rebase-v1-0-c8e5ab5ba79f@gmail.com/ v2: https://lore.kernel.org/bpf/20261004-scev-minimal-rebase-v2-0-f6254e29fdf2@gmail.com/ --- ==================== Link: https://patch.msgid.link/20261009-scev-minimal-rebase-v3-0-bcba9bc53ac9@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2026-10-09selftests/bpf: Tests for SCEV analysis and loop wideningEduard Zingerman
- Computed expression shapes: register and spilled-counter recurrences, substitution at latches, agreeing and conflicting backedge updates, and ALU, extension, byte-swap, load/store and atomic expressions. - Iteration bounds and header-visit counts for: - pre-condition loops using JEQ, JLT, JLE, JGE and JGT; - post-condition loops using JLT, JLE, JGE, JGT and JNE; - signed pre- and post-conditions using JSLT, JSLE, JSGT and JSGE; - increasing and decreasing counters, nonzero initial values, immediate and invariant-register bounds, and immediate exits; - additional exits that reduce the minimum iteration count or tighten the upper bound; - rounded bounds, counter wraparound, count overflow, extreme steps and JNE divisibility. - Widening, backedge clamping and state-pruning convergence, including multiple induction variables used for map-value accesses and nonconstant entry values requiring a common alignment. Check precision propagation to initial values and bounds. - Nested and sibling loops, shared headers, exits to another loop header, exits across multiple nesting levels, and side entries into loop nests. Check conservative summaries for irreducible children while still widening supported reducible descendants, value preservation on inner-loop exits, and detection of nonterminating outer loops. - Invalidation of stack-slot expressions after indirect stack writes and global calls. Widening across bpf_probe_read_kernel() calls in static subprograms. - Stack spill widths and slot states, including narrow spills, zero, unallocated and STACK_MISC slots, and counters spilled and filled using store-release/load-acquire. - Avoid widening registers used to address stack spills, fills and dynptr constructor arguments, including dependencies through nested loops. Conversely, allow widening addresses of byte-sized stores. - Conditional assignments joining scalar values and stack pointers, including preservation of a common base and gcd-derived step. - Pointer widening and comparisons with compatible memory origins, fallback for incompatible origins and nullable pointers, and invalidation of stale packet pointer relationships. - Conservative fallback for unsupported recurrences, unavailable counter spills and zero computed header counts. Signed-off-by: Eduard Zingerman <eddyz87@gmail.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://patch.msgid.link/20261009-scev-minimal-rebase-v3-51-bcba9bc53ac9@gmail.com
2026-10-09selftests/bpf: Tests for immediate dominator computationEduard Zingerman
Coverage: - straight-line code with an ldimm64 in the middle; - an asymmetric if-then-else diamond (unequal-depth idoms_intersect()); - a simple loop, a loop with an if-else body, and nested loops; - a loop header with two back edges (three predecessors); - an irreducible CFG (fixpoint convergence); - immediate dominators across subprogram boundaries, including a callee whose entry instruction is itself a loop header; - a self-loop; - an indirect jump (gotox) with a two-entry jump table. Signed-off-by: Eduard Zingerman <eddyz87@gmail.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://patch.msgid.link/20261009-scev-minimal-rebase-v3-50-bcba9bc53ac9@gmail.com
2026-10-09selftests/bpf: Tests for loop hierarchy computationEduard Zingerman
Test cases covering the following branches in bpf_compute_loops(): - Case B: simple backedge creating a loop (loop_single) - Case B: two independent loops (loop_two_independent) - Case B + D: nested loops where the inner header's loop_header points to the outer header (loop_nested) - Case C: diamond CFG with no loops (fwd_edges_no_loop) - Case D: sibling inner loops within one outer loop (loop_nested_siblings) - Three levels of loop nesting (loop_three_levels) - Loop with an if-else body containing forward branches (loop_with_if_else) - Case E: An irreducible loop (loop_irreducible) - A self-loop (loop_self) - A test with sibling loops nested in outer loops (loop_nested_siblings_common_ancestors) - A test case with outer loop's backedge originating from an inner loop (loop_outer_backedge_from_inner). Cases B, C, D and E are described in loops.c:compute_loops_in_subprog(). Signed-off-by: Eduard Zingerman <eddyz87@gmail.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com> Link: https://patch.msgid.link/20261009-scev-minimal-rebase-v3-49-bcba9bc53ac9@gmail.com
2026-10-09selftests/bpf: Tests for varying offset access to PTR_TO_BTF_IDEduard Zingerman
Verifier tests for accessing arrays at a varying offset through a PTR_TO_BTF_ID pointer, e.g. a[i].b where 'i' is a register with a varying value: - bpf_obj_new() is used to obtain a PTR_TO_BTF_ID to a program-defined struct - bpf_get_current_task_btf() is used to obtain a PTR_TO_BTF_ID from the kernel BTF. The cases cover: - in-bounds access to a field of an array of structs; - out-of-bounds access where the maximal offset runs past the array; - a scalar (long) array with a matching stride; - a byte array (step 1); - a 4-byte read whose maximal offset spills past the array end; - an unaligned step that is not a whole number of elements; - both dimensions of a 2D array; - an array of pointers within a program-allocated object, where reading a pointer member yields a SCALAR_VALUE but the varying offset is still validated against the array bounds (in-bounds and out-of-bounds); - a varying access into an array embedded in a kernel BTF type (task_struct's comm[]), covering the non-allocated, trusted-pointer path (in-bounds and out-of-bounds); - an array nested below a struct member at a non-zero offset, exercising the offset telescoping done while walking across a struct boundary (in-bounds and out-of-bounds); - a trailing flexible array member, whose unbounded tail makes a varying access have no upper bound to exceed. A program-defined struct cannot be used here because bpf_obj_new() forbids flexible array members, so a kernel type (struct vring_used, with its 'ring[]' tail) is used (in-bounds, and an unaligned step that is not a whole number of elements). Signed-off-by: Eduard Zingerman <eddyz87@gmail.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://patch.msgid.link/20261009-scev-minimal-rebase-v3-48-bcba9bc53ac9@gmail.com
2026-10-09selftests/bpf: Tests for register base/step state pruningEduard Zingerman
Tests for the base/step reasoning in states.c:range_within(): - step_prune_hit_multiple: prune a step-4 range contained in a cached step-2 range when the scalar is used to address the stack. - step_prune_miss_non_multiple: do not let a cached step-2 range hide a step-3 path reaching division by zero. - step_prune_hit_const_on_line: prune constant 6 against a cached base-0, step-3 range. - step_prune_miss_const_off_line: do not prune constant 7 against that range even though its bounds and tnum admit the value. Signed-off-by: Eduard Zingerman <eddyz87@gmail.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://patch.msgid.link/20261009-scev-minimal-rebase-v3-47-bcba9bc53ac9@gmail.com
2026-10-09selftests/bpf: Tests for register base/step arithmeticEduard Zingerman
- step_arith{32,64}_no_overflow: non-overflowing +, *, << operations maintain step and base. - step_neg_value_range: Preserve the signed range of {-3, 0, 3, 6} when intersecting with a non-power-of-two step across zero. - step_arith{32,64}_overflow: Reset the stride and preserve valid bounds when a {32,64}-bit operation wraps. - step_mov32_truncate: Reset the stride when MOV32 discards nonzero upper bits from positive values. - step_mov32_negative: Reset the stride when MOV32 zero-extends the low 32 bits of negative signed values. - step_movsx: Reset the stride when sign extension changes the register value. - step_movsx_bounds_on_line: Keep bounds and stride when sign extension does not change the register value. - step_bounds_resync_after_arith: Snap bounds refined from var_off back onto the line. - step_linked_regs_add64: Translate both bounds and base when propagating a comparison's refinement through a scalar-ID delta. Signed-off-by: Eduard Zingerman <eddyz87@gmail.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://patch.msgid.link/20261009-scev-minimal-rebase-v3-46-bcba9bc53ac9@gmail.com
2026-10-09selftests/bpf: Test for register liveness of subprogram argumentsEduard Zingerman
A static callee contributes the registers its code reads at the entry, a global callee its declared arguments. Signed-off-by: Eduard Zingerman <eddyz87@gmail.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://patch.msgid.link/20261009-scev-minimal-rebase-v3-45-bcba9bc53ac9@gmail.com
2026-10-09selftests/bpf: Tests for BTF-based global subprog stack livenessEduard Zingerman
Check that passing a stack pointer to a no-op global callee produces: - use, def and may_def marks for a fixed-size memory argument. - No stack effects for an untrusted BTF pointer argument. This verifies that call effects follow the declared argument types rather than the callee's body. Signed-off-by: Eduard Zingerman <eddyz87@gmail.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://patch.msgid.link/20261009-scev-minimal-rebase-v3-44-bcba9bc53ac9@gmail.com
2026-10-09selftests/bpf: Tests for map special cases in bpf_helper_stack_access_bytes()Eduard Zingerman
Tests for helper arguments whose access size or read/write effects depend on the map: - helper_map_output_known_size checks that for a known map access MEM_WRITE | MEM_UNINIT produces a must_write mark. - helper_map_output_merged_sizes checks that when maps with different value sizes merge, MEM_WRITE | MEM_UNINIT produces use and may_def marks over the maximum value size, without a def mark. - helper_bloom_peek_input checks that for bpf_map_peek_elem() on a bloom filter the buffer is treated as an input. Signed-off-by: Eduard Zingerman <eddyz87@gmail.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://patch.msgid.link/20261009-scev-minimal-rebase-v3-43-bcba9bc53ac9@gmail.com
2026-10-09selftests/bpf: Tests for stack pointer spills/fills through atomicsEduard Zingerman
Check stack write tracking for atomic operations: - Restored by 64-bit load-acquire, xchg, fetch_add and cmpxchg. - Spilled by store-release and restored by a plain load. - Restored from a caller's stack slot by xchg in a callee. Signed-off-by: Eduard Zingerman <eddyz87@gmail.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://patch.msgid.link/20261009-scev-minimal-rebase-v3-42-bcba9bc53ac9@gmail.com
2026-10-09selftests/bpf: Tests for may_def marks of atomic RMW operationsEduard Zingerman
Liveness analysis should produce may_def marks for read-modify-write atomic operations: - lock *(u64 *)(r10 -8) += r1 - r1 = atomic64_fetch_add((u64 *)(r10 -8), r1) - r1 = atomic64_xchg((u64 *)(r10 -8), r1) - r0 = atomic64_cmpxchg((u64 *)(r10 -8), r0, r1) Signed-off-by: Eduard Zingerman <eddyz87@gmail.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://patch.msgid.link/20261009-scev-minimal-rebase-v3-41-bcba9bc53ac9@gmail.com
2026-10-09selftests/bpf: Tests for may_write stack-liveness trackingEduard Zingerman
Branches to cover: - per-insn writes (record_stack_access_off): * off_cnt==1, fully covered slots -> def + may_def (equal) * partial coverage -> may_def only (no def) * off_cnt 2-4, precise offsets -> may_def only, per offset - whole-frame writes: * off_cnt==0 (offset lost) -> may_def SPIS_ALL * ARG_IMPRECISE (frame lost) -> may_def SPIS_ALL per frame - merge_instances(): * both passes touch a frame -> may_def union * one pass leaves a frame untouched -> may_def preserved - merge_may_write(): a callee's writes into ancestor frames are summarized as may_def at the caller's call instruction - analyze_subprog() -> may_def stack slot range when callback is unknown. Tests exercising them: - may_write_two_precise_offsets - off_cnt 2-4 precise multi-offset - imprecise_frame_write - cross-frame ARG_IMPRECISE write, plus its caller-side summarization - merge_preserves_may_write - map-value vs stack pointer at two callsites: union is preserved when one pass does not touch the frame - must_write_not_same_slot - off_cnt==0 whole-frame may_def - two_byte_write_no_kill - partial write, may_def without def - kfunc_iter_stack_liveness - full-slot def == may_def - helper_output_unknown_size - output size unknown to liveness, may_def without use or def - caller_stack_write, conditional_stx_in_subprog, shared_instance_must_write_overwrite - callee writes summarized as may_def at the call site - bpf_loop_two_callbacks - call to unknown callback marks full stack range as may_def. Signed-off-by: Eduard Zingerman <eddyz87@gmail.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://patch.msgid.link/20261009-scev-minimal-rebase-v3-40-bcba9bc53ac9@gmail.com
2026-10-09selftests/bpf: Test for stack-pointer subrange pruningEduard Zingerman
Validate changes from: "bpf: allow subrange relations for PTR_TO_STACK in regsafe()". Add a test case that checks that a widened stack pointer with range [-72, -16] is considered a superset of a stack pointer with range [-64, -16]. Signed-off-by: Eduard Zingerman <eddyz87@gmail.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://patch.msgid.link/20261009-scev-minimal-rebase-v3-39-bcba9bc53ac9@gmail.com