Archive-only list for patches
 help / color / mirror / Atom feed
* [PATCH 6.12 000/247] 6.12.115-rc1 review
@ 2026-10-28 16:56 Greg Kroah-Hartman
  2026-10-28 16:56 ` [PATCH 6.12 001/247] rose: set SOCK_DESTROY in rose_kill_by_device() for prompt cleanup Greg Kroah-Hartman
                   ` (254 more replies)
  0 siblings, 255 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:56 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, linux-kernel, torvalds, akpm, linux,
	shuah, patches, lkft-triage, pavel, jonathanh, f.fainelli,
	sudipm.mukherjee, rwarsow, conor, hargar, broonie, achill, sr

This is the start of the stable review cycle for the 6.12.115 release.
There are 247 patches in this series, all will be posted as a response
to this one.  If anyone has any issues with these being applied, please
let me know.

Responses should be made by Fri, 30 Oct 2026 16:59:22 +0000.
Anything received after that time might be too late.

The whole patch series can be found in one patch at:
	https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.12.115-rc1.gz
or in the git tree and branch at:
	git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-6.12.y
and the diffstat can be found below.

thanks,

greg k-h

-------------
Pseudo-Shortlog of commits:

Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    Linux 6.12.115-rc1

Jan Kara <jack@suse.cz>
    fanotify: Fix crash in fanotify_init(2)

Christian Brauner <brauner@kernel.org>
    signal: allow taks to temporarily block TIF_NOTIFY_SIGNAL

Christian Brauner <brauner@kernel.org>
    pid_namespace: prevent TIF_NOTIFY_SIGNAL from interrupting the reaper

Christian Brauner <brauner@kernel.org>
    fork: release the files of a failed fork after sched_cancel_fork()

Christian Brauner <brauner@kernel.org>
    ptrace: refuse to change the signal mask of a user worker

Christian Brauner <brauner@kernel.org>
    signal: don't retarget shared signals in a dying thread group

Christian Brauner <brauner@kernel.org>
    signal: only SIGKILL and the freezers interrupt a coredumping task

Christian Brauner <brauner@kernel.org>
    coredump: hold RCU while releasing parked threads

Aaron Ahmed <aarnahmd@amazon.com>
    ftrace: Initialize modname and offset in print_rec()

Weiming Shi <bestswngs@gmail.com>
    asymmetric_keys: reject trust keys without IDs

Srish Srinivasan <ssrish@linux.ibm.com>
    keys/trusted_keys: return immediately after TPM unseal failure

Stefano Garzarella <sgarzare@redhat.com>
    KEYS: trusted: Fix blob allocation size in tpm2_key_decode()

Adrian Martinez <adrimg3196@gmail.com>
    KEYS: Fix key_reject_and_link() race with keyring restriction

Cen Zhang <zzzccc427@gmail.com>
    keys: Protect the read method check against type removal

Kyle Zeng <kylebot@openai.com>
    keys: make keyring indexes independent of kernel addresses

Cen Zhang <zzzccc427@gmail.com>
    keys: Protect the type name while describing a key

Cen Zhang <zzzccc427@gmail.com>
    keys: Check the authorization payload in process keyring searches

Cen Zhang <zzzccc427@gmail.com>
    keys: Avoid the owner account dereference in named keyring lookup

Junyeong Lee <jylee5498@gmail.com>
    io_uring/waitid: prevent cancel reference wrap

Austin Schuh <austin.linux@gmail.com>
    io_uring/wait: wake real-time waiters from hard interrupt context

Tamaki Yanagawa <ty@000ty.net>
    io_uring/net: keep recv buffer select length within MAX_RW_COUNT

Jens Axboe <axboe@kernel.dk>
    io_uring/poll: don't loop on HUP with multiple references

Jens Axboe <axboe@kernel.dk>
    io_uring/timeout: don't lose a cancel as io-wq arms a timeout

Jens Axboe <axboe@kernel.dk>
    io_uring/timeout: don't flush with the sequence behind the last flush

Jens Axboe <axboe@kernel.dk>
    io_uring/timeout: don't put a sequence target behind the last flush

Juanlu Herrero <juanlu@fastmail.com>
    io_uring/poll: avoid retry wakeup loss when dropping ownership

Josef Bacik <josef@toxicpanda.com>
    io_uring: look up the file before queueing to io-wq

Josef Bacik <josef@toxicpanda.com>
    io_uring/timeout: don't end a linked timeout with 1

Josef Bacik <josef@toxicpanda.com>
    io_uring/timeout: no ABS update of multishot timeouts

Josef Bacik <josef@toxicpanda.com>
    io_uring/net: don't retry recv on uncommitted buffers

Josef Bacik <josef@toxicpanda.com>
    io_uring: don't pass restart error codes to userspace

Josef Bacik <josef@toxicpanda.com>
    io_uring/sqpoll: let the thread sleep on disabled rings

Josef Bacik <josef@toxicpanda.com>
    io_uring/kbuf: handle index wrap in last buffer check

Josef Bacik <josef@toxicpanda.com>
    io_uring/napi: don't busy poll past an expired timeout

Josef Bacik <josef@toxicpanda.com>
    io_uring/napi: make stale entries time out after 60s

Josef Bacik <josef@toxicpanda.com>
    io_uring/wait: no early -ETIME if min_wait finds work

Josef Bacik <josef@toxicpanda.com>
    io_uring/timeout: keep repeat count on multishot update

Josef Bacik <josef@toxicpanda.com>
    io_uring/timeout: don't skip over reached sequences

Josef Bacik <josef@toxicpanda.com>
    io_uring/poll: drop stale double poll entry on rearm

Josef Bacik <josef@toxicpanda.com>
    io_uring/wait: look at all CQ waiters on wake up

Josef Bacik <josef@toxicpanda.com>
    io_uring: wake ring pollers for local task_work

Josef Bacik <josef@toxicpanda.com>
    io_uring/cancel: let CANCEL_ALL find parked requests

Josef Bacik <josef@toxicpanda.com>
    io_uring/cancel: recognize "no timeout" on 32-bit

Josef Bacik <josef@toxicpanda.com>
    io_uring/cancel: don't forget that the work was running

Josef Bacik <josef@toxicpanda.com>
    io_uring: don't lose a cancel as io-wq parks a request

Josef Bacik <josef@toxicpanda.com>
    io_uring/poll: don't lose a cancel as io-wq arms poll

Josef Bacik <josef@toxicpanda.com>
    io_uring/io-wq: let cancel find picked up hashed work

Josef Bacik <josef@toxicpanda.com>
    io_uring/io-wq: don't exit with a creation pending

Josef Bacik <josef@toxicpanda.com>
    io_uring/io-wq: don't strand work when a worker exits

Josef Bacik <josef@toxicpanda.com>
    io_uring: don't flood a cancelling task with task_work

Josef Bacik <josef@toxicpanda.com>
    io_uring/io-wq: don't hide a link from cancellations

Josef Bacik <josef@toxicpanda.com>
    io_uring/io-wq: don't lose the signal that ends work

Josef Bacik <josef@toxicpanda.com>
    io_uring/wait: don't spin on a stuck overflow list

Josef Bacik <josef@toxicpanda.com>
    io_uring/cmd: don't leave list poison in ->hash_node

Josef Bacik <josef@toxicpanda.com>
    io_uring/waitid: own the request before clearing ->head

Christian Brauner <brauner@kernel.org>
    io-wq: order the exit bit against worker creation task work

Lee Jones <lee@kernel.org>
    tracing/histograms: Verify event_call identity when updating synth_event refcount

Donggeun Yoo <donggeunyoo.kernel@gmail.com>
    tracing: Fix 64-bit and signed histogram fields on 32-bit kernels

Donggeun Yoo <donggeunyoo.kernel@gmail.com>
    tracing: Unregister field variable histograms when the command fails

Donggeun Yoo <donggeunyoo.kernel@gmail.com>
    tracing: Save the event file instead of the compatible histogram

Kyle Zeng <kylebot@openai.com>
    tracing: Reject incomplete event filter expressions

Pauli Virtanen <pav@iki.fi>
    Bluetooth: L2CAP: refuse __l2cap_chan_add if chan already has conn

Jonas Köppeler <j.koeppeler@tu-berlin.de>
    net_sched: codel: fix stale state for empty flows in fq_codel

Sasha Levin <sashal@kernel.org>
    Revert "srcu: Use irq_work to start GP in tiny SRCU"

Damien Le Moal <dlemoal@kernel.org>
    block: avoid potential deadlock on zone revalidation failure

Hyunwoo Kim <imv4bel@gmail.com>
    mm/pagewalk: fix stale walk->action escaping walk_pmd_range()

Bernard Pidoux <bernard.f6bvp@gmail.com>
    ax25: don't free an incoming SABM skb left on the listener's queue

Bernard Pidoux <bernard.f6bvp@gmail.com>
    rose: bring up the link of the preferred route passed over by a connect request

Bernard Pidoux <bernard.f6bvp@gmail.com>
    ax25: send unacknowledged I frames again when a link is re-established

Bernard Pidoux <bernard.f6bvp@gmail.com>
    rose: clear the circuits of a neighbour that restarts the link

Bernard Pidoux <bernard.f6bvp@gmail.com>
    ax25: send a private copy of each I frame

Bernard Pidoux <bernard.f6bvp@gmail.com>
    ax25: don't accept frames on a device that is going down

Bernard Pidoux <bernard.f6bvp@gmail.com>
    ax25: wait for ax25_send_frame() before detaching the connections of a device

Bernard Pidoux <bernard.f6bvp@gmail.com>
    ax25: read the connection's ax25_dev only once when walking ax25_list

Bernard Pidoux <bernard.f6bvp@gmail.com>
    ax25: don't create two connections for the same link in ax25_send_frame()

Bernard Pidoux <bernard.f6bvp@gmail.com>
    rose: process received frames and send with the socket locked

Bernard Pidoux <bernard.f6bvp@gmail.com>
    ax25: serialise the transmission of I frames on a connection

Bernard Pidoux <bernard.f6bvp@gmail.com>
    rose: restart the link of a neighbour created over a live AX.25 connection

Bernard Pidoux <bernard.f6bvp@gmail.com>
    rose: clear through routes when a neighbour is removed from the tables

Bernard Pidoux <bernard.f6bvp@gmail.com>
    netrom: fix nr_node leak when nr_del_node() removes the last route

Bernard Pidoux <bernard.f6bvp@gmail.com>
    netrom: clear nr_neigh->ax25 under the routing lock in nr_link_failed()

Junjie Cao <junjie.cao@intel.com>
    netrom: fix reference count leak in nr_rt_device_down

Bernard Pidoux <bernard.f6bvp@gmail.com>
    netrom: look up and update routes in one critical section

Bernard Pidoux <bernard.f6bvp@gmail.com>
    netrom: use a single lock for the node and neighbour lists

Mashiro Chen <mashiro.chen@mailbox.org>
    net: ax25: fix integer overflow in ax25_rx_fragment()

Bernard Pidoux <bernard.f6bvp@gmail.com>
    ax25: check frame length in ax25_decode() and ax25_rx_iframe()

Ashutosh Desai <ashutoshdesai993@gmail.com>
    ax25: fix OOB read after address header strip in ax25_rcv()

Bernard Pidoux <bernard.f6bvp@gmail.com>
    netrom: bound fragment reassembly in nr_queue_rx_frame()

Mashiro Chen <mashiro.chen@mailbox.org>
    net: netrom: validate source address in nr_find_socket()

Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    netrom: require full NET/ROM headers in nr_route_frame()

Stanislav Fort <disclosure@aisle.com>
    netrom: linearize and validate lengths in nr_rx_frame()

Bernard Pidoux <bernard.f6bvp@gmail.com>
    rose: clear stale N(R)/N(S) before (re)transmitting a data frame

Yun Zhou <yun.zhou@windriver.com>
    xfs: don't hold buffer locks across sync transaction commit in xfs_sync_sb_buf

Frank Sorenson <sorenson@redhat.com>
    cifs: add revalidation on FSCTL failure in smb2_duplicate_extents()

Tejun Heo <tj@kernel.org>
    sched_ext: Fix stall when a task enqueued with SCX_ENQ_LAST lands back on its CPU's local DSQ

Jesse Zhang <Jesse.Zhang@amd.com>
    drm/amdgpu: free the userptr ranges when a CS fails after parser_bos

Dmitry Kandybka <d.kandybka@gmail.com>
    tracing: Fix ignored return value of resize_buffer_duplicate_size()

Dibin Moolakadan Subrahmanian <dibin.moolakadan.subrahmanian@intel.com>
    drm/i915/dmc: Harden DMC firmware payload parsing

Jann Horn <jannh@google.com>
    futex: Fix mm reuse handling for FUT_OFF_MMSHARED

Wentao Liang <vulab@iscas.ac.cn>
    i2c: viai2c-wmt: Fix clock leak in wmt_i2c_probe()

Enrico Zanda <e.zanda1@gmail.com>
    i2c: viai2c-wmt: Replace dev_err() with dev_err_probe() in probe function

Yao Kai <yaokai34@huawei.com>
    workqueue: Fix unbound pool lifetime for pending pwqs

Breno Leitao <leitao@debian.org>
    workqueue: release pwq pools by pool type

Ido Schimmel <idosch@nvidia.com>
    ipv4: udp: Create exceptions before socket matching

Daehyeon Ko <4ncienth@gmail.com>
    vsock/virtio: validate packet source for connected sockets

Bobby Eshleman <bobbyeshleman@meta.com>
    virtio: set skb owner of virtio_transport_reset_no_sock() reply

Cen Zhang (Microsoft Security FORGE Labs) <cenzhang@linux.microsoft.com>
    io_uring/cancel: don't spin on local work the task can't run

Taeyang Lee <0wn@theori.io>
    tracing: Keep the predicate limit separate from program capacity

Thomas Hellström <thomas.hellstrom@linux.intel.com>
    drm/xe: Bump LRU for external objects on exec and rebind

Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
    ASoC: SOF: ipc4-topology: Fix shift-out-of-bounds for aggregated ALH capture

Christian Brauner <brauner@kernel.org>
    ext4: free the sbi after a grace period

Christian Brauner <brauner@kernel.org>
    ntfs3: free the sbi after a grace period

Cen Zhang (Microsoft) <cenzhang@linux.microsoft.com>
    watch_queue: Fix note pool publication race in watch_queue_set_size()

K Prateek Nayak <kprateek.nayak@amd.com>
    kernel/watch_queue: Use pipe_buf() to retrieve the pipe buffer

Breno Leitao <leitao@debian.org>
    net: call getsockopt_iter if available

Joseph Qi <joseph.qi@linux.alibaba.com>
    eventfs: fix SRCU read lock leak in eventfs_iterate()

Lorenzo Stoakes (ARM) <ljs@kernel.org>
    perf: Track the perf mlock gift separately

Laurence Oberman <loberman@redhat.com>
    scsi: st: Fix use-after-free race between st_remove() and st_open()

Paulo Alcantara <pc@manguebit.org>
    smb: client: fix multiuser mount with krb5

Frank Sorenson <sorenson@redhat.com>
    smb: client: fix heap overflow in cifs_do_set_acl()

Aohan Mei <henrymei@tencent.com>
    net/sched: cls_flower: validate mask pointer after nla_next()

Aleksandr Khromov <haa@amicon.ru>
    ksmbd: zero the FS_OBJECT_ID_INFORMATION buffer before filling it in

Aleksandr Khromov <haa@amicon.ru>
    ksmbd: initialize FileSystemControlFlags in FS_CONTROL_INFORMATION

Aleksandr Khromov <haa@amicon.ru>
    ksmbd: fill in FileSysIdentifier in FS_POSIX_INFORMATION

Jun Yang <littleddfu@gmail.com>
    net: bridge: mcast: don't truncate the port group walk on teardown

Al Viro <viro@zeniv.linux.org.uk>
    fs: get rid of __FMODE_NONOTIFY kludge

Hyunwoo Kim <imv4bel@gmail.com>
    KVM: x86/mmu: Preserve nested TDP shadow page tables if they are used as roots

Lorenzo Stoakes (ARM) <ljs@kernel.org>
    mm/huge_memory: bypass THP tuneables for huge pfnmap mappings

Florian Westphal <fw@strlen.de>
    netfilter: nft_byteorder: remove multi-register support

Sasha Levin <sashal@kernel.org>
    Revert "s390/mm: Add missing secure storage access fixups for donated memory"

Matt Fleming <mfleming@cloudflare.com>
    mm/huge_memory: initialise workingset state before folio split

Kairui Song <kasong@tencent.com>
    mm, madvise: fix potential workingset node list_lru leaks

David Rosca <david.rosca@amd.com>
    drm/amdgpu: Fix VCE 3 ring align_mask

Zihan Xi <zihanx@nebusec.ai>
    ipv4: avoid divide by zero in fib_rebalance

Niklas Schnelle <schnelle@linux.ibm.com>
    s390/pci: Fix leak of uninitialized kernel data in SCLP report

Aswin Karuvally <aswin@linux.ibm.com>
    s390/ctcm: Prevent XID null dereference

Florian Schauer <florian@schauer.to>
    page_pool: keep frag_offset aligned for odd-sized requests

Charles Vosburgh <theminershive@gmail.com>
    sctp: validate chunk length in the inqueue parser

Chengfeng Ye <nicoyip.dev@gmail.com>
    tipc: protect node reset trace dump with node lock

Zqiang <qiang.zhang@linux.dev>
    workqueue: Use raise_softirq() to trigger softirq in irq_work handler

Carlos Maiolino <cem@kernel.org>
    xfs: fix capability check in xfs

Bryam Vargas <hexlabsecurity@proton.me>
    net/iucv: fix the recvmsg window update

Kaiwen Shi <skwkevin@mail.ustc.edu.cn>
    mac802154: fix data race and NULL deref on local->assoc_dev

Chen Cheng <chencheng@fnnas.com>
    dm-integrity: require stable writes for internal hash modes

Ben Cressey <ben@cressey.dev>
    dm-integrity: fix infinite loop on discard with large tag size

Genjian Zhang <zhanggenjian@kylinos.cn>
    dm-ebs: fix incorrect device offset check in ebs_ctr()

Ben Cressey <ben@cressey.dev>
    dm-crypt: fix a tiny race condition in crypt_dec_pending

Benjamin Marzinski <bmarzins@redhat.com>
    dm cache: fix issue with background work locking

Ming-Hung Tsai <mtsai@redhat.com>
    dm cache: fix demotion stats in passthrough mode

Etienne Perot <eperot@google.com>
    cgroup: fix spurious SIGKILL of CLONE_INTO_CGROUP children

Cen Zhang (Microsoft Security FORGE Labs) <blbllhy@gmail.com>
    tcp: fix use-after-free in do_tcp_getsockopt(TCP_CC_INFO)

Cen Zhang (Microsoft Security FORGE Labs) <blbllhy@gmail.com>
    tcp: fix use-after-free in do_tcp_getsockopt(TCP_CONGESTION)

Heyang Tan <thy15333007817@163.com>
    wifi: p54: validate firmware record lengths

Tengda Wu <wutengda@huaweicloud.com>
    tracing: Fix hist trigger timestamps for buffered events

Amit Machhiwal <amachhiw@linux.ibm.com>
    tracing: Do not initialize tracefs work if tracing is disabled

Taeyang Lee <0wn@theori.io>
    tracing: Check operator stack capacity before pushing

David Carlier <devnexen@gmail.com>
    tracing: Take trace_types_lock when dropping the buffer_meta reference

Donggeun Yoo <donggeunyoo.kernel@gmail.com>
    tracing: Fix the shift out of bounds in the log2 histogram modifier

Christian König <ckoenig.leichtzumerken@gmail.com>
    drm/exec: don't immediately add prelocked obj to array of locked objs

Jesse Zhang <Jesse.Zhang@amd.com>
    drm/amdgpu: don't drop the runtime PM reference twice in amdgpu_gpr

Timur Kristóf <timur.kristof@gmail.com>
    drm/amdgpu/sdma3: Work around POLL_REGMEM / FENCE hang

Yehyeong Lee <yhlee@isslab.korea.ac.kr>
    scsi: libiscsi: Validate the task named by a management response

Yehyeong Lee <yhlee@isslab.korea.ac.kr>
    scsi: libiscsi: Validate the ITT reflected in a Reject PDU

Yehyeong Lee <yhlee@isslab.korea.ac.kr>
    scsi: libiscsi: Reject a negative task index from parse_pdu_itt

Yehyeong Lee <yhlee@isslab.korea.ac.kr>
    scsi: xen/scsifront: Check for a NULL shadow entry on a backend response

Stanley Jhu <stanleyjhu@google.com>
    scsi: bsg: Pass reply_len to bsg_setup_queue() to fit UFS ARPMB replies

Krystian Kaniewski <krystianmkaniewski@gmail.com>
    ring-buffer: Fix false warning in ring_buffer_map_get_reader()

Donggeun Yoo <donggeunyoo.kernel@gmail.com>
    ring-buffer: Fix the sub-buffer array base in rb_meta_subbuf_idx()

David Carlier <devnexen@gmail.com>
    ring-buffer: Do not show buffer_meta for CPUs without a buffer

Antoine Huret <antoine.huret@bull.com>
    perf: Update cgroup time when rotating multiplexed events

Loic Poulain <loic.poulain@oss.qualcomm.com>
    i2c: qcom-cci: Fix HALT_ACK reset request being dropped

Lee Jones <lee@kernel.org>
    tracing/histograms: Reject non-stacktrace fields for synthetic stacktrace fields

Sasha Levin <sashal@kernel.org>
    tools: gpio: fix building from the top level with O=

Daehyeon Ko <4ncienth@gmail.com>
    sctp: revalidate output stream after association connect wait

Mario Limonciello <mario.limonciello@amd.com>
    pinctrl: amd: Clear S4 wake bits when firmware has _AEI

Aohan Mei <henrymei@tencent.com>
    net: rds: fix uninitialized trans dereference in CM event handler

Jérémy Jean <Jeremy.Jean@oss.cyber.gouv.fr>
    net/sched: fix use-after-free in __tcf_action_put()

Christian Brauner <brauner@kernel.org>
    namei: test for a negative dentry the way traverse_mounts() does

Christian Brauner <brauner@kernel.org>
    eventfs: Free the eventfs_inode after an rcu grace period too

Aviv Vaknin <vaknins33@gmail.com>
    pid_namespace: make zap_pid_ns_processes() freezable

Kyle Zeng <kylebot@openai.com>
    fsnotify: prevent mark additions during connector teardown

Amirmohammad Eftekhar <amirmohammadeftekhar@gmail.com>
    KVM: nVMX: Reset MMU back to the root MMU if loading L2 state fails for !VM-Entry

EJ Campbell <ejc3@meta.com>
    x86/kvm: Don't consume async #PF flags on a kernel #PF in NMI context

Christian Brauner <brauner@kernel.org>
    unicode: free the map after a grace period

Sung Byeongchan <tjdqudcks0424@naver.com>
    autofs: ignore notification errors from a replaced pipe

Christian Brauner <brauner@kernel.org>
    afs: free the super info after a grace period

Alexander Gruhlke <gruhlke@mailbox.org>
    PCI: Don't treat ~0 as ready in pci_dev_wait() with RRS SV

John Ogness <john.ogness@linutronix.de>
    printk: Postpone kthread startup

Haris Okanovic <harisokn@amazon.com>
    perf: Fix perf_pmu_migrate_context() leaving events behind

Peng Fan <peng.fan@nxp.com>
    gpio: mxc: fix wakeup_pads bit operations

Alexander Stein <alexander.stein@ew.tq-group.com>
    gpio: mxc: use BIT() macro

Peng Fan <peng.fan@nxp.com>
    gpio: mxc: fix both_edges bit operations

Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
    gpio: mxc: use lock guards for the generic GPIO chip lock

Kent Gibson <warthog618@gmail.com>
    gpiolib: fix memory leak in gpiod_set_array_value_complex() on error paths

Joas Antonio dos Santos <joasantonio108@gmail.com>
    calipso: keep BIG TCP payload_len in calipso_skbuff_setattr()

Alice Mikityanska <alice@isovalent.com>
    net/ipv6: Introduce payload_len helpers

Nicolai Buchwitz <nb@tipi-net.de>
    net: bcmgenet: unshare the skb before writing the control block

Kyle Zeng <kylebot@openai.com>
    netlink: avoid hashing the network namespace pointer

Xingui Yang <yangxingui@huawei.com>
    scsi: libsas: Fix SMP IO deadlock during HA resume

Martin Kaiser <martin@kaiser.cx>
    tracing: probes: error if BTF is required but unavailable

Kyle Zeng <kylebot@openai.com>
    pipe: preserve existing fasync readers on writer setup failure

Sasha Levin <sashal@kernel.org>
    samples: pidfd: fix userprogs typo

Cen Zhang <zzzccc427@gmail.com>
    ocfs2/dlm: Protect the recovery list during debugfs reads

Linfeng Sun <linfeng.sun.dev@gmail.com>
    scsi: target: iscsi: Fix race in discovery auth updates

Laurence Oberman <loberman@redhat.com>
    scsi: st: Save the visited block for the partition the drive is in

Keith Busch <kbusch@kernel.org>
    nios2: fix __wsum type degradation in csum_fold()

Carlos Jones Jr <carlosjr.jones@analog.com>
    spi: tegra114: assert CS GPIO for every transfer in a message

Kyle Zeng <kylebot@openai.com>
    netlink: reset skb headers before unicast and multicast filtering

Michael Reeves <michael.reeves077@gmail.com>
    regmap: Drop map lock during cache init and exit

Francesco Lavra <flavra@baylibre.com>
    regcache: Do not overwrite error code when finalizing cache after error

Andy Shevchenko <andriy.shevchenko@linux.intel.com>
    regcache: Add ->populate() callback to separate from ->init()

HyeongJun An <sammiee5311@gmail.com>
    ASoC: nau8822: Fix the 128x oversampling switch bits

HyeongJun An <sammiee5311@gmail.com>
    ASoC: wm8978: Fix the 128x oversampling switch bits

HyeongJun An <sammiee5311@gmail.com>
    ASoC: max98371: Fix the Speaker DHT Min Volume bits

HyeongJun An <sammiee5311@gmail.com>
    ASoC: pcm3168a: Fix the DAC zero flag polarity bit

HyeongJun An <sammiee5311@gmail.com>
    ASoC: cs42l52: Fix the NG Type Switch bit

HyeongJun An <sammiee5311@gmail.com>
    ASoC: cs42l56: Put the Limiter Cushion control on the limiter register

Avi Weiss <thnkslprpt@gmail.com>
    ASoC: stm32: spdifrx: fix synchronization state check

Sergey Tiraspolsky <stiraspo@gmail.com>
    ASoC: Intel: avs: Reset the stream unless it is already prepared

Allison Henderson <achender@kernel.org>
    net/rds: don't let the rdma_cm destroy an id RDS still owns on route failure

Michal Luczaj <mhal@rbox.co>
    vsock: treat TCP_CLOSING as once-established

Dave Stevenson <dave.stevenson@raspberrypi.com>
    drm/vc4: hdmi: Move packet RAM enable to PM runtime

Adriel Santos <adriel@adriel.eu>
    pinctrl: qcom: ipq5018: replace gcc_plltest with pwm2 on gpio12

Svyatoslav Ryhel <clamor95@gmail.com>
    power: supply: generic-adc-battery: Fix temperature IIO channel conversion

Len Brown <len.brown@intel.com>
    tools/power turbostat: Fix add_counter issue if > 24 counters.

Len Brown <len.brown@intel.com>
    tools/power turbostat: Fix fd_perf leak on reset

Gilberto Conde <gilbertorconde@gmail.com>
    pinctrl: qcom: ipq5018: add missing pwm3 function on gpio13

Michael Kelley <mhkelley58@gmail.com>
    Drivers: hv: Don't reset VMBus connection state on error/exit paths

Michael Kelley <mhkelley58@gmail.com>
    x86/hyperv: Avoid using per-cpu output page in hv_apicid_to_vp_index()

Waiman Long <longman@redhat.com>
    Drivers: hv: Avoid infinite retry loop in init_vp_index()

Xueqin Luo <luoxueqin@kylinos.cn>
    power: supply: ds2780: Fix ds2780_get_capacity() returning raw value

Karl Mehltretter <kmehltretter@gmail.com>
    power: supply: Fix maintenance charge table kernel-doc

Jinhui Guo <guojinhui.liam@bytedance.com>
    soc/tegra: fuse: Add missing newline to APBMISC error message

Matteo Croce <technoboy85@gmail.com>
    fat: stop reading directory entries past the end-of-directory marker

Abdul Wasey <w453y.me@gmail.com>
    mptcp: move the OoO check back into __mptcp_try_fallback()

Bernard Pidoux <bernard.f6bvp@gmail.com>
    rose: purge rose_neigh->queue on final teardown

Bernard Pidoux <bernard.f6bvp@gmail.com>
    ax25: bound REJ-driven fast retransmits with the existing N2 counter

Bernard Pidoux <bernard.f6bvp@gmail.com>
    rose: hold a reference on incoming sockets queued for accept()

Bernard Pidoux <bernard.f6bvp@gmail.com>
    rose: don't warn on stray CALL_ACCEPTED/CLEAR_CONFIRMATION in state 3

Bernard Pidoux <bernard.f6bvp@gmail.com>
    rose: use timer_shutdown_sync() for t0timer teardown

Bernard Pidoux <bernard.f6bvp@gmail.com>
    rose: guard rose_transmit_link() against a NULL neighbour

Bernard Pidoux <bernard.f6bvp@gmail.com>
    rose: keep the route needed for routing loop detection

Bernard Pidoux <bernard.f6bvp@gmail.com>
    rose: don't free fd-owned sockets when reaping in the heartbeat

Bernard Pidoux <bernard.f6bvp@gmail.com>
    rose: clear neighbour pointer in rose_kill_by_device()

Bernard Pidoux <bernard.f6bvp@gmail.com>
    rose: release netdev ref and destroy orphaned incoming sockets

Bernard Pidoux <bernard.f6bvp@gmail.com>
    rose: disconnect orphaned STATE_2 sockets when device is gone

Bernard Pidoux <bernard.f6bvp@gmail.com>
    rose: set SOCK_DESTROY in rose_kill_by_device() for prompt cleanup


-------------

Diffstat:

 Makefile                                           |   4 +-
 arch/nios2/include/asm/checksum.h                  |   2 +-
 arch/s390/mm/fault.c                               |  11 +-
 arch/s390/pci/pci_sysfs.c                          |   3 +
 arch/x86/hyperv/hv_init.c                          |   3 +-
 arch/x86/kernel/kvm.c                              |  32 +-
 arch/x86/kvm/mmu/mmu.c                             |   4 +-
 arch/x86/kvm/vmx/nested.c                          |   4 +-
 block/blk-zoned.c                                  |  37 +-
 block/blk.h                                        |   4 +-
 block/bsg-lib.c                                    |  13 +-
 block/genhd.c                                      |   2 +-
 crypto/asymmetric_keys/restrict.c                  |   8 +-
 drivers/base/regmap/internal.h                     |   1 +
 drivers/base/regmap/regcache-maple.c               |   9 +-
 drivers/base/regmap/regcache.c                     |  18 +-
 drivers/gpio/gpio-mxc.c                            |  69 ++--
 drivers/gpio/gpiolib.c                             |   9 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c             |   6 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c        |  23 +-
 drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c             |  25 +-
 drivers/gpu/drm/amd/amdgpu/vce_v3_0.c              |   2 +-
 drivers/gpu/drm/drm_exec.c                         |  77 +++--
 drivers/gpu/drm/i915/display/intel_dmc.c           |  21 +-
 drivers/gpu/drm/vc4/vc4_hdmi.c                     |  20 +-
 drivers/gpu/drm/xe/xe_exec.c                       |   7 +-
 drivers/gpu/drm/xe/xe_vm.c                         |  31 +-
 drivers/gpu/drm/xe/xe_vm.h                         |   2 +
 drivers/hv/channel_mgmt.c                          |  12 +-
 drivers/hv/connection.c                            |   1 -
 drivers/hv/vmbus_drv.c                             |   1 -
 drivers/i2c/busses/i2c-qcom-cci.c                  |   4 +-
 drivers/i2c/busses/i2c-viai2c-wmt.c                |  22 +-
 drivers/md/dm-cache-target.c                       |  59 ++--
 drivers/md/dm-crypt.c                              |   3 +-
 drivers/md/dm-ebs-target.c                         |   3 +-
 drivers/md/dm-integrity.c                          |   6 +-
 drivers/net/ethernet/broadcom/genet/bcmgenet.c     |  10 +
 drivers/net/wireless/intersil/p54/fwio.c           |  42 ++-
 drivers/pci/pci.c                                  |  15 +-
 drivers/pinctrl/pinctrl-amd.c                      |   9 +
 drivers/pinctrl/qcom/pinctrl-ipq5018.c             |  10 +-
 drivers/power/supply/ds2780_battery.c              |   2 +-
 drivers/power/supply/generic-adc-battery.c         |   9 +-
 drivers/s390/net/ctcm_mpc.c                        |   3 +-
 drivers/scsi/libiscsi.c                            |  14 +-
 drivers/scsi/libsas/sas_expander.c                 |  14 +-
 drivers/scsi/mpi3mr/mpi3mr_app.c                   |   2 +-
 drivers/scsi/scsi_transport_fc.c                   |   6 +-
 drivers/scsi/scsi_transport_iscsi.c                |   2 +-
 drivers/scsi/scsi_transport_sas.c                  |   6 +-
 drivers/scsi/st.c                                  |  18 +-
 drivers/scsi/xen-scsifront.c                       |   1 +
 drivers/soc/tegra/fuse/tegra-apbmisc.c             |   2 +-
 drivers/spi/spi-tegra114.c                         |   7 +
 drivers/target/iscsi/iscsi_target_configfs.c       |  26 +-
 drivers/ufs/core/ufs_bsg.c                         |   2 +-
 fs/afs/internal.h                                  |   2 +
 fs/afs/super.c                                     |   2 +-
 fs/autofs/waitq.c                                  |  25 +-
 fs/coredump.c                                      |  16 +-
 fs/ext4/ext4.h                                     |   2 +
 fs/ext4/extents_status.c                           |   7 +-
 fs/ext4/extents_status.h                           |   1 +
 fs/ext4/super.c                                    |  13 +-
 fs/fat/dir.c                                       |  44 ++-
 fs/fcntl.c                                         |   4 +-
 fs/namei.c                                         |   3 +-
 fs/notify/fanotify/fanotify_user.c                 |  25 +-
 fs/notify/mark.c                                   |  11 +
 fs/ntfs3/ntfs_fs.h                                 |   1 +
 fs/ntfs3/super.c                                   |  29 +-
 fs/ocfs2/dlm/dlmcommon.h                           |   2 +
 fs/ocfs2/dlm/dlmdebug.c                            |   5 +-
 fs/ocfs2/dlm/dlmrecovery.c                         |   2 +-
 fs/open.c                                          |  23 +-
 fs/pipe.c                                          |   6 +-
 fs/smb/client/cifssmb.c                            |  13 +-
 fs/smb/client/connect.c                            |  21 +-
 fs/smb/client/smb2ops.c                            |   7 +-
 fs/smb/server/smb2pdu.c                            |   5 +
 fs/tracefs/event_inode.c                           |  16 +-
 fs/unicode/utf8-core.c                             |  21 +-
 fs/xfs/libxfs/xfs_sb.c                             |  17 +-
 fs/xfs/xfs_fsmap.c                                 |   2 +-
 fs/xfs/xfs_ioctl.c                                 |   2 +-
 fs/xfs/xfs_iops.c                                  |   2 +-
 include/drm/drm_exec.h                             |  15 +-
 include/linux/bsg-lib.h                            |   3 +-
 include/linux/cgroup-defs.h                        |   5 +-
 include/linux/fs.h                                 |   6 +-
 include/linux/fsnotify_backend.h                   |   1 +
 include/linux/futex.h                              |  14 +-
 include/linux/huge_mm.h                            |   2 +-
 include/linux/io_uring_types.h                     |   3 +
 include/linux/ipv6.h                               |  22 ++
 include/linux/key-type.h                           |   1 +
 include/linux/key.h                                |   5 +
 include/linux/maple_tree.h                         |   4 +
 include/linux/mm_types.h                           |   3 +
 include/linux/power_supply.h                       |   6 +-
 include/linux/sched.h                              |   2 +-
 include/linux/sched/signal.h                       |  27 +-
 include/linux/sched/user.h                         |   8 +-
 include/linux/srcutiny.h                           |   4 -
 include/linux/unicode.h                            |   1 +
 include/net/af_vsock.h                             |   3 +
 include/net/ax25.h                                 |   6 +
 include/net/codel_impl.h                           |   1 +
 include/net/ipv6.h                                 |   2 -
 include/net/netfilter/nf_tables_ipv6.h             |   4 +-
 include/net/netrom.h                               |  18 +-
 include/net/rose.h                                 |  45 ++-
 include/uapi/asm-generic/fcntl.h                   |   1 -
 io_uring/cancel.c                                  |  29 +-
 io_uring/cancel.h                                  |   2 +
 io_uring/futex.c                                   |   7 +-
 io_uring/io-wq.c                                   | 110 +++++-
 io_uring/io-wq.h                                   |   4 +-
 io_uring/io_uring.c                                | 167 +++++++--
 io_uring/io_uring.h                                |  44 ++-
 io_uring/kbuf.c                                    |   2 +-
 io_uring/napi.c                                    |   4 +-
 io_uring/net.c                                     |  26 +-
 io_uring/poll.c                                    |  41 ++-
 io_uring/rw.c                                      |  18 -
 io_uring/sqpoll.c                                  |   7 +
 io_uring/tctx.c                                    |   1 +
 io_uring/timeout.c                                 |  91 +++--
 io_uring/uring_cmd.c                               |   2 +-
 io_uring/waitid.c                                  |  19 +-
 kernel/cgroup/cgroup.c                             |   6 +-
 kernel/events/core.c                               |  33 +-
 kernel/exit.c                                      |   2 +-
 kernel/fork.c                                      |  12 +-
 kernel/futex/core.c                                |  47 +--
 kernel/pid_namespace.c                             |   5 +-
 kernel/printk/printk.c                             |   2 +-
 kernel/ptrace.c                                    |   6 +
 kernel/rcu/srcutiny.c                              |  19 +-
 kernel/sched/ext.c                                 |  18 +-
 kernel/signal.c                                    |   4 +
 kernel/trace/ftrace.c                              |   4 +-
 kernel/trace/ring_buffer.c                         |  13 +-
 kernel/trace/trace.c                               |  13 +-
 kernel/trace/trace_events_filter.c                 |  15 +-
 kernel/trace/trace_events_hist.c                   |  52 +--
 kernel/trace/trace_events_synth.c                  |  10 +
 kernel/trace/trace_probe.c                         |   3 +-
 kernel/trace/trace_synth.h                         |   1 +
 kernel/watch_queue.c                               |  16 +-
 kernel/workqueue.c                                 |  24 +-
 mm/filemap.c                                       |   9 -
 mm/huge_memory.c                                   |  81 +++--
 mm/internal.h                                      |   6 +
 mm/khugepaged.c                                    |   3 +
 mm/pagewalk.c                                      |   6 +-
 net/ax25/af_ax25.c                                 |  81 ++++-
 net/ax25/ax25_ds_in.c                              |   2 +
 net/ax25/ax25_in.c                                 |  55 ++-
 net/ax25/ax25_out.c                                | 121 +++++--
 net/ax25/ax25_std_in.c                             |  44 +++
 net/ax25/ax25_subr.c                               |  44 ++-
 net/bluetooth/l2cap_core.c                         |   7 +-
 net/bluetooth/l2cap_sock.c                         |   2 +
 net/bridge/br_multicast.c                          |  13 +-
 net/bridge/br_netfilter_ipv6.c                     |   2 +-
 net/bridge/netfilter/nf_conntrack_bridge.c         |   4 +-
 net/core/page_pool.c                               |   3 +-
 net/ipv4/fib_semantics.c                           |   2 +-
 net/ipv4/tcp.c                                     |  18 +-
 net/ipv4/tcp_cong.c                                |   4 +-
 net/ipv4/tcp_dctcp.c                               |   4 +-
 net/ipv4/tcp_minisocks.c                           |   2 +-
 net/ipv4/tcp_output.c                              |   2 +-
 net/ipv4/udp.c                                     |  11 +-
 net/ipv6/calipso.c                                 |   6 +-
 net/ipv6/ip6_input.c                               |   2 +-
 net/ipv6/ip6_offload.c                             |   7 +-
 net/ipv6/output_core.c                             |   7 +-
 net/iucv/af_iucv.c                                 |  42 ++-
 net/mac802154/ieee802154_i.h                       |   7 +-
 net/mac802154/main.c                               |   1 +
 net/mac802154/scan.c                               |  51 ++-
 net/mptcp/protocol.c                               |  14 +-
 net/netfilter/ipvs/ip_vs_xmit.c                    |   2 +-
 net/netfilter/nf_conntrack_ovs.c                   |   2 +-
 net/netfilter/nf_log_syslog.c                      |   2 +-
 net/netfilter/nft_byteorder.c                      |  51 ++-
 net/netlink/af_netlink.c                           |  10 +-
 net/netrom/af_netrom.c                             |  33 +-
 net/netrom/nr_in.c                                 |  26 ++
 net/netrom/nr_route.c                              | 383 +++++++++++----------
 net/rds/rdma_transport.c                           |  38 +-
 net/rose/af_rose.c                                 |  73 +++-
 net/rose/rose_in.c                                 |  44 ++-
 net/rose/rose_link.c                               |  47 +++
 net/rose/rose_loopback.c                           |   2 +-
 net/rose/rose_out.c                                |   1 +
 net/rose/rose_route.c                              | 200 +++++++++--
 net/rose/rose_timer.c                              |  87 ++++-
 net/sched/act_api.c                                |  11 +-
 net/sched/cls_flower.c                             |   5 +
 net/sched/sch_cake.c                               |   2 +-
 net/sctp/inqueue.c                                 |   6 +-
 net/sctp/socket.c                                  |  33 +-
 net/socket.c                                       |  54 ++-
 net/tipc/node.c                                    |   2 +
 net/vmw_vsock/af_vsock.c                           |  49 ++-
 net/vmw_vsock/virtio_transport_common.c            |   9 +-
 samples/pidfd/Makefile                             |   2 +-
 security/keys/key.c                                |  13 +-
 security/keys/keyctl.c                             |  15 +-
 security/keys/keyring.c                            | 150 ++++----
 security/keys/process_keys.c                       |   5 +-
 security/keys/trusted-keys/trusted_tpm1.c          |   4 +-
 security/keys/trusted-keys/trusted_tpm2.c          |   2 +-
 sound/soc/codecs/cs42l52.c                         |   2 +-
 sound/soc/codecs/cs42l56.c                         |   2 +-
 sound/soc/codecs/max98371.c                        |   2 +-
 sound/soc/codecs/nau8822.c                         |   4 +-
 sound/soc/codecs/pcm3168a.c                        |   2 +-
 sound/soc/codecs/wm8978.c                          |   4 +-
 sound/soc/intel/avs/pcm.c                          |   2 +-
 sound/soc/sof/ipc4-topology.c                      |  16 +-
 sound/soc/stm/stm32_spdifrx.c                      |   2 +-
 tools/gpio/Makefile                                |   6 +
 tools/power/x86/turbostat/turbostat.c              |  11 +-
 .../test.d/filter/event-filter-incomplete.tc       |  24 ++
 229 files changed, 3065 insertions(+), 1216 deletions(-)



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 001/247] rose: set SOCK_DESTROY in rose_kill_by_device() for prompt cleanup
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
@ 2026-10-28 16:56 ` Greg Kroah-Hartman
  2026-10-28 16:56 ` [PATCH 6.12 002/247] rose: disconnect orphaned STATE_2 sockets when device is gone Greg Kroah-Hartman
                   ` (253 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:56 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Bernard Pidoux <bernard.f6bvp@gmail.com>

When rose_kill_by_device() is called (via NETDEV_DOWN on module exit
or interface removal), it calls rose_disconnect() which transitions
sockets to ROSE_STATE_0 and sets SOCK_DEAD.  However,
rose_heartbeat_expiry() only calls rose_destroy_socket() at
ROSE_STATE_0 if SOCK_DESTROY is set -- the SOCK_DEAD path is reserved
for TCP_LISTEN sockets.  Without SOCK_DESTROY, orphaned sockets in
ROSE_STATE_2 (clearing) loop indefinitely in the heartbeat without
ever being freed, keeping the module use-count elevated and blocking
modprobe -r rose until the T1 timer (up to 200 s) expires.

Set SOCK_DESTROY immediately after rose_disconnect() so the heartbeat
destroys the socket at its next tick (within 5 s), allowing clean
module unload.

Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>

(cherry picked from commit 741a4863ad570889c75f7a8e404567d8f3e46335)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/rose/af_rose.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index 03a298ecb8320..314f11fec831d 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -211,6 +211,11 @@ static void rose_kill_by_device(struct net_device *dev)
 		spin_lock_bh(&rose_list_lock);
 		if (rose->device == dev) {
 			rose_disconnect(sk, ENETUNREACH, ROSE_OUT_OF_ORDER, 0);
+			/* Mark for destruction so rose_heartbeat_expiry()
+			 * cleans up the socket at its next tick rather than
+			 * looping forever in ROSE_STATE_0 with no owner.
+			 */
+			sock_set_flag(sk, SOCK_DESTROY);
 			if (rose->neighbour)
 				rose_neigh_put(rose->neighbour);
 			netdev_put(rose->device, &rose->dev_tracker);
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 002/247] rose: disconnect orphaned STATE_2 sockets when device is gone
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
  2026-10-28 16:56 ` [PATCH 6.12 001/247] rose: set SOCK_DESTROY in rose_kill_by_device() for prompt cleanup Greg Kroah-Hartman
@ 2026-10-28 16:56 ` Greg Kroah-Hartman
  2026-10-28 16:56 ` [PATCH 6.12 003/247] rose: release netdev ref and destroy orphaned incoming sockets Greg Kroah-Hartman
                   ` (252 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:56 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Bernard Pidoux <bernard.f6bvp@gmail.com>

When ax25stop brings down ROSE interfaces, sockets in ROSE_STATE_2
(awaiting CLEAR CONFIRM) whose device pointer is already NULL are not
reached by rose_kill_by_device() and wait for T3 (up to 180s) before
self-cleaning via rose_timer_expiry().  This keeps the rose module
usecount at 1, blocking rmmod for the full T3 duration.

In rose_heartbeat_expiry(), detect ROSE_STATE_2 sockets with no device,
cancel T3, release the neighbour reference, and call rose_disconnect()
+ sock_set_flag(SOCK_DESTROY).  The next heartbeat tick (<=5s) then
destroys the socket via the existing ROSE_STATE_0/SOCK_DESTROY path,
allowing clean module unload within 10s instead of up to 180s.

Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>

(cherry picked from commit d4f4cf9f09a3f5fafa8f09110a7c1b5d10f2f261)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/rose/rose_timer.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/net/rose/rose_timer.c b/net/rose/rose_timer.c
index 53d198ac96e89..92c07ceaa3899 100644
--- a/net/rose/rose_timer.c
+++ b/net/rose/rose_timer.c
@@ -139,6 +139,20 @@ static void rose_heartbeat_expiry(struct timer_list *t)
 		}
 		break;
 
+	case ROSE_STATE_2:
+		/* Device gone before CLEAR CONFIRM arrived: stop waiting for T3
+		 * and disconnect now instead of blocking rmmod for up to 180s. */
+		if (!rose->device) {
+			rose_stop_timer(sk);
+			if (rose->neighbour) {
+				rose_neigh_put(rose->neighbour);
+				rose->neighbour = NULL;
+			}
+			rose_disconnect(sk, ENETDOWN, -1, -1);
+			sock_set_flag(sk, SOCK_DESTROY);
+		}
+		break;
+
 	case ROSE_STATE_3:
 		/*
 		 * Check for the state of the receive buffer.
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 003/247] rose: release netdev ref and destroy orphaned incoming sockets
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
  2026-10-28 16:56 ` [PATCH 6.12 001/247] rose: set SOCK_DESTROY in rose_kill_by_device() for prompt cleanup Greg Kroah-Hartman
  2026-10-28 16:56 ` [PATCH 6.12 002/247] rose: disconnect orphaned STATE_2 sockets when device is gone Greg Kroah-Hartman
@ 2026-10-28 16:56 ` Greg Kroah-Hartman
  2026-10-28 16:56 ` [PATCH 6.12 004/247] rose: clear neighbour pointer in rose_kill_by_device() Greg Kroah-Hartman
                   ` (251 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:56 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Bernard Pidoux <bernard.f6bvp@gmail.com>

Two related cleanup gaps left the module unremovable after a loopback
session:

1. rose_destroy_socket() did not release the device reference.  When
   an unaccepted incoming socket (created by rose_rx_call_request()) is
   destroyed via rose_heartbeat_expiry(), it is removed from rose_list
   before rose_kill_by_device() can find it, so the netdev_hold() taken
   in rose_rx_call_request() was never matched by netdev_put().  Add the
   release at the top of rose_destroy_socket() guarded by a NULL check
   so that rose_release() and rose_kill_by_device(), which already call
   netdev_put() and set device = NULL, are not affected.

2. rose_heartbeat_expiry() STATE_0 cleanup required TCP_LISTEN in
   addition to SOCK_DEAD.  Unaccepted incoming sockets are
   TCP_ESTABLISHED, so the condition was never true and those sockets
   lingered forever, holding the module use count above zero and
   blocking rmmod.  Drop the TCP_LISTEN restriction: any STATE_0 +
   SOCK_DEAD socket is orphaned and should be destroyed.

Together with the earlier rose_make_new() double-hold fix these three
patches allow clean rmmod after loopback sessions.

Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>

(cherry picked from commit df12be096302d2c947388acc25764456c7f18cc1)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/rose/af_rose.c    | 9 +++++++++
 net/rose/rose_timer.c | 9 +++++----
 2 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index 314f11fec831d..5aedbbf105c33 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -363,6 +363,7 @@ static void rose_destroy_timer(struct timer_list *t)
  */
 void rose_destroy_socket(struct sock *sk)
 {
+	struct rose_sock *rose = rose_sk(sk);
 	struct sk_buff *skb;
 
 	rose_remove_socket(sk);
@@ -370,6 +371,14 @@ void rose_destroy_socket(struct sock *sk)
 	rose_stop_idletimer(sk);
 	rose_stop_timer(sk);
 
+	/* Drop any device reference not already released by rose_kill_by_device()
+	 * or rose_release() -- e.g. incoming sockets that were never accepted.
+	 */
+	if (rose->device) {
+		netdev_put(rose->device, &rose->dev_tracker);
+		rose->device = NULL;
+	}
+
 	rose_clear_queues(sk);		/* Flush the queues */
 
 	while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
diff --git a/net/rose/rose_timer.c b/net/rose/rose_timer.c
index 92c07ceaa3899..b2c5f4653b11d 100644
--- a/net/rose/rose_timer.c
+++ b/net/rose/rose_timer.c
@@ -128,10 +128,11 @@ static void rose_heartbeat_expiry(struct timer_list *t)
 	}
 	switch (rose->state) {
 	case ROSE_STATE_0:
-		/* Magic here: If we listen() and a new link dies before it
-		   is accepted() it isn't 'dead' so doesn't get removed. */
-		if (sock_flag(sk, SOCK_DESTROY) ||
-		    (sk->sk_state == TCP_LISTEN && sock_flag(sk, SOCK_DEAD))) {
+		/* Destroy any orphaned STATE_0 socket: either explicitly
+		 * flagged SOCK_DESTROY, or SOCK_DEAD (covers both unaccepted
+		 * incoming connections and listening sockets whose link died).
+		 */
+		if (sock_flag(sk, SOCK_DESTROY) || sock_flag(sk, SOCK_DEAD)) {
 			bh_unlock_sock(sk);
 			rose_destroy_socket(sk);
 			sock_put(sk);
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 004/247] rose: clear neighbour pointer in rose_kill_by_device()
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (2 preceding siblings ...)
  2026-10-28 16:56 ` [PATCH 6.12 003/247] rose: release netdev ref and destroy orphaned incoming sockets Greg Kroah-Hartman
@ 2026-10-28 16:56 ` Greg Kroah-Hartman
  2026-10-28 16:56 ` [PATCH 6.12 005/247] rose: dont free fd-owned sockets when reaping in the heartbeat Greg Kroah-Hartman
                   ` (250 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:56 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Bernard Pidoux <bernard.f6bvp@gmail.com>

rose_kill_by_device() drops the neighbour reference but leaves
rose->neighbour pointing at it, unlike every other rose_neigh_put() site
(see "rose: clear neighbour pointer after rose_neigh_put() in state
machines"). The heartbeat STATE_0 reaping path then puts the same
neighbour a second time, causing a rose_neigh refcount underflow and a
use-after-free.

Set rose->neighbour = NULL after the put, restoring the invariant.

Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>

(cherry picked from commit 606e42d195b467480d4d405f8814c48d1651a76a)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/rose/af_rose.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index 5aedbbf105c33..e0294a5183b47 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -216,8 +216,16 @@ static void rose_kill_by_device(struct net_device *dev)
 			 * looping forever in ROSE_STATE_0 with no owner.
 			 */
 			sock_set_flag(sk, SOCK_DESTROY);
-			if (rose->neighbour)
+			if (rose->neighbour) {
 				rose_neigh_put(rose->neighbour);
+				/* Clear the pointer after dropping the reference, as
+				 * every other rose_neigh_put() site does.  Otherwise
+				 * rose_heartbeat_expiry() (STATE_0 reaping) sees a stale
+				 * rose->neighbour and puts it a second time -> rose_neigh
+				 * refcount underflow / use-after-free.
+				 */
+				rose->neighbour = NULL;
+			}
 			netdev_put(rose->device, &rose->dev_tracker);
 			rose->device = NULL;
 		}
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 005/247] rose: dont free fd-owned sockets when reaping in the heartbeat
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (3 preceding siblings ...)
  2026-10-28 16:56 ` [PATCH 6.12 004/247] rose: clear neighbour pointer in rose_kill_by_device() Greg Kroah-Hartman
@ 2026-10-28 16:56 ` Greg Kroah-Hartman
  2026-10-28 16:56 ` [PATCH 6.12 006/247] rose: keep the route needed for routing loop detection Greg Kroah-Hartman
                   ` (249 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:56 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Bernard Pidoux <bernard.f6bvp@gmail.com>

The heartbeat reaps orphaned ROSE sockets after their bound device goes
down. A socket still attached to a struct socket (sk->sk_socket != NULL --
e.g. an incoming connection an fpad client has accepted and kept open) is
owned by that userspace fd: rose_release() frees it on close(). Freeing it
from the heartbeat left the fd dangling, so the eventual close() touched
freed memory -- slab-use-after-free in rose_release().

Reap only sockets with sk->sk_socket == NULL (unaccepted incoming
connections and post-close orphans). For an fd-owned socket whose device
went down, disconnect it and fall through to the switch so close() does
the teardown. Also release the neighbour reference held by orphaned
incoming sockets before tearing them down.

Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>

(cherry picked from commit 56576518920edd7b6c3479477d8d490fe2ebdaaa)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/rose/rose_timer.c | 57 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 56 insertions(+), 1 deletion(-)

diff --git a/net/rose/rose_timer.c b/net/rose/rose_timer.c
index b2c5f4653b11d..3cd7e020422a5 100644
--- a/net/rose/rose_timer.c
+++ b/net/rose/rose_timer.c
@@ -126,13 +126,68 @@ static void rose_heartbeat_expiry(struct timer_list *t)
 		sk_reset_timer(sk, &sk->sk_timer, jiffies + HZ/20);
 		goto out;
 	}
+
+	/* The bound device went down while we still hold a reference on it.
+	 * This catches the narrow race where rose_loopback_timer() created a
+	 * socket in the window after rose_kill_by_device()'s NETDEV_DOWN sweep
+	 * but before rose_insert_socket() -- leaving a STATE_3 socket that no
+	 * other branch reaps.  A down device means the link is dead, so tear
+	 * the socket down regardless of state.  rose_destroy_socket() releases
+	 * the held netdev reference (rose->device still set).
+	 */
+	if (rose->device && !netif_running(rose->device)) {
+		if (rose->neighbour) {
+			rose_neigh_put(rose->neighbour);
+			rose->neighbour = NULL;
+		}
+		rose_disconnect(sk, ENETDOWN, -1, -1);
+
+		/* Only reap the socket if userspace no longer holds it.  A socket
+		 * still attached to a struct socket (sk->sk_socket != NULL -- e.g.
+		 * a connection an fpad client has accepted and kept open) is owned
+		 * by that fd: rose_release() will destroy it on close().  Dropping
+		 * the last reference here leaves the open fd dangling, so the
+		 * eventual close() touches freed memory -> slab-use-after-free in
+		 * rose_release().  Unaccepted incoming sockets and post-close
+		 * orphans have sk->sk_socket == NULL and stay safe to reap here.
+		 */
+		if (!sk->sk_socket) {
+			sock_set_flag(sk, SOCK_DESTROY);
+			bh_unlock_sock(sk);
+			rose_destroy_socket(sk);
+			sock_put(sk);
+			return;
+		}
+
+		/* Owned by userspace: the link is down and the socket is now
+		 * disconnected (rose_disconnect() moved it to STATE_0).  Fall
+		 * through to the switch, which re-arms the heartbeat; the close()
+		 * will tear the socket down. */
+	}
+
 	switch (rose->state) {
 	case ROSE_STATE_0:
 		/* Destroy any orphaned STATE_0 socket: either explicitly
 		 * flagged SOCK_DESTROY, or SOCK_DEAD (covers both unaccepted
 		 * incoming connections and listening sockets whose link died).
 		 */
-		if (sock_flag(sk, SOCK_DESTROY) || sock_flag(sk, SOCK_DEAD)) {
+		if ((sock_flag(sk, SOCK_DESTROY) || sock_flag(sk, SOCK_DEAD)) &&
+		    !sk->sk_socket) {
+			/* Reap only orphaned sockets (sk->sk_socket == NULL).  A
+			 * socket still owned by a userspace fd reaches here via the
+			 * STATE_2 device-gone branch, which sets SOCK_DESTROY without
+			 * knowing about the fd; freeing it would race rose_release()
+			 * at close() -> use-after-free.  Leave it for close().
+			 *
+			 * Orphaned incoming sockets (rose_rx_call_request) hold a
+			 * neighbour reference; release it before teardown, as the
+			 * STATE_2 and device-down branches do.  rose_destroy_socket()
+			 * does not drop it.
+			 */
+			if (rose->neighbour) {
+				rose_neigh_put(rose->neighbour);
+				rose->neighbour = NULL;
+			}
 			bh_unlock_sock(sk);
 			rose_destroy_socket(sk);
 			sock_put(sk);
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 006/247] rose: keep the route needed for routing loop detection
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (4 preceding siblings ...)
  2026-10-28 16:56 ` [PATCH 6.12 005/247] rose: dont free fd-owned sockets when reaping in the heartbeat Greg Kroah-Hartman
@ 2026-10-28 16:56 ` Greg Kroah-Hartman
  2026-10-28 16:56 ` [PATCH 6.12 007/247] rose: guard rose_transmit_link() against a NULL neighbour Greg Kroah-Hartman
                   ` (248 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:56 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Bernard Pidoux <bernard.f6bvp@gmail.com>

rose_route_frame() walks the route list before parsing the Call Request
facilities.  When a CALL REQUEST arrives on a LCI that already belongs
to a route, the "Remove an existing unused route" branch deletes that
route with rose_remove_route() and breaks out of the walk, so that a
new call is able to reuse a stale LCI.

The routing loop detection that follows looks for a route recording the
same random number and the same pair of callsigns as the incoming call.
The route that has just been deleted is exactly the one it would have
matched, so a call coming back to us around a routing loop is not
detected: it is routed again, a new route is allocated, and the next
copy repeats the cycle.  Two nodes whose routes point at each other then
relay the same call to each other as fast as the CPU allows.

This was observed on an AX.25 network where two nodes each believed the
route to a third one went through the other.  The same CALL REQUEST,
carrying the same random number, was re-sent every 400 us, interleaved
with CLEAR REQUEST "Not obtainable", diagnostic 120, until the AX.25
link collapsed.  Over nine days one node emitted 204 million frames on
a link that normally carries a few frames per minute.  The outgoing LCI
stayed at 001 the whole time, because deleting the route freed it for
immediate reuse.

Parse the facilities before walking the route list, and in both
branches remove the route only when the incoming call differs from the
one it records.  When it is the same call, keep the route and clear the
call with diagnostic 120, which is what the loop detection would have
done.  The predicate is factored out as rose_same_call() and reused by
the loop detection itself.

Tested with two ROSE nodes routing a call back to each other.  Before
this change the kernel relayed 377 CALL REQUEST in ten seconds, never
emitted a CLEAR, and the AX.25 link dropped.  After it, the first call
is relayed once, the next copy is cleared with diagnostic 120, and the
link stays up.

Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
(cherry picked from commit a7e80823ff751d751411f62770bbd61f01be81db)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/rose/rose_route.c | 71 ++++++++++++++++++++++++++++++++++---------
 1 file changed, 56 insertions(+), 15 deletions(-)

diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c
index 28746ae5a2582..000d7a8bf7535 100644
--- a/net/rose/rose_route.c
+++ b/net/rose/rose_route.c
@@ -851,6 +851,21 @@ void rose_link_device_down(struct net_device *dev)
 	}
 }
 
+/*
+ *	Is this Call Request the very same call as the one an existing route
+ *	was built for?  Both the loop detection and the reuse of a stale LCI
+ *	below rely on this test.
+ */
+static bool rose_same_call(const struct rose_route *rose_route,
+			   const rose_address *src_addr,
+			   const struct rose_facilities_struct *facilities)
+{
+	return rose_route->rand == facilities->rand &&
+	       rosecmp(src_addr, &rose_route->src_addr) == 0 &&
+	       ax25cmp(&facilities->dest_call, &rose_route->src_call) == 0 &&
+	       ax25cmp(&facilities->source_call, &rose_route->dest_call) == 0;
+}
+
 /*
  *	Route a frame to an appropriate AX.25 connection.
  *	A NULL ax25_cb indicates an internally generated frame.
@@ -961,6 +976,16 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
 		goto out;
 	}
 
+	memset(&facilities, 0x00, sizeof(struct rose_facilities_struct));
+
+	if (frametype == ROSE_CALL_REQUEST &&
+	    !rose_parse_facilities(skb->data + ROSE_CALL_REQ_FACILITIES_OFF,
+				   skb->len - ROSE_CALL_REQ_FACILITIES_OFF,
+				   &facilities)) {
+		rose_transmit_clear_request(rose_neigh, lci, ROSE_INVALID_FACILITY, 76);
+		goto out;
+	}
+
 	/*
 	 *	Route it to the next in line if we have an entry for it.
 	 */
@@ -969,7 +994,21 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
 		if (rose_route->lci1 == lci &&
 		    rose_route->neigh1 == rose_neigh) {
 			if (frametype == ROSE_CALL_REQUEST) {
-				/* F6FBB - Remove an existing unused route */
+				if (rose_same_call(rose_route, src_addr,
+						   &facilities)) {
+					/*
+					 *	The very same call coming back
+					 *	to us: a routing loop.  Keep
+					 *	the route, the loop detection
+					 *	below is what matches on it.
+					 */
+					rose_transmit_clear_request(rose_neigh,
+								    lci,
+								    ROSE_NOT_OBTAINABLE,
+								    120);
+					goto out;
+				}
+				/* Remove an existing unused route */
 				rose_remove_route(rose_route);
 				break;
 			} else if (rose_route->neigh2 != NULL) {
@@ -990,7 +1029,21 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
 		if (rose_route->lci2 == lci &&
 		    rose_route->neigh2 == rose_neigh) {
 			if (frametype == ROSE_CALL_REQUEST) {
-				/* F6FBB - Remove an existing unused route */
+				if (rose_same_call(rose_route, src_addr,
+						   &facilities)) {
+					/*
+					 *	The very same call coming back
+					 *	to us: a routing loop.  Keep
+					 *	the route, the loop detection
+					 *	below is what matches on it.
+					 */
+					rose_transmit_clear_request(rose_neigh,
+								    lci,
+								    ROSE_NOT_OBTAINABLE,
+								    120);
+					goto out;
+				}
+				/* Remove an existing unused route */
 				rose_remove_route(rose_route);
 				break;
 			} else if (rose_route->neigh1 != NULL) {
@@ -1021,24 +1074,12 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
 		goto out;
 	}
 
-	memset(&facilities, 0x00, sizeof(struct rose_facilities_struct));
-
-	if (!rose_parse_facilities(skb->data + ROSE_CALL_REQ_FACILITIES_OFF,
-				   skb->len - ROSE_CALL_REQ_FACILITIES_OFF,
-				   &facilities)) {
-		rose_transmit_clear_request(rose_neigh, lci, ROSE_INVALID_FACILITY, 76);
-		goto out;
-	}
-
 	/*
 	 *	Check for routing loops.
 	 */
 	rose_route = rose_route_list;
 	while (rose_route != NULL) {
-		if (rose_route->rand == facilities.rand &&
-		    rosecmp(src_addr, &rose_route->src_addr) == 0 &&
-		    ax25cmp(&facilities.dest_call, &rose_route->src_call) == 0 &&
-		    ax25cmp(&facilities.source_call, &rose_route->dest_call) == 0) {
+		if (rose_same_call(rose_route, src_addr, &facilities)) {
 			rose_transmit_clear_request(rose_neigh, lci, ROSE_NOT_OBTAINABLE, 120);
 			goto out;
 		}
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 007/247] rose: guard rose_transmit_link() against a NULL neighbour
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (5 preceding siblings ...)
  2026-10-28 16:56 ` [PATCH 6.12 006/247] rose: keep the route needed for routing loop detection Greg Kroah-Hartman
@ 2026-10-28 16:56 ` Greg Kroah-Hartman
  2026-10-28 16:56 ` [PATCH 6.12 008/247] rose: use timer_shutdown_sync() for t0timer teardown Greg Kroah-Hartman
                   ` (247 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:56 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Bernard Pidoux <bernard.f6bvp@gmail.com>

rose_kick() and rose_write_internal() call rose_transmit_link(skb,
rose->neighbour) without checking that rose->neighbour is still set.
Since commit e8eb0c6faa88 ("rose: clear neighbour pointer after
rose_neigh_put() in state machines"), the state machines routinely set
rose->neighbour to NULL once the underlying AX.25 link is gone, while
leaving the socket in ROSE_STATE_3. rose_kick() only checks the
state, not the neighbour, so a write() on such a socket reaches
rose_transmit_link() with neigh == NULL, which immediately
dereferences neigh->loopback and crashes:

  Unable to handle kernel NULL pointer dereference at
  virtual address 0000000000000036
  ...
  pc : rose_transmit_link+0x14/0x1c8 [rose]
  lr : rose_kick+0xec/0x198 [rose]
  Call trace:
   rose_transmit_link+0x14/0x1c8 [rose] (P)
   rose_kick+0xec/0x198 [rose]
   rose_sendmsg+0x260/0x3c8 [rose]

Reproduced on f6bvp-8 (a real ROSE/FPAC node) when the BBS daemon
wrote to a socket whose neighbour had just been cleared. Confirmed
by recompiling rose_link.o with a static_assert on
offsetof(struct rose_neigh, loopback), which matches the faulting
address (0x36) exactly.

Drop the skb and return early when neigh is NULL, matching what
rose_transmit_link() already does for other frames it cannot send.

Fixes: e8eb0c6faa88 ("rose: clear neighbour pointer after rose_neigh_put() in state machines")
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
(cherry picked from commit 2aa2cf6eb000bd324c8296a877680186b5df5fe9)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/rose/rose_link.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/net/rose/rose_link.c b/net/rose/rose_link.c
index 0f77ae8ef944a..cbfb11fc3ac52 100644
--- a/net/rose/rose_link.c
+++ b/net/rose/rose_link.c
@@ -263,6 +263,11 @@ void rose_transmit_link(struct sk_buff *skb, struct rose_neigh *neigh)
 {
 	unsigned char *dptr;
 
+	if (!neigh) {
+		kfree_skb(skb);
+		return;
+	}
+
 	if (neigh->loopback) {
 		rose_loopback_queue(skb, neigh);
 		return;
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 008/247] rose: use timer_shutdown_sync() for t0timer teardown
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (6 preceding siblings ...)
  2026-10-28 16:56 ` [PATCH 6.12 007/247] rose: guard rose_transmit_link() against a NULL neighbour Greg Kroah-Hartman
@ 2026-10-28 16:56 ` Greg Kroah-Hartman
  2026-10-28 16:56 ` [PATCH 6.12 009/247] rose: dont warn on stray CALL_ACCEPTED/CLEAR_CONFIRMATION in state 3 Greg Kroah-Hartman
                   ` (246 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:56 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, syzbot+caa052a0958a9146870d,
	Bernard Pidoux, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Bernard Pidoux <bernard.f6bvp@gmail.com>

rose_t0timer_expiry() re-arms itself via rose_start_t0timer() at its
own tail. rose_neigh_put() and rose_remove_neigh() stop it with
timer_delete_sync() before freeing (or unlinking) the neighbour, but
that only guarantees the callback is not running *at the moment the
call returns* -- it does nothing to stop the very invocation that was
just waited out from re-arming the timer on its way out. That re-arm
races the kfree() in rose_neigh_put(): the timer can fire again on
freed memory, and rose_t0timer_expiry() -> rose_transmit_restart_request()
-> rose_send_frame() -> ax25_send_frame() dereferences the freed
neigh->digipeat, use-after-free.

This matches a syzbot report (KASAN slab-use-after-free read in
ax25_find_cb()) that stayed open with both cause and fix bisection
failing -- consistent with a hole that timer_delete_sync() alone
cannot close for a self-rearming timer, a case documented in its own
kerneldoc ("there is no way to get this correct with
timer_delete_sync()").

Use timer_shutdown_sync() instead in both call sites. Unlike
timer_delete_sync(), it also marks the timer so that any further
add_timer()/mod_timer() on it is silently ignored, which closes the
window regardless of how the self-rearm and the free are interleaved.
ftimer's handler is a no-op and never re-arms, but it is switched the
same way for consistency: both timers are being torn down for good in
both of these call sites.

Reported-by: syzbot+caa052a0958a9146870d@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=caa052a0958a9146870d
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
(cherry picked from commit 1cc5d2ead3cc0fc370f27728360bf8def008ee18)
[ Adjusted context: 6.12 still calls del_timer_sync() in
  rose_remove_neigh(). ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 include/net/rose.h    | 28 ++++++++++++++++++----------
 net/rose/rose_route.c | 10 ++++++++--
 2 files changed, 26 insertions(+), 12 deletions(-)

diff --git a/include/net/rose.h b/include/net/rose.h
index 95d1f9c582dcc..0d957b8dd0ba3 100644
--- a/include/net/rose.h
+++ b/include/net/rose.h
@@ -161,17 +161,25 @@ static inline void rose_neigh_put(struct rose_neigh *rose_neigh)
 {
 	if (refcount_dec_and_test(&rose_neigh->use)) {
 		/* We are dropping the last reference, so we are about to free the
-		 * neighbour.  Its timers may still be armed -- t0timer in particular
-		 * re-arms itself in rose_t0timer_expiry().  rose_remove_neigh()
-		 * cancels them before its own put, but callers that drop the final
-		 * reference without first calling rose_remove_neigh() (the socket
-		 * heartbeat reaping path) would otherwise kfree() a neighbour with a
-		 * live timer -> use-after-free.  timer_delete_sync() (not the async
-		 * variant) is required: it waits out a concurrently running handler
-		 * and loops until the self-rearming timer stays stopped.
+		 * neighbour.  t0timer is self-rearming: rose_t0timer_expiry() calls
+		 * rose_start_t0timer() at its own tail, so a plain timer_delete_sync()
+		 * is not enough here.  It only guarantees that the callback is not
+		 * running *at the moment it returns* -- it does nothing to stop the
+		 * very invocation we just waited out from re-arming the timer on its
+		 * way out, which races the kfree() below (syzbot: use-after-free read
+		 * in ax25_find_cb(), reached via rose_t0timer_expiry() ->
+		 * rose_transmit_restart_request() -> rose_send_frame() ->
+		 * ax25_send_frame(), dereferencing the freed neigh->digipeat).
+		 * timer_shutdown_sync() closes that hole: once it returns, any
+		 * further add_timer()/mod_timer() on this timer is silently ignored,
+		 * so a self-rearm racing the free can no longer bring the timer back
+		 * to life on freed memory.  ftimer's handler is a no-op and never
+		 * re-arms, but it is shut down the same way here for consistency --
+		 * this is final teardown, neither timer has any business firing
+		 * again.
 		 */
-		timer_delete_sync(&rose_neigh->ftimer);
-		timer_delete_sync(&rose_neigh->t0timer);
+		timer_shutdown_sync(&rose_neigh->ftimer);
+		timer_shutdown_sync(&rose_neigh->t0timer);
 		if (rose_neigh->ax25)
 			ax25_cb_put(rose_neigh->ax25);
 		kfree(rose_neigh->digipeat);
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c
index 000d7a8bf7535..fd196f2e2fd64 100644
--- a/net/rose/rose_route.c
+++ b/net/rose/rose_route.c
@@ -229,8 +229,14 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh)
 {
 	struct rose_neigh *s;
 
-	del_timer_sync(&rose_neigh->ftimer);
-	del_timer_sync(&rose_neigh->t0timer);
+	/* Being removed from the list is final teardown for this neighbour:
+	 * shut the timers down rather than just deleting them, so a t0timer
+	 * self-rearm losing the race with this removal can't bring it back to
+	 * life later.  See the comment in rose_neigh_put() (include/net/rose.h)
+	 * for the full story.
+	 */
+	timer_shutdown_sync(&rose_neigh->ftimer);
+	timer_shutdown_sync(&rose_neigh->t0timer);
 
 	skb_queue_purge(&rose_neigh->queue);
 
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 009/247] rose: dont warn on stray CALL_ACCEPTED/CLEAR_CONFIRMATION in state 3
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (7 preceding siblings ...)
  2026-10-28 16:56 ` [PATCH 6.12 008/247] rose: use timer_shutdown_sync() for t0timer teardown Greg Kroah-Hartman
@ 2026-10-28 16:56 ` Greg Kroah-Hartman
  2026-10-28 16:56 ` [PATCH 6.12 010/247] rose: hold a reference on incoming sockets queued for accept() Greg Kroah-Hartman
                   ` (245 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:56 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Bernard Pidoux <bernard.f6bvp@gmail.com>

rose_state3_machine() logs "ROSE: unknown %02X in state 3" at
KERN_WARNING for any frame type it does not handle during data
transfer. Two of them reach that default arm routinely on real AX.25
links and alarm sysops watching the console, even though they are
harmless:

  - CALL_ACCEPTED (0x0F): a late or duplicated Call Accepted that
    arrives after the socket has already moved to STATE_3, typically a
    retransmission on a slow link.

  - CLEAR_CONFIRMATION (0x17): crossed clearing, or a clear confirmation
    left over from a previous incarnation of a reused logical channel.

In both cases the frame is simply dropped: no state change, no
teardown, nothing freed. Only the noise is a problem.

Drop these two frame types silently. Keep reporting any other,
genuinely unexpected frame type, but through net_warn_ratelimited() so
a misbehaving peer cannot flood the kernel log.

Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
(cherry picked from commit 8649e4074ca29a6a8ef0076c2892ebc980b7153f)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/rose/rose_in.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/net/rose/rose_in.c b/net/rose/rose_in.c
index 666153a3dd8f7..69b2af24e85a6 100644
--- a/net/rose/rose_in.c
+++ b/net/rose/rose_in.c
@@ -202,7 +202,18 @@ static int rose_state3_machine(struct sock *sk, struct sk_buff *skb, int framety
 		break;
 
 	default:
-		printk(KERN_WARNING "ROSE: unknown %02X in state 3\n", frametype);
+		/*
+		 * CALL_ACCEPTED (0x0F) and CLEAR_CONFIRMATION (0x17) may show
+		 * up in state 3 as a late or duplicated Call Accepted, or as
+		 * crossed clearing / a reused logical channel on a slow AX.25
+		 * link. These are harmless protocol races, so drop them
+		 * silently. Any other frame type is genuinely unexpected and
+		 * is still reported, rate limited to avoid flooding the log.
+		 */
+		if (frametype != ROSE_CALL_ACCEPTED &&
+		    frametype != ROSE_CLEAR_CONFIRMATION)
+			net_warn_ratelimited("ROSE: unknown %02X in state 3\n",
+					     frametype);
 		break;
 	}
 
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 010/247] rose: hold a reference on incoming sockets queued for accept()
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (8 preceding siblings ...)
  2026-10-28 16:56 ` [PATCH 6.12 009/247] rose: dont warn on stray CALL_ACCEPTED/CLEAR_CONFIRMATION in state 3 Greg Kroah-Hartman
@ 2026-10-28 16:56 ` Greg Kroah-Hartman
  2026-10-28 16:56 ` [PATCH 6.12 011/247] ax25: bound REJ-driven fast retransmits with the existing N2 counter Greg Kroah-Hartman
                   ` (244 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:56 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Bernard Pidoux <bernard.f6bvp@gmail.com>

rose_rx_call_request() creates the socket for an incoming call and
queues the call's skb on the listening socket with skb->sk pointing at
it, without taking a reference. If the caller clears the call before
it is accepted, rose_disconnect() leaves that socket in STATE_0 with
SOCK_DEAD set, and since commit "rose: release netdev ref and destroy
orphaned incoming sockets" rose_heartbeat_expiry() reaps such orphaned
sockets and frees them. The skb stays on the listener's queue, so:

- closing the listener makes rose_destroy_socket() walk its queue and
  set flags and restart the heartbeat on the freed socket;
- accept() can hand the freed socket to user space.

On a live node running a KASAN kernel, stopping the FPAC daemons shortly
after a local (loopback) call had been set up and dropped gave:

  BUG: KASAN: slab-use-after-free in rose_destroy_socket+0x24a/0x570 [rose]
  Write of size 8 ... by task fpacwpd
   rose_destroy_socket
   rose_release
  Allocated by task 0: ... rose_rx_call_request <- rose_loopback_timer
  Freed by task ...: ... sk_free <- rose_heartbeat_expiry
  refcount_t: addition on 0; use-after-free.
   rose_start_heartbeat <- rose_destroy_socket <- rose_release

followed a few seconds later by a page fault in the re-armed heartbeat
and a kernel panic.

Make the listener's queue own a reference on each pending socket,
taken when the call is queued and dropped by rose_accept() or by the
listener's rose_destroy_socket() once the skb is off the queue. Have
the heartbeat set SOCK_DESTROY under the socket lock before reaping a
dead socket, as the other reaping paths already do, and make both
consumers check it under the child's lock: rose_accept() skips a
reaped socket and waits for the next call, and rose_destroy_socket()
no longer re-arms the heartbeat of a socket that is gone.

Fixes: df12be096302 ("rose: release netdev ref and destroy orphaned incoming sockets")
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
(cherry picked from commit 6b0223a4795f5db52dee038a7a29e9906122b0f7)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/rose/af_rose.c    | 44 ++++++++++++++++++++++++++++++++++++++-----
 net/rose/rose_timer.c |  5 +++++
 2 files changed, 44 insertions(+), 5 deletions(-)

diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index e0294a5183b47..420408a5ad61c 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -390,11 +390,25 @@ void rose_destroy_socket(struct sock *sk)
 	rose_clear_queues(sk);		/* Flush the queues */
 
 	while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
-		if (skb->sk != sk) {	/* A pending connection */
-			/* Queue the unaccepted socket for death */
-			sock_set_flag(skb->sk, SOCK_DEAD);
-			rose_start_heartbeat(skb->sk);
-			rose_sk(skb->sk)->state = ROSE_STATE_0;
+		struct sock *child = skb->sk;
+
+		if (child != sk) {	/* A pending connection */
+			/* Queue the unaccepted socket for death, unless
+			 * rose_heartbeat_expiry() has already reaped it or is
+			 * about to (SOCK_DESTROY).
+			 */
+			local_bh_disable();
+			bh_lock_sock_nested(child);
+			if (!sock_flag(child, SOCK_DESTROY)) {
+				sock_set_flag(child, SOCK_DEAD);
+				rose_start_heartbeat(child);
+				rose_sk(child)->state = ROSE_STATE_0;
+			}
+			bh_unlock_sock(child);
+			local_bh_enable();
+
+			skb->sk = NULL;
+			sock_put(child);	/* the queue's reference */
 		}
 
 		kfree_skb(skb);
@@ -980,6 +994,7 @@ static int rose_accept(struct socket *sock, struct socket *newsock,
 	 *	The write queue this time is holding sockets ready to use
 	 *	hooked into the SABM we saved
 	 */
+again:
 	for (;;) {
 		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
 
@@ -1005,12 +1020,27 @@ static int rose_accept(struct socket *sock, struct socket *newsock,
 		goto out_release;
 
 	newsk = skb->sk;
+	lock_sock_nested(newsk, SINGLE_DEPTH_NESTING);
+	if (sock_flag(newsk, SOCK_DESTROY)) {
+		/* The call went away and rose_heartbeat_expiry() reaped (or
+		 * is about to reap) the socket before it was accepted: drop
+		 * it and wait for the next one.
+		 */
+		release_sock(newsk);
+		skb->sk = NULL;
+		kfree_skb(skb);
+		sk_acceptq_removed(sk);
+		sock_put(newsk);	/* the queue's reference */
+		goto again;
+	}
 	sock_graft(newsk, newsock);
+	release_sock(newsk);
 
 	/* Now attach up the new socket */
 	skb->sk = NULL;
 	kfree_skb(skb);
 	sk_acceptq_removed(sk);
+	sock_put(newsk);		/* the queue's reference */
 
 out_release:
 	release_sock(sk);
@@ -1124,6 +1154,10 @@ int rose_rx_call_request(struct sk_buff *skb, struct net_device *dev, struct ros
 
 	rose_insert_socket(make);
 
+	/* The listener's queue holds a reference on the pending socket
+	 * until rose_accept() or rose_destroy_socket() takes it off.
+	 */
+	sock_hold(make);
 	skb_queue_head(&sk->sk_receive_queue, skb);
 
 	rose_start_heartbeat(make);
diff --git a/net/rose/rose_timer.c b/net/rose/rose_timer.c
index 3cd7e020422a5..5ba0c89e4ee1b 100644
--- a/net/rose/rose_timer.c
+++ b/net/rose/rose_timer.c
@@ -188,6 +188,11 @@ static void rose_heartbeat_expiry(struct timer_list *t)
 				rose_neigh_put(rose->neighbour);
 				rose->neighbour = NULL;
 			}
+			/* Tell rose_accept() and the listener's teardown, which
+			 * may still hold this socket on their queue, that it is
+			 * gone.
+			 */
+			sock_set_flag(sk, SOCK_DESTROY);
 			bh_unlock_sock(sk);
 			rose_destroy_socket(sk);
 			sock_put(sk);
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 011/247] ax25: bound REJ-driven fast retransmits with the existing N2 counter
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (9 preceding siblings ...)
  2026-10-28 16:56 ` [PATCH 6.12 010/247] rose: hold a reference on incoming sockets queued for accept() Greg Kroah-Hartman
@ 2026-10-28 16:56 ` Greg Kroah-Hartman
  2026-10-28 16:56 ` [PATCH 6.12 012/247] rose: purge rose_neigh->queue on final teardown Greg Kroah-Hartman
                   ` (243 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:56 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Bernard Pidoux <bernard.f6bvp@gmail.com>

REJ deliberately bypasses the T1/N2 backoff to trigger an immediate
go-back-N retransmit -- that is the whole point of REJ, fast recovery
from a single lost or out-of-order frame. But unlike every other
recovery path in this same state machine (T1 timeout, state 4
enquiry/DM, state 1/2 SABM retries), the REJ case in
ax25_std_state3_machine() never touches n2count, so it has no bound.

If something keeps corrupting or reordering every retransmitted burst
-- lossy RF, or packet reordering over a UDP-based transport such as
axudp -- each attempt draws an immediate fresh REJ and the link
retransmits at wire/CPU speed indefinitely, a "machine-gun" storm that
never reaches the N2 give-up already relied on everywhere else in this
file.

Reported independently twice: Chris Maness (KQ6UP) on a plain AX.25
link with no ROSE involved at all, and observed live on a ROSE/FPAC
White Pages link (f6bvp-8<->f6bvp-10, same LAN, so plain network
reordering over the Internet is not the trigger there -- likely lossy
retransmission of the same PDU) reaching ~5900 pkt/s. Both hit the same
code path since ax25_std_in.c is shared regardless of what rides on
top of AX.25.

Count consecutive REJ-driven fast retransmits the same way a T1
timeout already does in this state, and once N2 of them have failed to
get an in-sequence frame through, fall back to the paced state 4
enquiry -- which will genuinely disconnect after N2 further tries if
the link stays bad, exactly like every other recovery path already
does. A single frame accepted in sequence resets the counter, so an
isolated REJ during otherwise healthy traffic never gets close to N2.

Deployed on three Raspberry Pi nodes (f6bvp-12, f6bvp-8, f6bvp-10)
since 2026-09-13, running live production AX.25/ROSE/NET-ROM traffic
since, with no recurrence of the machine-gun storm and no other AX.25
regression observed.

Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
(cherry picked from commit a3aa611e37d4345ebcc98c847dedaf4bcf23c7ee)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/ax25/ax25_std_in.c | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/net/ax25/ax25_std_in.c b/net/ax25/ax25_std_in.c
index ba176196ae068..f280683f83fcf 100644
--- a/net/ax25/ax25_std_in.c
+++ b/net/ax25/ax25_std_in.c
@@ -196,6 +196,38 @@ static int ax25_std_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int frame
 		if (ax25_validate_nr(ax25, nr)) {
 			ax25_frames_acked(ax25, nr);
 			ax25_calculate_rtt(ax25);
+			/*
+			 * REJ triggers an immediate go-back-N retransmit,
+			 * deliberately bypassing the T1/N2 backoff that
+			 * paces every other recovery path in this state
+			 * machine -- that is the whole point of REJ, fast
+			 * recovery from a single lost/out-of-order frame.
+			 * But unlike every other recovery path here, this
+			 * one never touches n2count, so it has no bound: if
+			 * something keeps corrupting or reordering each
+			 * retransmitted burst (lossy RF, or reordering over
+			 * a UDP-based link such as axudp), every attempt
+			 * draws an immediate fresh REJ and the link is
+			 * retransmitted at wire/CPU speed indefinitely
+			 * ("machine-gun" storm), never reaching the N2 give
+			 * up that bounds every other recovery attempt.
+			 * Count consecutive REJ-driven fast retransmits the
+			 * same way a T1 timeout would in this state, and
+			 * once N2 of them have failed to make it through,
+			 * fall back to the normal paced state 4 enquiry
+			 * (which will genuinely give up and disconnect after
+			 * N2 further tries if the link stays bad). A single
+			 * frame accepted in sequence resets the counter (see
+			 * the AX25_I case below), so an isolated REJ during
+			 * otherwise healthy traffic never gets close to N2.
+			 */
+			if (ax25->n2count == ax25->n2) {
+				ax25->n2count = 1;
+				ax25_std_transmit_enquiry(ax25);
+				ax25->state = AX25_STATE_4;
+				break;
+			}
+			ax25->n2count++;
 			ax25_stop_t1timer(ax25);
 			ax25_start_t3timer(ax25);
 			ax25_requeue_frames(ax25);
@@ -226,6 +258,10 @@ static int ax25_std_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int frame
 			if (ax25->condition & AX25_COND_OWN_RX_BUSY)
 				ax25->vr = ns;	/* ax25->vr - 1 */
 			ax25->condition &= ~AX25_COND_REJECT;
+			/* Genuine forward progress: a frame made it through in
+			 * sequence, so this is not part of a REJ storm.
+			 */
+			ax25->n2count = 0;
 			if (pf) {
 				ax25_std_enquiry_response(ax25);
 			} else {
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 012/247] rose: purge rose_neigh->queue on final teardown
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (10 preceding siblings ...)
  2026-10-28 16:56 ` [PATCH 6.12 011/247] ax25: bound REJ-driven fast retransmits with the existing N2 counter Greg Kroah-Hartman
@ 2026-10-28 16:56 ` Greg Kroah-Hartman
  2026-10-28 16:56 ` [PATCH 6.12 013/247] mptcp: move the OoO check back into __mptcp_try_fallback() Greg Kroah-Hartman
                   ` (242 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:56 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Bernard Pidoux <bernard.f6bvp@gmail.com>

rose_transmit_link() queues an outgoing frame on rose_neigh->queue
instead of sending it immediately whenever the neighbour isn't
"restarted" yet (link not up) -- notably the CLEAR_REQUEST built by
rose_write_internal() when a socket is released (e.g. its owning
process is killed) while the underlying AX.25 link to that neighbour
is still coming up.

rose_neigh_put() already tears down both timers and drops the ax25/
digipeat references before freeing the neighbour, but never empties
this queue. kfree(rose_neigh) only frees the rose_neigh struct itself
(the sk_buff_head embedded in it is just three next/prev/len words),
not the skbs still linked into it -- every frame still queued here at
that point leaks for good.

rose_remove_neigh() (rose_route.c) already purges this same queue, but
it is only one of about two dozen call sites that can drop the last
reference and trigger the real kfree() in rose_neigh_put() -- every
socket releasing its own rose->neighbour reference (af_rose.c,
rose_in.c, rose_timer.c) can just as well be the one that does. Doing
the purge once, centrally, in rose_neigh_put() itself covers all of
them regardless of which call site happens to be last, rather than
relying on whichever caller happened to remember it.

Matches a leak pattern observed and documented back in May 2026
(mailbbs killed -> rose_release() -> rose_write_internal() ->
rose_transmit_link() queues the CLEAR_REQUEST -> skb never freed),
never root-caused until now.

Deployed and running since 2026-09-13/15 on three independent nodes
(f6bvp-12, f6bvp-8, f6bvp-10 -- three different kernel bases,
6.12.94/6.18.46/6.18.34), no regression observed.

Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
(cherry picked from commit e59e4523182e4f58f4f29b5e4bce44c1ef152d70)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 include/net/rose.h | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/include/net/rose.h b/include/net/rose.h
index 0d957b8dd0ba3..49140668b3dd0 100644
--- a/include/net/rose.h
+++ b/include/net/rose.h
@@ -180,6 +180,18 @@ static inline void rose_neigh_put(struct rose_neigh *rose_neigh)
 		 */
 		timer_shutdown_sync(&rose_neigh->ftimer);
 		timer_shutdown_sync(&rose_neigh->t0timer);
+		/* rose_transmit_link() queues a frame here instead of sending
+		 * it immediately whenever the neighbour isn't "restarted" yet
+		 * (link not up) -- e.g. the CLEAR_REQUEST built by
+		 * rose_write_internal() when a socket is released while its
+		 * underlying AX.25 link is still coming up. If this neighbour
+		 * is freed before that link ever comes up, nothing else ever
+		 * empties this queue: kfree() below only frees the
+		 * rose_neigh struct itself (including the three next/prev/len
+		 * words of the sk_buff_head), not the skbs it points to,
+		 * leaking every frame still queued here.
+		 */
+		skb_queue_purge(&rose_neigh->queue);
 		if (rose_neigh->ax25)
 			ax25_cb_put(rose_neigh->ax25);
 		kfree(rose_neigh->digipeat);
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 013/247] mptcp: move the OoO check back into __mptcp_try_fallback()
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (11 preceding siblings ...)
  2026-10-28 16:56 ` [PATCH 6.12 012/247] rose: purge rose_neigh->queue on final teardown Greg Kroah-Hartman
@ 2026-10-28 16:56 ` Greg Kroah-Hartman
  2026-10-28 16:56 ` [PATCH 6.12 014/247] fat: stop reading directory entries past the end-of-directory marker Greg Kroah-Hartman
                   ` (241 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:56 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Abdul Wasey, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Abdul Wasey <w453y.me@gmail.com>

The 6.12.y backport of upstream commit 1bba3f219c5e ("mptcp: do not
fallback when OoO is present") put the out-of-order queue check
in __mptcp_finish_join() instead of __mptcp_try_fallback().

So the fix itself is missing, as fallback still happens with OoO data
queued. Worse, the passive side now refuses every MP_JOIN while its
OoO queue is not empty, which is the normal state of a connection
already sending data over more than one subflow. The joining subflow
is reset, so such a connection can't add a new path, and a path that
comes back after an outage can't rejoin while data is in flight.

Move the check to __mptcp_try_fallback(), as upstream does.

Tested on 6.12.113 in netns: 6 connections (5 uploading) over two paths,
then a third endpoint added mid-transfer. Without this patch only the
idle connection gets a subflow on the new path and the other 5 joins
are reset. With it, all 6 join. Same result in 3 of 3 runs each.

Fixes: aab400cf8e35 ("mptcp: do not fallback when OoO is present")
Signed-off-by: Abdul Wasey <w453y.me@gmail.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/mptcp/protocol.c |   14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -74,6 +74,13 @@ bool __mptcp_try_fallback(struct mptcp_s
 	if (__mptcp_check_fallback(msk))
 		return true;
 
+	/* The caller possibly is not holding the msk socket lock, but
+	 * in the fallback case only the current subflow is touching
+	 * the OoO queue.
+	 */
+	if (!RB_EMPTY_ROOT(&msk->out_of_order_queue))
+		return false;
+
 	spin_lock_bh(&msk->fallback_lock);
 	if (!msk->allow_infinite_fallback) {
 		spin_unlock_bh(&msk->fallback_lock);
@@ -943,13 +950,6 @@ static bool __mptcp_finish_join(struct m
 	if (sk->sk_state != TCP_ESTABLISHED)
 		return false;
 
-	/* The caller possibly is not holding the msk socket lock, but
-	 * in the fallback case only the current subflow is touching
-	 * the OoO queue.
-	 */
-	if (!RB_EMPTY_ROOT(&msk->out_of_order_queue))
-		return false;
-
 	spin_lock_bh(&msk->fallback_lock);
 	if (!msk->allow_subflows) {
 		spin_unlock_bh(&msk->fallback_lock);



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 014/247] fat: stop reading directory entries past the end-of-directory marker
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (12 preceding siblings ...)
  2026-10-28 16:56 ` [PATCH 6.12 013/247] mptcp: move the OoO check back into __mptcp_try_fallback() Greg Kroah-Hartman
@ 2026-10-28 16:56 ` Greg Kroah-Hartman
  2026-10-28 16:56 ` [PATCH 6.12 015/247] soc/tegra: fuse: Add missing newline to APBMISC error message Greg Kroah-Hartman
                   ` (240 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:56 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Timothy Redaelli, OGAWA Hirofumi,
	Matteo Croce, Christian Brauner (Amutable), Nicolai Buchwitz,
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Matteo Croce <technoboy85@gmail.com>

commit 6a2875517c778ac1111b6920e94cbab91cda8724 upstream.

The FAT specification[1] (FAT Directory Structure -> "DIR_Name[0]") states:

    If DIR_Name[0] == 0x00, then the directory entry is free (same as for
    0xE5), and there are no allocated directory entries after this one
    (all of the DIR_Name[0] bytes in all of the entries after this one
    are also set to 0).

    The special 0 value, rather than the 0xE5 value, indicates to FAT
    file system driver code that the rest of the entries in this
    directory do not need to be examined because they are all free.

Linux did not honour this. fat_get_entry() kept advancing past the 0x00
terminator; if the trailing on-disk slots were not zero-filled (buggy
formatters, read-only media written by other operating systems, on-disk
corruption) the driver surfaced arbitrary bytes as real directory
entries. On a typical affected image, `ls /mnt` returns ~150 bogus
entries with random binary names, multi-gigabyte sizes, dates ranging
from 1980 to 2106, and a flood of -EIO from stat().

Earlier attempts (v1..v3, see [2][3][4]) added `de->name[0] == 0` guards
at each call site. As Hirofumi pointed out on v3, those guards reject
the entry but fat_get_entry() has already advanced *pos past it; the
next readdir() resumes after the marker and walks straight back into
the garbage. His suggestion was to centralise the check.

This patch:

  * Adds fat_get_entry_eod(), a small wrapper around fat_get_entry()
    that returns -1 when name[0] == 0 and seeks *pos to dir->i_size.
    Per spec every slot after the 0x00 marker is also zero, so jumping
    to the end of the directory is correct: subsequent reads return -1
    from fat_bmap() without re-fetching trailing zero slots, and
    callers persisting *pos across invocations (notably readdir's
    ctx->pos) keep reporting end-of-directory on re-entry.

  * Converts the read/search paths to use the new wrapper:
      fat_parse_long(), fat_search_long(), __fat_readdir(),
      and fat_get_short_entry() -- the last covers
      fat_get_dotdot_entry(), fat_dir_empty(), fat_subdirs(),
      fat_scan(), and fat_scan_logstart() transitively.

  * Leaves fat_add_entries() and __fat_remove_entries() on raw
    fat_get_entry(): the write paths legitimately need to operate on
    free/zero slots. fat_add_entries() additionally detects an
    allocated entry past a 0x00 marker (the spec violation that
    produces the garbage) and treats it as filesystem corruption:
    fat_fs_error_ratelimit() is called -- which honours the configured
    errors= mount option (panic / remount-ro / continue) -- and the
    operation returns -EIO so we don't write fresh entries into an
    already-corrupt directory.

[1] https://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/fatgen103.doc
[2] https://lore.kernel.org/lkml/20181207013410.7050-1-mcroce@redhat.com/
[3] https://lore.kernel.org/lkml/20181216231510.26854-1-mcroce@redhat.com/
[4] https://lore.kernel.org/lkml/20190201001408.7453-1-mcroce@redhat.com/

Reported-by: Timothy Redaelli <tredaelli@redhat.com>
Suggested-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Signed-off-by: Matteo Croce <teknoraver@meta.com>
Link: https://patch.msgid.link/20260616163346.32603-1-technoboy85@gmail.com
Acked-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
[nb: keep i_pos in fat_add_entries(), it is still used here because
  the fat_add_new_entries() rework is not in this tree]
Signed-off-by: Nicolai Buchwitz <nb@tipi-net.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 fs/fat/dir.c | 44 ++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 40 insertions(+), 4 deletions(-)

diff --git a/fs/fat/dir.c b/fs/fat/dir.c
index acbec5bdd5210..ce6b87210e189 100644
--- a/fs/fat/dir.c
+++ b/fs/fat/dir.c
@@ -128,6 +128,31 @@ static inline int fat_get_entry(struct inode *dir, loff_t *pos,
 	return fat__get_entry(dir, pos, bh, de);
 }
 
+/*
+ * Like fat_get_entry(), but honour the FAT end-of-directory marker:
+ * a dirent whose first name byte is NUL terminates iteration per the
+ * spec, which also guarantees that every following slot is zeroed.
+ * Skip straight to the end of the directory so the next call returns
+ * -1 from fat_bmap() without re-reading the trailing zero slots, and
+ * so callers that persist *pos across invocations (e.g. readdir's
+ * ctx->pos) keep reporting EOD.  Release *bh and set it to NULL to
+ * match fat_get_entry()'s contract that *bh is NULL on the -1 return.
+ */
+static int fat_get_entry_eod(struct inode *dir, loff_t *pos,
+			     struct buffer_head **bh,
+			     struct msdos_dir_entry **de)
+{
+	int err = fat_get_entry(dir, pos, bh, de);
+
+	if (err == 0 && (*de)->name[0] == 0) {
+		brelse(*bh);
+		*bh = NULL;
+		*pos = dir->i_size;
+		return -1;
+	}
+	return err;
+}
+
 /*
  * Convert Unicode 16 to UTF-8, translated Unicode, or ASCII.
  * If uni_xlate is enabled and we can't get a 1:1 conversion, use a
@@ -325,7 +350,7 @@ static int fat_parse_long(struct inode *dir, loff_t *pos,
 
 		if (ds->id & 0x40)
 			(*unicode)[offset + 13] = 0;
-		if (fat_get_entry(dir, pos, bh, de) < 0)
+		if (fat_get_entry_eod(dir, pos, bh, de) < 0)
 			return PARSE_EOF;
 		if (slot == 0)
 			break;
@@ -487,7 +512,7 @@ int fat_search_long(struct inode *inode, const unsigned char *name,
 
 	err = -ENOENT;
 	while (1) {
-		if (fat_get_entry(inode, &cpos, &bh, &de) == -1)
+		if (fat_get_entry_eod(inode, &cpos, &bh, &de) == -1)
 			goto end_of_dir;
 parse_record:
 		nr_slots = 0;
@@ -599,7 +624,7 @@ static int __fat_readdir(struct inode *inode, struct file *file,
 
 	bh = NULL;
 get_new:
-	if (fat_get_entry(inode, &cpos, &bh, &de) == -1)
+	if (fat_get_entry_eod(inode, &cpos, &bh, &de) == -1)
 		goto end_of_dir;
 parse_record:
 	nr_slots = 0;
@@ -882,7 +907,7 @@ static int fat_get_short_entry(struct inode *dir, loff_t *pos,
 			       struct buffer_head **bh,
 			       struct msdos_dir_entry **de)
 {
-	while (fat_get_entry(dir, pos, bh, de) >= 0) {
+	while (fat_get_entry_eod(dir, pos, bh, de) >= 0) {
 		/* free entry or long name entry or volume label */
 		if (!IS_FREE((*de)->name) && !((*de)->attr & ATTR_VOLUME))
 			return 0;
@@ -1299,6 +1324,7 @@ int fat_add_entries(struct inode *dir, void *slots, int nr_slots,
 	struct msdos_dir_entry *de;
 	int err, free_slots, i, nr_bhs;
 	loff_t pos, i_pos;
+	bool saw_eod;
 
 	sinfo->nr_slots = nr_slots;
 
@@ -1307,12 +1333,15 @@ int fat_add_entries(struct inode *dir, void *slots, int nr_slots,
 	bh = prev = NULL;
 	pos = 0;
 	err = -ENOSPC;
+	saw_eod = false;
 	while (fat_get_entry(dir, &pos, &bh, &de) > -1) {
 		/* check the maximum size of directory */
 		if (pos >= FAT_MAX_DIR_SIZE)
 			goto error;
 
 		if (IS_FREE(de->name)) {
+			if (de->name[0] == 0)
+				saw_eod = true;
 			if (prev != bh) {
 				get_bh(bh);
 				bhs[nr_bhs] = prev = bh;
@@ -1322,6 +1351,13 @@ int fat_add_entries(struct inode *dir, void *slots, int nr_slots,
 			if (free_slots == nr_slots)
 				goto found;
 		} else {
+			if (saw_eod) {
+				fat_fs_error_ratelimit(sb,
+					"allocated dir entry found after end-of-directory marker (i_pos %lld)",
+					MSDOS_I(dir)->i_pos);
+				err = -EIO;
+				goto error;
+			}
 			for (i = 0; i < nr_bhs; i++)
 				brelse(bhs[i]);
 			prev = NULL;
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 015/247] soc/tegra: fuse: Add missing newline to APBMISC error message
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (13 preceding siblings ...)
  2026-10-28 16:56 ` [PATCH 6.12 014/247] fat: stop reading directory entries past the end-of-directory marker Greg Kroah-Hartman
@ 2026-10-28 16:56 ` Greg Kroah-Hartman
  2026-10-28 16:56 ` [PATCH 6.12 016/247] power: supply: Fix maintenance charge table kernel-doc Greg Kroah-Hartman
                   ` (239 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:56 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Jinhui Guo, Thierry Reding,
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Jinhui Guo <guojinhui.liam@bytedance.com>

[ Upstream commit 2f4a0fb66d313f03832f061bc3ec25b33c8198c9 ]

The error message printed by tegra_acpi_init_apbmisc() when failing to
get APBMISC memory resources is missing a trailing newline. This can
cause the message to be merged with the following kernel log line, making
the log harder to read.

Add the missing newline to keep the error output properly formatted.

Fixes: 7b0c505eb341 ("soc/tegra: fuse: Add tegra_acpi_init_apbmisc()")
Signed-off-by: Jinhui Guo <guojinhui.liam@bytedance.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/soc/tegra/fuse/tegra-apbmisc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/soc/tegra/fuse/tegra-apbmisc.c b/drivers/soc/tegra/fuse/tegra-apbmisc.c
index e2ca5d55fd312..b506ed40e1080 100644
--- a/drivers/soc/tegra/fuse/tegra-apbmisc.c
+++ b/drivers/soc/tegra/fuse/tegra-apbmisc.c
@@ -277,7 +277,7 @@ void tegra_acpi_init_apbmisc(void)
 
 	ret = acpi_dev_get_memory_resources(adev, &resource_list);
 	if (ret < 0) {
-		pr_err("failed to get APBMISC memory resources");
+		pr_err("failed to get APBMISC memory resources\n");
 		goto out_put_acpi_dev;
 	}
 
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 016/247] power: supply: Fix maintenance charge table kernel-doc
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (14 preceding siblings ...)
  2026-10-28 16:56 ` [PATCH 6.12 015/247] soc/tegra: fuse: Add missing newline to APBMISC error message Greg Kroah-Hartman
@ 2026-10-28 16:56 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 017/247] power: supply: ds2780: Fix ds2780_get_capacity() returning raw value Greg Kroah-Hartman
                   ` (238 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:56 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Karl Mehltretter, Sebastian Reichel,
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Karl Mehltretter <kmehltretter@gmail.com>

[ Upstream commit 45d4af4e80a25881b6b75e8e34872c555c43a41d ]

struct power_supply_maintenance_charge_table contains
charge_safety_timer_minutes, but its kernel-doc describes
safety_timer_minutes. This leaves the real member undescribed and adds a
nonexistent member to the generated documentation.

Use the member's actual name.

Fixes: d72ce7d32478 ("power: supply: ab8500: Standardize maintenance charging")
Assisted-by: LLM
Signed-off-by: Karl Mehltretter <kmehltretter@gmail.com>
Link: https://patch.msgid.link/20260909064623.90737-1-kmehltretter@gmail.com
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 include/linux/power_supply.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 910d407ebe632..b03991a29a65e 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -360,9 +360,9 @@ struct power_supply_vbat_ri_table {
  * @charge_voltage_max_uv: maintenance charging voltage that is usually a bit
  *   lower than the constant_charge_voltage_max_uv. We can apply this settings
  *   charge_current_max_ua until we get back up to this voltage.
- * @safety_timer_minutes: maintenance charging safety timer, with an expiry
- *   time in minutes. We will only use maintenance charging in this setting
- *   for a certain amount of time, then we will first move to the next
+ * @charge_safety_timer_minutes: maintenance charging safety timer, with an
+ *   expiry time in minutes. We will only use maintenance charging in this
+ *   setting for a certain amount of time, then we will first move to the next
  *   maintenance charge current and voltage pair in respective array and wait
  *   for the next safety timer timeout, or, if we reached the last maintencance
  *   charging setting, disable charging until we reach
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 017/247] power: supply: ds2780: Fix ds2780_get_capacity() returning raw value
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (15 preceding siblings ...)
  2026-10-28 16:56 ` [PATCH 6.12 016/247] power: supply: Fix maintenance charge table kernel-doc Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 018/247] Drivers: hv: Avoid infinite retry loop in init_vp_index() Greg Kroah-Hartman
                   ` (237 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Xueqin Luo, Sebastian Reichel,
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Xueqin Luo <luoxueqin@kylinos.cn>

[ Upstream commit a58cbc8b36ec0cd00d2ba3de7d003de818a27523 ]

ds2780_get_capacity() returns the raw register value instead of 0 on
success.  The capacity is already stored in *capacity, so the function
should return 0 to indicate success.

Fixes: 275ac74629c4 ("w1: add Maxim/Dallas DS2780 Stand-Alone Fuel Gauge IC support")
Signed-off-by: Xueqin Luo <luoxueqin@kylinos.cn>
Link: https://patch.msgid.link/20260901072954.1953121-1-luoxueqin@kylinos.cn
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/power/supply/ds2780_battery.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/power/supply/ds2780_battery.c b/drivers/power/supply/ds2780_battery.c
index 1e7f297f6cb18..7219ee3def5ad 100644
--- a/drivers/power/supply/ds2780_battery.c
+++ b/drivers/power/supply/ds2780_battery.c
@@ -304,7 +304,7 @@ static int ds2780_get_capacity(struct ds2780_device_info *dev_info,
 		return ret;
 
 	*capacity = raw;
-	return raw;
+	return 0;
 }
 
 static int ds2780_get_status(struct ds2780_device_info *dev_info, int *status)
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 018/247] Drivers: hv: Avoid infinite retry loop in init_vp_index()
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (16 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 017/247] power: supply: ds2780: Fix ds2780_get_capacity() returning raw value Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 019/247] x86/hyperv: Avoid using per-cpu output page in hv_apicid_to_vp_index() Greg Kroah-Hartman
                   ` (236 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Waiman Long, Michael Kelley, Wei Liu,
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Waiman Long <longman@redhat.com>

[ Upstream commit 32ea0a33e3a0fb7c10c601b43e1b2f6c06a3f5fd ]

There is a retry loop in init_vp_index() where the CPUs from a certain
node are stripped out if they have already been in the allocated cpumask
or not in HK_TYPE_MANAGED_IRQ housekeeping cpumask. If there is no
CPU left, the allocated cpumask is ignored and the process is retried
again. However, if the HK_TYPE_MANAGED_IRQ housekeeping cpumask turns
out not to contain any CPU in that particular node, that will become an
infinite retry loop.  This particular problem was reported by sashiko
[1]. This should rarely happen, but we still need to guard against this.

Fix this infinite loop problem by also skipping NUMA node that has no
housekeeping CPU in the inner while loop of init_vp_index(). Also update
the early abort check to check for the absence of online housekeeping
CPUs instead of just the emptiness of the cpumask. As the outer for
loop will only be reached if the housekeeping cpumask has at least one
online CPU, a NUMA node with housekeeping CPUs will eventually be found.

Link: https://sashiko.dev/#/message/20260422030903.E1BFCC2BCB0%40smtp.kernel.org [1]
Fixes: 6640b5df1a38 ("Drivers: hv: vmbus: Don't assign VMbus channel interrupts to isolated CPUs")
Signed-off-by: Waiman Long <longman@redhat.com>
Reviewed-by: Michael Kelley <mhkelley@outlook.com>
Signed-off-by: Wei Liu <wei.liu@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/hv/channel_mgmt.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index 3c6011a48dabe..914d479d78723 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -743,13 +743,14 @@ static void init_vp_index(struct vmbus_channel *channel)
 	u32 i, ncpu = num_online_cpus();
 	cpumask_var_t available_mask;
 	struct cpumask *allocated_mask;
+	const struct cpumask *node_mask;
 	const struct cpumask *hk_mask = housekeeping_cpumask(HK_TYPE_MANAGED_IRQ);
 	u32 target_cpu;
 	int numa_node;
 
 	if (!perf_chn ||
 	    !alloc_cpumask_var(&available_mask, GFP_KERNEL) ||
-	    cpumask_empty(hk_mask)) {
+	    !cpumask_intersects(hk_mask, cpu_online_mask)) {
 		/*
 		 * If the channel is not a performance critical
 		 * channel, bind it to VMBUS_CONNECT_CPU.
@@ -771,14 +772,19 @@ static void init_vp_index(struct vmbus_channel *channel)
 				next_numa_node_id = 0;
 				continue;
 			}
-			if (cpumask_empty(cpumask_of_node(numa_node)))
+			/*
+			 * Try next NUMA node if current NUMA node has no CPU
+			 * or doesn't contain any housekeeping CPU.
+			 */
+			node_mask = cpumask_of_node(numa_node);
+			if (!cpumask_intersects(node_mask, hk_mask))
 				continue;
 			break;
 		}
 		allocated_mask = &hv_context.hv_numa_map[numa_node];
 
 retry:
-		cpumask_xor(available_mask, allocated_mask, cpumask_of_node(numa_node));
+		cpumask_xor(available_mask, allocated_mask, node_mask);
 		cpumask_and(available_mask, available_mask, hk_mask);
 
 		if (cpumask_empty(available_mask)) {
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 019/247] x86/hyperv: Avoid using per-cpu output page in hv_apicid_to_vp_index()
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (17 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 018/247] Drivers: hv: Avoid infinite retry loop in init_vp_index() Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 020/247] Drivers: hv: Dont reset VMBus connection state on error/exit paths Greg Kroah-Hartman
                   ` (235 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Michael Kelley, Tianyu Lan, Wei Liu,
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Michael Kelley <mhkelley58@gmail.com>

[ Upstream commit 7b74c117e2aac78e0f723e1c9c3644451c56b0d9 ]

hv_apicid_to_vp_index() currently uses the per-cpu hypercall input
and output pages. This function is called when running in VTL2 and
when running in an SEV-SNP CoCo VM with no paravisor. In the former
case, the output page is allocated, but in the latter case it is
not, so the hypervisor stores the output VP index in memory that has
not been allocated by the guest.

Fix this by using the input page for both input and output. The
hypercall has very small input and output, so sharing the same
page for both is straightforward. An alternative fix is to
allocate the per-cpu output page when running in an SEV-SNP CoCo
guest, but this uses significantly more memory, particularly
with larger vCPUs counts.

Fixes: 86c48271e0d6 ("x86/hyperv: Fix APIC ID and VP index confusion in hv_snp_boot_ap()")
Signed-off-by: Michael Kelley <mhklinux@outlook.com>
Reviewed-by: Tianyu Lan <tiala@microsoft.com>
Signed-off-by: Wei Liu <wei.liu@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 arch/x86/hyperv/hv_init.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
index 5d7e5b53e33ea..733802ffcc66e 100644
--- a/arch/x86/hyperv/hv_init.c
+++ b/arch/x86/hyperv/hv_init.c
@@ -750,7 +750,8 @@ int hv_apicid_to_vp_index(u32 apic_id)
 	input->partition_id = HV_PARTITION_ID_SELF;
 	input->apic_ids[0] = apic_id;
 
-	output = *this_cpu_ptr(hyperv_pcpu_output_arg);
+	/* Treat input as having 2 APIC IDs so output is 64-bit aligned */
+	output = (void *)input + struct_size(input, apic_ids, 2);
 
 	control = HV_HYPERCALL_REP_COMP_1 | HVCALL_GET_VP_ID_FROM_APIC_ID;
 	status = hv_do_hypercall(control, input, output);
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 020/247] Drivers: hv: Dont reset VMBus connection state on error/exit paths
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (18 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 019/247] x86/hyperv: Avoid using per-cpu output page in hv_apicid_to_vp_index() Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 021/247] pinctrl: qcom: ipq5018: add missing pwm3 function on gpio13 Greg Kroah-Hartman
                   ` (234 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Sashiko, Michael Kelley, Wei Liu,
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Michael Kelley <mhkelley58@gmail.com>

[ Upstream commit ec31dc39e835ccde0930daccece8c492d28282fc ]

In two places, current code forces vmbus_connection.conn_state to
DISCONNECTED prior to calling vmbus_disconnect(). But vmbus_disconnect()
calls vmbus_initiate_unload(), which unloads the VMBus connection
only if the conn_state is CONNECTED. Consequently, the connection
remains and the Hyper-V host might continue to send messages or post
VMBus interrupts.

The problem was introduced in commit 74347a99e73ae ("x86/Hyper-V:
Unload vmbus channel in hv panic callback"), in that
vmbus_initiate_unload() started checking the current connection
state before doing the unload. This commit removed some occurrences
where conn_state was forced to DISCONNECTED, but these two remained,
apparently due to an oversight at the time.

Fix this by not forcing conn_state to DISCONNECTED during VMBus exit,
or if a failure occurs when establishing the connection in the first
place. Whatever value conn_state has at the time is then read by
vmbus_initiate_unload() to determine if there is a connection to
be unloaded.

Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://lore.kernel.org/linux-hyperv/20260805205806.B5AC31F000E9@smtp.kernel.org/
Fixes: 74347a99e73ae ("x86/Hyper-V: Unload vmbus channel in hv panic callback")
Signed-off-by: Michael Kelley <mhklinux@outlook.com>
Signed-off-by: Wei Liu <wei.liu@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/hv/connection.c | 1 -
 drivers/hv/vmbus_drv.c  | 1 -
 2 files changed, 2 deletions(-)

diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c
index 3cdba13b132f0..722c07ec05be4 100644
--- a/drivers/hv/connection.c
+++ b/drivers/hv/connection.c
@@ -340,7 +340,6 @@ int vmbus_connect(void)
 cleanup:
 	pr_err("Unable to connect to host\n");
 
-	vmbus_connection.conn_state = DISCONNECTED;
 	vmbus_disconnect();
 
 	kfree(msginfo);
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index 1ddbbc80cf13f..153633bda1426 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -2899,7 +2899,6 @@ static void __exit vmbus_exit(void)
 
 	hv_remove_kexec_handler();
 	hv_remove_crash_handler();
-	vmbus_connection.conn_state = DISCONNECTED;
 	hv_stimer_global_cleanup();
 	vmbus_disconnect();
 	if (vmbus_irq == -1) {
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 021/247] pinctrl: qcom: ipq5018: add missing pwm3 function on gpio13
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (19 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 020/247] Drivers: hv: Dont reset VMBus connection state on error/exit paths Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 022/247] tools/power turbostat: Fix fd_perf leak on reset Greg Kroah-Hartman
                   ` (233 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Gilberto Conde, Konrad Dybcio,
	Bartosz Golaszewski, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Gilberto Conde <gilbertorconde@gmail.com>

[ Upstream commit c6c159fcdb4e9a678eda0831f971e4a3a488ec47 ]

GPIO13 supports the PWM3 function at mux select value 4, but the
pingroup table leaves that slot empty and gpio13 is not listed in
pwm3_groups. Selecting pwm3 on gpio13 is therefore rejected by the
pinmux core:

  ipq5018-tlmm: invalid group "gpio13" for function "pwm3"

The GL.iNet GL-X2000 drives its fan from PWM3 on this pin, and the
vendor firmware muxes it with select value 4:

  gpio13 : out low  func4 8mA no pull

Add pwm3 to the fourth function slot of gpio13 and list gpio13 in
pwm3_groups. With this the pin muxes as expected:

  pin 13 (GPIO_13): device 1941010.pwm function pwm3 group gpio13

Fixes: 725d1c891658 ("pinctrl: qcom: Add IPQ5018 pinctrl driver")
Signed-off-by: Gilberto Conde <gilbertorconde@gmail.com>
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Link: https://patch.msgid.link/20260921093419.2870168-1-gilbertorconde@gmail.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/pinctrl/qcom/pinctrl-ipq5018.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/pinctrl/qcom/pinctrl-ipq5018.c b/drivers/pinctrl/qcom/pinctrl-ipq5018.c
index 68f65b57003e9..18e68f7185bd5 100644
--- a/drivers/pinctrl/qcom/pinctrl-ipq5018.c
+++ b/drivers/pinctrl/qcom/pinctrl-ipq5018.c
@@ -565,7 +565,7 @@ static const char * const qdss_cti_trig_out_b1_groups[] = {
 };
 
 static const char * const pwm3_groups[] = {
-	"gpio45",
+	"gpio45", "gpio13",
 };
 
 static const char * const qdss_cti_trig_in_b1_groups[] = {
@@ -691,7 +691,7 @@ static const struct msm_pingroup ipq5018_groups[] = {
 	PINGROUP(10, blsp0_spi, blsp1_uart0, led0, gcc_plltest, qdss_tracedata_a, _, _, _, _),
 	PINGROUP(11, blsp0_spi, blsp1_uart0, _, gcc_tlmm, qdss_tracedata_a, _, _, _, _),
 	PINGROUP(12, blsp0_spi, blsp0_i2c, blsp1_uart0, _, gcc_plltest, qdss_tracedata_a, _, _, _),
-	PINGROUP(13, blsp0_spi, blsp0_i2c, blsp1_uart0, _, qdss_tracedata_a, _, _, _, _),
+	PINGROUP(13, blsp0_spi, blsp0_i2c, blsp1_uart0, pwm3, qdss_tracedata_a, _, _, _, _),
 	PINGROUP(14, pcie0_clk, _, _, cri_trng0, qdss_tracedata_a, _, _, _, _),
 	PINGROUP(15, _, _, cri_trng1, qdss_tracedata_a, _, _, _, _, _),
 	PINGROUP(16, pcie0_wake, _, _, cri_trng, qdss_tracedata_a, _, _, _, _),
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 022/247] tools/power turbostat: Fix fd_perf leak on reset
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (20 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 021/247] pinctrl: qcom: ipq5018: add missing pwm3 function on gpio13 Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 023/247] tools/power turbostat: Fix add_counter issue if > 24 counters Greg Kroah-Hartman
                   ` (232 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Len Brown, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Len Brown <len.brown@intel.com>

[ Upstream commit 767c64414c4c5fffd6cbc3a1cf1fb8138b28645b ]

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: 67bab430f4e7 ("tools/power turbostat: Group SMI counter with APERF and MPERF")
Assisted-by: GitHub Copilot (claude-sonnet-4.6)
Signed-off-by: Len Brown <len.brown@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 tools/power/x86/turbostat/turbostat.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index fb1c65f6ff9de..8b6180baa188d 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -5194,7 +5194,7 @@ void free_fd_msr(void)
 	if (!msr_counter_info)
 		return;
 
-	for (int cpu = 0; cpu < topo.max_cpu_num; ++cpu) {
+	for (int cpu = 0; cpu <= topo.max_cpu_num; ++cpu) {
 		if (msr_counter_info[cpu].fd_perf != -1)
 			close(msr_counter_info[cpu].fd_perf);
 	}
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 023/247] tools/power turbostat: Fix add_counter issue if > 24 counters.
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (21 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 022/247] tools/power turbostat: Fix fd_perf leak on reset Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 024/247] power: supply: generic-adc-battery: Fix temperature IIO channel conversion Greg Kroah-Hartman
                   ` (231 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Len Brown, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Len Brown <len.brown@intel.com>

[ Upstream commit 154b96dab83fd953b9b82c8bcfa041cd6a9d74d3 ]

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: 388e9c8134be ("tools/power turbostat: Make extensible via the --add parameter")
Assisted-by: Claude: Claude Sonnet 4.6
Signed-off-by: Len Brown <len.brown@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 tools/power/x86/turbostat/turbostat.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 8b6180baa188d..4947c38fc4f3c 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -9330,10 +9330,11 @@ int add_counter(unsigned int msr_num, char *path, char *name,
 				fprintf(stderr, "%s: %s FOUND\n", __func__, name);
 			break;
 		}
-		if (sys.added_thread_counters++ >= MAX_ADDED_THREAD_COUNTERS) {
+		if (sys.added_thread_counters >= MAX_ADDED_THREAD_COUNTERS) {
 			warnx("ignoring thread counter %s", name);
 			return -1;
 		}
+		sys.added_thread_counters++;
 		break;
 	case SCOPE_CORE:
 		msrp = find_msrp_by_name(sys.cp, name);
@@ -9342,10 +9343,11 @@ int add_counter(unsigned int msr_num, char *path, char *name,
 				fprintf(stderr, "%s: %s FOUND\n", __func__, name);
 			break;
 		}
-		if (sys.added_core_counters++ >= MAX_ADDED_CORE_COUNTERS) {
+		if (sys.added_core_counters >= MAX_ADDED_CORE_COUNTERS) {
 			warnx("ignoring core counter %s", name);
 			return -1;
 		}
+		sys.added_core_counters++;
 		break;
 	case SCOPE_PACKAGE:
 		msrp = find_msrp_by_name(sys.pp, name);
@@ -9354,10 +9356,11 @@ int add_counter(unsigned int msr_num, char *path, char *name,
 				fprintf(stderr, "%s: %s FOUND\n", __func__, name);
 			break;
 		}
-		if (sys.added_package_counters++ >= MAX_ADDED_PACKAGE_COUNTERS) {
+		if (sys.added_package_counters >= MAX_ADDED_PACKAGE_COUNTERS) {
 			warnx("ignoring package counter %s", name);
 			return -1;
 		}
+		sys.added_package_counters++;
 		break;
 	default:
 		warnx("ignoring counter %s with unknown scope", name);
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 024/247] power: supply: generic-adc-battery: Fix temperature IIO channel conversion
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (22 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 023/247] tools/power turbostat: Fix add_counter issue if > 24 counters Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 025/247] pinctrl: qcom: ipq5018: replace gcc_plltest with pwm2 on gpio12 Greg Kroah-Hartman
                   ` (230 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Svyatoslav Ryhel, Sebastian Reichel,
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Svyatoslav Ryhel <clamor95@gmail.com>

[ Upstream commit 6bca94e64255053ab2aa56f2588fda73d399b790 ]

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: 33088c0513818 ("power: supply: generic-adc-battery: add temperature support")
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
Link: https://patch.msgid.link/20260926142905.206215-2-clamor95@gmail.com
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/power/supply/generic-adc-battery.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/power/supply/generic-adc-battery.c b/drivers/power/supply/generic-adc-battery.c
index 7bdc6b2636090..aebc824aa2ede 100644
--- a/drivers/power/supply/generic-adc-battery.c
+++ b/drivers/power/supply/generic-adc-battery.c
@@ -90,12 +90,17 @@ static int gab_read_channel(struct gab *adc_bat, enum gab_chan_type channel,
 	int ret;
 
 	ret = iio_read_channel_processed(adc_bat->channel[channel], result);
-	if (ret < 0)
+	if (ret < 0) {
 		dev_err(&adc_bat->psy->dev, "read channel error: %d\n", ret);
+		return ret;
+	}
+
+	if (channel == GAB_TEMP)
+		*result /= 100; /* Convert from milli- to deci-degree */
 	else
 		*result *= 1000;
 
-	return ret;
+	return 0;
 }
 
 static int gab_get_property(struct power_supply *psy,
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 025/247] pinctrl: qcom: ipq5018: replace gcc_plltest with pwm2 on gpio12
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (23 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 024/247] power: supply: generic-adc-battery: Fix temperature IIO channel conversion Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 026/247] drm/vc4: hdmi: Move packet RAM enable to PM runtime Greg Kroah-Hartman
                   ` (229 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Adriel Santos, Dmitry Baryshkov,
	Bartosz Golaszewski, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Adriel Santos <adriel@adriel.eu>

[ Upstream commit 709ba1c547eaf37da36ded2ecf3ea4e304cdfa9a ]

The pingroup table has gcc_plltest at function 5 of gpio12 and does not
offer pwm2 on that pin, so the pinmux core rejects a request for pwm2 on
gpio12 as an invalid group. On the hardware, function 5 of gpio12
carries the PWM2 output: the Xiaomi AX3000T v2 drives its blue status
LED from PWM2 on gpio12.

The vendor kernel shipped on that router (Linux 4.4, stock firmware
2.0.28) has pwm2 in this slot. Its pingroup table, as read from the
firmware image, lists these functions for gpio12:

  gpio, blsp0_spi, blsp0_i2c, blsp1_uart0, _, pwm2, qdss_tracedata_a,
  _, _, _

and has pwm3 at function 4 of gpio13, matching commit c6c159fcdb4e
("pinctrl: qcom: ipq5018: add missing pwm3 function on gpio13").

Measured on the board: with gpio12 set to each of the 16 function
values in turn, and PWM2 held at 0% and then at 100% duty, the pad
level read back from GPIO_IN follows PWM2 only at function 5. There it
does not follow PWM channels 0, 1 or 3, and the LED switches with PWM2.
Functions 4 and 7, which the table leaves empty, do not carry PWM2.

Put pwm2 in function 5 of gpio12 and list gpio12 in pwm2_groups. Drop
gpio12 from gcc_plltest_groups: none of its functions is gcc_plltest
any more, and selecting it would trigger the WARN_ON() in
msm_pinmux_set_mux().

Fixes: 725d1c891658 ("pinctrl: qcom: Add IPQ5018 pinctrl driver")
Assisted-by: LLM
Signed-off-by: Adriel Santos <adriel@adriel.eu>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Link: https://patch.msgid.link/20261002160958.908424-1-adriel@adriel.eu
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/pinctrl/qcom/pinctrl-ipq5018.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/pinctrl/qcom/pinctrl-ipq5018.c b/drivers/pinctrl/qcom/pinctrl-ipq5018.c
index 18e68f7185bd5..2bbc409924f8b 100644
--- a/drivers/pinctrl/qcom/pinctrl-ipq5018.c
+++ b/drivers/pinctrl/qcom/pinctrl-ipq5018.c
@@ -363,7 +363,7 @@ static const char * const blsp1_uart0_groups[] = {
 };
 
 static const char * const gcc_plltest_groups[] = {
-	"gpio10", "gpio12",
+	"gpio10",
 };
 
 static const char * const gcc_tlmm_groups[] = {
@@ -557,7 +557,7 @@ static const char * const qdss_cti_trig_in_b0_groups[] = {
 };
 
 static const char * const pwm2_groups[] = {
-	"gpio44",
+	"gpio12", "gpio44",
 };
 
 static const char * const qdss_cti_trig_out_b1_groups[] = {
@@ -690,7 +690,7 @@ static const struct msm_pingroup ipq5018_groups[] = {
 	PINGROUP(9, sdc1_clk, qspi_clk, _, qdss_tracedata_a, _, _, _, _, _),
 	PINGROUP(10, blsp0_spi, blsp1_uart0, led0, gcc_plltest, qdss_tracedata_a, _, _, _, _),
 	PINGROUP(11, blsp0_spi, blsp1_uart0, _, gcc_tlmm, qdss_tracedata_a, _, _, _, _),
-	PINGROUP(12, blsp0_spi, blsp0_i2c, blsp1_uart0, _, gcc_plltest, qdss_tracedata_a, _, _, _),
+	PINGROUP(12, blsp0_spi, blsp0_i2c, blsp1_uart0, _, pwm2, qdss_tracedata_a, _, _, _),
 	PINGROUP(13, blsp0_spi, blsp0_i2c, blsp1_uart0, pwm3, qdss_tracedata_a, _, _, _, _),
 	PINGROUP(14, pcie0_clk, _, _, cri_trng0, qdss_tracedata_a, _, _, _, _),
 	PINGROUP(15, _, _, cri_trng1, qdss_tracedata_a, _, _, _, _, _),
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 026/247] drm/vc4: hdmi: Move packet RAM enable to PM runtime
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (24 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 025/247] pinctrl: qcom: ipq5018: replace gcc_plltest with pwm2 on gpio12 Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 027/247] vsock: treat TCP_CLOSING as once-established Greg Kroah-Hartman
                   ` (228 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Dave Stevenson, Maxime Ripard,
	Maíra Canal, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Dave Stevenson <dave.stevenson@raspberrypi.com>

[ Upstream commit 3f57b34485dc01e5a2db60a89a6ae5439a897e53 ]

Audio can be triggered by the HPD handler and start up before video has
been restored, calling vc4_hdmi_write_infoframe() for the audio infoframe.
vc4_hdmi_write_infoframe() needs Packet RAM to be on to store the
infoframe, however, if the video hasn't been enabled,
vc4_hdmi_encoder_post_crtc_enable() hasn't been called and therefore, the
Packet RAM can be disabled by the time vc4_hdmi_write_infoframe() executes,
causing the following splat:

[  201.570266] ------------[ cut here ]------------
[  201.570293] Packet RAM has to be on to store the packet.
[  201.570367] WARNING: drivers/gpu/drm/vc4/vc4_hdmi.c:683 at vc4_hdmi_write_infoframe+0x404/0x494 [vc4], CPU#0: wireplumber/1606
[...]
[  201.658650] Hardware name: Raspberry Pi 4 Model B Rev 1.5 (DT)
[...]
[  201.758499] Call trace:
[  201.760967]  vc4_hdmi_write_infoframe+0x404/0x494 [vc4] (P)
[  201.766607]  vc4_hdmi_write_audio_infoframe+0x1c/0x28 [vc4]
[  201.772247]  write_infoframe+0xbc/0x140 [drm_display_helper]
[  201.777975]  drm_atomic_helper_connector_hdmi_update_audio_infoframe+0x80/0xdc [drm_display_helper]
[  201.787140]  vc4_hdmi_audio_prepare+0x4ac/0x570 [vc4]
[  201.792252]  drm_connector_hdmi_audio_prepare+0x24/0x30 [drm_display_helper]
[  201.799390]  hdmi_codec_prepare+0x100/0x160 [snd_soc_hdmi_codec]
[  201.805471]  snd_soc_pcm_dai_prepare+0xd4/0x100 [snd_soc_core]
[  201.811375]  __soc_pcm_prepare+0x60/0x12c [snd_soc_core]
[  201.816752]  soc_pcm_prepare+0x34/0x58 [snd_soc_core]
[  201.821863]  snd_pcm_do_prepare+0x70/0x8c [snd_pcm]
[  201.826798]  snd_pcm_action_nonatomic+0xe4/0x174 [snd_pcm]
[  201.832350]  snd_pcm_prepare+0xc8/0xd8 [snd_pcm]
[  201.837021]  snd_pcm_common_ioctl+0x458/0x614 [snd_pcm]
[  201.842308]  snd_pcm_ioctl+0x30/0x48 [snd_pcm]
[  201.846802]  __arm64_sys_ioctl+0x88/0xd8
[  201.850769]  invoke_syscall+0x48/0xf4
[  201.854470]  el0_svc_common+0x80/0xd8
[  201.858171]  do_el0_svc+0x1c/0x28
[  201.861520]  el0_svc+0x3c/0xb0
[  201.864605]  el0t_64_sync_handler+0x68/0xdc
[  201.868834]  el0t_64_sync+0x198/0x19c
[  201.872536] ---[ end trace 0000000000000000 ]---

Considering that Packet RAM enable is essentially a power management
configuration, move its enabling/disabling to the Runtime PM hooks.

Note that post_crtc_disable() still stops all infoframes, but keeps Packet
RAM enabled, leaving it to be disabled by runtime suspend.

Link: https://github.com/raspberrypi/linux/issues/7069
Fixes: b47a72f30768 ("drm/vc4: hdmi: Switch to HDMI connector")
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Acked-by: Maxime Ripard <mripard@kernel.org>
Link: https://patch.msgid.link/20261002-vc4-hdmi-packet-ram-fix-v1-1-3d73148096c9@igalia.com
Reviewed-by: Maíra Canal <mcanal@igalia.com>
Signed-off-by: Maíra Canal <mcanal@igalia.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 9655027f1c0ab..7ea1622377b58 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -857,7 +857,7 @@ static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder,
 
 	spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
 
-	HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0);
+	HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, VC4_HDMI_RAM_PACKET_ENABLE);
 
 	HDMI_WRITE(HDMI_VID_CTL, HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_CLRRGB);
 
@@ -1616,9 +1616,6 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder,
 		WARN_ONCE(ret, "Timeout waiting for "
 			  "VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n");
 	} else {
-		HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
-			   HDMI_READ(HDMI_RAM_PACKET_CONFIG) &
-			   ~(VC4_HDMI_RAM_PACKET_ENABLE));
 		HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
 			   HDMI_READ(HDMI_SCHEDULER_CONTROL) &
 			   ~VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
@@ -1637,9 +1634,6 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder,
 		WARN_ON(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
 			  VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE));
 
-		HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
-			   VC4_HDMI_RAM_PACKET_ENABLE);
-
 		spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
 		vc4_hdmi->packet_ram_enabled = true;
 
@@ -3125,6 +3119,11 @@ static int vc5_hdmi_init_resources(struct drm_device *drm,
 static int vc4_hdmi_runtime_suspend(struct device *dev)
 {
 	struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev);
+	unsigned long flags;
+
+	spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
+	HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0);
+	spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
 
 	clk_disable_unprepare(vc4_hdmi->hsm_clock);
 
@@ -3134,9 +3133,8 @@ static int vc4_hdmi_runtime_suspend(struct device *dev)
 static int vc4_hdmi_runtime_resume(struct device *dev)
 {
 	struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev);
-	unsigned long __maybe_unused flags;
+	unsigned long rate, flags;
 	u32 __maybe_unused value;
-	unsigned long rate;
 	int ret;
 
 	ret = clk_prepare_enable(vc4_hdmi->hsm_clock);
@@ -3178,6 +3176,10 @@ static int vc4_hdmi_runtime_resume(struct device *dev)
 	}
 #endif
 
+	spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
+	HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, VC4_HDMI_RAM_PACKET_ENABLE);
+	spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
+
 	return 0;
 
 err_disable_clk:
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 027/247] vsock: treat TCP_CLOSING as once-established
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (25 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 026/247] drm/vc4: hdmi: Move packet RAM enable to PM runtime Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 028/247] net/rds: dont let the rdma_cm destroy an id RDS still owns on route failure Greg Kroah-Hartman
                   ` (227 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Hyunwoo Kim, Michal Luczaj,
	Stefano Garzarella, Paolo Abeni, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Michal Luczaj <mhal@rbox.co>

[ Upstream commit 4f6ac74fa594a918d41255c941256e1d51592d3b ]

Handle the TCP_ESTABLISHED -> TCP_CLOSING transition on OP_RST, which can
race with the connect loop. Immediately break and return 0 on
ESTABLISHED/CLOSING. The return value of connect() should reflect what
happened up to the point the connection was established or failed. Events
that occur afterwards must not affect it. E.g. even if OP_RW has already
set sk_err, connect() should still return 0, not ENOBUFS because of it.
Adapt the inaccurate comment above signal_pending().

Resetting a socket that is still present in connected_table can lead to
memory corruption. The reporter noted lost transports for in-flight skbs,
and I have reproduced crashes caused by re-insertion into connected_table.

  list_add double add: new=, prev=, next=.
  kernel BUG at lib/list_debug.c:35!
  Oops: invalid opcode: 0000 [#1] SMP KASAN NOPTI
  Workqueue: vsock-loopback vsock_loopback_work
  RIP: 0010:__list_add_valid_or_report+0x11f/0x130
  Call Trace:
   vsock_insert_connected.cold+0xe/0x13
   virtio_transport_recv_pkt+0x10e9/0x1460
   vsock_loopback_work+0x305/0x480
   process_one_work+0xe4c/0x1560
   worker_thread+0x4f1/0xd60
   kthread+0x36e/0x470
   ret_from_fork+0x47b/0x6b0
   ret_from_fork_asm+0x1a/0x30

This fix is supplementary to commit 002541ef650b ("vsock: Ignore
signal/timeout on connect() if already established"). Details under Link.

Fixes: d021c344051a ("VSOCK: Introduce VM Sockets")
Reported-by: Hyunwoo Kim <imv4bel@gmail.com>
Link: https://lore.kernel.org/netdev/anzT1fREOSyHT99k@v4bel/
Signed-off-by: Michal Luczaj <mhal@rbox.co>
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
Link: https://patch.msgid.link/20261005-vsock-connect-reset-closing-v4-1-15d41cfda3ed@rbox.co
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/vmw_vsock/af_vsock.c | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
index 1fa4dd2ca405b..228e45bf2d769 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -1633,23 +1633,22 @@ static int vsock_connect(struct socket *sock, struct sockaddr *addr,
 		timeout = schedule_timeout(timeout);
 		lock_sock(sk);
 
-		/* Connection established. Whatever happens to socket once we
-		 * release it, that's not connect()'s concern. No need to go
+		/* Connection was established. Whatever happens to socket once
+		 * we release it, that's not connect()'s concern. No need to go
 		 * into signal and timeout handling. Call it a day.
 		 *
 		 * Note that allowing to "reset" an already established socket
 		 * here is racy and insecure.
 		 */
-		if (sk->sk_state == TCP_ESTABLISHED)
-			break;
+		if (sk->sk_state == TCP_ESTABLISHED ||
+		    sk->sk_state == TCP_CLOSING) {
+			err = 0;
+			goto out_wait;
+		}
 
 		/* If connection was _not_ established and a signal/timeout came
 		 * to be, we want the socket's state reset. User space may want
-		 * to retry.
-		 *
-		 * sk_state != TCP_ESTABLISHED implies that socket is not on
-		 * vsock_connected_table. We keep the binding and the transport
-		 * assigned.
+		 * to retry, so we keep the binding and the transport assigned.
 		 */
 		if (signal_pending(current) || timeout == 0) {
 			err = timeout == 0 ? -ETIMEDOUT : sock_intr_errno(timeout);
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 028/247] net/rds: dont let the rdma_cm destroy an id RDS still owns on route failure
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (26 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 027/247] vsock: treat TCP_CLOSING as once-established Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 029/247] ASoC: Intel: avs: Reset the stream unless it is already prepared Greg Kroah-Hartman
                   ` (226 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Allison Henderson, Paolo Abeni,
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Allison Henderson <achender@kernel.org>

[ Upstream commit 98d446b7c013254a8a7b49720557676a3a851fde ]

rds_rdma_cm_event_handler_cmn() hands the return value of
rdma_resolve_route() straight back to the rdma_cm on
RDMA_CM_EVENT_ADDR_RESOLVED.  A synchronous failure there - -ENOMEM
from the route work allocation, an SA query that cannot be set up, a
RoCE route with no usable device - makes addr_handler() destroy the
id the event was delivered on.  That id is ic->i_cm_id, and nothing
clears the pointer: the connection sits in RDS_CONN_CONNECTING with a
freed id until its shutdown calls rdma_disconnect() and
rdma_destroy_id() on it.

The ROUTE_RESOLVED case already avoids this: rds_ib_cm_initiate_connect()
forces a zero return while ic->i_cm_id == cm_id, as the comment there
explains.  Do the same here - drop the connection and return 0 - so
the id stays RDS's to destroy from the shutdown, and the reconnect
gets a fresh one.

Fixes: 55b7ed0b582f ("RDS: Common RDMA transport code")
Assisted-by: LLM
Signed-off-by: Allison Henderson <achender@kernel.org>
Link: https://patch.msgid.link/20261003163408.250568-3-achender@kernel.org
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/rds/rdma_transport.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/net/rds/rdma_transport.c b/net/rds/rdma_transport.c
index b15cf316b23a2..21738a5690917 100644
--- a/net/rds/rdma_transport.c
+++ b/net/rds/rdma_transport.c
@@ -89,9 +89,19 @@ static int rds_rdma_cm_event_handler_cmn(struct rdma_cm_id *cm_id,
 		if (conn) {
 			rdma_set_service_type(cm_id, conn->c_tos);
 			rdma_set_min_rnr_timer(cm_id, IB_RNR_TIMER_000_32);
-			/* XXX do we need to clean up if this fails? */
 			ret = rdma_resolve_route(cm_id,
 						 RDS_RDMA_RESOLVE_TIMEOUT_MS);
+			if (ret) {
+				/* A non-zero return has the rdma_cm destroy
+				 * the id, but it is still ic->i_cm_id, which
+				 * the connection's shutdown would then
+				 * disconnect and destroy again.  Drop the
+				 * connection and keep the id for that
+				 * shutdown.
+				 */
+				rds_conn_drop(conn);
+				ret = 0;
+			}
 		}
 		break;
 
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 029/247] ASoC: Intel: avs: Reset the stream unless it is already prepared
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (27 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 028/247] net/rds: dont let the rdma_cm destroy an id RDS still owns on route failure Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 030/247] ASoC: stm32: spdifrx: fix synchronization state check Greg Kroah-Hartman
                   ` (225 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Sergey Tiraspolsky, Cezary Rojewski,
	Mark Brown, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Sergey Tiraspolsky <stiraspo@gmail.com>

[ Upstream commit f6be9f558a83fe30a03bd3adae461c821a0cef8c ]

Commit cfca1637bc2b ("ASoC: Intel: avs: Unprepare a stream when XRUN
occurs") resets the HDA stream when ->prepare() is called in the XRUN
state. User space does not always recover that way. PipeWire's ALSA
backend recovers from an underrun with snd_pcm_drop(), snd_pcm_prepare()
and a new start, so ->prepare() runs in the SETUP state,
hdac_stream->prepared is still set and the reset is skipped. Every
recovery attempt then fails the same way:

  spa.alsa: hw:avsmax98927,1p: snd_pcm_avail after recover: Broken pipe

On a Google Pixelbook (Kaby Lake, max98927 speakers) this happens after
an occasional underrun during normal playback and silences the speakers
for one to four minutes, until the PCM is closed. It can be provoked by
stopping PipeWire with SIGSTOP for 0.5 s during playback: in one run
that single underrun led to 1297 failed recoveries over two minutes,
until the sink was suspended. A plain alsa-lib program that recovers
with snd_pcm_drop() and snd_pcm_prepare() hits the same loop, while
snd_pcm_prepare() straight from XRUN recovers at once.

Skip the reset only when the stream is already PREPARED, the repeated
->prepare() case the check exists for, and reset it otherwise. With
this change both kinds of recovery succeed with a single restart.

Fixes: cfca1637bc2b ("ASoC: Intel: avs: Unprepare a stream when XRUN occurs")
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Sergey Tiraspolsky <stiraspo@gmail.com>
Acked-by: Cezary Rojewski <cezary.rojewski@intel.com>
Link: https://patch.msgid.link/20261010103753.16969-1-stiraspo@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 sound/soc/intel/avs/pcm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/intel/avs/pcm.c b/sound/soc/intel/avs/pcm.c
index 81fe4f0218c1a..78b330e225704 100644
--- a/sound/soc/intel/avs/pcm.c
+++ b/sound/soc/intel/avs/pcm.c
@@ -660,7 +660,7 @@ static int avs_dai_fe_prepare(struct snd_pcm_substream *substream, struct snd_so
 	data = snd_soc_dai_get_dma_data(dai, substream);
 	host_stream = data->host_stream;
 
-	if (runtime->state == SNDRV_PCM_STATE_XRUN)
+	if (runtime->state != SNDRV_PCM_STATE_PREPARED)
 		hdac_stream(host_stream)->prepared = false;
 	if (hdac_stream(host_stream)->prepared)
 		return 0;
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 030/247] ASoC: stm32: spdifrx: fix synchronization state check
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (28 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 029/247] ASoC: Intel: avs: Reset the stream unless it is already prepared Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 031/247] ASoC: cs42l56: Put the Limiter Cushion control on the limiter register Greg Kroah-Hartman
                   ` (224 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Avi Weiss, Olivier Moysan,
	Mark Brown, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Avi Weiss <thnkslprpt@gmail.com>

[ Upstream commit 0936bbd35a247665c64886135835faa3c3f4f29f ]

The interrupt handler uses a logical AND to check whether SPDIFRX
was in the SYNC state before clearing errors. Since both SYNC (1)
and ENABLE (3) are nonzero, this also treats ENABLE as SYNC (and
any other non-zero value that might be added).

The logical && basically just converts this to check for != 0.

So errors occurring while SPDIFRX is enabled cause the driver
to retry synch instead of disconnecting the PCM stream.

Fix is to change the logical && to equality (==) and only retry
when exactly in sync state.

Fixes: 0c93c291321f2 ("ASoC: stm32: spdifrx: retry synchronization in sync state")
Signed-off-by: Avi Weiss <thnkslprpt@gmail.com>
Reviewed-by: Olivier Moysan <olivier.moysan@foss.st.com>
Link: https://patch.msgid.link/20261011035459.2289403-1-thnkslprpt@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 sound/soc/stm/stm32_spdifrx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/stm/stm32_spdifrx.c b/sound/soc/stm/stm32_spdifrx.c
index 9e30852de93cd..6cc6ff5f6c289 100644
--- a/sound/soc/stm/stm32_spdifrx.c
+++ b/sound/soc/stm/stm32_spdifrx.c
@@ -728,7 +728,7 @@ static irqreturn_t stm32_spdifrx_isr(int irq, void *devid)
 
 	if (err) {
 		regmap_read(spdifrx->regmap, STM32_SPDIFRX_CR, &cr);
-		sync_state = FIELD_GET(SPDIFRX_CR_SPDIFEN_MASK, cr) &&
+		sync_state = FIELD_GET(SPDIFRX_CR_SPDIFEN_MASK, cr) ==
 			     SPDIFRX_SPDIFEN_SYNC;
 
 		/* SPDIFRX is in STATE_STOP. Disable SPDIFRX to clear errors */
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 031/247] ASoC: cs42l56: Put the Limiter Cushion control on the limiter register
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (29 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 030/247] ASoC: stm32: spdifrx: fix synchronization state check Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 032/247] ASoC: cs42l52: Fix the NG Type Switch bit Greg Kroah-Hartman
                   ` (223 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, HyeongJun An, Mark Brown,
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: HyeongJun An <sammiee5311@gmail.com>

[ Upstream commit 203436d2aeb7093290459e344e1912a418a6ebfd ]

The Limiter Cushion control writes bits 4:2 of the ALC Thresholds
register. Those bits are ALCMIN, which the ALC MIN control owns. The
datasheet puts CUSH at bits 4:2 of the Limit Thresholds Control
register, next to LMAX, which the Limiter MAX control already uses.

So setting the limiter cushion changes the ALC minimum threshold, and
the cushion itself cannot be set.

Use CS42L56_LIM_THRESHOLD_CTL.

Fixes: 272b5edd3b8f ("ASoC: Add support for CS42L56 CODEC")
Link: https://statics.cirrus.com/pubs/proDatasheet/CS42L56_F2.pdf
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: HyeongJun An <sammiee5311@gmail.com>
Link: https://patch.msgid.link/20261008130953.2446692-2-sammiee5311@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 sound/soc/codecs/cs42l56.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/codecs/cs42l56.c b/sound/soc/codecs/cs42l56.c
index aaa10c459b52d..0058ce2d55e83 100644
--- a/sound/soc/codecs/cs42l56.c
+++ b/sound/soc/codecs/cs42l56.c
@@ -449,7 +449,7 @@ static const struct snd_kcontrol_new cs42l56_snd_controls[] = {
 			0, 0x3f, 0, 0),
 	SOC_SINGLE_TLV("Limiter MAX", CS42L56_LIM_THRESHOLD_CTL,
 			5, 0x07, 1, alc_tlv),
-	SOC_SINGLE_TLV("Limiter Cushion", CS42L56_ALC_THRESHOLD,
+	SOC_SINGLE_TLV("Limiter Cushion", CS42L56_LIM_THRESHOLD_CTL,
 			2, 0x07, 1, alc_tlv),
 
 	SOC_SINGLE("NG Switch", CS42L56_NOISE_GATE_CTL, 6, 1, 1),
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 032/247] ASoC: cs42l52: Fix the NG Type Switch bit
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (30 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 031/247] ASoC: cs42l56: Put the Limiter Cushion control on the limiter register Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 033/247] ASoC: pcm3168a: Fix the DAC zero flag polarity bit Greg Kroah-Hartman
                   ` (222 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, HyeongJun An, Mark Brown,
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: HyeongJun An <sammiee5311@gmail.com>

[ Upstream commit 8b08b98796d2da103f2432550c14a7c687e72080 ]

The NG Type Switch enum selects between "Apply Specific" and "Apply
All", which is the NGALL bit. The datasheet puts NGALL at bit 7 of the
Noise Gate Control register. The enum uses bit 6, which is NG, the
noise gate enable owned by the NG Enable Switch. cs42l52.h names it
CS42L52_NG_ENABLE_SHIFT. cs42l56 has the same Noise Gate register and
puts its NG All Switch at bit 7.

So changing the noise gate type turns the noise gate on or off, and
NGALL cannot be set.

Use bit 7.

Fixes: dfe0f98b8d2e ("ASoC: Add support for CS42L52 Codec")
Link: https://statics.cirrus.com/pubs/proDatasheet/CS42L52_F2.pdf
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: HyeongJun An <sammiee5311@gmail.com>
Link: https://patch.msgid.link/20261008130953.2446692-3-sammiee5311@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 sound/soc/codecs/cs42l52.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c
index 7128d4c62f504..dda012be02b96 100644
--- a/sound/soc/codecs/cs42l52.c
+++ b/sound/soc/codecs/cs42l52.c
@@ -273,7 +273,7 @@ static const char * const cs42l52_ng_type_text[] = {
 };
 
 static SOC_ENUM_SINGLE_DECL(ng_type_enum,
-			    CS42L52_NOISE_GATE_CTL, 6,
+			    CS42L52_NOISE_GATE_CTL, 7,
 			    cs42l52_ng_type_text);
 
 static const char * const left_swap_text[] = {
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 033/247] ASoC: pcm3168a: Fix the DAC zero flag polarity bit
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (31 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 032/247] ASoC: cs42l52: Fix the NG Type Switch bit Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 034/247] ASoC: max98371: Fix the Speaker DHT Min Volume bits Greg Kroah-Hartman
                   ` (221 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, HyeongJun An, Cezary Rojewski,
	Mark Brown, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: HyeongJun An <sammiee5311@gmail.com>

[ Upstream commit b26edc925c1cfa0184cd270ed81d4833db045ce0 ]

The DAC Zero Flag Polarity enum uses PCM3168A_DAC_ATSPDA_SHIFT, which
is bit 6 of register 70. That bit is ATSPDA, the attenuation speed,
which the DAC Volume Rate Multiplier enum already owns. The datasheet
puts ZREV, the zero flag polarity, at bit 0. The header defines
PCM3168A_DAC_ZREV_SHIFT for it, but nothing uses it.

So changing the zero flag polarity changes the attenuation speed, and
ZREV cannot be set.

Use PCM3168A_DAC_ZREV_SHIFT.

Fixes: a9b17a638af5 ("ASoC: pcm3168a: Add driver for pcm3168a codec")
Link: https://www.ti.com/lit/ds/symlink/pcm3168a.pdf
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: HyeongJun An <sammiee5311@gmail.com>
Reviewed-by: Cezary Rojewski <cezary.rojewski@intel.com>
Link: https://patch.msgid.link/20261008130953.2446692-4-sammiee5311@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 sound/soc/codecs/pcm3168a.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/codecs/pcm3168a.c b/sound/soc/codecs/pcm3168a.c
index ad1564e7d8faa..ce68b239b9ef9 100644
--- a/sound/soc/codecs/pcm3168a.c
+++ b/sound/soc/codecs/pcm3168a.c
@@ -103,7 +103,7 @@ static SOC_ENUM_SINGLE_DECL(pcm3168a_dac_zf_func, PCM3168A_DAC_ATT_DEMP_ZF,
 static const char *const pcm3168a_pol[] = { "Active High", "Active Low" };
 
 static SOC_ENUM_SINGLE_DECL(pcm3168a_dac_zf_pol, PCM3168A_DAC_ATT_DEMP_ZF,
-		PCM3168A_DAC_ATSPDA_SHIFT, pcm3168a_pol);
+		PCM3168A_DAC_ZREV_SHIFT, pcm3168a_pol);
 
 static const char *const pcm3168a_con[] = { "Differential", "Single-Ended" };
 
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 034/247] ASoC: max98371: Fix the Speaker DHT Min Volume bits
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (32 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 033/247] ASoC: pcm3168a: Fix the DAC zero flag polarity bit Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 035/247] ASoC: wm8978: Fix the 128x oversampling switch bits Greg Kroah-Hartman
                   ` (220 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, HyeongJun An, Mark Brown,
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: HyeongJun An <sammiee5311@gmail.com>

[ Upstream commit f7934340c56a84fc1b246ebf6b2e806d775f3b54 ]

Register 0x31 holds two 4-bit fields. The datasheet puts SPK_GAIN_MIN
at bits 7:4 and DHT_VROT_PNT at bits 3:0. The Speaker DHT Min Volume
and Speaker DHT Rotation Volume controls both use bits 3:0.

So setting the minimum speaker gain changes the DHT rotation point, and
SPK_GAIN_MIN cannot be set.

Move Speaker DHT Min Volume to bits 7:4.

Fixes: ca2cd6bc6663 ("ASoC: Add max98371 codec driver")
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: HyeongJun An <sammiee5311@gmail.com>
Link: https://patch.msgid.link/20261008130953.2446692-5-sammiee5311@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 sound/soc/codecs/max98371.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/codecs/max98371.c b/sound/soc/codecs/max98371.c
index 852db211ba1e7..c53f76f0ade76 100644
--- a/sound/soc/codecs/max98371.c
+++ b/sound/soc/codecs/max98371.c
@@ -166,7 +166,7 @@ static const struct snd_kcontrol_new max98371_snd_controls[] = {
 			0, (1<<MAX98371_DHT_MAX_WIDTH)-1, 0,
 			max98371_dht_max_gain),
 	SOC_SINGLE_TLV("Speaker DHT Min Volume", MAX98371_DHT_GAIN,
-			0, (1<<MAX98371_DHT_GAIN_WIDTH)-1, 0,
+			4, (1<<MAX98371_DHT_GAIN_WIDTH)-1, 0,
 			max98371_dht_min_gain),
 	SOC_SINGLE_TLV("Speaker DHT Rotation Volume", MAX98371_DHT_GAIN,
 			0, (1<<MAX98371_DHT_ROT_WIDTH)-1, 0,
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 035/247] ASoC: wm8978: Fix the 128x oversampling switch bits
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (33 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 034/247] ASoC: max98371: Fix the Speaker DHT Min Volume bits Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 036/247] ASoC: nau8822: " Greg Kroah-Hartman
                   ` (219 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, HyeongJun An, Mark Brown,
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: HyeongJun An <sammiee5311@gmail.com>

[ Upstream commit d0567ca9a2faa33efbe5ae84ef7b86423a93bffd ]

The DAC and ADC 128x Oversampling Switches use bit 5 of R10 and R14.
Table 66 of the WM8978 datasheet puts DACOSR128 and ADCOSR128 at bit 3
of those registers.

In R14, bit 5 is inside HPFCUT[6:4], which the High Pass Cut Off
control owns. So turning on ADC oversampling changes the high pass
cut-off, and the oversampling bit cannot be set. In R10, bit 5 is
reserved, so the DAC switch has no effect.

Use bit 3 for both.

Fixes: 823dba519122 ("ASoC: Fix broken bitfield definitions in WM8978")
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: HyeongJun An <sammiee5311@gmail.com>
Link: https://patch.msgid.link/20261008130953.2446692-6-sammiee5311@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 sound/soc/codecs/wm8978.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c
index 40d22b36b7a96..a80538722dfdb 100644
--- a/sound/soc/codecs/wm8978.c
+++ b/sound/soc/codecs/wm8978.c
@@ -255,9 +255,9 @@ static const struct snd_kcontrol_new wm8978_snd_controls[] = {
 
 	/* DAC / ADC oversampling */
 	SOC_SINGLE("DAC 128x Oversampling Switch", WM8978_DAC_CONTROL,
-		   5, 1, 0),
+		   3, 1, 0),
 	SOC_SINGLE("ADC 128x Oversampling Switch", WM8978_ADC_CONTROL,
-		   5, 1, 0),
+		   3, 1, 0),
 };
 
 /* Mixer #1: Output (OUT1, OUT2) Mixer: mix AUX, Input mixer output and DAC */
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 036/247] ASoC: nau8822: Fix the 128x oversampling switch bits
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (34 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 035/247] ASoC: wm8978: Fix the 128x oversampling switch bits Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 037/247] regcache: Add ->populate() callback to separate from ->init() Greg Kroah-Hartman
                   ` (218 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, HyeongJun An, Mark Brown,
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: HyeongJun An <sammiee5311@gmail.com>

[ Upstream commit 4db45fc1da3d62d0fa6e8f1e457ae92e8741ed07 ]

The DAC and ADC 128x Oversampling Switches use bit 5 of R10 and R14.
The NAU8822 datasheet register map puts DACOS and ADCOS at bit 3 of
those registers.

In R14, bit 5 is inside HPF[6:4], which the High Pass Cut Off control
owns. So turning on ADC oversampling changes the high pass cut-off, and
the oversampling bit cannot be set. In R10, bit 5 is reserved, so the
DAC switch has no effect.

Use bit 3 for both.

Fixes: 1e3cb6c321be ("ASoC: nau8822: new codec driver")
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: HyeongJun An <sammiee5311@gmail.com>
Link: https://patch.msgid.link/20261008130953.2446692-7-sammiee5311@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 sound/soc/codecs/nau8822.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sound/soc/codecs/nau8822.c b/sound/soc/codecs/nau8822.c
index fd4a96a12060e..dcf317ec97512 100644
--- a/sound/soc/codecs/nau8822.c
+++ b/sound/soc/codecs/nau8822.c
@@ -380,9 +380,9 @@ static const struct snd_kcontrol_new nau8822_snd_controls[] = {
 		NAU8822_REG_RIGHT_ADC_BOOST_CONTROL, 0, 7, 0, boost_tlv),
 
 	SOC_SINGLE("DAC 128x Oversampling Switch",
-		NAU8822_REG_DAC_CONTROL, 5, 1, 0),
+		NAU8822_REG_DAC_CONTROL, 3, 1, 0),
 	SOC_SINGLE("ADC 128x Oversampling Switch",
-		NAU8822_REG_ADC_CONTROL, 5, 1, 0),
+		NAU8822_REG_ADC_CONTROL, 3, 1, 0),
 };
 
 /* LMAIN and RMAIN Mixer */
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 037/247] regcache: Add ->populate() callback to separate from ->init()
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (35 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 036/247] ASoC: nau8822: " Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 038/247] regcache: Do not overwrite error code when finalizing cache after error Greg Kroah-Hartman
                   ` (217 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Andy Shevchenko, Charles Keepax,
	Mark Brown, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

[ Upstream commit 94a3a95f03154d8d4c6206950a7f6ef9a30baec6 ]

In the future changes we would like to change the flow of the cache handling.
Add ->populate() callback in order to prepare for that.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Link: https://patch.msgid.link/20251031080540.3970776-2-andriy.shevchenko@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Stable-dep-of: abff0a48b110 ("regmap: Drop map lock during cache init and exit")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/base/regmap/internal.h |  1 +
 drivers/base/regmap/regcache.c | 16 ++++++++++++++++
 2 files changed, 17 insertions(+)

diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index bdb450436cbc5..e3ce87ffdd8c2 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -186,6 +186,7 @@ struct regcache_ops {
 	enum regcache_type type;
 	int (*init)(struct regmap *map);
 	int (*exit)(struct regmap *map);
+	int (*populate)(struct regmap *map);
 #ifdef CONFIG_DEBUG_FS
 	void (*debugfs_init)(struct regmap *map);
 #endif
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index d3659ba3cc112..d2630a55bb50b 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -201,8 +201,24 @@ int regcache_init(struct regmap *map, const struct regmap_config *config)
 		if (ret)
 			goto err_free;
 	}
+
+	if (map->num_reg_defaults && map->cache_ops->populate) {
+		dev_dbg(map->dev, "Populating %s cache\n", map->cache_ops->name);
+		map->lock(map->lock_arg);
+		ret = map->cache_ops->populate(map);
+		map->unlock(map->lock_arg);
+		if (ret)
+			goto err_exit;
+	}
 	return 0;
 
+err_exit:
+	if (map->cache_ops->exit) {
+		dev_dbg(map->dev, "Destroying %s cache\n", map->cache_ops->name);
+		map->lock(map->lock_arg);
+		ret = map->cache_ops->exit(map);
+		map->unlock(map->lock_arg);
+	}
 err_free:
 	kfree(map->reg_defaults);
 	if (map->cache_free)
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 038/247] regcache: Do not overwrite error code when finalizing cache after error
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (36 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 037/247] regcache: Add ->populate() callback to separate from ->init() Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 039/247] regmap: Drop map lock during cache init and exit Greg Kroah-Hartman
                   ` (216 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Francesco Lavra, Mark Brown,
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Francesco Lavra <flavra@baylibre.com>

[ Upstream commit 9108f7fa493b4c88cbc09503e0c164244456bad5 ]

During regcache initialization, if an error occurs in the
cache_ops->populate callback, and if cache operations include an exit
callback, the error code from populate() is overwritten with the return
value from exit(). This hides the error condition from the caller of
regcache_init(), and can cause NULL pointer dereferences when the regcache
is later accessed.

Fixes: 94a3a95f0315 ("regcache: Add ->populate() callback to separate from ->init()")
Signed-off-by: Francesco Lavra <flavra@baylibre.com>
Link: https://patch.msgid.link/20260616114429.1852456-1-flavra@baylibre.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Stable-dep-of: abff0a48b110 ("regmap: Drop map lock during cache init and exit")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/base/regmap/regcache.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index d2630a55bb50b..0e929e7ac68aa 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -216,7 +216,7 @@ int regcache_init(struct regmap *map, const struct regmap_config *config)
 	if (map->cache_ops->exit) {
 		dev_dbg(map->dev, "Destroying %s cache\n", map->cache_ops->name);
 		map->lock(map->lock_arg);
-		ret = map->cache_ops->exit(map);
+		map->cache_ops->exit(map);
 		map->unlock(map->lock_arg);
 	}
 err_free:
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 039/247] regmap: Drop map lock during cache init and exit
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (37 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 038/247] regcache: Do not overwrite error code when finalizing cache after error Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 040/247] netlink: reset skb headers before unicast and multicast filtering Greg Kroah-Hartman
                   ` (215 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Mark Brown, Liam R. Howlett,
	Michael Reeves, Peng Fan, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Michael Reeves <michael.reeves077@gmail.com>

[ Upstream commit abff0a48b110fe52d43999b4cb7c793a510a6bf1 ]

On systems with CONFIG_PROVE_RAW_LOCK_NESTING enabled, Apple GPIO probe
triggers an "Invalid wait context" lockdep warning.

The driver uses a regmap with a raw spinlock and REGCACHE_FLAT. During
regcache_init(), regcache_flat_init() allocates memory while holding the
raw spinlock. The memory allocator can acquire a non-raw spinlock, which
causes an invalid raw-to-non-raw lock nesting error. The abbreviated call
chain is:

  apple_gpio_pinctrl_probe
    regcache_init
      regcache_flat_init
        __kmalloc_noprof
          __pcs_replace_empty_main
            refill_objects
              _raw_spin_lock_irqsave

Cache allocation occurs before the regmap is published, cache destruction
occurs after users have stopped accessing it, and regmap_reinit_cache()
requires callers to prevent concurrent access. Remove the outer map lock
from cache initialization and destruction. Keep it for cache population
and normal register access.

The Maple cache still uses its internal spinlock during teardown. That
lock can also be acquired from hard IRQ context during register access.
Add Maple-state irqsave helpers and use them during teardown to preserve
the lock's IRQ-safe lockdep state.

Fixes: fd4ebc07b4df ("regmap: Hold the regmap lock when allocating and freeing the cache")
Suggested-by: Mark Brown <broonie@kernel.org>
Suggested-by: Liam R. Howlett <liam@infradead.org>
Signed-off-by: Michael Reeves <michael.reeves077@gmail.com>
Reviewed-by: Peng Fan <peng.fan@nxp.com>
Link: https://patch.msgid.link/20261006-regcache-lifecycle-submit-v3-2-37bdd82fd47c@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/base/regmap/regcache-maple.c | 9 +++++++--
 drivers/base/regmap/regcache.c       | 6 ------
 include/linux/maple_tree.h           | 4 ++++
 3 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/drivers/base/regmap/regcache-maple.c b/drivers/base/regmap/regcache-maple.c
index 34440e188f925..82d9410591654 100644
--- a/drivers/base/regmap/regcache-maple.c
+++ b/drivers/base/regmap/regcache-maple.c
@@ -296,16 +296,21 @@ static int regcache_maple_exit(struct regmap *map)
 	struct maple_tree *mt = map->cache;
 	MA_STATE(mas, mt, 0, UINT_MAX);
 	unsigned int *entry;
+	unsigned long flags;
 
 	/* if we've already been called then just return */
 	if (!mt)
 		return 0;
 
-	mas_lock(&mas);
+	/*
+	 * Register access may take the Maple lock from hard IRQ context, so
+	 * preserve its IRQ-safe lockdep state during teardown.
+	 */
+	mas_lock_irqsave(&mas, flags);
 	mas_for_each(&mas, entry, UINT_MAX)
 		kfree(entry);
 	__mt_destroy(mt);
-	mas_unlock(&mas);
+	mas_unlock_irqrestore(&mas, flags);
 
 	kfree(mt);
 	map->cache = NULL;
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index 0e929e7ac68aa..5592cd704cf04 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -195,9 +195,7 @@ int regcache_init(struct regmap *map, const struct regmap_config *config)
 	if (map->cache_ops->init) {
 		dev_dbg(map->dev, "Initializing %s cache\n",
 			map->cache_ops->name);
-		map->lock(map->lock_arg);
 		ret = map->cache_ops->init(map);
-		map->unlock(map->lock_arg);
 		if (ret)
 			goto err_free;
 	}
@@ -215,9 +213,7 @@ int regcache_init(struct regmap *map, const struct regmap_config *config)
 err_exit:
 	if (map->cache_ops->exit) {
 		dev_dbg(map->dev, "Destroying %s cache\n", map->cache_ops->name);
-		map->lock(map->lock_arg);
 		map->cache_ops->exit(map);
-		map->unlock(map->lock_arg);
 	}
 err_free:
 	kfree(map->reg_defaults);
@@ -241,9 +237,7 @@ void regcache_exit(struct regmap *map)
 	if (map->cache_ops->exit) {
 		dev_dbg(map->dev, "Destroying %s cache\n",
 			map->cache_ops->name);
-		map->lock(map->lock_arg);
 		map->cache_ops->exit(map);
-		map->unlock(map->lock_arg);
 	}
 }
 
diff --git a/include/linux/maple_tree.h b/include/linux/maple_tree.h
index ecbcc2b3e59a6..4300f7746f2dc 100644
--- a/include/linux/maple_tree.h
+++ b/include/linux/maple_tree.h
@@ -466,9 +466,13 @@ struct ma_wr_state {
 };
 
 #define mas_lock(mas)           spin_lock(&((mas)->tree->ma_lock))
+#define mas_lock_irqsave(mas, flags) \
+		spin_lock_irqsave(&((mas)->tree->ma_lock), flags)
 #define mas_lock_nested(mas, subclass) \
 		spin_lock_nested(&((mas)->tree->ma_lock), subclass)
 #define mas_unlock(mas)         spin_unlock(&((mas)->tree->ma_lock))
+#define mas_unlock_irqrestore(mas, flags) \
+		spin_unlock_irqrestore(&((mas)->tree->ma_lock), flags)
 
 /*
  * Special values for ma_state.node.
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 040/247] netlink: reset skb headers before unicast and multicast filtering
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (38 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 039/247] regmap: Drop map lock during cache init and exit Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 041/247] spi: tegra114: assert CS GPIO for every transfer in a message Greg Kroah-Hartman
                   ` (214 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Kyle Zeng, Paolo Abeni, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Kyle Zeng <kylebot@openai.com>

[ Upstream commit 8bf659bd54e1f00e34cf5244b1d289c506fa47c0 ]

Socket filters can use SKF_NET_OFF and SKF_LL_OFF to read relative to
an skb's network and MAC headers. Netlink producers may reserve
headroom without resetting those headers, allowing a receiving socket's
filter to read data before the initialized message.

For example, IWPM HELLO replies are allocated with dev_alloc_skb(),
which reserves NET_SKB_PAD bytes. An unprivileged NETLINK_RDMA user can
attach a classic socket filter and disclose this headroom through the
length of the delivered reply. The resets in netlink_dump() do not help
because IWPM sends a separately allocated skb through netlink_unicast().

Reset both headers before running the receiver's filter in unicast and
broadcast delivery, as is already done for dump skbs. This also covers
other netlink producers that reserve headroom without changing their
allocation or message-building code.

Fixes: b1153f29ee07 ("netlink: make socket filters work on netlink")
Assisted-by: LLM
Signed-off-by: Kyle Zeng <kylebot@openai.com>
Link: https://patch.msgid.link/20261006224232.50724-1-kylebot@openai.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/netlink/af_netlink.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index e250d4a3d0309..a0a8f185ccdeb 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1338,6 +1338,8 @@ int netlink_unicast(struct sock *ssk, struct sk_buff *skb,
 	if (netlink_is_kernel(sk))
 		return netlink_unicast_kernel(sk, skb, ssk);
 
+	skb_reset_network_header(skb);
+	skb_reset_mac_header(skb);
 	if (sk_filter(sk, skb)) {
 		err = skb->len;
 		kfree_skb(skb);
@@ -1472,6 +1474,8 @@ static void do_one_broadcast(struct sock *sk,
 		goto out;
 	}
 
+	skb_reset_network_header(p->skb2);
+	skb_reset_mac_header(p->skb2);
 	if (sk_filter(sk, p->skb2)) {
 		kfree_skb(p->skb2);
 		p->skb2 = NULL;
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 041/247] spi: tegra114: assert CS GPIO for every transfer in a message
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (39 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 040/247] netlink: reset skb headers before unicast and multicast filtering Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 042/247] nios2: fix __wsum type degradation in csum_fold() Greg Kroah-Hartman
                   ` (213 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Carlos Jones Jr, Mark Brown,
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Carlos Jones Jr <carlosjr.jones@analog.com>

[ Upstream commit 8980bc573ae2d2b9d86d76aeb86c76e1597070bf ]

The driver provides its own transfer_one_message() and therefore drives
the chip-select GPIO itself rather than through the SPI core. The GPIO is
asserted only in the is_first_of_msg path of
tegra_spi_setup_transfer_one(), but tegra_spi_transfer_end() deasserts it
whenever a transfer has cs_change set. For a multi-transfer message whose
earlier transfers request cs_change -- for example a register read that
sends the address in one transfer and clocks the data back in the next --
the CS GPIO is released after the first transfer and never re-asserted,
so the remaining transfers are clocked with chip-select inactive and the
peripheral never drives the bus.

This was observed with an ADIS16470 IMU (adis16475 driver), whose
register read is a two-transfer, cs_change-framed exchange: a logic
analyzer showed the data frame clocked with CS high, and the driver read
0 while the device drove 0x4056 on the wire.

Re-assert the CS GPIO for every transfer so that multi-transfer messages
keep chip-select active across the whole message. gpiod_set_value() is
idempotent and polarity-aware, so this is a no-op for the first transfer
and for messages that keep CS asserted throughout.

Fixes: 63c1440596ff ("spi: tegra114: add support for gpio based CS")
Signed-off-by: Carlos Jones Jr <carlosjr.jones@analog.com>
Link: https://patch.msgid.link/20261002085540.1625-1-carlosjr.jones@analog.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/spi/spi-tegra114.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index 5b8bd34e6bfd9..622bcaa0fe6e9 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -859,6 +859,13 @@ static u32 tegra_spi_setup_transfer_one(struct spi_device *spi,
 		command1 |= SPI_BIT_LENGTH(bits_per_word - 1);
 	}
 
+	/*
+	 * Re-assert the CS GPIO for every transfer: transfer_end() drops it
+	 * on cs_change, and the assert above only covers is_first_of_msg.
+	 */
+	if (spi_get_csgpiod(spi, 0))
+		gpiod_set_value(spi_get_csgpiod(spi, 0), 1);
+
 	return command1;
 }
 
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 042/247] nios2: fix __wsum type degradation in csum_fold()
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (40 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 041/247] spi: tegra114: assert CS GPIO for every transfer in a message Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 043/247] scsi: st: Save the visited block for the partition the drive is in Greg Kroah-Hartman
                   ` (212 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, kernel test robot, Keith Busch,
	Dinh Nguyen, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Keith Busch <kbusch@kernel.org>

[ Upstream commit b963f2345fa20417401c51a69dedb6a58eea33a9 ]

csum_fold() shifts a bitwise __wsum type, which sparse reports as
"restricted __wsum degrades to integer". Sparse only checks the body of
a static inline once something instantiates it, so this went unnoticed
until a recent block layer change added the first csum_fold() caller to
a file built on this architecture.

Force cast to a __u32 for the shift, as the other architectures do.

Fixes: eea9507a69d6 ("nios2: Library functions")
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202609222053.5gjiJjtb-lkp@intel.com/
Signed-off-by: Keith Busch <kbusch@kernel.org>
Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 arch/nios2/include/asm/checksum.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/nios2/include/asm/checksum.h b/arch/nios2/include/asm/checksum.h
index 69004e07a1ba3..b6b415ae17a08 100644
--- a/arch/nios2/include/asm/checksum.h
+++ b/arch/nios2/include/asm/checksum.h
@@ -27,7 +27,7 @@ static inline __sum16 csum_fold(__wsum sum)
 		"add	%0, %0, r8\n"
 		"nor	%0, %0, %0\n"
 		: "=r" (sum)
-		: "r" (sum << 16), "0" (sum)
+		: "r" ((__force u32)sum << 16), "0" (sum)
 		: "r8");
 	return (__force __sum16) sum;
 }
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 043/247] scsi: st: Save the visited block for the partition the drive is in
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (41 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 042/247] nios2: fix __wsum type degradation in csum_fold() Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 044/247] scsi: target: iscsi: Fix race in discovery auth updates Greg Kroah-Hartman
                   ` (211 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Laurence Oberman,
	Martin K. Petersen (Oracle), Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Laurence Oberman <loberman@redhat.com>

[ Upstream commit c9e9f024dd4f61f0f6636c9f2ed0830f87060e11 ]

set_location() saves the current tape location before switching
partitions, so that switch_partition() can return to it later. It reads
the location with READ POSITION but stores it in the st_partstat of
STp->partition, ignoring the partition the drive reports.

The two differ after a device reset. When the reset is recovered with
MTREW, MTSEEK or MTEOM, st_ioctl() sets STp->partition = 0 and calls
switch_partition() to return to STp->new_partition. A drive that was in
partition 1 is still there, so set_location() files the partition 1
position under partition 0. The next switch to partition 0 locates to
that block: if partition 0 holds less data, MTSETPART fails with EIO
(BLANK CHECK), otherwise the tape is silently positioned at the wrong
block.

IBM ULTRIUM-TD5 (LTO-5), LU reset in partition 1 at block 1025:

  st 12:0:0:0: [st0] Visited block 1025 for partition 0 saved.
  ...
  st 12:0:0:0: [st0] Setting block to 1025 and partition to 0.
  st 12:0:0:0: [st0] Error: 402, cmd: 2b 2 0 0 0 4
  st 12:0:0:0: [st0] Sense Key : Blank Check [current]
  st 12:0:0:0: [st0] Add. Sense: End-of-data detected

Store the location in the st_partstat of the partition reported by READ
POSITION. With the fix:

  st 12:0:0:0: [st0] Visited block 1025 for partition 1 saved.

This is a pre-existing issue. It was not caught when testing the recent
st reset series because the partition test was only run on scsi_debug:
on the LTO drive it was skipped, since can-partitions is off in the test
harness's stinit.conf, as is normal for LTO. scsi_debug hides the
problem because its emulated tape returns to the beginning of partition
0 on an LU reset. It was found while validating a backport of that
series to RHEL 9.8, when the partition tests were run on real hardware
with can-partitions enabled. The same failure then reproduced on
unmodified RHEL 9.8 and on upstream, and the fix makes the test pass on
v7.3-rc3 and RHEL 9.8 with an LTO-5.

The harness (https://gitlab.com/loberman/tapetest, test X03) now refuses
to silently skip the partition tests on hardware.

Fixes: 7081dc75df79 ("scsi: st: Restore some drive settings after reset")
Assisted-by: Claude
Signed-off-by: Laurence Oberman <loberman@redhat.com>
Link: https://patch.msgid.link/20261006164250.773840-1-loberman@redhat.com
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/scsi/st.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 3e982c166baf9..95da0d15e0490 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -3194,14 +3194,20 @@ static int set_location(struct scsi_tape *STp, unsigned int block, int partition
 	    partition >= ST_NBR_PARTITIONS)
 		return (-EINVAL);
 	if (partition != STp->partition) {
-		if (get_location(STp, &blk, &p, 1))
+		/*
+		 * Save the location for the partition the drive reports,
+		 * not for STp->partition: after a reset STp->partition may
+		 * not match the partition the drive is in.
+		 */
+		if (get_location(STp, &blk, &p, 1) ||
+		    p < 0 || p >= ST_NBR_PARTITIONS)
 			STps->last_block_valid = 0;
 		else {
-			STps->last_block_valid = 1;
-			STps->last_block_visited = blk;
+			STp->ps[p].last_block_valid = 1;
+			STp->ps[p].last_block_visited = blk;
 			DEBC_printk(STp, "Visited block %d for "
 				    "partition %d saved.\n",
-				    blk, STp->partition);
+				    blk, p);
 		}
 	}
 
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 044/247] scsi: target: iscsi: Fix race in discovery auth updates
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (42 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 043/247] scsi: st: Save the visited block for the partition the drive is in Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 045/247] ocfs2/dlm: Protect the recovery list during debugfs reads Greg Kroah-Hartman
                   ` (210 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Linfeng Sun, Mike Christie,
	Martin K. Petersen (Oracle), Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Linfeng Sun <linfeng.sun.dev@gmail.com>

[ Upstream commit e15b81f602edbdee39c335546f25486a1747f3f0 ]

Separate configfs opens can concurrently update the discovery AuthMethod
parameter. Both callers may free the same value in
iscsi_update_param_value(), causing a double-free.

Protect the lookup and replacement with the discovery TPG access lock,
as used by the other TPG configfs parameter updates.

Fixes: e48354ce078c ("iscsi-target: Add iSCSI fabric support for target v4.1")
Signed-off-by: Linfeng Sun <linfeng.sun.dev@gmail.com>
Reviewed-by: Mike Christie <michael.christie@oracle.com>
Link: https://patch.msgid.link/20260811124843.6817-1-linfeng.sun.dev@gmail.com
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/target/iscsi/iscsi_target_configfs.c | 26 ++++++++++++++------
 1 file changed, 19 insertions(+), 7 deletions(-)

diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c
index 88db94f382bb9..5e01ab65cec5f 100644
--- a/drivers/target/iscsi/iscsi_target_configfs.c
+++ b/drivers/target/iscsi/iscsi_target_configfs.c
@@ -1306,17 +1306,24 @@ static ssize_t iscsi_disc_enforce_discovery_auth_store(struct config_item *item,
 		return -EINVAL;
 	}
 
+	if (iscsit_get_tpg(discovery_tpg) < 0)
+		return -EINVAL;
+
 	param = iscsi_find_param_from_key(AUTHMETHOD,
 				discovery_tpg->param_list);
-	if (!param)
-		return -EINVAL;
+	if (!param) {
+		err = -EINVAL;
+		goto out;
+	}
 
 	if (op) {
 		/*
 		 * Reset the AuthMethod key to CHAP.
 		 */
-		if (iscsi_update_param_value(param, CHAP) < 0)
-			return -EINVAL;
+		if (iscsi_update_param_value(param, CHAP) < 0) {
+			err = -EINVAL;
+			goto out;
+		}
 
 		discovery_tpg->tpg_attrib.authentication = 1;
 		iscsit_global->discovery_acl.node_auth.enforce_discovery_auth = 1;
@@ -1327,8 +1334,10 @@ static ssize_t iscsi_disc_enforce_discovery_auth_store(struct config_item *item,
 		/*
 		 * Reset the AuthMethod key to CHAP,None
 		 */
-		if (iscsi_update_param_value(param, "CHAP,None") < 0)
-			return -EINVAL;
+		if (iscsi_update_param_value(param, "CHAP,None") < 0) {
+			err = -EINVAL;
+			goto out;
+		}
 
 		discovery_tpg->tpg_attrib.authentication = 0;
 		iscsit_global->discovery_acl.node_auth.enforce_discovery_auth = 0;
@@ -1337,7 +1346,10 @@ static ssize_t iscsi_disc_enforce_discovery_auth_store(struct config_item *item,
 			" Discovery TPG\n");
 	}
 
-	return count;
+	err = count;
+out:
+	iscsit_put_tpg(discovery_tpg);
+	return err;
 }
 
 CONFIGFS_ATTR(iscsi_disc_, enforce_discovery_auth);
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 045/247] ocfs2/dlm: Protect the recovery list during debugfs reads
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (43 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 044/247] scsi: target: iscsi: Fix race in discovery auth updates Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 046/247] samples: pidfd: fix userprogs typo Greg Kroah-Hartman
                   ` (209 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Cen Zhang, Joseph Qi,
	Christian Brauner (Amutable), Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Cen Zhang <zzzccc427@gmail.com>

[ Upstream commit 4c435828932bf46f29860e4a0375bcae101b778a ]

Recovery participant records must remain alive while debug_state_print()
walks reco.node_data and formats their fields. The formatter holds
dlm->spinlock, but the recovery participant list is protected by
dlm_reco_state_lock. In particular, dlm_destroy_recovery_area() detaches
the list under dlm_reco_state_lock and frees the detached records after
releasing it. A concurrent debugfs open can therefore read freed memory.

Protect the participant traversal and field reads in debug_state_print()
with dlm_reco_state_lock, matching the existing list writers. This also
serializes the traversal against list_add_tail() during recovery-area
initialization. Make the existing lock available to the debug code
through dlmcommon.h; the lock remains internal to the OCFS2 DLM module.

Release dlm->spinlock after formatting the other domain state and before
acquiring dlm_reco_state_lock, so the debug reader does not nest the two
locks. Leave recovery list insertion, detachment and freeing unchanged.

KASAN report as below:

    BUG: KASAN: slab-use-after-free in debug_state_open+0x1169/0x12d0
    Read of size 4 at addr ffff88810662ef80 by task dlm-state-stres/896

    CPU: 1 UID: 0 PID: 896 Comm: dlm-state-stres Not tainted 7.3.0-rc4-next-20260921-pmb-ocfs2-functional-v1+ #1 PREEMPT(lazy)
    Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
    Call Trace:
     <TASK>
     dump_stack_lvl+0x93/0xd0
     print_report+0xce/0x630
     ? debug_state_open+0x1169/0x12d0
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __virt_addr_valid+0x20e/0x420
     ? debug_state_open+0x1169/0x12d0
     kasan_report+0xe0/0x110
     ? debug_state_open+0x1169/0x12d0
     debug_state_open+0x1169/0x12d0
     ? __pfx_debug_state_open+0x10/0x10
     full_proxy_open_regular+0x193/0x310
     do_dentry_open+0x595/0x12d0
     ? __pfx_full_proxy_open_regular+0x10/0x10
     vfs_open_consume+0xd1/0x400
     ? srso_alias_return_thunk+0x5/0xfbef5
     path_openat+0x18d0/0x2020
     ? __pfx_path_openat+0x10/0x10
     do_file_open+0x21e/0x470
     ? __pfx_do_file_open+0x10/0x10
     ? _raw_spin_unlock+0x23/0x40
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? alloc_fd+0x3a6/0x6b0
     do_sys_openat2+0xf4/0x1b0
     ? __pfx_do_sys_openat2+0x10/0x10
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __fput+0x5b5/0xa60
     __x64_sys_openat+0x136/0x1e0
     ? __pfx___x64_sys_openat+0x10/0x10
     do_syscall_64+0x114/0x620
     entry_SYSCALL_64_after_hwframe+0x77/0x7f
    [Register dump omitted.]
     </TASK>

    Allocated by task 880:
     kasan_save_stack+0x33/0x60
     kasan_save_track+0x14/0x30
     __kasan_kmalloc+0xaa/0xb0
     __kmalloc_cache_noprof+0x28d/0x610
     dlm_remaster_locks+0x147/0x1d90
     dlm_do_recovery+0xde1/0x1580
     dlm_recovery_thread+0x109/0x300
     kthread+0x351/0x460
     ret_from_fork+0x659/0x940
     ret_from_fork_asm+0x1a/0x30

    Freed by task 880:
     kasan_save_stack+0x33/0x60
     kasan_save_track+0x14/0x30
     kasan_save_free_info+0x3b/0x60
     __kasan_slab_free+0x5f/0x80
     kfree+0x308/0x580
     dlm_destroy_recovery_area+0x285/0x460
     dlm_remaster_locks+0x17c4/0x1d90
     dlm_do_recovery+0xde1/0x1580
     dlm_recovery_thread+0x109/0x300
     kthread+0x351/0x460
     ret_from_fork+0x659/0x940
     ret_from_fork_asm+0x1a/0x30

    The buggy address belongs to the object at ffff88810662ef80
     which belongs to the cache kmalloc-32 of size 32
    The buggy address is located 0 bytes inside of
     freed 32-byte region [ffff88810662ef80, ffff88810662efa0)

    [Page and memory-state dumps omitted.]

Fixes: 007dce53a29c ("ocfs2/dlm: Dump the dlm state in a debugfs file")
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Link: https://patch.msgid.link/pm-ocfs2-objects-candidate-0049-v3-184e46c47f5283f06191@gmail.com
Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 fs/ocfs2/dlm/dlmcommon.h   | 2 ++
 fs/ocfs2/dlm/dlmdebug.c    | 5 ++++-
 fs/ocfs2/dlm/dlmrecovery.c | 2 +-
 3 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/fs/ocfs2/dlm/dlmcommon.h b/fs/ocfs2/dlm/dlmcommon.h
index 20f790a47484a..58b28dfa8d34e 100644
--- a/fs/ocfs2/dlm/dlmcommon.h
+++ b/fs/ocfs2/dlm/dlmcommon.h
@@ -435,6 +435,8 @@ enum {
 	DLM_DEREF_LOCKRES_DONE		= 522,
 };
 
+extern spinlock_t dlm_reco_state_lock;
+
 struct dlm_reco_node_data
 {
 	int state;
diff --git a/fs/ocfs2/dlm/dlmdebug.c b/fs/ocfs2/dlm/dlmdebug.c
index e62ed98df7de4..afaea6396b6f9 100644
--- a/fs/ocfs2/dlm/dlmdebug.c
+++ b/fs/ocfs2/dlm/dlmdebug.c
@@ -792,8 +792,11 @@ static int debug_state_print(struct dlm_ctxt *dlm, char *buf, int len)
 				 buf + out, len - out);
 	out += scnprintf(buf + out, len - out, "\n");
 
+	spin_unlock(&dlm->spinlock);
+
 	/* Recovery Node State: */
 	out += scnprintf(buf + out, len - out, "Recovery Node State:\n");
+	spin_lock(&dlm_reco_state_lock);
 	list_for_each_entry(node, &dlm->reco.node_data, list) {
 		switch (node->state) {
 		case DLM_RECO_NODE_DATA_INIT:
@@ -825,7 +828,7 @@ static int debug_state_print(struct dlm_ctxt *dlm, char *buf, int len)
 				node->node_num, state);
 	}
 
-	spin_unlock(&dlm->spinlock);
+	spin_unlock(&dlm_reco_state_lock);
 
 	return out;
 }
diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c
index 739da8bd7dbf0..591dd17ef4f5e 100644
--- a/fs/ocfs2/dlm/dlmrecovery.c
+++ b/fs/ocfs2/dlm/dlmrecovery.c
@@ -80,7 +80,7 @@ static int dlm_lockres_master_requery(struct dlm_ctxt *dlm,
 
 static u64 dlm_get_next_mig_cookie(void);
 
-static DEFINE_SPINLOCK(dlm_reco_state_lock);
+DEFINE_SPINLOCK(dlm_reco_state_lock);
 static DEFINE_SPINLOCK(dlm_mig_cookie_lock);
 static u64 dlm_mig_cookie = 1;
 
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 046/247] samples: pidfd: fix userprogs typo
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (44 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 045/247] ocfs2/dlm: Protect the recovery list during debugfs reads Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 047/247] pipe: preserve existing fasync readers on writer setup failure Greg Kroah-Hartman
                   ` (208 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Sasha Levin, Christian Brauner

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

[ Upstream commit f1365f97fb7498d805981102eee22d362ae643f2 ]

The Makefile adds pidfd-metadata to "usertprogs-always-y", which kbuild
does not know, so the sample has not been built since the conversion to
userprogs, even with CONFIG_SAMPLE_PIDFD=y.

Fix the variable name. pidfd-metadata.c builds without warnings with
gcc and clang for x86_64 and arm64.

Fixes: 60fb0b1239719 ("samples: pidfd: build sample program for target architecture")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Link: https://patch.msgid.link/20261011223358.2327625-14-sashal@kernel.org
Reviewed-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 samples/pidfd/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/samples/pidfd/Makefile b/samples/pidfd/Makefile
index 9754e2d81f70d..d82409f7061f3 100644
--- a/samples/pidfd/Makefile
+++ b/samples/pidfd/Makefile
@@ -1,4 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
-usertprogs-always-y += pidfd-metadata
+userprogs-always-y += pidfd-metadata
 
 userccflags += -I usr/include
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 047/247] pipe: preserve existing fasync readers on writer setup failure
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (45 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 046/247] samples: pidfd: fix userprogs typo Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 048/247] tracing: probes: error if BTF is required but unavailable Greg Kroah-Hartman
                   ` (207 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Kyle Zeng,
	Christian Brauner (Amutable), Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Kyle Zeng <kylebot@openai.com>

[ Upstream commit 40bb03d3ea6f6a915218508819ecc4d7a7fa260d ]

F_SETFL and FIOASYNC decide whether to invoke ->fasync() before
pipe_fasync() takes pipe->mutex. Two enables of one O_RDWR FIFO can
therefore both enter the callback.

fasync_helper() allocates before checking for an existing entry. If the
first enable installs both entries, a second enable can update the
reader entry and then fail the allocation for the writer entry. The
error path removes the pre-existing reader entry, clearing FASYNC while
the writer entry remains registered. __fput() then skips ->fasync(), so a
later pipe notification can dereference the freed file or its f_owner.
An unprivileged memory-pressure reproducer triggers a KASAN
slab-use-after-free in send_sigio() through this path.

Keep the reader helper's result and undo the registration only if this
call added it. The pipe mutex serializes changes to both lists, so a
failed new registration still removes its reader, while a failed
duplicate preserves the existing registrations and FASYNC. Successful
duplicate enables continue to update fa_fd as before.

Fixes: 76398425bb06 ("Move FASYNC bit handling to f_op->fasync()")
Signed-off-by: Kyle Zeng <kylebot@openai.com>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 fs/pipe.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/fs/pipe.c b/fs/pipe.c
index 12b22c2723b7e..d2e75e726e63b 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -753,9 +753,11 @@ pipe_fasync(int fd, struct file *filp, int on)
 	if (filp->f_mode & FMODE_READ)
 		retval = fasync_helper(fd, filp, on, &pipe->fasync_readers);
 	if ((filp->f_mode & FMODE_WRITE) && retval >= 0) {
+		int read_ret = retval;
+
 		retval = fasync_helper(fd, filp, on, &pipe->fasync_writers);
-		if (retval < 0 && (filp->f_mode & FMODE_READ))
-			/* this can happen only if on == T */
+		/* Undo only a reader entry added by this call. */
+		if (retval < 0 && read_ret > 0)
 			fasync_helper(-1, filp, 0, &pipe->fasync_readers);
 	}
 	mutex_unlock(&pipe->mutex);
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 048/247] tracing: probes: error if BTF is required but unavailable
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (46 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 047/247] pipe: preserve existing fasync readers on writer setup failure Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 049/247] scsi: libsas: Fix SMP IO deadlock during HA resume Greg Kroah-Hartman
                   ` (206 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Martin Kaiser, Steven Rostedt,
	Masami Hiramatsu (Google), Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Martin Kaiser <martin@kaiser.cx>

[ Upstream commit 66c658033d842bb75f81f20aaa4a378fe47be1a1 ]

traceprobe_expand_meta_args expands probe arguments based on BTF info.

Return an error if we have arguments that need expanding but BTF is not
supported.

The params variable is now unused, it can be removed.

Link: https://lore.kernel.org/all/20261014083838.31020-1-martin@kaiser.cx/

Fixes: d157d7694460 ("tracing/probes: Support BTF field access from $retval")
Signed-off-by: Martin Kaiser <martin@kaiser.cx>
Reviewed-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 kernel/trace/trace_probe.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c
index 95201c0daa8f0..c7e4758505f26 100644
--- a/kernel/trace/trace_probe.c
+++ b/kernel/trace/trace_probe.c
@@ -1709,7 +1709,6 @@ const char **traceprobe_expand_meta_args(int argc, const char *argv[],
 					 int *new_argc, char *buf, int bufsize,
 					 struct traceprobe_parse_context *ctx)
 {
-	const struct btf_param *params = NULL;
 	int i, j, n, used, ret, args_idx = -1;
 	const char **new_argv = NULL;
 
@@ -1727,7 +1726,7 @@ const char **traceprobe_expand_meta_args(int argc, const char *argv[],
 		if (args_idx != -1) {
 			/* $arg* requires BTF info */
 			trace_probe_log_err(0, NOSUP_BTFARG);
-			return (const char **)params;
+			return ERR_PTR(-EOPNOTSUPP);
 		}
 		*new_argc = argc;
 		return NULL;
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 049/247] scsi: libsas: Fix SMP IO deadlock during HA resume
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (47 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 048/247] tracing: probes: error if BTF is required but unavailable Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 050/247] netlink: avoid hashing the network namespace pointer Greg Kroah-Hartman
                   ` (205 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Xingui Yang, John Garry,
	Martin K. Petersen (Oracle), Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Xingui Yang <yangxingui@huawei.com>

[ Upstream commit 81e097a064b28b4a1f6ca1a8b433e659c1bd64c0 ]

smp_execute_task_sg() calls pm_runtime_get_sync() on the host before
issuing an SMP command. When that command is itself issued from the HA
resume path, the get_sync() deadlocks: it waits for the ongoing resume
(the device is RPM_RESUMING), while the resume is blocked in
sas_drain_work() waiting for that same SMP IO to complete.

The deadlock needs an expander-attached SATA disk. During
sas_resume_ha() -> sas_drain_work(), DISCE_RESUME -> sas_resume_sata()
-> ata_sas_port_resume() requests ATA_EH_RESET, and the hard reset for
such a disk is done via SMP PHY CONTROL (sas_ata_hard_reset() ->
sas_phy_reset() -> sas_smp_phy_control() ->
smp_execute_task_sg()). Direct-attached SATA resets through
lldd_control_phy() and SSP devices use TMFs, so neither hits this.

Replace the get_sync()/put_sync() pair with
pm_runtime_get_noresume()/pm_runtime_put(). smp_execute_task_sg() only
needs to hold off autosuspend while the SMP is in flight, and it must
not try to resume the host: a sync resume issued from the HA resume path
itself is what deadlocks, and by the time sas_resume_ha() runs, hw_init
has already reinitialized the hardware, so the device is accessible
without one.

The usage reference is still required. Discovery work normally runs
inside an event worker's PM reference, taken at sas_notify_port_event()
notify time and held until the handler has flushed the disco
queue. sas_rediscover_ex_phy() however requeues DISCE_REVALIDATE_DOMAIN
from within the revalidation worker itself, and flush_workqueue() does
not wait for work items queued during execution, so that chained
revalidation runs with no outer PM reference - without the
get_noresume(), its SMP could race autosuspend.

For the BSG path, sas_smp_handler() is the only caller which may find
the host autosuspended: expander SMP requests do not go through any SCSI
device request queue, so nothing else in that path holds the host
awake. Resume it there with pm_runtime_resume_and_get() and check the
result.

Fixes: 3dbbbf656b850 ("scsi: libsas: Fix HA resume deadlock and hisi_sas disk-wake race")
Signed-off-by: Xingui Yang <yangxingui@huawei.com>
Reviewed-by: John Garry <john.garry@linux.dev>
Link: https://patch.msgid.link/20260928040234.992912-1-yangxingui@huawei.com
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/scsi/libsas/sas_expander.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index 2b8004eb6f1b3..165c0c588c68b 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -62,7 +62,11 @@ static int smp_execute_task_sg(struct domain_device *dev,
 		to_sas_internal(dev->port->ha->shost->transportt);
 	struct sas_ha_struct *ha = dev->port->ha;
 
-	pm_runtime_get_sync(ha->dev);
+	/*
+	 * Non-blocking: a sync resume here would deadlock against
+	 * sas_drain_work() during HA resume.
+	 */
+	pm_runtime_get_noresume(ha->dev);
 	mutex_lock(&dev->ex_dev.cmd_mutex);
 	for (retry = 0; retry < 3; retry++) {
 		if (test_bit(SAS_DEV_GONE, &dev->state)) {
@@ -135,7 +139,7 @@ static int smp_execute_task_sg(struct domain_device *dev,
 		}
 	}
 	mutex_unlock(&dev->ex_dev.cmd_mutex);
-	pm_runtime_put_sync(ha->dev);
+	pm_runtime_put(ha->dev);
 
 	BUG_ON(retry == 3 && task != NULL);
 	sas_free_task(task);
@@ -2165,6 +2169,11 @@ void sas_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
 		goto out;
 	}
 
+	/* The host may have autosuspended, resume it here. */
+	ret = pm_runtime_resume_and_get(dev->port->ha->dev);
+	if (ret)
+		goto out;
+
 	ret = smp_execute_task_sg(dev, job->request_payload.sg_list,
 			job->reply_payload.sg_list);
 	if (ret >= 0) {
@@ -2172,6 +2181,7 @@ void sas_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
 		rcvlen = job->reply_payload.payload_len - ret;
 		ret = 0;
 	}
+	pm_runtime_put(dev->port->ha->dev);
 
 out:
 	bsg_job_done(job, ret, rcvlen);
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 050/247] netlink: avoid hashing the network namespace pointer
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (48 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 049/247] scsi: libsas: Fix SMP IO deadlock during HA resume Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 051/247] net: bcmgenet: unshare the skb before writing the control block Greg Kroah-Hartman
                   ` (204 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Kyle Zeng, Simon Horman,
	Eric Dumazet, Paolo Abeni, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Kyle Zeng <kylebot@openai.com>

[ Upstream commit f88bb3606e4bd11ee035b682cddc2999e604609a ]

The netlink rhashtable key includes a raw struct net pointer and a
user-controlled port ID. Both /proc/net/netlink and socket diagnostics
expose the table's bucket order. By binding and rebinding chosen
NETLINK_USERSOCK port IDs, an unprivileged reader can distinguish equal
buckets and recover the low bits of the Jenkins hash. Its 32-bit seed
and the limited set of kernel-image slides can then be searched offline
to recover the address of init_net.

Use the namespace's unique, non-address net_cookie in the comparison
key instead. It is assigned before the per-net initializers run and
remains unchanged for the namespace's lifetime. The lookup key and
object hash are still built by netlink_compare_arg_init(), keeping
lookup, insertion, removal and rehashing consistent while preserving
namespace separation. Neither public table walker needs to change.

Reading the socket's namespace cookie in netlink_compare() is safe
under RCU, including during namespace teardown. netlink_release()
removes the socket from the hash table and defers its final put with
call_rcu(). cleanup_net() runs the per-net exit methods and waits for
outstanding RCU callbacks with rcu_barrier() before freeing namespace
storage.

Unlike ns.ns_id, net_cookie is also available and initialized during
setup_net() in older stable kernels, making the change straightforward
to backport to v5.15 and later.

Fixes: c428ecd1a21f ("netlink: Move namespace into hash key")
Assisted-by: LLM
Signed-off-by: Kyle Zeng <kylebot@openai.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Reviewed-by: Eric Dumazet <edumazet@kernel.org>
Link: https://patch.msgid.link/20261008011359.63727-2-kylebot@openai.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/netlink/af_netlink.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index a0a8f185ccdeb..7e1c087a98647 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -463,7 +463,7 @@ netlink_unlock_table(void)
 
 struct netlink_compare_arg
 {
-	possible_net_t pnet;
+	u64 net_cookie;
 	u32 portid;
 };
 
@@ -478,14 +478,14 @@ static inline int netlink_compare(struct rhashtable_compare_arg *arg,
 	const struct netlink_sock *nlk = ptr;
 
 	return nlk->portid != x->portid ||
-	       !net_eq(sock_net(&nlk->sk), read_pnet(&x->pnet));
+	       sock_net(&nlk->sk)->net_cookie != x->net_cookie;
 }
 
 static void netlink_compare_arg_init(struct netlink_compare_arg *arg,
 				     struct net *net, u32 portid)
 {
 	memset(arg, 0, sizeof(*arg));
-	write_pnet(&arg->pnet, net);
+	arg->net_cookie = net->net_cookie;
 	arg->portid = portid;
 }
 
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 051/247] net: bcmgenet: unshare the skb before writing the control block
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (49 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 050/247] netlink: avoid hashing the network namespace pointer Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 052/247] net/ipv6: Introduce payload_len helpers Greg Kroah-Hartman
                   ` (203 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Nicolai Buchwitz, Florian Fainelli,
	Paolo Abeni, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Nicolai Buchwitz <nb@tipi-net.de>

[ Upstream commit 89771ce4f8f67dcffae561b2ccac95c0f6e3aa01 ]

bcmgenet stores first_cb, last_cb and bytes_sent in the skb control
block and reads them back on completion to free the skb and credit BQL.
ether_setup() leaves IFF_TX_SKB_SHARING set, so the stack can resubmit
a shared skb that is still in the ring. The next transmit overwrites
last_cb, so the earlier slots complete without crediting their bytes
and BQL stalls the queue until the watchdog resets it.

Unshare the skb before writing the control block.

Reproduce with pktgen in clone_skb mode, which hands the driver the same
skb while earlier copies are still in the ring:

  modprobe pktgen
  pg=/proc/net/pktgen
  echo "add_device eth0" > $pg/kpktgend_0
  echo "dst_mac AA:BB:CC:DD:EE:FF" > $pg/eth0
  echo "dst 192.0.2.1" > $pg/eth0
  echo "clone_skb 8" > $pg/eth0
  echo "count 0" > $pg/eth0
  echo start > $pg/pgctrl &
  sleep 5
  echo stop > $pg/pgctrl
  wait
  cat /sys/class/net/eth0/queues/tx-0/byte_queue_limits/inflight

inflight stays nonzero on the now idle queue. clone_skb 0 leaves it at
zero.

Fixes: f48bed16a756 ("net: bcmgenet: Free skb after last Tx frag")
Signed-off-by: Nicolai Buchwitz <nb@tipi-net.de>
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
Link: https://patch.msgid.link/20261009-nb-genet-shared-skb-net-v1-1-c6d0a841977d@tipi-net.de
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/net/ethernet/broadcom/genet/bcmgenet.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
index 7da4a2114a771..0402e8f69c6fa 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -2095,6 +2095,16 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)
 		goto out;
 	}
 
+	/* We store Tx state in the control block, so the skb must not be
+	 * shared, but ether_setup() leaves IFF_TX_SKB_SHARING set.
+	 */
+	skb = skb_share_check(skb, GFP_ATOMIC);
+	if (!skb) {
+		BCMGENET_STATS64_INC((&ring->stats64), dropped);
+		ret = NETDEV_TX_OK;
+		goto out;
+	}
+
 	/* Retain how many bytes will be sent on the wire, without TSB inserted
 	 * by transmit checksum offload
 	 */
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 052/247] net/ipv6: Introduce payload_len helpers
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (50 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 051/247] net: bcmgenet: unshare the skb before writing the control block Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 053/247] calipso: keep BIG TCP payload_len in calipso_skbuff_setattr() Greg Kroah-Hartman
                   ` (202 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Alice Mikityanska, Paolo Abeni,
	Eric Dumazet, Jakub Kicinski, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Alice Mikityanska <alice@isovalent.com>

[ Upstream commit b2936b4fd56294e49d6c8e9152ea6c4982757c7d ]

The next commits will transition away from using the hop-by-hop
extension header to encode packet length for BIG TCP. Add wrappers
around ip6->payload_len that return the actual value if it's non-zero,
and calculate it from skb->len if payload_len is set to zero (and a
symmetrical setter).

The new helpers are used wherever the surrounding code supports the
hop-by-hop jumbo header for BIG TCP IPv6, or the corresponding IPv4 code
uses skb_ip_totlen (e.g., in include/net/netfilter/nf_tables_ipv6.h).

No behavioral change in this commit.

Signed-off-by: Alice Mikityanska <alice@isovalent.com>
Acked-by: Paolo Abeni <pabeni@redhat.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20260205133925.526371-2-alice.kernel@fastmail.im
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Stable-dep-of: 8070ed578b6b ("calipso: keep BIG TCP payload_len in calipso_skbuff_setattr()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 include/linux/ipv6.h                       | 22 ++++++++++++++++++++++
 include/net/ipv6.h                         |  2 --
 include/net/netfilter/nf_tables_ipv6.h     |  4 ++--
 net/bridge/br_netfilter_ipv6.c             |  2 +-
 net/bridge/netfilter/nf_conntrack_bridge.c |  4 ++--
 net/ipv6/ip6_input.c                       |  2 +-
 net/ipv6/ip6_offload.c                     |  7 +++----
 net/ipv6/output_core.c                     |  7 +------
 net/netfilter/ipvs/ip_vs_xmit.c            |  2 +-
 net/netfilter/nf_conntrack_ovs.c           |  2 +-
 net/netfilter/nf_log_syslog.c              |  2 +-
 net/sched/sch_cake.c                       |  2 +-
 12 files changed, 36 insertions(+), 22 deletions(-)

diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index ad5f09765e0c7..6f3c5d4049e24 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -125,6 +125,28 @@ static inline unsigned int ipv6_transport_len(const struct sk_buff *skb)
 	       skb_network_header_len(skb);
 }
 
+static inline unsigned int
+ipv6_payload_len(const struct sk_buff *skb, const struct ipv6hdr *ip6)
+{
+	u32 len = ntohs(ip6->payload_len);
+
+	return (len || !skb_is_gso(skb) || !skb_is_gso_tcp(skb)) ?
+		len :
+		skb->len - skb_network_offset(skb) - sizeof(struct ipv6hdr);
+}
+
+static inline unsigned int skb_ipv6_payload_len(const struct sk_buff *skb)
+{
+	return ipv6_payload_len(skb, ipv6_hdr(skb));
+}
+
+#define IPV6_MAXPLEN		65535
+
+static inline void ipv6_set_payload_len(struct ipv6hdr *ip6, unsigned int len)
+{
+	ip6->payload_len = len <= IPV6_MAXPLEN ? htons(len) : 0;
+}
+
 /* 
    This structure contains results of exthdrs parsing
    as offsets from skb->nh.
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 3f3e312bced4f..e87eb9769516a 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -25,8 +25,6 @@ struct ip_tunnel_info;
 
 #define SIN6_LEN_RFC2133	24
 
-#define IPV6_MAXPLEN		65535
-
 /*
  *	NextHeader field of IPv6 header
  */
diff --git a/include/net/netfilter/nf_tables_ipv6.h b/include/net/netfilter/nf_tables_ipv6.h
index a0633eeaec977..c53ac00bb974d 100644
--- a/include/net/netfilter/nf_tables_ipv6.h
+++ b/include/net/netfilter/nf_tables_ipv6.h
@@ -42,7 +42,7 @@ static inline int __nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt)
 	if (ip6h->version != 6)
 		return -1;
 
-	pkt_len = ntohs(ip6h->payload_len);
+	pkt_len = ipv6_payload_len(pkt->skb, ip6h);
 	skb_len = pkt->skb->len - skb_network_offset(pkt->skb);
 	if (pkt_len + sizeof(*ip6h) > skb_len)
 		return -1;
@@ -86,7 +86,7 @@ static inline int nft_set_pktinfo_ipv6_ingress(struct nft_pktinfo *pkt)
 	if (ip6h->version != 6)
 		goto inhdr_error;
 
-	pkt_len = ntohs(ip6h->payload_len);
+	pkt_len = ipv6_payload_len(pkt->skb, ip6h);
 	if (pkt_len + sizeof(*ip6h) > pkt->skb->len) {
 		idev = __in6_dev_get(nft_in(pkt));
 		__IP6_INC_STATS(nft_net(pkt), idev, IPSTATS_MIB_INTRUNCATEDPKTS);
diff --git a/net/bridge/br_netfilter_ipv6.c b/net/bridge/br_netfilter_ipv6.c
index e0421eaa3abc7..76ce70b4e7f3b 100644
--- a/net/bridge/br_netfilter_ipv6.c
+++ b/net/bridge/br_netfilter_ipv6.c
@@ -58,7 +58,7 @@ int br_validate_ipv6(struct net *net, struct sk_buff *skb)
 	if (hdr->version != 6)
 		goto inhdr_error;
 
-	pkt_len = ntohs(hdr->payload_len);
+	pkt_len = ipv6_payload_len(skb, hdr);
 	if (hdr->nexthdr == NEXTHDR_HOP && nf_ip6_check_hbh_len(skb, &pkt_len))
 		goto drop;
 
diff --git a/net/bridge/netfilter/nf_conntrack_bridge.c b/net/bridge/netfilter/nf_conntrack_bridge.c
index cfa8091102426..b17962672ebfc 100644
--- a/net/bridge/netfilter/nf_conntrack_bridge.c
+++ b/net/bridge/netfilter/nf_conntrack_bridge.c
@@ -234,7 +234,7 @@ static int nf_ct_br_ipv6_check(const struct sk_buff *skb)
 	if (hdr->version != 6)
 		return -1;
 
-	len = ntohs(hdr->payload_len) + sizeof(struct ipv6hdr) + nhoff;
+	len = ipv6_payload_len(skb, hdr) + sizeof(struct ipv6hdr) + nhoff;
 	if (skb->len < len)
 		return -1;
 
@@ -274,7 +274,7 @@ static unsigned int nf_ct_bridge_pre(void *priv, struct sk_buff *skb,
 		if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
 			return NF_ACCEPT;
 
-		len = sizeof(struct ipv6hdr) + ntohs(ipv6_hdr(skb)->payload_len);
+		len = sizeof(struct ipv6hdr) + skb_ipv6_payload_len(skb);
 		if (pskb_trim_rcsum(skb, len))
 			return NF_ACCEPT;
 
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index f0a98c61a087a..54fc4b0eb57ba 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -262,7 +262,7 @@ static struct sk_buff *ip6_rcv_core(struct sk_buff *skb, struct net_device *dev,
 	skb->transport_header = skb->network_header + sizeof(*hdr);
 	IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr);
 
-	pkt_len = ntohs(hdr->payload_len);
+	pkt_len = ipv6_payload_len(skb, hdr);
 
 	/* pkt_len may be zero if Jumbo payload option is present */
 	if (pkt_len || hdr->nexthdr != NEXTHDR_HOP) {
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
index fce91183797a6..6762ce7909c8a 100644
--- a/net/ipv6/ip6_offload.c
+++ b/net/ipv6/ip6_offload.c
@@ -372,12 +372,11 @@ INDIRECT_CALLABLE_SCOPE int ipv6_gro_complete(struct sk_buff *skb, int nhoff)
 		hop_jumbo->jumbo_payload_len = htonl(payload_len + hoplen);
 
 		iph->nexthdr = NEXTHDR_HOP;
-		iph->payload_len = 0;
-	} else {
-		iph = (struct ipv6hdr *)(skb->data + nhoff);
-		iph->payload_len = htons(payload_len);
 	}
 
+	iph = (struct ipv6hdr *)(skb->data + nhoff);
+	ipv6_set_payload_len(iph, payload_len);
+
 	nhoff += sizeof(*iph) + ipv6_exthdrs_len(iph, &ops);
 	if (WARN_ON(!ops || !ops->callbacks.gro_complete))
 		goto out;
diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c
index d21fe27fe21e3..4396a6b58b607 100644
--- a/net/ipv6/output_core.c
+++ b/net/ipv6/output_core.c
@@ -123,12 +123,7 @@ EXPORT_SYMBOL(ip6_dst_hoplimit);
 
 int __ip6_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)
 {
-	int len;
-
-	len = skb->len - sizeof(struct ipv6hdr);
-	if (len > IPV6_MAXPLEN)
-		len = 0;
-	ipv6_hdr(skb)->payload_len = htons(len);
+	ipv6_set_payload_len(ipv6_hdr(skb), skb->len - sizeof(struct ipv6hdr));
 	IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr);
 
 	/* if egress device is enslaved to an L3 master device pass the
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
index e0c2820be57ee..9589abea2f034 100644
--- a/net/netfilter/ipvs/ip_vs_xmit.c
+++ b/net/netfilter/ipvs/ip_vs_xmit.c
@@ -985,7 +985,7 @@ ip_vs_prepare_tunneled_skb(struct sk_buff *skb, int skb_af,
 		*next_protocol = IPPROTO_IPV6;
 		if (payload_len)
 			*payload_len =
-				ntohs(old_ipv6h->payload_len) +
+				ipv6_payload_len(skb, old_ipv6h) +
 				sizeof(*old_ipv6h);
 		old_dsfield = ipv6_get_dsfield(old_ipv6h);
 		*ttl = old_ipv6h->hop_limit;
diff --git a/net/netfilter/nf_conntrack_ovs.c b/net/netfilter/nf_conntrack_ovs.c
index 068e9489e1c27..a6988eeb15797 100644
--- a/net/netfilter/nf_conntrack_ovs.c
+++ b/net/netfilter/nf_conntrack_ovs.c
@@ -121,7 +121,7 @@ int nf_ct_skb_network_trim(struct sk_buff *skb, int family)
 		len = skb_ip_totlen(skb);
 		break;
 	case NFPROTO_IPV6:
-		len = ntohs(ipv6_hdr(skb)->payload_len);
+		len = skb_ipv6_payload_len(skb);
 		if (ipv6_hdr(skb)->nexthdr == NEXTHDR_HOP) {
 			int err = nf_ip6_check_hbh_len(skb, &len);
 
diff --git a/net/netfilter/nf_log_syslog.c b/net/netfilter/nf_log_syslog.c
index de51b15cf53d9..e2c109d5f069c 100644
--- a/net/netfilter/nf_log_syslog.c
+++ b/net/netfilter/nf_log_syslog.c
@@ -562,7 +562,7 @@ dump_ipv6_packet(struct net *net, struct nf_log_buf *m,
 
 	/* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */
 	nf_log_buf_add(m, "LEN=%zu TC=%u HOPLIMIT=%u FLOWLBL=%u ",
-		       ntohs(ih->payload_len) + sizeof(struct ipv6hdr),
+		       ipv6_payload_len(skb, ih) + sizeof(struct ipv6hdr),
 		       (ntohl(*(__be32 *)ih) & 0x0ff00000) >> 20,
 		       ih->hop_limit,
 		       (ntohl(*(__be32 *)ih) & 0x000fffff));
diff --git a/net/sched/sch_cake.c b/net/sched/sch_cake.c
index a60aae42398a3..62390153abccc 100644
--- a/net/sched/sch_cake.c
+++ b/net/sched/sch_cake.c
@@ -1263,7 +1263,7 @@ static struct sk_buff *cake_ack_filter(struct cake_sched_data *q,
 			    ipv6_addr_cmp(&ipv6h_check->daddr, &ipv6h->daddr))
 				continue;
 
-			seglen = ntohs(ipv6h_check->payload_len);
+			seglen = ipv6_payload_len(skb, ipv6h_check);
 		} else {
 			continue;
 		}
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 053/247] calipso: keep BIG TCP payload_len in calipso_skbuff_setattr()
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (51 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 052/247] net/ipv6: Introduce payload_len helpers Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 054/247] gpiolib: fix memory leak in gpiod_set_array_value_complex() on error paths Greg Kroah-Hartman
                   ` (201 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Eric Dumazet, Wang Zhan,
	Joas Antonio dos Santos, Paul Moore, Paolo Abeni, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Joas Antonio dos Santos <joasantonio108@gmail.com>

[ Upstream commit 8070ed578b6b9134e045627fb745c887a806d46e ]

calipso_skbuff_setattr() adjusts payload_len by the length of the
option it inserts or resizes:

	payload = ntohs(ip6_hdr->payload_len);
	ip6_hdr->payload_len = htons(payload + len_delta);

GRO can build BIG TCP packets larger than IPV6_MAXPLEN, and stores
payload_len == 0 for them; ipv6_payload_len() then falls back to
skb->len.  For such a packet forwarded to a destination mapped to
CALIPSO, the code above writes len_delta (or 65536 + len_delta when
shrinking) into payload_len, and ipv6_payload_len() no longer falls
back to skb->len.  nf_tables, conntrack and sch_cake rely on it.

The same arithmetic also wraps when a packet grows past IPV6_MAXPLEN,
and a BIG TCP packet that shrinks below IPV6_MAXPLEN should get its
real length back.

Set payload_len from the skb length with ipv6_set_payload_len(), which
stores 0 above IPV6_MAXPLEN and the real length otherwise, as
ipv6_gro_complete() does.  The network header was just reset to
skb->data, so skb->len - sizeof(*ip6_hdr) is the payload length.

Tested on one kernel (arm64, QEMU) with SELinux permissive, a minimal
mdp-generated policy (network_peer_controls=1), "netlabelctl calipso
add pass doi:16" and a NetLabel mapping of fd00:2::/64 to CALIPSO
DOI 16.  calipso_skbuff_setattr() was called through
netlbl_skbuff_setattr() from a test-only debugfs hook (not part of
this patch) adding a level-only label; payload_len after the call:

  case                         before fix   after fix   real length
  1000, unlabeled                    1016        1016          1016
  70000 GSO, payload_len 0             16           0         70016
  65530 GSO, grows past MAXPLEN        10           0         65546
  65540 GSO with a 24 byte hop
  header, shrinks below MAXPLEN     65528       65532         65532
  1000 with a 24 byte hop header      992         992           992

(0 means ipv6_payload_len() returns the real length.)  On the forward
path, with a client injecting unlabeled UDP through a router to a
server, the router adds the CALIPSO option and the server delivers all
datagrams (Udp6InDatagrams 5, Ip6InTruncatedPkts 0) with this patch.

Fixes: 81fbc812132c ("ipv6/gro: insert temporary HBH/jumbo header")
Suggested-by: Eric Dumazet <edumazet@kernel.org>
Suggested-by: Wang Zhan <wang.zhan@smartx.com>
Signed-off-by: Joas Antonio dos Santos <joasantonio108@gmail.com>
Assisted-by: Claude:claude-opus-5-5
Reviewed-by: Wang Zhan <wang.zhan@smartx.com>
Acked-by: Paul Moore <paul@paul-moore.com>
Link: https://patch.msgid.link/179156155963.36253.400481753322266658@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/ipv6/calipso.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/net/ipv6/calipso.c b/net/ipv6/calipso.c
index f5cc02ea3092d..3ab22f9b416ec 100644
--- a/net/ipv6/calipso.c
+++ b/net/ipv6/calipso.c
@@ -1319,7 +1319,7 @@ static int calipso_skbuff_setattr(struct sk_buff *skb,
 	struct ipv6hdr *ip6_hdr;
 	struct ipv6_opt_hdr *hop;
 	unsigned char buf[CALIPSO_MAX_BUFFER];
-	int len_delta, new_end, pad, payload;
+	int len_delta, new_end, pad;
 	unsigned int start, end;
 
 	ip6_hdr = ipv6_hdr(skb);
@@ -1358,8 +1358,8 @@ static int calipso_skbuff_setattr(struct sk_buff *skb,
 			sizeof(*ip6_hdr) + start);
 		skb_reset_network_header(skb);
 		ip6_hdr = ipv6_hdr(skb);
-		payload = ntohs(ip6_hdr->payload_len);
-		ip6_hdr->payload_len = htons(payload + len_delta);
+		/* 0 above IPV6_MAXPLEN (BIG TCP), the real length otherwise */
+		ipv6_set_payload_len(ip6_hdr, skb->len - sizeof(*ip6_hdr));
 	}
 
 	hop = (struct ipv6_opt_hdr *)(ip6_hdr + 1);
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 054/247] gpiolib: fix memory leak in gpiod_set_array_value_complex() on error paths
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (52 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 053/247] calipso: keep BIG TCP payload_len in calipso_skbuff_setattr() Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 055/247] gpio: mxc: use lock guards for the generic GPIO chip lock Greg Kroah-Hartman
                   ` (200 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Sashiko, Kent Gibson,
	Bartosz Golaszewski, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Kent Gibson <warthog618@gmail.com>

[ Upstream commit c28846ca1ac6134881114d272314623c8433e372 ]

A drive-by review by Sashiko reports that, after a failed call to
gpiochip_set_multiple(), gpiod_set_array_value() returns abruptly,
bypassing the freeing of possibly alloced bitmaps, potentially leaking
memory. It is an unlikely error path, but is possible.

Defer the return code check until after the bitmap_free() block.

Fixes: 9b407312755f ("gpiolib: rework the wrapper around gpio_chip::set_multiple()")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Link: https://lore.kernel.org/linux-gpio/sashiko-outbox-168233@kernel.org/
Signed-off-by: Kent Gibson <warthog618@gmail.com>
Link: https://patch.msgid.link/20261015025749.47039-1-warthog618@gmail.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/gpio/gpiolib.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 144f1e174c545..bffdaa91d86c5 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -3578,16 +3578,17 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep,
 		} while ((i < array_size) &&
 			 gpio_device_chip_cmp(desc_array[i]->gdev, guard.gc));
 		/* push collected bits to outputs */
-		if (count != 0) {
+		ret = 0;
+		if (count != 0)
 			ret = gpiochip_set_multiple(guard.gc, mask, bits);
-			if (ret)
-				return ret;
-		}
 
 		if (mask != fastpath_mask)
 			bitmap_free(mask);
 		if (bits != fastpath_bits)
 			bitmap_free(bits);
+
+		if (ret)
+			return ret;
 	}
 	return 0;
 }
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 055/247] gpio: mxc: use lock guards for the generic GPIO chip lock
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (53 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 054/247] gpiolib: fix memory leak in gpiod_set_array_value_complex() on error paths Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 056/247] gpio: mxc: fix both_edges bit operations Greg Kroah-Hartman
                   ` (199 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Linus Walleij, Bartosz Golaszewski,
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>

[ Upstream commit ba441322c7aac4735d78fc6781e497a01fb8eac7 ]

Simplify the code by using lock guards for the bgpio_lock.

Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Link: https://lore.kernel.org/r/20250702-gpio-mmio-rework-v2-2-6b77aab684d8@linaro.org
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Stable-dep-of: b7719c575dec ("gpio: mxc: fix both_edges bit operations")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/gpio/gpio-mxc.c | 48 ++++++++++++++++++-----------------------
 1 file changed, 21 insertions(+), 27 deletions(-)

diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index a61bc17b27081..c404d3d56a9dc 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -7,6 +7,7 @@
 // Authors: Daniel Mack, Juergen Beisert.
 // Copyright (C) 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved.
 
+#include <linux/cleanup.h>
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/init.h>
@@ -161,7 +162,6 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
 {
 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
 	struct mxc_gpio_port *port = gc->private;
-	unsigned long flags;
 	u32 bit, val;
 	u32 gpio_idx = d->hwirq;
 	int edge;
@@ -200,41 +200,38 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
 		return -EINVAL;
 	}
 
-	raw_spin_lock_irqsave(&port->gc.bgpio_lock, flags);
+	scoped_guard(raw_spinlock_irqsave, &port->gc.bgpio_lock) {
+		if (GPIO_EDGE_SEL >= 0) {
+			val = readl(port->base + GPIO_EDGE_SEL);
+			if (edge == GPIO_INT_BOTH_EDGES)
+				writel(val | (1 << gpio_idx),
+				       port->base + GPIO_EDGE_SEL);
+			else
+				writel(val & ~(1 << gpio_idx),
+				       port->base + GPIO_EDGE_SEL);
+		}
 
-	if (GPIO_EDGE_SEL >= 0) {
-		val = readl(port->base + GPIO_EDGE_SEL);
-		if (edge == GPIO_INT_BOTH_EDGES)
-			writel(val | (1 << gpio_idx),
-				port->base + GPIO_EDGE_SEL);
-		else
-			writel(val & ~(1 << gpio_idx),
-				port->base + GPIO_EDGE_SEL);
-	}
+		if (edge != GPIO_INT_BOTH_EDGES) {
+			reg += GPIO_ICR1 + ((gpio_idx & 0x10) >> 2); /* lower or upper register */
+			bit = gpio_idx & 0xf;
+			val = readl(reg) & ~(0x3 << (bit << 1));
+			writel(val | (edge << (bit << 1)), reg);
+		}
 
-	if (edge != GPIO_INT_BOTH_EDGES) {
-		reg += GPIO_ICR1 + ((gpio_idx & 0x10) >> 2); /* lower or upper register */
-		bit = gpio_idx & 0xf;
-		val = readl(reg) & ~(0x3 << (bit << 1));
-		writel(val | (edge << (bit << 1)), reg);
+		writel(1 << gpio_idx, port->base + GPIO_ISR);
+		port->pad_type[gpio_idx] = type;
 	}
 
-	writel(1 << gpio_idx, port->base + GPIO_ISR);
-	port->pad_type[gpio_idx] = type;
-
-	raw_spin_unlock_irqrestore(&port->gc.bgpio_lock, flags);
-
 	return port->gc.direction_input(&port->gc, gpio_idx);
 }
 
 static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio)
 {
 	void __iomem *reg = port->base;
-	unsigned long flags;
 	u32 bit, val;
 	int edge;
 
-	raw_spin_lock_irqsave(&port->gc.bgpio_lock, flags);
+	guard(raw_spinlock_irqsave)(&port->gc.bgpio_lock);
 
 	reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */
 	bit = gpio & 0xf;
@@ -250,12 +247,9 @@ static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio)
 	} else {
 		pr_err("mxc: invalid configuration for GPIO %d: %x\n",
 		       gpio, edge);
-		goto unlock;
+		return;
 	}
 	writel(val | (edge << (bit << 1)), reg);
-
-unlock:
-	raw_spin_unlock_irqrestore(&port->gc.bgpio_lock, flags);
 }
 
 /* handle 32 interrupts in one status register */
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 056/247] gpio: mxc: fix both_edges bit operations
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (54 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 055/247] gpio: mxc: use lock guards for the generic GPIO chip lock Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 057/247] gpio: mxc: use BIT() macro Greg Kroah-Hartman
                   ` (198 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Frank Li, Peng Fan, Linus Walleij,
	Andy Shevchenko, Bartosz Golaszewski, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Peng Fan <peng.fan@nxp.com>

[ Upstream commit b7719c575dec69146f6d537fd616b27083c0cf45 ]

gpio_set_irq_type() can be called concurrently for different pins on
the same port.  The IRQ core serializes per irq descriptor, but
different pins have different descriptors, so on SMP systems two
concurrent gpio_set_irq_type() calls for pins on the same port run
without mutual exclusion.

The read-modify-write of port->both_edges is performed outside the
port-wide scoped_guard(gpio_generic_lock_irqsave) section, so
concurrent updates for different pins can overwrite each other,
causing missed interrupts or stuck IRQ lines on dual-edge triggered
pins.

The original uniprocessor MXC SoCs were not affected; the race
became reachable on multi-core i.MX7 and i.MX8 SoCs that reuse this
driver.

Convert both_edges from u32 to unsigned long and use set_bit(),
clear_bit(), and test_bit() to make the modifications atomic.

Fixes: 910862ec092c ("mxc: emulate GPIO interrupt on both-edges")
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
Reviewed-by: Linus Walleij <linusw@kernel.org>
Reviewed-by: Andy Shevchenko <andy@kernel.org>
Link: https://patch.msgid.link/20261013-gpio-mxc-cleanup-v7-2-c4d769587d3e@nxp.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/gpio/gpio-mxc.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index c404d3d56a9dc..e9120bb67db3e 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -7,6 +7,7 @@
 // Authors: Daniel Mack, Juergen Beisert.
 // Copyright (C) 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved.
 
+#include <linux/bitops.h>
 #include <linux/cleanup.h>
 #include <linux/clk.h>
 #include <linux/err.h>
@@ -67,7 +68,7 @@ struct mxc_gpio_port {
 	struct irq_domain *domain;
 	struct gpio_chip gc;
 	struct device *dev;
-	u32 both_edges;
+	unsigned long both_edges;
 	struct mxc_gpio_reg_saved gpio_saved_reg;
 	bool power_off;
 	u32 wakeup_pads;
@@ -167,7 +168,7 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
 	int edge;
 	void __iomem *reg = port->base;
 
-	port->both_edges &= ~(1 << gpio_idx);
+	clear_bit(gpio_idx, &port->both_edges);
 	switch (type) {
 	case IRQ_TYPE_EDGE_RISING:
 		edge = GPIO_INT_RISE_EDGE;
@@ -187,7 +188,7 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
 				edge = GPIO_INT_HIGH_LEV;
 				pr_debug("mxc: set GPIO %d to high trigger\n", gpio_idx);
 			}
-			port->both_edges |= 1 << gpio_idx;
+			set_bit(gpio_idx, &port->both_edges);
 		}
 		break;
 	case IRQ_TYPE_LEVEL_LOW:
@@ -258,7 +259,7 @@ static void mxc_gpio_irq_handler(struct mxc_gpio_port *port, u32 irq_stat)
 	while (irq_stat != 0) {
 		int irqoffset = fls(irq_stat) - 1;
 
-		if (port->both_edges & (1 << irqoffset))
+		if (test_bit(irqoffset, &port->both_edges))
 			mxc_flip_edge(port, irqoffset);
 
 		generic_handle_domain_irq(port->domain, irqoffset);
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 057/247] gpio: mxc: use BIT() macro
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (55 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 056/247] gpio: mxc: fix both_edges bit operations Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 058/247] gpio: mxc: fix wakeup_pads bit operations Greg Kroah-Hartman
                   ` (197 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Alexander Stein, Frank Li,
	Bartosz Golaszewski, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Alexander Stein <alexander.stein@ew.tq-group.com>

[ Upstream commit 9de94681ee48770ec7e2062451a572b557bf9298 ]

Replace the open-code with the BIT() macro.

Signed-off-by: Alexander Stein <alexander.stein@ew.tq-group.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Link: https://patch.msgid.link/20260526063504.25916-2-alexander.stein@ew.tq-group.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Stable-dep-of: 170aeff46fb5 ("gpio: mxc: fix wakeup_pads bit operations")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/gpio/gpio-mxc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index e9120bb67db3e..1131934e7880e 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -330,13 +330,13 @@ static int gpio_set_wake_irq(struct irq_data *d, u32 enable)
 			ret = enable_irq_wake(port->irq_high);
 		else
 			ret = enable_irq_wake(port->irq);
-		port->wakeup_pads |= (1 << gpio_idx);
+		port->wakeup_pads |= BIT(gpio_idx);
 	} else {
 		if (port->irq_high && (gpio_idx >= 16))
 			ret = disable_irq_wake(port->irq_high);
 		else
 			ret = disable_irq_wake(port->irq);
-		port->wakeup_pads &= ~(1 << gpio_idx);
+		port->wakeup_pads &= ~BIT(gpio_idx);
 	}
 
 	return ret;
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 058/247] gpio: mxc: fix wakeup_pads bit operations
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (56 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 057/247] gpio: mxc: use BIT() macro Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 059/247] perf: Fix perf_pmu_migrate_context() leaving events behind Greg Kroah-Hartman
                   ` (196 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Frank Li, Peng Fan, Andy Shevchenko,
	Bartosz Golaszewski, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Peng Fan <peng.fan@nxp.com>

[ Upstream commit 170aeff46fb54f41545c85a72aec525aebc79d44 ]

gpio_set_wake_irq() can be called concurrently for different pins on
the same port. The writer-vs-writer race is the concern: two concurrent
gpio_set_wake_irq() calls for different pins on the same port both do
a non-atomic read-modify-write on the same wakeup_pads word. The old
|= and &= compile to separate load/modify/store instructions that can
interleave, losing one CPU's update.

assign_bit() uses an atomic RMW instruction, so concurrent writers to
different bits in the same word are safe.

The reader side (for_each_set_bit in noirq_suspend, wakeup_pads > 0)
runs in noirq context where no concurrent writer can execute, so
reader atomicity is not needed.

wakeup_pads is a u32, while assign_bit() operates on unsigned long
pointers. On 64-bit platforms, this causes an 8-byte read-modify-write
on a 4-byte field, corrupting the adjacent is_pad_wakeup. So change
wakeup_pads to unsigned long and reorder to avoid wasting words.

And fix the enable/disable path unconditionally sets/clears the
wakeup_pads bit even when enable_irq_wake()/disable_irq_wake() fails.
Only update the bit on success.

Fixes: f60c9eac54af ("gpio: mxc: enable pad wakeup on i.MX8x platforms")
Assisted-by: LLM
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
Reviewed-by: Andy Shevchenko <andy@kernel.org>
Link: https://patch.msgid.link/20261013-gpio-mxc-cleanup-v7-3-c4d769587d3e@nxp.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/gpio/gpio-mxc.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index 1131934e7880e..30e03acbe8596 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -71,8 +71,8 @@ struct mxc_gpio_port {
 	unsigned long both_edges;
 	struct mxc_gpio_reg_saved gpio_saved_reg;
 	bool power_off;
-	u32 wakeup_pads;
 	bool is_pad_wakeup;
+	unsigned long wakeup_pads;
 	u32 pad_type[32];
 	const struct mxc_gpio_hwdata *hwdata;
 };
@@ -330,16 +330,18 @@ static int gpio_set_wake_irq(struct irq_data *d, u32 enable)
 			ret = enable_irq_wake(port->irq_high);
 		else
 			ret = enable_irq_wake(port->irq);
-		port->wakeup_pads |= BIT(gpio_idx);
 	} else {
 		if (port->irq_high && (gpio_idx >= 16))
 			ret = disable_irq_wake(port->irq_high);
 		else
 			ret = disable_irq_wake(port->irq);
-		port->wakeup_pads &= ~BIT(gpio_idx);
 	}
+	if (ret)
+		return ret;
 
-	return ret;
+	assign_bit(gpio_idx, &port->wakeup_pads, enable);
+
+	return 0;
 }
 
 static int mxc_gpio_init_gc(struct mxc_gpio_port *port, int irq_base)
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 059/247] perf: Fix perf_pmu_migrate_context() leaving events behind
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (57 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 058/247] gpio: mxc: fix wakeup_pads bit operations Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 060/247] printk: Postpone kthread startup Greg Kroah-Hartman
                   ` (195 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Haris Okanovic,
	Peter Zijlstra (Intel), Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Haris Okanovic <harisokn@amazon.com>

[ Upstream commit e76b36b4be7160eaa14b416681e548b125702395 ]

__perf_pmu_remove() walks the group leaders of a CPU and PMU with
perf_event_groups_for_cpu_pmu(), removing each one as it goes.
perf_remove_from_context() takes the leader out of the groups rbtree,
after which rb_next() on that node returns NULL, prematurely ending the
walk. Other groups stay behind in the source context.

On CPU hotplug, they are then torn down with the dying CPU. They keep
running until teardown, while the PMU's interrupt and migrated events
are on a new CPU, which drivers rely on never happening.

Walk ctx->event_list instead and pick out the PMU's events by their
pmu_ctx.

Fixes: bd2756811766 ("perf: Rewrite core context handling")
Signed-off-by: Haris Okanovic <harisokn@amazon.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://patch.msgid.link/20261013185603.1347265-2-harisokn@amazon.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 kernel/events/core.c | 20 +++++++-------------
 1 file changed, 7 insertions(+), 13 deletions(-)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index 6c9c3bfc0da27..a076236b3a49b 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -13326,23 +13326,18 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
 }
 EXPORT_SYMBOL_GPL(perf_event_create_kernel_counter);
 
-static void __perf_pmu_remove(struct perf_event_context *ctx,
-			      int cpu, struct pmu *pmu,
-			      struct perf_event_groups *groups,
+static void __perf_pmu_remove(struct perf_event_context *ctx, struct pmu *pmu,
 			      struct list_head *events)
 {
-	struct perf_event *event, *sibling;
+	struct perf_event *event, *tmp;
+
+	list_for_each_entry_safe(event, tmp, &ctx->event_list, event_entry) {
+		if (event->pmu_ctx->pmu != pmu)
+			continue;
 
-	perf_event_groups_for_cpu_pmu(event, groups, cpu, pmu) {
 		perf_remove_from_context(event, 0);
 		put_pmu_ctx(event->pmu_ctx);
 		list_add(&event->migrate_entry, events);
-
-		for_each_sibling_event(sibling, event) {
-			perf_remove_from_context(sibling, 0);
-			put_pmu_ctx(sibling->pmu_ctx);
-			list_add(&sibling->migrate_entry, events);
-		}
 	}
 }
 
@@ -13418,8 +13413,7 @@ void perf_pmu_migrate_context(struct pmu *pmu, int src_cpu, int dst_cpu)
 	 */
 	mutex_lock_double(&src_ctx->mutex, &dst_ctx->mutex);
 
-	__perf_pmu_remove(src_ctx, src_cpu, pmu, &src_ctx->pinned_groups, &events);
-	__perf_pmu_remove(src_ctx, src_cpu, pmu, &src_ctx->flexible_groups, &events);
+	__perf_pmu_remove(src_ctx, pmu, &events);
 
 	if (!list_empty(&events)) {
 		/*
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 060/247] printk: Postpone kthread startup
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (58 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 059/247] perf: Fix perf_pmu_migrate_context() leaving events behind Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 061/247] PCI: Dont treat ~0 as ready in pci_dev_wait() with RRS SV Greg Kroah-Hartman
                   ` (194 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Derek Barbosa, John Ogness,
	Petr Mladek, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: John Ogness <john.ogness@linutronix.de>

[ Upstream commit 5f339c46f153184570f16c8e789c9709b14cbe8b ]

There have been various bug reports related to SMP systems hanging
on boot. The reports vary but seem to have some overlap with regard
to missed IPI's during SMP setup. The reports also show that
reverting NBCON console usage allows the bugs to disappear.

The NBCON kthreads for console printing are started very early
during boot using early_initcall(). Since these kthreads are
asynchronously enabling/disabling interrupts during early boot, they
may be interfering with early SMP setup on some hardware platforms.

Starting the console printing kthreads later has shown to avoid the
hanging on systems that could previously reproduce the issue.

Postpone kthread starting until after all arch initcalls have
completed.

Reported-by: Derek Barbosa <debarbos@redhat.com>
Closes: https://lore.kernel.org/linux-rt-users/arPmYPbFLf2EldIl@debarbos-thinkpadt14gen5.rmtusma.csb
Fixes: 76f258bf3f2a ("printk: nbcon: Introduce printer kthreads")
Signed-off-by: John Ogness <john.ogness@linutronix.de>
Tested-by: Derek Barbosa <debarbos@redhat.com>
Link: https://patch.msgid.link/20261016085441.857695-1-john.ogness@linutronix.de
Signed-off-by: Petr Mladek <pmladek@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 kernel/printk/printk.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index d5c1dff1617c4..72845f87089b6 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -3767,7 +3767,7 @@ static int __init printk_set_kthreads_ready(void)
 
 	return 0;
 }
-early_initcall(printk_set_kthreads_ready);
+subsys_initcall(printk_set_kthreads_ready);
 #endif /* CONFIG_PRINTK */
 
 static int __read_mostly keep_bootcon;
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 061/247] PCI: Dont treat ~0 as ready in pci_dev_wait() with RRS SV
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (59 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 060/247] printk: Postpone kthread startup Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 062/247] afs: free the super info after a grace period Greg Kroah-Hartman
                   ` (193 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Lukas Wunner, Alexander Gruhlke,
	Bjorn Helgaas, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Alexander Gruhlke <gruhlke@mailbox.org>

[ Upstream commit e8df1d194c39b7a5159d570798941851f70a8668 ]

With RRS Software Visibility, pci_dev_wait() considers a device ready as
soon as reading the Vendor ID doesn't return the RRS value.  Devices aren't
required to respond with RRS while they aren't ready, so the read may
return ~0 and pci_dev_wait() stops waiting too early.  This was seen with
Intel [8086:0a54] and Samsung [144d:a80c] NVMe SSDs.

Also wait while the Vendor ID reads ~0.  A VF's Vendor ID always reads ~0,
so check its Command register instead, as is done without RRS SV.

Fixes: d591f6804e7e ("PCI: Wait for device readiness with Configuration RRS")
Link: https://lore.kernel.org/r/20250611101442.387378-1-hui.wang@canonical.com
Suggested-by: Lukas Wunner <lukas@wunner.de>
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Alexander Gruhlke <gruhlke@mailbox.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Lukas Wunner <lukas@wunner.de>
Link: https://patch.msgid.link/20261011190145.23621-3-gruhlke@mailbox.org
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/pci/pci.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 0d33b30ec2f67..f96801d1c833f 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1312,9 +1312,11 @@ static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout)
 	 * initialize.
 	 *
 	 * If the device is below a Root Port with Configuration RRS
-	 * Software Visibility enabled, reading the Vendor ID returns a
+	 * Software Visibility enabled, reading the Vendor ID may return a
 	 * special data value if the device responded with RRS.  Read the
-	 * Vendor ID until we get non-RRS status.
+	 * Vendor ID until we get non-RRS status and something other than
+	 * ~0.  The Vendor ID of VFs reads ~0, so check their Command
+	 * register instead.
 	 *
 	 * If there's no Root Port or Configuration RRS Software Visibility
 	 * is not enabled, the device may still respond with RRS, but
@@ -1334,8 +1336,13 @@ static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout)
 
 		if (root && root->config_rrs_sv) {
 			pci_read_config_dword(dev, PCI_VENDOR_ID, &id);
-			if (!pci_bus_rrs_vendor_id(id))
-				break;
+			if (!pci_bus_rrs_vendor_id(id)) {
+				if (PCI_POSSIBLE_ERROR(id) && dev->is_virtfn)
+					pci_read_config_dword(dev, PCI_COMMAND,
+							      &id);
+				if (!PCI_POSSIBLE_ERROR(id))
+					break;
+			}
 		} else {
 			pci_read_config_dword(dev, PCI_COMMAND, &id);
 			if (!PCI_POSSIBLE_ERROR(id))
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 062/247] afs: free the super info after a grace period
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (60 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 061/247] PCI: Dont treat ~0 as ready in pci_dev_wait() with RRS SV Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 063/247] autofs: ignore notification errors from a replaced pipe Greg Kroah-Hartman
                   ` (192 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Christian Brauner (Amutable)

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Christian Brauner <brauner@kernel.org>

commit 59e483739f2fd14327ece3f60c4995d060ca46b7 upstream.

afs_atcell_get_link() resolves the @cell and .@cell symlinks of a
dynamic root in rcu pathwalk mode. Before it looks at the dentry it gets
the afs_net through afs_i2net(), which reads ->net_ns from the
afs_super_info in sb->s_fs_info. The @cell dentries are kept around when
unused and the dynamic root has no ->d_revalidate(), so a lookup that
finds @cell in the dcache gets to ->get_link() in rcu mode.

afs_kill_super() frees the afs_super_info with a plain kfree() in
afs_destroy_sbi(). Right now a pathwalk can't still be in
afs_atcell_get_link() at that point, but only by accident. umount(2)
waits for a grace period in namespace_unlock() before it drops the
mount. And a mount whose last reference goes away elsewhere, like the
chdir out of a lazily unmounted directory, still gets a grace period
from bdi_unregister(). afs_fill_super() sets up a private bdi, so
generic_shutdown_super() unregisters it from kill_anon_super() and
bdi_remove_from_list() waits in synchronize_rcu_expedited() before
afs_destroy_sbi() runs. That grace period protects the rcu readers of
bdi_list in the writeback code. It has nothing to do with pathwalk.

Don't rely on it and free the afs_super_info after a grace period.

Fixes: 30bca65bbbae ("afs: Make /afs/@cell and /afs/.@cell symlinks")
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20261009-work-fixes-rcu-v1-2-7446d2d335e6@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 fs/afs/internal.h |    2 ++
 fs/afs/super.c    |    2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -264,6 +264,8 @@ struct afs_super_info {
 	struct afs_volume	*volume;	/* volume record */
 	enum afs_flock_mode	flock_mode:8;	/* File locking emulation mode */
 	bool			dyn_root;	/* True if dynamic root */
+	/* afs_atcell_get_link() reads ->net_ns in rcu pathwalk */
+	struct rcu_head		rcu;
 };
 
 static inline struct afs_super_info *AFS_FS_S(struct super_block *sb)
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -523,7 +523,7 @@ static void afs_destroy_sbi(struct afs_s
 		afs_put_volume(as->volume, afs_volume_trace_put_destroy_sbi);
 		afs_unuse_cell(as->cell, afs_cell_trace_unuse_sbi);
 		put_net(as->net_ns);
-		kfree(as);
+		kfree_rcu(as, rcu);
 	}
 }
 



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 063/247] autofs: ignore notification errors from a replaced pipe
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (61 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 062/247] afs: free the super info after a grace period Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 064/247] unicode: free the map after a grace period Greg Kroah-Hartman
                   ` (191 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Sung Byeongchan, Ian Kent,
	Christian Brauner (Amutable)

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Sung Byeongchan <tjdqudcks0424@naver.com>

commit 65676cd4203c0e41a94caf54080a7f0a95434bda upstream.

autofs_notify_daemon() takes a reference to the current notification
pipe under wq_mutex, then drops the mutex before writing the request. The
write can block while the daemon enters catatonic mode and installs a
replacement pipe.

If the old pipe's reader is then closed, the delayed write returns -EPIPE
and the generic error path enters catatonic mode again. That transition
acts on the current superblock state, closes the replacement pipe, and
releases the new daemon generation's wait queues.

Only enter catatonic mode when the pipe which failed is still the current
pipe. Factor the already-locked transition so the identity check and state
change are atomic with respect to another replacement.

This was reproduced on v7.3-rc5-337-gff47652a4b66c in a local QEMU guest.
An unprivileged UID 65534 lookup filled the old packet pipe before a
normal CATATONIC/SETPIPEFD restart. On the unmodified kernel, the new pipe
received HUP and both a pending victim lookup and a later lookup failed
with ENOENT in two out of two fresh-mount runs.

With this change, the new pipe remained active, received an intact
304-byte request, and both victim lookups completed in two out of two
runs. Normal lookup and restart-without-a-blocked-writer controls passed.
No KASAN, oops, refcount, or lock diagnostic was observed. A source
reproducer and complete local logs are available privately on request.

The demonstrated impact is limited to denial of a shared autofs service
during a legitimate daemon restart. No memory corruption, information leak,
privilege escalation, or code execution primitive was observed.

Fixes: 8d7b48e0bc5fa ("autofs4: add miscellaneous device for ioctls")
Cc: stable@vger.kernel.org
Signed-off-by: Sung Byeongchan <tjdqudcks0424@naver.com>
Link: https://patch.msgid.link/20261007173542.593624-1-tjdqudcks0424@naver.com
Acked-by: Ian Kent <raven@themaw.net>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 fs/autofs/waitq.c |   25 +++++++++++++++++++------
 1 file changed, 19 insertions(+), 6 deletions(-)

--- a/fs/autofs/waitq.c
+++ b/fs/autofs/waitq.c
@@ -12,15 +12,13 @@
  */
 static autofs_wqt_t autofs_next_wait_queue = 1;
 
-void autofs_catatonic_mode(struct autofs_sb_info *sbi)
+static void autofs_catatonic_mode_locked(struct autofs_sb_info *sbi)
 {
 	struct autofs_wait_queue *wq, *nwq;
 
-	mutex_lock(&sbi->wq_mutex);
-	if (sbi->flags & AUTOFS_SBI_CATATONIC) {
-		mutex_unlock(&sbi->wq_mutex);
+	lockdep_assert_held(&sbi->wq_mutex);
+	if (sbi->flags & AUTOFS_SBI_CATATONIC)
 		return;
-	}
 
 	pr_debug("entering catatonic mode\n");
 
@@ -40,6 +38,21 @@ void autofs_catatonic_mode(struct autofs
 	fput(sbi->pipe);	/* Close the pipe */
 	sbi->pipe = NULL;
 	sbi->pipefd = -1;
+}
+
+void autofs_catatonic_mode(struct autofs_sb_info *sbi)
+{
+	mutex_lock(&sbi->wq_mutex);
+	autofs_catatonic_mode_locked(sbi);
+	mutex_unlock(&sbi->wq_mutex);
+}
+
+static void autofs_catatonic_mode_for_pipe(struct autofs_sb_info *sbi,
+					   struct file *pipe)
+{
+	mutex_lock(&sbi->wq_mutex);
+	if (sbi->pipe == pipe)
+		autofs_catatonic_mode_locked(sbi);
 	mutex_unlock(&sbi->wq_mutex);
 }
 
@@ -170,7 +183,7 @@ static void autofs_notify_daemon(struct
 		autofs_wait_release(sbi, wq->wait_queue_token, ret);
 		break;
 	default:
-		autofs_catatonic_mode(sbi);
+		autofs_catatonic_mode_for_pipe(sbi, pipe);
 		break;
 	}
 	fput(pipe);



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 064/247] unicode: free the map after a grace period
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (62 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 063/247] autofs: ignore notification errors from a replaced pipe Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 065/247] x86/kvm: Dont consume async #PF flags on a kernel #PF in NMI context Greg Kroah-Hartman
                   ` (190 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Christian Brauner (Amutable)

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Christian Brauner <brauner@kernel.org>

commit a96c5299bd7305eb984377681eb3222a57376405 upstream.

generic_ci_d_hash() and generic_ci_d_compare() read sb->s_encoding and
dereference the unicode map while a pathwalk in rcu mode holds nothing
but rcu_read_lock(). The filesystems that use them, ext4, f2fs and
tmpfs, drop the map with utf8_unload() from ->put_super(), which runs
when the last reference to the mount goes away. A lookup that is still
inside such a filesystem at that point reads a freed map.

With a pathwalk held up in utf8_casefold_hash() while the last reference
to a casefolded tmpfs goes away:

  BUG: KASAN: slab-use-after-free in utf8nlookup+0x74c/0x950
  Read of size 8 at addr ff110001030fe658 by task walker/98
  Call Trace:
   <TASK>
   utf8nlookup+0x74c/0x950
   utf8byte+0x160/0x1560
   utf8_casefold_hash+0x167/0x230
   generic_ci_d_hash+0xdd/0x1c0
   link_path_walk+0x11ad/0x1d30
   path_lookupat+0x63/0xb00
   filename_lookup+0x1f1/0x5b0
   vfs_statx+0xd7/0x3b0
  [...]
  Allocated by task 94:
   __kmalloc_cache_noprof+0x249/0x560
   utf8_load+0x4e/0x570
   shmem_parse_opt_casefold.isra.0+0x92/0x270
  [...]
  Freed by task 97:
   kfree+0x1db/0x5b0
   shmem_put_super+0x72/0x170
   generic_shutdown_super+0x14c/0x530
   kill_anon_super+0x3a/0x60
   deactivate_locked_super+0x9c/0xf0
   cleanup_mnt+0x9f/0x130

So far that has been hard to hit. umount(2) waits for a grace period
in namespace_unlock() before it drops the mount, so only a mount whose
last reference goes away elsewhere, like the close of a file or a chdir
out of a lazily unmounted directory, can race a walker. So it is
reachable.

Delay the free until a grace period has passed. The map and the data
table it holds a reference to then outlive any pathwalk that found the
superblock before the mount went away. The reference on the data table
module is dropped from the rcu callback as well. utf8-core is built in
whenever CONFIG_UNICODE is set, so there is no module exit that would
have to wait for the callbacks.

Overlayfs points the s_encoding of an overlay at the map of its first
layer without taking a reference of its own. That stays correct. The
layer is held by the overlay, so its map is dropped only after the
overlay is gone.

Fixes: b886ee3e778e ("ext4: Support case-insensitive file name lookups")
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20261009-work-fixes-rcu-v1-6-7446d2d335e6@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 fs/unicode/utf8-core.c  |   21 +++++++++++++++++----
 include/linux/unicode.h |    1 +
 2 files changed, 18 insertions(+), 4 deletions(-)

--- a/fs/unicode/utf8-core.c
+++ b/fs/unicode/utf8-core.c
@@ -3,6 +3,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/slab.h>
+#include <linux/rcupdate.h>
 #include <linux/parser.h>
 #include <linux/errno.h>
 #include <linux/stringhash.h>
@@ -205,12 +206,24 @@ out_free_um:
 }
 EXPORT_SYMBOL(utf8_load);
 
+static void utf8_unload_rcu(struct rcu_head *head)
+{
+	struct unicode_map *um = container_of(head, struct unicode_map, rcu);
+
+	symbol_put(utf8_data_table);
+	kfree(um);
+}
+
+/*
+ * A pathwalk in rcu mode may still be in ->d_hash() or ->d_compare() of a
+ * filesystem that is being torn down and read the map through its
+ * superblock, so the map and the tables it points to have to outlive the
+ * grace period.
+ */
 void utf8_unload(struct unicode_map *um)
 {
-	if (um) {
-		symbol_put(utf8_data_table);
-		kfree(um);
-	}
+	if (um)
+		call_rcu(&um->rcu, utf8_unload_rcu);
 }
 EXPORT_SYMBOL(utf8_unload);
 
--- a/include/linux/unicode.h
+++ b/include/linux/unicode.h
@@ -51,6 +51,7 @@ struct unicode_map {
 	unsigned int version;
 	const struct utf8data *ntab[UTF8_NMAX];
 	const struct utf8data_table *tables;
+	struct rcu_head rcu;
 };
 
 int utf8_validate(const struct unicode_map *um, const struct qstr *str);



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 065/247] x86/kvm: Dont consume async #PF flags on a kernel #PF in NMI context
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (63 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 064/247] unicode: free the map after a grace period Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 066/247] KVM: nVMX: Reset MMU back to the root MMU if loading L2 state fails for !VM-Entry Greg Kroah-Hartman
                   ` (189 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, EJ Campbell, Paolo Bonzini

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: EJ Campbell <ejc3@meta.com>

commit 81d99abe2bd81379abfb595e403bbbee6fbfc624 upstream.

An async #PF "page not present" event arrives through the #PF vector,
and its reason sits in the per-CPU apf_reason.flags until
__kvm_handle_async_pf() reads and clears it. If an NMI arrives after
the event is injected and before the #PF handler reads the flags, and
the NMI handler itself takes a #PF, that fault reads and clears the
flags belonging to the #PF it interrupted. It then finds interrupts
disabled in the NMI context it interrupted, and panics:

  Kernel panic - not syncing: Host injected async #PF in interrupt
disabled region
  Call Trace:
   <NMI>
   panic+0x52/0x60
   __kvm_handle_async_pf+0xb0/0xb0
   exc_page_fault+0x71/0xb0
   asm_exc_page_fault+0x27/0x30
  RIP: 0010:__get_user_nocheck_8+0x6/0x20
   perf_callchain_user+0x147/0x1a0
   get_perf_callchain+0x12d/0x1c0
   ...
   perf_event_nmi_handler+0x26/0x50
   exc_nmi+0xe8/0x110
  RIP: 0010:asm_exc_page_fault+0x0/0x30
   </NMI>

The last RIP line shows the NMI landing on the first instruction of
the #PF entry. perf with user call chains takes such a fault: the
sampling NMI walks the user stack with __get_user(), which faults when
a saved frame pointer is not a valid user address or the walk runs off
the top of the stack. The same window exists when KVM, running as an
L1 hypervisor with DELIVERY_AS_PF_VMEXIT, reads the flags itself after
a #PF VM-exit.

The NMI entry code saves and restores CR2 for this nesting, but not the
async #PF reason. Andy Lutomirski described the race, with perf as the
example, when async #PF delivery was reworked in 2020 [1]. Saving and
clearing the flags across the NMI, next to CR2, was discussed there but
not merged.

Since that rework, Linux has stopped setting KVM_ASYNC_PF_SEND_ALWAYS,
so the host delivers "page not present" only for user mode faults and
a kernel-mode fault in NMI context (including kernel-mode #MC and #DB)
cannot be an async page fault.  In that case, return without touching
the flags so that the interrupted handler finds them intact.

Tested on v7.3-rc5 in a 4-vCPU, 2 GiB guest restored from a snapshot
whose memory is served on demand through userfaultfd, so that reading
it back takes async #PFs, while every thread samples hardware cycles
with user call chains and points its frame pointer at an unmapped page.
Without this patch the guest panicked as above in 3 of 3 runs. With it,
the guest survived 3 of 3 runs of 60 seconds, and the host counted
148,441 to 153,334 kvm_async_pf_not_present events in the first 20
seconds of each. On 6.18.50 the results were the same: the guest
panicked without the patch and survived with it.

Link: https://lore.kernel.org/all/ed71d0967113a35f670a9625a058b8e6e0b2f104.1583547991.git.luto@kernel.org/ [1]
Link: https://lore.kernel.org/all/20211126123145.2772-1-jiangshanlai@gmail.com/ [2]
Cc: stable@vger.kernel.org # v5.9+
Signed-off-by: EJ Campbell <ejc3@meta.com>
Link: https://patch.msgid.link/CADkxfh-uQTca_6jB1JPDq1MsKffF_UKGQR339oQSJNcoV75GNQ@mail.gmail.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 arch/x86/kernel/kvm.c |   32 +++++++++++++++++++++++++++++---
 1 file changed, 29 insertions(+), 3 deletions(-)

--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -255,11 +255,39 @@ noinstr u32 kvm_read_and_reset_apf_flags
 }
 EXPORT_SYMBOL_GPL(kvm_read_and_reset_apf_flags);
 
+static __always_inline bool kvm_apf_reason_pending(void)
+{
+	return __this_cpu_read(async_pf_enabled) &&
+	       __this_cpu_read(apf_reason.flags);
+}
+
 noinstr bool __kvm_handle_async_pf(struct pt_regs *regs, u32 token)
 {
-	u32 flags = kvm_read_and_reset_apf_flags();
 	irqentry_state_t state;
+	u32 flags;
+
+	if (!kvm_apf_reason_pending())
+		return false;
+
+	/*
+	 * The guest does not enable KVM_ASYNC_PF_SEND_ALWAYS, so the host
+	 * delivers async #PF only to user mode (or as a #PF VM-exit, which KVM
+	 * reads itself). A #PF from kernel mode can still arrive between that
+	 * delivery and the read of the reason flags, inside an NMI that
+	 * interrupted it, for instance perf reading user memory for a call
+	 * chain. Such a fault is not async, so leave the async PF flags
+	 * untouched for the outer handler.  Outside NMI context, on the other
+	 * hand, async PF flags on a kernel-mode fault mean the host is broken.
+	 */
+	if (!user_mode(regs)) {
+		if (likely(in_nmi()))
+			return false;
+		state = irqentry_enter(regs);
+		instrumentation_begin();
+		panic("Host injected async #PF in kernel mode\n");
+	}
 
+	flags = kvm_read_and_reset_apf_flags();
 	if (!flags)
 		return false;
 
@@ -275,8 +303,6 @@ noinstr bool __kvm_handle_async_pf(struc
 		panic("Host injected async #PF in interrupt disabled region\n");
 
 	if (flags & KVM_PV_REASON_PAGE_NOT_PRESENT) {
-		if (unlikely(!(user_mode(regs))))
-			panic("Host injected async #PF in kernel mode\n");
 		/* Page is swapped out by the host. */
 		kvm_async_pf_task_wait_schedule(token);
 	} else {



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 066/247] KVM: nVMX: Reset MMU back to the root MMU if loading L2 state fails for !VM-Entry
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (64 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 065/247] x86/kvm: Dont consume async #PF flags on a kernel #PF in NMI context Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 067/247] fsnotify: prevent mark additions during connector teardown Greg Kroah-Hartman
                   ` (188 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, David Woodhouse,
	Amirmohammad Eftekhar, Sean Christopherson, Paolo Bonzini

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Amirmohammad Eftekhar <amirmohammadeftekhar@gmail.com>

commit c8f4cfe1cf93bce924e27f2abead7a4c4a487505 upstream.

Reset the vCPU's MMU pointer back to the root MMU if loading L2 state fails
in the "not from VM-Entry" case, i.e. when emulating RSM or handling
KVM_SET_NESTED_STATE.  Failure to unwind the MMU pointer results in KVM
trying to run L1 with a nested MMU, and is especially problematic if the
vCPU manages to free its nested state before the VM crashes.  Constructing
the root for a nested EPT MMU goes through vmcs12, which is dynamically
allocated/freed when nVMX is enabled/disabled.  And so if the nested state
is freed with the MMU still pointing at the nested MMU, KVM will hit a NULL
pointer deref when attempting to get L1=>L2 EPTP.

  BUG: kernel NULL pointer dereference, address: 0000000000000078
  #PF: supervisor read access in kernel mode
  #PF: error_code(0x0000) - not-present page
  PGD 114a2d067 P4D 111743067 PUD 11141f067 PMD 0
  Oops: Oops: 0000 [#1] SMP
  CPU: 20 UID: 1000 PID: 1272 Comm: nested_tdp_faul Not tainted 7.3.0-rc4-8c89f11d1a99b-sink-vm #1914 PREEMPTLAZY
  Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015
  RIP: 0010:nested_ept_get_eptp+0xb/0x10 [kvm_intel]
  Call Trace:
   <TASK>
   kvm_mmu_load+0xcd/0x870 [kvm]
   kvm_arch_vcpu_ioctl_run+0x18f5/0x1f80 [kvm]
   kvm_vcpu_ioctl+0x2c7/0x970 [kvm]
   __x64_sys_ioctl+0x90/0xd0
   do_syscall_64+0x9c/0x4d0
   entry_SYSCALL_64_after_hwframe+0x4b/0x53
  RIP: 0033:0x47491b
   </TASK>
  Modules linked in: kvm_intel kvm irqbypass
  CR2: 0000000000000078
  ---[ end trace 0000000000000000 ]---
  RIP: 0010:nested_ept_get_eptp+0xb/0x10 [kvm_intel]

Cc: David Woodhouse <dwmw2@infradead.org>
Fixes: 72e9cbdb4338 ("KVM: nVMX: fix SMI injection in guest mode")
Fixes: 8fcc4b5923af ("kvm: nVMX: Introduce KVM_CAP_NESTED_STATE")
Cc: stable@vger.kernel.org
Signed-off-by: Amirmohammad Eftekhar <amirmohammadeftekhar@gmail.com>
[sean: write changelog]
Signed-off-by: Sean Christopherson <seanjc@google.com>
Link: https://patch.msgid.link/20261001214356.3825100-2-seanjc@google.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 arch/x86/kvm/vmx/nested.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

--- a/arch/x86/kvm/vmx/nested.c
+++ b/arch/x86/kvm/vmx/nested.c
@@ -3689,8 +3689,10 @@ vmentry_fail_vmexit_guest_mode:
 vmentry_fail_vmexit:
 	vmx_switch_vmcs(vcpu, &vmx->vmcs01);
 
-	if (!from_vmentry)
+	if (!from_vmentry) {
+		nested_ept_uninit_mmu_context(vcpu);
 		return NVMX_VMENTRY_VMEXIT;
+	}
 
 	kvm_vcpu_unmap(vcpu, &vmx->nested.apic_access_page_map, false);
 	kvm_vcpu_unmap(vcpu, &vmx->nested.virtual_apic_map, true);



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 067/247] fsnotify: prevent mark additions during connector teardown
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (65 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 066/247] KVM: nVMX: Reset MMU back to the root MMU if loading L2 state fails for !VM-Entry Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 068/247] pid_namespace: make zap_pid_ns_processes() freezable Greg Kroah-Hartman
                   ` (187 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Kyle Zeng,
	Christian Brauner (Amutable)

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Kyle Zeng <kylebot@openai.com>

commit 36ebddca56b9d8993d6dc984fdecc748ee1f5e06 upstream.

fsnotify_destroy_marks() keeps a reference to its current mark while it
drops conn->lock to destroy the mark. This stabilizes the forward-walk
cursor, but does not prevent a new mark from being inserted before it.
For example, an inotify watch re-added after IN_IGNORED sorts before the
old, detached mark for the same group. The walk can miss the replacement
and then detach the entire connector from the object.

The replacement is still on its group's marks_list and, for inotify, in
the watch IDR. The group mutex no longer protects the connector's object
from disappearing. An unprivileged fdinfo read racing the final detach
can consequently call igrab(NULL):

  BUG: KASAN: null-ptr-deref in igrab+0x24/0x100
  Write of size 4 at addr 0000000000000148
  Call Trace:
   igrab+0x24/0x100
   inotify_show_fdinfo+0x1dc/0x5e0
   seq_show+0x397/0x690

Set a DESTROYING flag under conn->lock before starting the walk, and
reject new marks on that connector with -ENOENT. The existing add-mark
error paths undo the temporary group-list entry and the backend's watch
allocation. Do not wait for teardown while holding the group mutex,
which the destroyer needs. Once the old connector is detached, an add
can install a fresh connector as before.

This closes the insertion race for all object types using the common
connector teardown, without changing the mark reference or SRCU lifetime
rules.

Fixes: 6b3f05d24d35 ("fsnotify: Detach mark from object list when last reference is dropped")
Cc: stable@vger.kernel.org
Signed-off-by: Kyle Zeng <kylebot@openai.com>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 fs/notify/mark.c                 |   11 +++++++++++
 include/linux/fsnotify_backend.h |    1 +
 2 files changed, 12 insertions(+)

--- a/fs/notify/mark.c
+++ b/fs/notify/mark.c
@@ -779,6 +779,11 @@ restart:
 		goto restart;
 	}
 
+	if (conn->flags & FSNOTIFY_CONN_FLAG_DESTROYING) {
+		err = -ENOENT;
+		goto out_err;
+	}
+
 	/* is mark the first mark? */
 	if (hlist_empty(&conn->list)) {
 		hlist_add_head_rcu(&mark->obj_list, &conn->list);
@@ -966,6 +971,12 @@ void fsnotify_destroy_marks(fsnotify_con
 	if (!conn)
 		return;
 	/*
+	 * New marks could be inserted before our cursor and survive the final
+	 * detachment of the connector from the object. Prevent additions to
+	 * this connector before dropping its lock.
+	 */
+	conn->flags |= FSNOTIFY_CONN_FLAG_DESTROYING;
+	/*
 	 * We have to be careful since we can race with e.g.
 	 * fsnotify_clear_marks_by_group() and once we drop the conn->lock, the
 	 * list can get modified. However we are holding mark reference and
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -468,6 +468,7 @@ struct fsnotify_mark_connector {
 	unsigned char prio;	/* Highest priority group */
 #define FSNOTIFY_CONN_FLAG_IS_WATCHED	0x01
 #define FSNOTIFY_CONN_FLAG_HAS_IREF	0x02
+#define FSNOTIFY_CONN_FLAG_DESTROYING	0x04
 	unsigned short flags;	/* flags [lock] */
 	union {
 		/* Object pointer [lock] */



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 068/247] pid_namespace: make zap_pid_ns_processes() freezable
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (66 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 067/247] fsnotify: prevent mark additions during connector teardown Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 069/247] eventfs: Free the eventfs_inode after an rcu grace period too Greg Kroah-Hartman
                   ` (186 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Oleg Nesterov, Aviv Vaknin,
	Bradley Morgan, Christian Brauner (Amutable)

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Aviv Vaknin <vaknins33@gmail.com>

commit 81933038f5e273d17ed22792f906889393b204c5 upstream.

When the init of a pid namespace exits, zap_pid_ns_processes() waits
until all other pids in the namespace are freed. A tracer outside the
namespace that does not reap its traced zombies keeps those pids
allocated, so this wait has no upper bound, and while it lasts every
suspend attempt fails:

  Freezing user space processes failed after 20.006 seconds (2 tasks refusing to freeze, wq_busy=0):

Neither wait is freezable. The first loop sleeps in do_wait(), which
returns -ERESTARTSYS on the freezer's fake signal; the loop then clears
TIF_SIGPENDING and waits again without ever freezing. The final loop
sleeps in TASK_INTERRUPTIBLE, and since nothing clears TIF_SIGPENDING
there, schedule() returns immediately after the first freeze attempt
and the task spins until the wait ends.

Sleep in TASK_INTERRUPTIBLE | TASK_FREEZABLE in do_wait(), so that the
freezer can freeze tasks waiting there directly, and in TASK_IDLE |
TASK_FREEZABLE in the final loop, like coredump_task_exit() does.

This was hit with Chromium-based browsers: crashpad ptrace-attaches the
threads of a crashed renderer, which is a pid namespace init, and does
not reap those killed during the dump.

Fixes: 3eb07c8c8adb ("pid namespaces: destroy pid namespace on init's death")
Fixes: b9a985db9896 ("pid_ns: Sleep in TASK_INTERRUPTIBLE in zap_pid_ns_processes")
Cc: stable@vger.kernel.org # 6.1+
Suggested-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Aviv Vaknin <vaknins33@gmail.com>
Link: https://patch.msgid.link/20261002202820.3433318-1-vaknins33@gmail.com
Acked-by: Oleg Nesterov <oleg@redhat.com>
Reviewed-by: Bradley Morgan <brads@mainlining.org>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 kernel/exit.c          |    2 +-
 kernel/pid_namespace.c |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -1696,7 +1696,7 @@ static long do_wait(struct wait_opts *wo
 	add_wait_queue(&current->signal->wait_chldexit, &wo->child_wait);
 
 	do {
-		set_current_state(TASK_INTERRUPTIBLE);
+		set_current_state(TASK_INTERRUPTIBLE | TASK_FREEZABLE);
 		retval = __do_wait(wo);
 		if (retval != -ERESTARTSYS)
 			break;
--- a/kernel/pid_namespace.c
+++ b/kernel/pid_namespace.c
@@ -246,7 +246,7 @@ void zap_pid_ns_processes(struct pid_nam
 	 * free_pid() will awaken this task.
 	 */
 	for (;;) {
-		set_current_state(TASK_INTERRUPTIBLE);
+		set_current_state(TASK_IDLE | TASK_FREEZABLE);
 		if (pid_ns->pid_allocated == init_pids)
 			break;
 		schedule();



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 069/247] eventfs: Free the eventfs_inode after an rcu grace period too
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (67 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 068/247] pid_namespace: make zap_pid_ns_processes() freezable Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 070/247] namei: test for a negative dentry the way traverse_mounts() does Greg Kroah-Hartman
                   ` (185 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Christian Brauner (Amutable),
	Steven Rostedt

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Christian Brauner <brauner@kernel.org>

commit 2cd88c498ecff8e22bf4c397b8eb226db70ac343 upstream.

tracefs_d_revalidate() reads ->is_freed of the eventfs_inode that
dentry->d_fsdata points to, and ->d_revalidate() is called in rcu
pathwalk mode with nothing but rcu_read_lock() held. The dentry itself
stays around for such a walker, but tracefs_d_release() drops its
reference to the eventfs_inode when the dentry is killed, and
release_ei() then frees it after a grace period of eventfs_srcu. An
SRCU grace period doesn't wait for rcu_read_lock() sections, so the
walker can read an eventfs_inode that is already gone.

With a pathwalk held up in tracefs_d_revalidate() while the dentry goes
away:

  BUG: KASAN: slab-use-after-free in tracefs_d_revalidate+0x76/0x90
  Read of size 1 at addr ff1100010152d8d0 by task walker/97
  Call Trace:
   <TASK>
   tracefs_d_revalidate+0x76/0x90
   lookup_fast+0x320/0x640
   path_lookupat+0x160/0xb00
   filename_lookup+0x1f1/0x5b0
   vfs_statx+0xd7/0x3b0
   vfs_fstatat+0x4d/0x90
   __do_sys_newfstatat+0xa0/0x100
   do_syscall_64+0x10e/0x5e0
   entry_SYSCALL_64_after_hwframe+0x77/0x7f
  [...]
  Allocated by task 1:
   __kmalloc_cache_noprof+0x249/0x560
   eventfs_create_dir+0x7a/0x590
   event_create_dir+0x2fb/0xcf0
   trace_add_event_call+0xbf/0x150
  [...]
  Freed by task 11:
   kfree+0x1db/0x5b0
   srcu_invoke_callbacks+0x3a3/0x620
   process_one_work+0x937/0x1810
   worker_thread+0x4f1/0xd60

Before commit 8e556432477e ("eventfs: Use SRCU for freeing
eventfs_inodes") release_ei() used call_rcu(), which covered the walker,
while eventfs_iterate() needs the SRCU grace period. Wait for both and
chain call_rcu() from the SRCU callback.

Cc: stable@vger.kernel.org
Fixes: 8e556432477e ("eventfs: Use SRCU for freeing eventfs_inodes")
Link: https://patch.msgid.link/20261009-work-fixes-rcu-v1-4-7446d2d335e6@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 fs/tracefs/event_inode.c |   10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

--- a/fs/tracefs/event_inode.c
+++ b/fs/tracefs/event_inode.c
@@ -91,6 +91,14 @@ static void free_ei_rcu(struct rcu_head
 	}
 }
 
+/* read under eventfs_srcu and, by tracefs_d_revalidate(), in rcu pathwalk */
+static void free_ei_srcu(struct rcu_head *rcu)
+{
+	struct eventfs_inode *ei = container_of(rcu, struct eventfs_inode, rcu);
+
+	call_rcu(&ei->rcu, free_ei_rcu);
+}
+
 /*
  * eventfs_inode reference count management.
  *
@@ -112,7 +120,7 @@ static void release_ei(struct kref *ref)
 			entry->release(entry->name, ei->data);
 	}
 
-	call_srcu(&eventfs_srcu, &ei->rcu, free_ei_rcu);
+	call_srcu(&eventfs_srcu, &ei->rcu, free_ei_srcu);
 }
 
 static inline void put_ei(struct eventfs_inode *ei)



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 070/247] namei: test for a negative dentry the way traverse_mounts() does
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (68 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 069/247] eventfs: Free the eventfs_inode after an rcu grace period too Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 071/247] net/sched: fix use-after-free in __tcf_action_put() Greg Kroah-Hartman
                   ` (184 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Jeff Layton,
	Christian Brauner (Amutable)

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Christian Brauner <brauner@kernel.org>

commit 98b6cf102b35b2bb48d1fd74d5f664eb66fe83eb upstream.

lookup_fast_for_open() only hands an O_CREAT open a cached dentry if
it's positive. Otherwise the open goes on to lookup_open(), which takes
the directory lock and creates the file. It tests for that with
!dentry->d_inode, but traverse_mounts() later decides with the type in
d_flags. And when a dentry is instantiated __d_set_inode_and_type()
stores ->d_inode first and only then releases the type into ->d_flags.

So a refwalk that took its reference to a negative dentry right before
another task instantiates it can find ->d_inode already set in
lookup_fast_for_open(), go on to step_into(), and still find the
negative type in traverse_mounts(). The open then fails with -ENOENT,
which an O_CREAT open must never do. rcuwalk doesn't get that far, the
d_seq check in step_into() catches the instantiation.

Use d_is_negative() so both look at the type. While the type is still
negative the open takes lookup_open() and waits for the directory lock
like any other O_CREAT open of a negative dentry.

On its own the window is a couple of instructions in the creating task,
so it takes an interrupt or a preempted vcpu in exactly the right spot.
I haven't caught it without help in about 600 million racing O_CREAT
opens.

The debug patch below stalls the creating task between the two stores
for names starting with "ocrace", the way an interrupt landing there
would. The reproducer below opens "ocrace" with O_CREAT through
symlinks on a strictatime tmpfs: following them updates their atime,
which drops the walk out of rcuwalk, so the name is always looked up in
refwalk. With

  echo 20 > /proc/sys/fs/ocrace_instantiate_us
  ./ocreat_enoent -t 60

on a KASAN kernel open() failed with -ENOENT 43 times in 4.9 million
calls. With this patch it never failed in 4.8 million calls. Tracing
step_into_slowpath() during such a run, each of the 98 -ENOENTs it
returned came right after the same task had entered it with a dentry
that was still typed negative.

  // SPDX-License-Identifier: GPL-2.0
  /*
   * ocreat_enoent: open(O_CREAT) racing the creation of the same name.
   *
   * Writers unlink "ocrace" and create it again. Readers open it with
   * O_CREAT through a symlink of their own on a strictatime tmpfs.
   * Following the symlink updates its atime, which drops the walk out of
   * rcu mode, so the name is always looked up in refwalk. An O_CREAT open
   * must never fail with ENOENT.
   *
   * -p arms a cpu-clock perf timer with that period in ns on every writer,
   * so that interrupts land at random points in it.
   *
   *   usage: ocreat_enoent [-t secs] [-w writers] [-r readers] [-p ns]
   */
  #define _GNU_SOURCE
  #include <errno.h>
  #include <fcntl.h>
  #include <pthread.h>
  #include <stdatomic.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include <sys/mount.h>
  #include <sys/stat.h>
  #include <sys/syscall.h>
  #include <unistd.h>
  #include <linux/perf_event.h>

  #define DIR "/tmp/oc"

  static atomic_int stop;
  static atomic_long opens, creates, enoent, other;
  static long period;

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

  static void *writer(void *arg)
  {
  	(void)arg;
  	if (period) {
  		struct perf_event_attr attr = {
  			.type = PERF_TYPE_SOFTWARE,
  			.size = sizeof(attr),
  			.config = PERF_COUNT_SW_CPU_CLOCK,
  			.sample_period = period,
  		};

  		if (syscall(SYS_perf_event_open, &attr, 0, -1, -1, 0) < 0)
  			die("perf_event_open");
  	}
  	while (!atomic_load(&stop)) {
  		int fd;

  		unlink(DIR "/ocrace");
  		fd = open(DIR "/ocrace", O_CREAT | O_RDWR | O_CLOEXEC, 0644);
  		if (fd >= 0)
  			close(fd);
  		atomic_fetch_add(&creates, 1);
  	}
  	return NULL;
  }

  static void *reader(void *arg)
  {
  	char lnk[64];

  	snprintf(lnk, sizeof(lnk), DIR "/lnk.%ld", (long)arg);
  	while (!atomic_load(&stop)) {
  		int fd = open(lnk, O_CREAT | O_RDWR | O_CLOEXEC, 0644);

  		if (fd >= 0)
  			close(fd);
  		else if (errno == ENOENT)
  			atomic_fetch_add(&enoent, 1);
  		else
  			atomic_fetch_add(&other, 1);
  		atomic_fetch_add(&opens, 1);
  	}
  	return NULL;
  }

  int main(int argc, char **argv)
  {
  	int secs = 60, nw = 4, nr = 12, c, n = 0;
  	pthread_t t[256];

  	while ((c = getopt(argc, argv, "t:w:r:p:")) != -1) {
  		switch (c) {
  		case 't': secs = atoi(optarg); break;
  		case 'w': nw = atoi(optarg); break;
  		case 'r': nr = atoi(optarg); break;
  		case 'p': period = atol(optarg); break;
  		default: return 2;
  		}
  	}
  	if (nw + nr > 256)
  		return 2;
  	mkdir(DIR, 0755);
  	if (mount("oc", DIR, "tmpfs", MS_STRICTATIME, "mode=0755"))
  		die("tmpfs");
  	for (long i = 0; i < nr; i++) {
  		char lnk[64];

  		snprintf(lnk, sizeof(lnk), DIR "/lnk.%ld", i);
  		if (symlink("ocrace", lnk))
  			die("symlink");
  	}
  	for (long i = 0; i < nw; i++)
  		if (pthread_create(&t[n++], NULL, writer, NULL))
  			die("writer");
  	for (long i = 0; i < nr; i++)
  		if (pthread_create(&t[n++], NULL, reader, (void *)i))
  			die("reader");
  	sleep(secs);
  	atomic_store(&stop, 1);
  	for (int i = 0; i < n; i++)
  		pthread_join(t[i], NULL);
  	printf("%ds: %ld opens, %ld creates, ENOENT %ld, other errors %ld\n",
  	       secs, atomic_load(&opens), atomic_load(&creates),
  	       atomic_load(&enoent), atomic_load(&other));
  	umount2(DIR, MNT_DETACH);
  	return atomic_load(&enoent) ? 1 : 0;
  }

#  diff --git a/fs/dcache.c b/fs/dcache.c
#  --- a/fs/dcache.c
#  +++ b/fs/dcache.c
#  @@ -32,9 +32,13 @@
#   #include <linux/bit_spinlock.h>
#   #include <linux/rculist_bl.h>
#   #include <linux/list_lru.h>
#  +#include <linux/delay.h>
#   #include "internal.h"
#   #include "mount.h"
#
#  +/* debug: stall "ocrace*" names between ->d_inode and the type */
#  +static int sysctl_ocrace_instantiate_us;
#  +
#   #include <asm/runtime-const.h>
#
#   /*
#  @@ -200,6 +204,13 @@
#   }
#
#   static const struct ctl_table fs_dcache_sysctls[] = {
#  +	{
#  +		.procname	= "ocrace_instantiate_us",
#  +		.data		= &sysctl_ocrace_instantiate_us,
#  +		.maxlen		= sizeof(int),
#  +		.mode		= 0644,
#  +		.proc_handler	= proc_dointvec,
#  +	},
#   	{
#   		.procname	= "dentry-state",
#   		.data		= &dentry_stat,
#  @@ -405,6 +416,10 @@
#   	unsigned flags;
#
#   	dentry->d_inode = inode;
#  +	/* debug: an interrupt landing right here */
#  +	if (unlikely(READ_ONCE(sysctl_ocrace_instantiate_us)) &&
#  +	    !strncmp(dentry->d_name.name, "ocrace", 6))
#  +		udelay(READ_ONCE(sysctl_ocrace_instantiate_us));
#   	flags = READ_ONCE(dentry->d_flags);
#   	flags &= ~DCACHE_ENTRY_TYPE;
#   	flags |= type_flags;

Fixes: e747e15156b7 ("fs: try an opportunistic lookup for O_CREAT opens too")
Cc: stable@vger.kernel.org # v6.12+
Link: https://patch.msgid.link/20261012-work-namei-ocreate-v1-1-c7883b17ee28@kernel.org
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 fs/namei.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

--- a/fs/namei.c
+++ b/fs/namei.c
@@ -3726,8 +3726,7 @@ static struct dentry *lookup_fast_for_op
 		return dentry;
 
 	if (open_flag & O_CREAT) {
-		/* Discard negative dentries. Need inode_lock to do the create */
-		if (!dentry->d_inode) {
+		if (d_is_negative(dentry)) {
 			if (!(nd->flags & LOOKUP_RCU))
 				dput(dentry);
 			dentry = NULL;



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 071/247] net/sched: fix use-after-free in __tcf_action_put()
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (69 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 070/247] namei: test for a negative dentry the way traverse_mounts() does Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 072/247] net: rds: fix uninitialized trans dereference in CM event handler Greg Kroah-Hartman
                   ` (183 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Jérémy Jean, Simon Horman,
	Paolo Abeni

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Jérémy Jean <Jeremy.Jean@oss.cyber.gouv.fr>

commit 7b16eb911091aae237a8673da94e4dfb9cd21d54 upstream.

__tcf_action_put() decrements the reference count before decrementing the
binding count. Another thread can free the action between these operations,
causing the binding-count update to access freed memory. KASAN reports it
as:

  BUG: KASAN: slab-use-after-free in __tcf_action_put+0x327/0x340
  Write of size 4 at addr ff11000000d46420 by task tc-put-pause/64

Hold the action IDR mutex across both counter updates and IDR removal,
keeping cleanup outside the lock.

Fixes: 16af6067392c ("net: sched: implement reference counted action release")
Cc: stable@vger.kernel.org
Assisted-by: LLM
Signed-off-by: Jérémy Jean <Jeremy.Jean@oss.cyber.gouv.fr>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20261008181348.527035-2-Jeremy.Jean@oss.cyber.gouv.fr
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 net/sched/act_api.c |   11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -372,9 +372,10 @@ static int __tcf_action_put(struct tc_ac
 {
 	struct tcf_idrinfo *idrinfo = p->idrinfo;
 
-	if (refcount_dec_and_mutex_lock(&p->tcfa_refcnt, &idrinfo->lock)) {
-		if (bind)
-			atomic_dec(&p->tcfa_bindcnt);
+	mutex_lock(&idrinfo->lock);
+	if (bind)
+		atomic_dec(&p->tcfa_bindcnt);
+	if (refcount_dec_and_test(&p->tcfa_refcnt)) {
 		idr_remove(&idrinfo->action_idr, p->tcfa_index);
 		mutex_unlock(&idrinfo->lock);
 
@@ -382,9 +383,7 @@ static int __tcf_action_put(struct tc_ac
 		return 1;
 	}
 
-	if (bind)
-		atomic_dec(&p->tcfa_bindcnt);
-
+	mutex_unlock(&idrinfo->lock);
 	return 0;
 }
 



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 072/247] net: rds: fix uninitialized trans dereference in CM event handler
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (70 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 071/247] net/sched: fix use-after-free in __tcf_action_put() Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 073/247] pinctrl: amd: Clear S4 wake bits when firmware has _AEI Greg Kroah-Hartman
                   ` (182 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, TencentOS Corvus AI, Aohan Mei,
	Allison Henderson, Paolo Abeni

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Aohan Mei <henrymei@tencent.com>

commit 492ba6ac1b1ffb8a06ff52db0825c1af2cdb28c8 upstream.

rds_rdma_cm_event_handler_cmn() assigns trans only when the RDMA
device is an InfiniBand CA (RDMA_NODE_IB_CA).  On any other device
type, e.g. an iWARP RNIC such as siw, trans stays uninitialized, but
the event switch dereferences it: unconditionally in the
RDMA_CM_EVENT_CONNECT_REQUEST case via trans->cm_handle_connect(),
and (with a connection context) in the ROUTE_RESOLVED and
ESTABLISHED cases.

An RDS listener on an iWARP device therefore crashes the kernel as
soon as a connect request arrives: with CONFIG_INIT_STACK_ALL_ZERO
the wild load becomes a NULL dereference at offset 0xa0
(&trans->cm_handle_connect) in the iw_cm_wq workqueue.

GCC masks the bug in default builds by folding the uninitialized
load into &rds_ib_transport; Clang-built kernels take the real
uninitialized path and oops.

The active side can land on a non-IB device too: the id that
rds_ib_conn_path_connect() creates is not restricted to a node type,
so rdma_resolve_addr() binds it to whichever device serves the local
address, and an iWARP RNIC on the same netdev qualifies.  The crash
there is different: resolving a route on an iWARP id never fills in
cm_id->route.path_rec, and the ROUTE_RESOLVED case writes
path_rec[0].sl before it calls into the transport.

The iWARP transport was dropped long ago and IB is the only
transport left, so make that explicit: initialize trans to
&rds_ib_transport at declaration, drop the conditional assignment,
reject a connect request that arrives on a non-IB device, and drop a
connection whose address resolved to one instead of resolving a
route on it.  The rejection is limited to RDMA_CM_EVENT_CONNECT_REQUEST
on purpose: a non-zero return from the handler makes rdma_cm destroy
the id the event was delivered on, which is right for the request's
freshly created id but would free a connection id that RDS still owns
for any other event.  On the active side the id stays ic->i_cm_id and
the connection's shutdown destroys it, so that case returns 0.

Fixes: dcdede0406d3 ("RDS: Drop stale iWARP RDMA transport")
Reported-by: TencentOS Corvus AI <corvus@tencent.com>
Link: https://lore.kernel.org/netdev/20260824111701.2979194-1-ljp1205831794@gmail.com/
Link: https://lore.kernel.org/netdev/20260825021223.3483044-1-ljp1205831794@gmail.com/
Cc: stable@vger.kernel.org
Assisted-by: CodeBuddy:Kimi-K3
Signed-off-by: Aohan Mei <henrymei@tencent.com>
[achender: reject only on RDMA_CM_EVENT_CONNECT_REQUEST instead of
 bailing out for every event on a non-IB device, so that rdma_cm does
 not destroy connection ids RDS still tracks; drop a connection whose
 address resolved to a non-IB device before a route is resolved on it;
 changelog adjusted]
Assisted-by: LLM
Signed-off-by: Allison Henderson <achender@kernel.org>
Link: https://patch.msgid.link/20261003163408.250568-2-achender@kernel.org
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 net/rds/rdma_transport.c |   26 ++++++++++++++++++++++----
 1 file changed, 22 insertions(+), 4 deletions(-)

--- a/net/rds/rdma_transport.c
+++ b/net/rds/rdma_transport.c
@@ -52,7 +52,7 @@ static int rds_rdma_cm_event_handler_cmn
 {
 	/* this can be null in the listening path */
 	struct rds_connection *conn = cm_id->context;
-	struct rds_transport *trans;
+	struct rds_transport *trans = &rds_ib_transport;
 	int ret = 0;
 	int *err;
 	u8 len;
@@ -60,9 +60,6 @@ static int rds_rdma_cm_event_handler_cmn
 	rdsdebug("conn %p id %p handling event %u (%s)\n", conn, cm_id,
 		 event->event, rdma_event_msg(event->event));
 
-	if (cm_id->device->node_type == RDMA_NODE_IB_CA)
-		trans = &rds_ib_transport;
-
 	/* Prevent shutdown from tearing down the connection
 	 * while we're executing. */
 	if (conn) {
@@ -82,11 +79,32 @@ static int rds_rdma_cm_event_handler_cmn
 
 	switch (event->event) {
 	case RDMA_CM_EVENT_CONNECT_REQUEST:
+		/* Only the IB transport is supported, but RDS listens on
+		 * every RDMA device: reject a request that arrived on any
+		 * other kind.  A non-zero return has rdma_cm destroy the
+		 * request's id, which is what we want here and only here.
+		 */
+		if (cm_id->device->node_type != RDMA_NODE_IB_CA) {
+			ret = 1;
+			break;
+		}
 		ret = trans->cm_handle_connect(cm_id, event, isv6);
 		break;
 
 	case RDMA_CM_EVENT_ADDR_RESOLVED:
 		if (conn) {
+			/* The address resolved to a device RDS has no
+			 * transport for.  Do not go on to resolve a route:
+			 * an iWARP route leaves cm_id->route.path_rec
+			 * unset, which the ROUTE_RESOLVED case below
+			 * dereferences.  Drop the connection instead; the
+			 * id is still ic->i_cm_id, so return 0 and let the
+			 * shutdown destroy it.
+			 */
+			if (cm_id->device->node_type != RDMA_NODE_IB_CA) {
+				rds_conn_drop(conn);
+				break;
+			}
 			rdma_set_service_type(cm_id, conn->c_tos);
 			rdma_set_min_rnr_timer(cm_id, IB_RNR_TIMER_000_32);
 			ret = rdma_resolve_route(cm_id,



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 073/247] pinctrl: amd: Clear S4 wake bits when firmware has _AEI
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (71 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 072/247] net: rds: fix uninitialized trans dereference in CM event handler Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 074/247] sctp: revalidate output stream after association connect wait Greg Kroah-Hartman
                   ` (181 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Olzhas Marat, Shyam Sundar S K,
	Mario Limonciello, Linus Walleij

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Mario Limonciello <mario.limonciello@amd.com>

commit 1cca81a683da7f0ef2fbaf34442376044cbbad22 upstream.

Commit ffe8a0c6b552 ("pinctrl-amd: Don't clear S4 wake bits at probe")
preserves firmware-programmed S4 wake sources because some PCIe devices
rely on them for Wake-on-LAN. The system that motivated that change does
not expose ACPI GPIO events through _AEI.

On a Chuwi CoreBook Plus, firmware exposes _AEI but also leaves the S4/S5
wake bit set for GPIO 24. This causes the machine to power back on
immediately after shutdown even though Wake-on-LAN is not enabled.

GPIO register dumps show that the only relevant difference is bit 15 on
GPIO 24. Clearing that bit makes the machine remain off. GPIO 24 is not
itself listed in _AEI, so _AEI is not a per-pin indication of which pins
the OS manages; it is a platform level signal of which wake model the
firmware follows.

Use that signal to decide what to clear. Continue clearing S0i3/S3 bits on
every system. Clear S4 bits when firmware exposes _AEI, indicating that the
platform hands GPIO events to the OS, but preserve S4 bits when _AEI is
absent so that firmware-programmed sources such as PCIe PME that bypass the
GPIO IRQ wake API keep working.

A platform that exposes _AEI for some pins while routing a wake capable
device through a raw GPIO not listed in _AEI would lose that wake source
unless firmware re-arms it during the sleep transition. No such system has
been reported.

Fixes: ffe8a0c6b552 ("pinctrl-amd: Don't clear S4 wake bits at probe")
Reported-by: Olzhas Marat <marat.olzhas@gmail.com>
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=222041
Cc: stable@vger.kernel.org
Tested-by: Olzhas Marat <marat.olzhas@gmail.com>
Reviewed-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Linus Walleij <linusw@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/pinctrl/pinctrl-amd.c |    9 +++++++++
 1 file changed, 9 insertions(+)

--- a/drivers/pinctrl/pinctrl-amd.c
+++ b/drivers/pinctrl/pinctrl-amd.c
@@ -871,6 +871,15 @@ static void amd_gpio_irq_init(struct amd
 
 	mask = BIT(WAKE_CNTRL_OFF_S0I3) | BIT(WAKE_CNTRL_OFF_S3);
 
+#ifdef CONFIG_ACPI
+	/*
+	 * Platforms without _AEI leave GPIO wake sources to firmware, so
+	 * preserve their S4 wake bits.
+	 */
+	if (acpi_has_method(ACPI_HANDLE(&gpio_dev->pdev->dev), "_AEI"))
+		mask |= BIT(WAKE_CNTRL_OFF_S4);
+#endif
+
 	for (i = 0; i < desc->npins; i++) {
 		int pin = desc->pins[i].number;
 		const struct pin_desc *pd = pin_desc_get(gpio_dev->pctrl, pin);



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 074/247] sctp: revalidate output stream after association connect wait
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (72 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 073/247] pinctrl: amd: Clear S4 wake bits when firmware has _AEI Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 075/247] tools: gpio: fix building from the top level with O= Greg Kroah-Hartman
                   ` (180 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Daehyeon Ko, Xin Long, Paolo Abeni

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Daehyeon Ko <4ncienth@gmail.com>

commit b7ad72414c673ce1fa1f463e807cd4f34f8be9bf upstream.

When message interleaving is enabled, the first send waits for association
establishment before building its data chunks.  The wait drops the socket
lock, and handshake processing can reduce the output stream count to the
peer-advertised inbound stream count.  sctp_stream_init() then frees the
extension of every removed stream.

The sender resumes with the stream that it checked before the wait.  If the
peer removed that stream, sctp_outq_tail() later dereferences its NULL
extension.  Fatal-oops policies then panic the host.

KASAN: null-ptr-deref in range [0x38-0x3f]
RIP: sctp_outq_tail+0x49e/0xaa0
Call Trace:
 sctp_primitive_SEND
 sctp_sendmsg_to_asoc
 sctp_sendmsg

A range check alone is insufficient.  Stream reconfiguration can grow the
output count again while the lock is released without recreating extensions
freed by the earlier shrink.  The stream can then be in range while its
extension remains NULL.  The send-buffer wait has the same issue.

Factor the range and extension checks into a helper and repeat both after
each send-path wait that drops the socket lock.  Once the lock is
reacquired, the validation remains stable through data creation and
queueing.

If validation fails after the connect wait, the auto-created association is
already established.  Return ESRCH so the existing caller path keeps it
under state-machine ownership instead of freeing it directly, which would
leave protocol, counter and socket state inconsistent.

Fixes: 668c9beb9020 ("sctp: implement assign_number for sctp_stream_interleave")
Cc: stable@vger.kernel.org
Assisted-by: LLM
Signed-off-by: Daehyeon Ko <4ncienth@gmail.com>
Acked-by: Xin Long <lucien.xin@gmail.com>
Link: https://patch.msgid.link/20261007035739.3472432-1-4ncienth@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 net/sctp/socket.c |   33 +++++++++++++++++++++------------
 1 file changed, 21 insertions(+), 12 deletions(-)

--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -1786,6 +1786,18 @@ static int sctp_sendmsg_check_sflags(str
 	return 1;
 }
 
+static int sctp_sendmsg_check_stream(struct sctp_association *asoc,
+				     struct sctp_sndrcvinfo *sinfo)
+{
+	if (unlikely(sinfo->sinfo_stream >= asoc->stream.outcnt))
+		return -EINVAL;
+
+	if (unlikely(!SCTP_SO(&asoc->stream, sinfo->sinfo_stream)->ext))
+		return sctp_stream_init_ext(&asoc->stream, sinfo->sinfo_stream);
+
+	return 0;
+}
+
 static int sctp_sendmsg_to_asoc(struct sctp_association *asoc,
 				struct msghdr *msg, size_t msg_len,
 				struct sctp_transport *transport,
@@ -1800,16 +1812,9 @@ static int sctp_sendmsg_to_asoc(struct s
 	long timeo;
 	int err;
 
-	if (sinfo->sinfo_stream >= asoc->stream.outcnt) {
-		err = -EINVAL;
+	err = sctp_sendmsg_check_stream(asoc, sinfo);
+	if (err)
 		goto err;
-	}
-
-	if (unlikely(!SCTP_SO(&asoc->stream, sinfo->sinfo_stream)->ext)) {
-		err = sctp_stream_init_ext(&asoc->stream, sinfo->sinfo_stream);
-		if (err)
-			goto err;
-	}
 
 	if (sp->disable_fragments && msg_len > asoc->frag_point) {
 		err = -EMSGSIZE;
@@ -1830,10 +1835,9 @@ static int sctp_sendmsg_to_asoc(struct s
 		err = sctp_wait_for_sndbuf(asoc, transport, &timeo, msg_len);
 		if (err)
 			goto err;
-		if (unlikely(sinfo->sinfo_stream >= asoc->stream.outcnt)) {
-			err = -EINVAL;
+		err = sctp_sendmsg_check_stream(asoc, sinfo);
+		if (err)
 			goto err;
-		}
 	}
 
 	if (sctp_state(asoc, CLOSED)) {
@@ -1848,6 +1852,11 @@ static int sctp_sendmsg_to_asoc(struct s
 				err = -ESRCH;
 				goto err;
 			}
+			err = sctp_sendmsg_check_stream(asoc, sinfo);
+			if (err) {
+				err = -ESRCH;
+				goto err;
+			}
 		} else {
 			wait_connect = true;
 		}



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 075/247] tools: gpio: fix building from the top level with O=
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (73 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 074/247] sctp: revalidate output stream after association connect wait Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:57 ` [PATCH 6.12 076/247] tracing/histograms: Reject non-stacktrace fields for synthetic stacktrace fields Greg Kroah-Hartman
                   ` (179 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Sasha Levin, Bartosz Golaszewski

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Sasha Levin <sashal@kernel.org>

commit 52336337f1a01ad803c7f3ddb23f40222e9ad58d upstream.

"make O=<dir> tools/gpio" fails:

  Makefile:27: /tools/build/Makefile.include: No such file or directory

tools/Makefile clears srctree, and the gpio Makefile only works it out
again when building_out_of_srctree is not set, which the top-level
Makefile sets for O= builds.

Also work out srctree when it is empty, as tools/bpf/Makefile does
since commit a89b2cbf71d64 ("tools, bpf: Fix build for 'make -s
tools/bpf O=<dir>'").

Fixes: 4a6a6f5c4aeed ("tools: gpio: Use !building_out_of_srctree to determine srctree")
Cc: stable@vger.kernel.org
Assisted-by: LLM
Signed-off-by: Sasha Levin <sashal@kernel.org>
Link: https://patch.msgid.link/20261011223358.2327625-5-sashal@kernel.org
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 tools/gpio/Makefile |    6 ++++++
 1 file changed, 6 insertions(+)

--- a/tools/gpio/Makefile
+++ b/tools/gpio/Makefile
@@ -7,7 +7,13 @@ bindir ?= /usr/bin
 # isn't set and when invoked from selftests build, where srctree
 # is set to ".". building_out_of_srctree is undefined for in srctree
 # builds
+ifeq ($(srctree),)
+update_srctree := 1
+endif
 ifndef building_out_of_srctree
+update_srctree := 1
+endif
+ifeq ($(update_srctree),1)
 srctree := $(patsubst %/,%,$(dir $(CURDIR)))
 srctree := $(patsubst %/,%,$(dir $(srctree)))
 endif



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 076/247] tracing/histograms: Reject non-stacktrace fields for synthetic stacktrace fields
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (74 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 075/247] tools: gpio: fix building from the top level with O= Greg Kroah-Hartman
@ 2026-10-28 16:57 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 077/247] i2c: qcom-cci: Fix HALT_ACK reset request being dropped Greg Kroah-Hartman
                   ` (178 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:57 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Lee Jones, Masami Hiramatsu (Google),
	Steven Rostedt

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Lee Jones <lee@kernel.org>

commit a244c241593b5b38a08f0df2cb43c26574efbdcb upstream.

In check_synth_field(), when a synthetic event field is a stacktrace
(field->is_stack) and the histogram field is not a "long[" stacktrace
array, validation falls through to the generic size and signedness
comparison.

Because parse_synth_field() sets a stacktrace field's type to
"__data_loc unsigned long[]", its size is sizeof(u64) and
synth_field_signed() marks it as signed.  Consequently, any 8-byte
signed scalar histogram field passes the fallback check, and its scalar
value is subsequently dereferenced as a kernel stacktrace pointer in
get_field_size() and trace_stack().

Furthermore, checking strstr(hist_field->type, "long[") is insufficient
because tracepoint fields defined with __bitmask() or __rel_bitmask()
also have type "__data_loc unsigned long[]" or "__rel_loc unsigned
long[]", whilst create_hist_field() treats them as 4-byte scalar values
without HIST_FIELD_FL_STACKTRACE.

Propagate HIST_FIELD_FL_STACKTRACE to variable references and field
variables (whilst excluding variable aliases from per-element
stacktrace capture), and reject any mismatch between
HIST_FIELD_FL_STACKTRACE and field->is_stack in check_synth_field().

Cc: stable@vger.kernel.org
Fixes: 00cf3d672a9d ("tracing: Allow synthetic events to pass around stacktraces")
Link: https://patch.msgid.link/20261013112449.1006088-1-lee@kernel.org
Signed-off-by: Lee Jones <lee@kernel.org>
Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 kernel/trace/trace_events_hist.c |   15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

--- a/kernel/trace/trace_events_hist.c
+++ b/kernel/trace/trace_events_hist.c
@@ -2098,7 +2098,8 @@ static int init_var_ref(struct hist_fiel
 	ref_field->size = var_field->size;
 	ref_field->is_signed = var_field->is_signed;
 	ref_field->flags |= var_field->flags &
-		(HIST_FIELD_FL_TIMESTAMP | HIST_FIELD_FL_TIMESTAMP_USECS);
+		(HIST_FIELD_FL_TIMESTAMP | HIST_FIELD_FL_TIMESTAMP_USECS |
+		 HIST_FIELD_FL_STACKTRACE);
 
 	if (system) {
 		ref_field->system = kstrdup(system, GFP_KERNEL);
@@ -3286,6 +3287,7 @@ static struct field_var *create_field_va
 		ret =  -ENOMEM;
 		goto err;
 	}
+	var->flags |= val->flags & HIST_FIELD_FL_STACKTRACE;
 
 	field_var->var = var;
 	field_var->val = val;
@@ -3904,7 +3906,10 @@ static int check_synth_field(struct synt
 	    && field->is_dynamic)
 		return 0;
 
-	if (strstr(hist_field->type, "long[") && field->is_stack)
+	if (!!(hist_field->flags & HIST_FIELD_FL_STACKTRACE) != field->is_stack)
+		return -EINVAL;
+
+	if (field->is_stack)
 		return 0;
 
 	if (strcmp(field->type, hist_field->type) != 0) {
@@ -4443,7 +4448,8 @@ static int create_var_field(struct hist_
 	if (!ret && hist_data->fields[val_idx]->flags & HIST_FIELD_FL_EXECNAME)
 		update_var_execname(hist_data->fields[val_idx]);
 
-	if (!ret && hist_data->fields[val_idx]->flags &
+	if (!ret && !(hist_data->fields[val_idx]->flags & HIST_FIELD_FL_ALIAS) &&
+	    hist_data->fields[val_idx]->flags &
 	    (HIST_FIELD_FL_STRING | HIST_FIELD_FL_STACKTRACE))
 		hist_data->fields[val_idx]->var_str_idx = hist_data->n_var_str++;
 
@@ -5184,7 +5190,8 @@ static void hist_trigger_elt_update(stru
 		if (hist_field->flags & HIST_FIELD_FL_VAR) {
 			var_idx = hist_field->var.idx;
 
-			if (hist_field->flags &
+			if (!(hist_field->flags & HIST_FIELD_FL_ALIAS) &&
+			    hist_field->flags &
 			    (HIST_FIELD_FL_STRING | HIST_FIELD_FL_STACKTRACE)) {
 				unsigned int str_start, var_str_idx, idx;
 				char *str, *val_str;



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 077/247] i2c: qcom-cci: Fix HALT_ACK reset request being dropped
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (75 preceding siblings ...)
  2026-10-28 16:57 ` [PATCH 6.12 076/247] tracing/histograms: Reject non-stacktrace fields for synthetic stacktrace fields Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 078/247] perf: Update cgroup time when rotating multiplexed events Greg Kroah-Hartman
                   ` (177 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Loic Poulain, Konrad Dybcio,
	Andi Shyti

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Loic Poulain <loic.poulain@oss.qualcomm.com>

commit 195f3d74b5de98969dc4fad956393bb00787efd1 upstream.

A HALT_ACK interrupt indicates that the corresponding I2C master has
entered the halted state and must be reset before further operation.

The M0 and M1 HALT_ACK status bits may be asserted simultaneously in a
single interrupt. However, the interrupt handler currently overwrites
the reset mask when processing each HALT_ACK condition, causing the
first reset request to be lost if both events are reported together.

Accumulate reset requests instead of overwriting them so that both
masters are properly reset when M0 and M1 HALT_ACK events occur in the
same interrupt.

Fixes: e517526195de4 ("i2c: Add Qualcomm CCI I2C driver")
Signed-off-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
Cc: <stable@vger.kernel.org> # v5.8+
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
Link: https://patch.msgid.link/20261012-cci-fixes-v1-1-8cd4eb1fc5f9@oss.qualcomm.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/i2c/busses/i2c-qcom-cci.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

--- a/drivers/i2c/busses/i2c-qcom-cci.c
+++ b/drivers/i2c/busses/i2c-qcom-cci.c
@@ -168,12 +168,12 @@ static irqreturn_t cci_isr(int irq, void
 	}
 
 	if (unlikely(val & CCI_IRQ_STATUS_0_I2C_M0_Q0Q1_HALT_ACK)) {
-		reset = CCI_RESET_CMD_M0_MASK;
+		reset |= CCI_RESET_CMD_M0_MASK;
 		ret = IRQ_HANDLED;
 	}
 
 	if (unlikely(val & CCI_IRQ_STATUS_0_I2C_M1_Q0Q1_HALT_ACK)) {
-		reset = CCI_RESET_CMD_M1_MASK;
+		reset |= CCI_RESET_CMD_M1_MASK;
 		ret = IRQ_HANDLED;
 	}
 



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 078/247] perf: Update cgroup time when rotating multiplexed events
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (76 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 077/247] i2c: qcom-cci: Fix HALT_ACK reset request being dropped Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 079/247] ring-buffer: Do not show buffer_meta for CPUs without a buffer Greg Kroah-Hartman
                   ` (176 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Antoine Huret,
	Peter Zijlstra (Intel)

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Antoine Huret <antoine.huret@bull.com>

commit e4c7c401c6b9174c0c893084fdaa6a84bd2520d7 upstream.

Since commit bd2756811766 ("perf: Rewrite core context handling"),
perf_rotate_context() only updates the context time before scheduling
out the flexible events. It no longer updates the cgroup time, which
ctx_sched_out() used to do.

Cgroup events take their times from the per-cpu cgroup clock, so
between two cgroup switches the rotations see a frozen clock. The
events rotated out lose the running time they accumulated, and the next
update, usually a read, credits the whole interval to the events that
happen to be on the PMU at that moment.

As a result, the time_running of multiplexed cgroup events is wrong,
and so are their scaled counts, as long as no other cgroup runs on the
CPU, e.g. a busy job alone on its CPUs. Counting cycles over one second
of a busy loop in a cgroup gives from half to several times the max
frequency of the CPU.

Update the cgroup time before rotating the CPU context, as was done
before the rewrite.

Fixes: bd2756811766 ("perf: Rewrite core context handling")
Closes: https://lore.kernel.org/r/PR3PR07MB69223331EED5BEBE150375B7849C2@PR3PR07MB6922.eurprd07.prod.outlook.com/
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Antoine Huret <antoine.huret@bull.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20261015-perf-cgroup-rotation-time-v1-1-93e177dfee5d@bull.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 kernel/events/core.c |    1 +
 1 file changed, 1 insertion(+)

--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -4451,6 +4451,7 @@ static bool perf_rotate_context(struct p
 
 	if (cpu_event) {
 		update_context_time(&cpuctx->ctx);
+		update_cgrp_time_from_cpuctx(cpuctx, false);
 		__pmu_ctx_sched_out(cpu_epc, EVENT_FLEXIBLE);
 		rotate_ctx(&cpuctx->ctx, cpu_event);
 		__pmu_ctx_sched_in(cpu_epc, EVENT_FLEXIBLE);



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 079/247] ring-buffer: Do not show buffer_meta for CPUs without a buffer
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (77 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 078/247] perf: Update cgroup time when rotating multiplexed events Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 080/247] ring-buffer: Fix the sub-buffer array base in rb_meta_subbuf_idx() Greg Kroah-Hartman
                   ` (175 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Sashiko, David Carlier,
	Steven Rostedt

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: David Carlier <devnexen@gmail.com>

commit 3f23cae09a4677a3f7c163a68388512cb231ff22 upstream.

The per_cpu/cpuN/buffer_meta files are created for every possible CPU,
but buffer->buffers[cpu] is only allocated once that CPU comes online.
Reading the file of a CPU that never came online dereferences a NULL
cpu_buffer in rbm_start().

Fail the open with -ENODEV when the CPU has no buffer, as the other
per CPU ring buffer interfaces do.

Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20260914133506.4865-3-devnexen@gmail.com
Fixes: 950032ffcee7 ("ring-buffer: Add output of ring buffer meta page")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://lore.kernel.org/all/20260913134906.6E8A01F000FF@smtp.kernel.org/
Signed-off-by: David Carlier <devnexen@gmail.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 kernel/trace/ring_buffer.c |    3 +++
 1 file changed, 3 insertions(+)

--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -2106,6 +2106,9 @@ int ring_buffer_meta_seq_init(struct fil
 	struct seq_file *m;
 	int ret;
 
+	if (!cpumask_test_cpu(cpu, buffer->cpumask))
+		return -ENODEV;
+
 	ret = seq_open(file, &rb_meta_seq_ops);
 	if (ret)
 		return ret;



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 080/247] ring-buffer: Fix the sub-buffer array base in rb_meta_subbuf_idx()
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (78 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 079/247] ring-buffer: Do not show buffer_meta for CPUs without a buffer Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 081/247] ring-buffer: Fix false warning in ring_buffer_map_get_reader() Greg Kroah-Hartman
                   ` (174 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Donggeun Yoo, Vincent Donnefort,
	Masami Hiramatsu (Google), Steven Rostedt

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Donggeun Yoo <donggeunyoo.kernel@gmail.com>

commit 25132363c723afc39aace8b098f547ab4a0ea759 upstream.

On a persistent ring buffer, rb_meta_subbuf_idx() can return an index one
sub-buffer too high.  rb_setup_ids_meta_page() then fills subbuf_ids[]
shifted by one and leaves subbuf_ids[0] NULL, which __rb_map_vma()
dereferences when userspace maps trace_pipe_raw.  rb_update_meta_reader()
writes two such indices into meta->buffers[], which rb_cpu_meta_valid()
would reject on the next boot, discarding the previous boot's trace.

A CPU's sub-buffer array starts after its meta header and the nr_subbufs
integers that follow, aligned up to a sub-buffer.  rb_meta_subbuf_idx()
inverts that calculation but skips only the integers, not the header, so
its base is one sub-buffer low whenever the omitted header size crosses
the alignment boundary.

Invert the calculation with rb_subbufs_from_meta() rather than repeating
it.  rb_range_buffer() maps an index back to an address through the same
helper, so the two directions can no longer disagree.

Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20260918071507.1019251-1-donggeunyoo.kernel@gmail.com
Fixes: b14d032973d4 ("ring-buffer: Add ring_buffer_meta data")
Signed-off-by: Donggeun Yoo <donggeunyoo.kernel@gmail.com>
Reviewed-by: Vincent Donnefort <vdonnefort@google.com>
Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 kernel/trace/ring_buffer.c |    4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -3203,10 +3203,8 @@ static void rb_inc_iter(struct ring_buff
 /* Return the index into the sub-buffers for a given sub-buffer */
 static int rb_meta_subbuf_idx(struct ring_buffer_meta *meta, void *subbuf)
 {
-	void *subbuf_array;
+	void *subbuf_array = rb_subbufs_from_meta(meta);
 
-	subbuf_array = (void *)meta + sizeof(int) * meta->nr_subbufs;
-	subbuf_array = (void *)ALIGN((unsigned long)subbuf_array, meta->subbuf_size);
 	return (subbuf - subbuf_array) / meta->subbuf_size;
 }
 



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 081/247] ring-buffer: Fix false warning in ring_buffer_map_get_reader()
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (79 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 080/247] ring-buffer: Fix the sub-buffer array base in rb_meta_subbuf_idx() Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 082/247] scsi: bsg: Pass reply_len to bsg_setup_queue() to fit UFS ARPMB replies Greg Kroah-Hartman
                   ` (173 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, syzbot+de3d7f9bcc9212f3fae1,
	Krystian Kaniewski, Vincent Donnefort, Steven Rostedt

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Krystian Kaniewski <krystianmkaniewski@gmail.com>

commit 89bab1dba8a0167ef0d819e0f55b6bafa038e87f upstream.

The mmap reader can warn when it catches up with a writer that is still
committing events. rb_get_reader_page() returns NULL in this case, but
ring_buffer_map_get_reader() treats that result as an error.

The initial rb_per_cpu_empty() check filters out an empty buffer, but it
does not guarantee that the next reader page has committed data. Writers
do not take reader_lock and can advance commit_page before publishing the
committed length on the new page. rb_get_reader_page() can swap to that
page, catch up with the writer and return NULL.

Handle NULL through the existing no-data exit without warning. Remove the
caller's reader_page == commit_page check as well, since the reader-page
helper already handles that case. The existing metadata update and return
path remain in place.

Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20260924084946.20104-1-krystianmkaniewski@gmail.com
Fixes: 117c39200d9d ("ring-buffer: Introducing ring-buffer mapping functions")
Assisted-by: Gemini:gemini-3.8-flash syzbot
Reported-by: syzbot+de3d7f9bcc9212f3fae1@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=de3d7f9bcc9212f3fae1
Link: https://syzkaller.appspot.com/ai_job?id=488adc18-a10e-42d2-a205-25327c38837f
Signed-off-by: Krystian Kaniewski <krystianmkaniewski@gmail.com>
Reviewed-by: Vincent Donnefort <vdonnefort@google.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 kernel/trace/ring_buffer.c |    6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -7358,12 +7358,8 @@ consume:
 		goto out;
 	}
 
-	/* Did the reader catch up with the writer? */
-	if (cpu_buffer->reader_page == cpu_buffer->commit_page)
-		goto out;
-
 	reader = rb_get_reader_page(cpu_buffer);
-	if (WARN_ON(!reader))
+	if (!reader)
 		goto out;
 
 	/* Check if any events were dropped */



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 082/247] scsi: bsg: Pass reply_len to bsg_setup_queue() to fit UFS ARPMB replies
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (80 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 081/247] ring-buffer: Fix false warning in ring_buffer_map_get_reader() Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 083/247] scsi: xen/scsifront: Check for a NULL shadow entry on a backend response Greg Kroah-Hartman
                   ` (172 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Stanley Jhu,
	Martin K. Petersen (Oracle)

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Stanley Jhu <stanleyjhu@google.com>

commit ec6b083915e8146e147314a5f4f1285d07b57bfc upstream.

bsg-lib allocates a 96-byte (SCSI_SENSE_BUFFERSIZE) reply buffer per
job, but struct ufs_rpmb_reply is 104 bytes: a 40-byte struct
ufs_bsg_reply followed by a 64-byte EHS. When an Advanced RPMB command
returns an EHS, ufshcd_advanced_rpmb_req_handler() copies it right after
the 40-byte header and writes 8 bytes past the end of the buffer.

Let each BSG transport pass its reply buffer size to bsg_setup_queue()
and have ufs_bsg request sizeof(struct ufs_rpmb_reply), so the full
reply reaches user space. Other transports keep SCSI_SENSE_BUFFERSIZE.

Fixes: 6ff265fc5ef6 ("scsi: ufs: core: bsg: Add advanced RPMB support in ufs_bsg")
Cc: stable@vger.kernel.org
Signed-off-by: Stanley Jhu <stanleyjhu@google.com>
Link: https://patch.msgid.link/20261013132708.1669415-1-stanleyjhu@google.com
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 block/bsg-lib.c                     |   13 ++++++++++---
 drivers/scsi/mpi3mr/mpi3mr_app.c    |    2 +-
 drivers/scsi/scsi_transport_fc.c    |    6 ++++--
 drivers/scsi/scsi_transport_iscsi.c |    2 +-
 drivers/scsi/scsi_transport_sas.c   |    6 ++++--
 drivers/ufs/core/ufs_bsg.c          |    2 +-
 include/linux/bsg-lib.h             |    3 ++-
 7 files changed, 23 insertions(+), 11 deletions(-)

--- a/block/bsg-lib.c
+++ b/block/bsg-lib.c
@@ -23,11 +23,14 @@ struct bsg_set {
 	struct bsg_device	*bd;
 	bsg_job_fn		*job_fn;
 	bsg_timeout_fn		*timeout_fn;
+	unsigned int		reply_len;
 };
 
 static int bsg_transport_sg_io_fn(struct request_queue *q, struct sg_io_v4 *hdr,
 		bool open_for_write, unsigned int timeout)
 {
+	struct bsg_set *bset =
+		container_of(q->tag_set, struct bsg_set, tag_set);
 	struct bsg_job *job;
 	struct request *rq;
 	struct bio *bio;
@@ -50,7 +53,7 @@ static int bsg_transport_sg_io_fn(struct
 	reply = job->reply;
 	memset(job, 0, sizeof(*job));
 	job->reply = reply;
-	job->reply_len = SCSI_SENSE_BUFFERSIZE;
+	job->reply_len = bset->reply_len;
 	job->dd_data = job + 1;
 
 	job->request_len = hdr->request_len;
@@ -301,9 +304,10 @@ out:
 static int bsg_init_rq(struct blk_mq_tag_set *set, struct request *req,
 		       unsigned int hctx_idx, unsigned int numa_node)
 {
+	struct bsg_set *bset = container_of(set, struct bsg_set, tag_set);
 	struct bsg_job *job = blk_mq_rq_to_pdu(req);
 
-	job->reply = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
+	job->reply = kzalloc(bset->reply_len, GFP_KERNEL);
 	if (!job->reply)
 		return -ENOMEM;
 	return 0;
@@ -358,10 +362,12 @@ static const struct blk_mq_ops bsg_mq_op
  * @job_fn: bsg job handler
  * @timeout: timeout handler function pointer
  * @dd_job_size: size of LLD data needed for each job
+ * @reply_len: size of the reply buffer needed for each job
  */
 struct request_queue *bsg_setup_queue(struct device *dev, const char *name,
 		struct queue_limits *lim, bsg_job_fn *job_fn,
-		bsg_timeout_fn *timeout, int dd_job_size)
+		bsg_timeout_fn *timeout, int dd_job_size,
+		unsigned int reply_len)
 {
 	struct bsg_set *bset;
 	struct blk_mq_tag_set *set;
@@ -374,6 +380,7 @@ struct request_queue *bsg_setup_queue(st
 
 	bset->job_fn = job_fn;
 	bset->timeout_fn = timeout;
+	bset->reply_len = reply_len;
 
 	set = &bset->tag_set;
 	set->ops = &bsg_mq_ops;
--- a/drivers/scsi/mpi3mr/mpi3mr_app.c
+++ b/drivers/scsi/mpi3mr/mpi3mr_app.c
@@ -2968,7 +2968,7 @@ void mpi3mr_bsg_init(struct mpi3mr_ioc *
 	}
 
 	q = bsg_setup_queue(bsg_dev, dev_name(bsg_dev), &lim,
-			mpi3mr_bsg_request, NULL, 0);
+			mpi3mr_bsg_request, NULL, 0, SCSI_SENSE_BUFFERSIZE);
 	if (IS_ERR(q)) {
 		ioc_err(mrioc, "%s: bsg registration failed\n",
 		    dev_name(bsg_dev));
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -4290,7 +4290,8 @@ fc_bsg_hostadd(struct Scsi_Host *shost,
 	scsi_init_limits(shost, &lim);
 	lim.max_segments = min_not_zero(lim.max_segments, i->f->max_bsg_segments);
 	q = bsg_setup_queue(dev, bsg_name, &lim, fc_bsg_dispatch,
-			fc_bsg_job_timeout, i->f->dd_bsg_size);
+			fc_bsg_job_timeout, i->f->dd_bsg_size,
+			SCSI_SENSE_BUFFERSIZE);
 	if (IS_ERR(q)) {
 		dev_err(dev,
 			"fc_host%d: bsg interface failed to initialize - setup queue\n",
@@ -4323,7 +4324,8 @@ fc_bsg_rportadd(struct Scsi_Host *shost,
 	scsi_init_limits(shost, &lim);
 	lim.max_segments = min_not_zero(lim.max_segments, i->f->max_bsg_segments);
 	q = bsg_setup_queue(dev, dev_name(dev), &lim, fc_bsg_dispatch_prep,
-				fc_bsg_job_timeout, i->f->dd_bsg_size);
+				fc_bsg_job_timeout, i->f->dd_bsg_size,
+				SCSI_SENSE_BUFFERSIZE);
 	if (IS_ERR(q)) {
 		dev_err(dev, "failed to setup bsg queue\n");
 		return PTR_ERR(q);
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -1545,7 +1545,7 @@ iscsi_bsg_host_add(struct Scsi_Host *sho
 	snprintf(bsg_name, sizeof(bsg_name), "iscsi_host%d", shost->host_no);
 	scsi_init_limits(shost, &lim);
 	q = bsg_setup_queue(dev, bsg_name, &lim, iscsi_bsg_host_dispatch, NULL,
-			0);
+			0, SCSI_SENSE_BUFFERSIZE);
 	if (IS_ERR(q)) {
 		shost_printk(KERN_ERR, shost, "bsg interface failed to "
 			     "initialize - no request queue\n");
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -199,7 +199,8 @@ static int sas_bsg_initialize(struct Scs
 
 	if (rphy) {
 		q = bsg_setup_queue(&rphy->dev, dev_name(&rphy->dev), NULL,
-				sas_smp_dispatch, NULL, 0);
+				sas_smp_dispatch, NULL, 0,
+				SCSI_SENSE_BUFFERSIZE);
 		if (IS_ERR(q))
 			return PTR_ERR(q);
 		rphy->q = q;
@@ -208,7 +209,8 @@ static int sas_bsg_initialize(struct Scs
 
 		snprintf(name, sizeof(name), "sas_host%d", shost->host_no);
 		q = bsg_setup_queue(&shost->shost_gendev, name, NULL,
-				sas_smp_dispatch, NULL, 0);
+				sas_smp_dispatch, NULL, 0,
+				SCSI_SENSE_BUFFERSIZE);
 		if (IS_ERR(q))
 			return PTR_ERR(q);
 		to_sas_host_attrs(shost)->q = q;
--- a/drivers/ufs/core/ufs_bsg.c
+++ b/drivers/ufs/core/ufs_bsg.c
@@ -257,7 +257,7 @@ int ufs_bsg_probe(struct ufs_hba *hba)
 		goto out;
 
 	q = bsg_setup_queue(bsg_dev, dev_name(bsg_dev), NULL, ufs_bsg_request,
-			NULL, 0);
+			NULL, 0, sizeof(struct ufs_rpmb_reply));
 	if (IS_ERR(q)) {
 		ret = PTR_ERR(q);
 		device_del(bsg_dev);
--- a/include/linux/bsg-lib.h
+++ b/include/linux/bsg-lib.h
@@ -66,7 +66,8 @@ void bsg_job_done(struct bsg_job *job, i
 		  unsigned int reply_payload_rcv_len);
 struct request_queue *bsg_setup_queue(struct device *dev, const char *name,
 		struct queue_limits *lim, bsg_job_fn *job_fn,
-		bsg_timeout_fn *timeout, int dd_job_size);
+		bsg_timeout_fn *timeout, int dd_job_size,
+		unsigned int reply_len);
 void bsg_remove_queue(struct request_queue *q);
 void bsg_job_put(struct bsg_job *job);
 int __must_check bsg_job_get(struct bsg_job *job);



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 083/247] scsi: xen/scsifront: Check for a NULL shadow entry on a backend response
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (81 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 082/247] scsi: bsg: Pass reply_len to bsg_setup_queue() to fit UFS ARPMB replies Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 084/247] scsi: libiscsi: Reject a negative task index from parse_pdu_itt Greg Kroah-Hartman
                   ` (171 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Yehyeong Lee, Juergen Gross,
	Martin K. Petersen (Oracle)

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Yehyeong Lee <yhlee@isslab.korea.ac.kr>

commit 8c8222c255772713eb36cde695777a1fce224917 upstream.

scsifront_do_response() validates the rqid in a backend response against
VSCSIIF_MAX_REQS before using it to index info->shadow[], but then
dereferences the entry to test ->inflight without checking that the slot
is populated.  Shadow slots are NULL before a command is submitted (the
host private area is zeroed at allocation) and are reset to NULL in
_scsifront_put_rqid() once a request completes, so an in-range rqid that
does not correspond to an outstanding request makes the frontend
dereference a NULL pointer.

A malicious or buggy backend can thus crash the guest by returning a
response whose rqid is in range but not in flight -- for example a
spurious response before any command has been issued, or a duplicate of
one already completed.  The ring has only VSCSIIF_MAX_REQS (16) slots,
so before the first command every in-range rqid selects a NULL slot.

Reject a response whose shadow slot is not populated.

Fixes: 6d1c2f48f3fc ("xen/scsifront: harden driver against malicious backend")
Cc: stable@vger.kernel.org
Signed-off-by: Yehyeong Lee <yhlee@isslab.korea.ac.kr>
Reviewed-by: Juergen Gross <jgross@suse.com>
Link: https://patch.msgid.link/20261005123555.253995-1-yhlee@isslab.korea.ac.kr
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/scsi/xen-scsifront.c |    1 +
 1 file changed, 1 insertion(+)

--- a/drivers/scsi/xen-scsifront.c
+++ b/drivers/scsi/xen-scsifront.c
@@ -367,6 +367,7 @@ static void scsifront_do_response(struct
 	struct vscsifrnt_shadow *shadow;
 
 	if (ring_rsp->rqid >= VSCSIIF_MAX_REQS ||
+	    !info->shadow[ring_rsp->rqid] ||
 	    !info->shadow[ring_rsp->rqid]->inflight) {
 		scsifront_set_error(info, "illegal rqid returned by backend!");
 		return;



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 084/247] scsi: libiscsi: Reject a negative task index from parse_pdu_itt
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (82 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 083/247] scsi: xen/scsifront: Check for a NULL shadow entry on a backend response Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 085/247] scsi: libiscsi: Validate the ITT reflected in a Reject PDU Greg Kroah-Hartman
                   ` (170 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Mike Christie, Yehyeong Lee,
	Martin K. Petersen (Oracle)

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Yehyeong Lee <yhlee@isslab.korea.ac.kr>

commit 8ee2a09a1dbb257c9e828ad2497f8e4832dfb142 upstream.

A transport that implements parse_pdu_itt hands libiscsi an index taken
from the PDU, and both lookups bound it from above only:

      if (i >= session->cmds_max)

i and cmds_max are both int, so a negative index passes and
session->cmds[i] is read from before the array.

be2iscsi produces one. beiscsi_parse_pdu() assigns the raw tag,

      *index = (int)itt;

and beiscsi_complete_pdu() forwards an unsolicited NOP-In from the
hardware async ring without replacing its ITT, so the value is the
target's. It also reports the session's own age rather than the one in
the tag, which leaves the age comparison in iscsi_verify_itt() with
nothing to reject.

Bound the index from below in both lookups.

Fixes: bfead3b2cb46 ("[SCSI] be2iscsi: Adding msix and mcc_rings V3")
Cc: stable@vger.kernel.org
Reviewed-by: Mike Christie <michael.christie@oracle.com>
Signed-off-by: Yehyeong Lee <yhlee@isslab.korea.ac.kr>
Link: https://patch.msgid.link/20261007015842.634893-2-yhlee@isslab.korea.ac.kr
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/scsi/libiscsi.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1191,7 +1191,7 @@ struct iscsi_task *iscsi_itt_to_task(str
 		session->tt->parse_pdu_itt(conn, itt, &i, NULL);
 	else
 		i = get_itt(itt);
-	if (i >= session->cmds_max)
+	if (i < 0 || i >= session->cmds_max)
 		return NULL;
 
 	return session->cmds[i];
@@ -1384,7 +1384,7 @@ int iscsi_verify_itt(struct iscsi_conn *
 		return ISCSI_ERR_BAD_ITT;
 	}
 
-	if (i >= session->cmds_max) {
+	if (i < 0 || i >= session->cmds_max) {
 		iscsi_conn_printk(KERN_ERR, conn,
 				  "received invalid itt index %u (max cmds "
 				   "%u.\n", i, session->cmds_max);



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 085/247] scsi: libiscsi: Validate the ITT reflected in a Reject PDU
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (83 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 084/247] scsi: libiscsi: Reject a negative task index from parse_pdu_itt Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 086/247] scsi: libiscsi: Validate the task named by a management response Greg Kroah-Hartman
                   ` (169 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Mike Christie, Yehyeong Lee,
	Martin K. Petersen (Oracle)

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Yehyeong Lee <yhlee@isslab.korea.ac.kr>

commit c5958c770b2a0ee492414e26b07da9164a0d1f5d upstream.

A Reject PDU carries a copy of the header it rejects, and
iscsi_handle_reject() takes the ITT out of that copy to find the task to
clean up:

      memcpy(&rejected_pdu, data, sizeof(struct iscsi_hdr));
      ...
      task = iscsi_itt_to_task(conn, rejected_pdu.itt);

That value is whatever the target put there. iscsi_itt_to_task() bounds
the index against cmds_max and checks nothing else, so any task in the
pool can be named, and iscsi_nop_out_rsp() then completes it.

An index that has never been used gives a NULL task->conn: the pool is
zeroed at session setup and conn is assigned only when a task is
allocated. If the task was used and returned, iscsi_complete_task() hits
its WARN_ON_ONCE(task->state == ISCSI_TASK_FREE) and the refcount
underflows. An in-flight SCSI command is completed as successful - a 1
MiB read returned 1048576 with none of its buffer written and no
warning.

Validate the reflected ITT the way iscsi_itt_to_ctask() validates a
command ITT, and require the task to be in flight and not a SCSI
command.

[    6.248477] Oops: general protection fault, probably for non-canonical address 0xdffffc000000000c: 0000 [#1] SMP KASAN NOPTI
[    6.249357] KASAN: null-ptr-deref in range [0x0000000000000060-0x0000000000000067]
[    6.249951] CPU: 1 UID: 0 PID: 0 Comm: swapper/1 Not tainted 7.2.0-rc5-ISCSI1-gf5098b6bae76 #1 PREEMPT(lazy)
[    6.250718] Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[    6.251616] RIP: 0010:iscsi_nop_out_rsp.constprop.0+0x46/0x160
[    6.252043] Code: c1 ea 03 48 83 ec 08 80 3c 02 00 0f 85 f5 00 00 00 48 b8 00 00 00 00 00 fc ff df 48 8b 6b 58 48 8d 7d 60 48 89 fa 48 c1 ea 03 <80> 3c 02 00 0f 85 c0 00 00 00 48 8b 45 60 48 39 c3 74 50 48 b8 00
[    6.252813] RSP: 0018:ffff88806c907b80 EFLAGS: 00010206
[    6.253042] RAX: dffffc0000000000 RBX: ffff88800607e000 RCX: ffffffff8d571a25
[    6.253345] RDX: 000000000000000c RSI: ffff88806c907c38 RDI: 0000000000000060
[    6.253642] RBP: 0000000000000000 R08: 0000000000000000 R09: fffffbfff235a504
[    6.253947] R10: 0000000000000003 R11: 7463656e6e6f6320 R12: 0000000000000000
[    6.254251] R13: 0000000000000000 R14: ffff88806c907c38 R15: 0000000000000000
[    6.254549] FS:  0000000000000000(0000) GS:ffff8880d95bc000(0000) knlGS:0000000000000000
[    6.254887] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[    6.255140] CR2: 00007fc393e8ffc0 CR3: 0000000005252006 CR4: 0000000000770ef0
[    6.255439] PKRU: 55555554
[    6.255564] Call Trace:
[    6.255674]  <IRQ>
[    6.255768]  __iscsi_complete_pdu+0x18bf/0x22a0
[    6.256733]  iscsi_complete_pdu+0x54/0xa0
[    6.256905]  iscsi_tcp_data_recv_done+0xf4/0x250
[    6.257103]  iscsi_tcp_recv_skb+0x31e/0xec0
[    6.257680]  iscsi_sw_tcp_recv+0x12f/0x390
[    6.258061]  __tcp_read_sock+0x1ab/0x810
[    6.258853]  iscsi_sw_tcp_data_ready+0x18b/0x510
[    6.259808]  tcp_data_queue+0x1f13/0x4cd0
[    6.260567]  tcp_rcv_established+0x8a5/0x3a00
[    6.261931]  tcp_v4_do_rcv+0x449/0x960
[    6.262269]  tcp_v4_rcv+0x2245/0x3bc0

Fixes: 8afa1439fcff ("[SCSI] libiscsi: handle immediate command rejections")
Cc: stable@vger.kernel.org
Reviewed-by: Mike Christie <michael.christie@oracle.com>
Signed-off-by: Yehyeong Lee <yhlee@isslab.korea.ac.kr>
Link: https://patch.msgid.link/20261007015842.634893-3-yhlee@isslab.korea.ac.kr
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/scsi/libiscsi.c |    8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1142,13 +1142,15 @@ static int iscsi_handle_reject(struct is
 			spin_unlock(&conn->session->frwd_lock);
 			spin_lock(&conn->session->back_lock);
 		} else {
-			struct iscsi_task *task;
+			struct iscsi_task *task = NULL;
 			/*
 			 * Our nop as ping got dropped. We know the target
 			 * and transport are ok so just clean up
 			 */
-			task = iscsi_itt_to_task(conn, rejected_pdu.itt);
-			if (!task) {
+			if (!iscsi_verify_itt(conn, rejected_pdu.itt))
+				task = iscsi_itt_to_task(conn, rejected_pdu.itt);
+			if (!task || task->state == ISCSI_TASK_FREE ||
+			    task->sc) {
 				iscsi_conn_printk(KERN_ERR, conn,
 						 "Invalid pdu reject. Could "
 						 "not lookup rejected task.\n");



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 086/247] scsi: libiscsi: Validate the task named by a management response
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (84 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 085/247] scsi: libiscsi: Validate the ITT reflected in a Reject PDU Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 087/247] drm/amdgpu/sdma3: Work around POLL_REGMEM / FENCE hang Greg Kroah-Hartman
                   ` (168 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Mike Christie, Yehyeong Lee,
	Martin K. Petersen (Oracle)

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Yehyeong Lee <yhlee@isslab.korea.ac.kr>

commit 11bffcd9cb346732eab2914ef44fe777a3f0b585 upstream.

__iscsi_complete_pdu() fetches the task for five response types from one
place and checks only that the index resolved:

      case ISCSI_OP_LOGOUT_RSP:
      case ISCSI_OP_LOGIN_RSP:
      case ISCSI_OP_TEXT_RSP:
      case ISCSI_OP_SCSI_TMFUNC_RSP:
      case ISCSI_OP_NOOP_IN:
              task = iscsi_itt_to_task(conn, hdr->itt);
              if (!task)
                      return ISCSI_ERR_BAD_ITT;

iscsi_itt_to_task() bounds the index against cmds_max and looks at
nothing else, so a target can name any slot in the pool, including one
that has never been used. task->conn is then NULL, and both
iscsi_nop_out_rsp() and iscsi_complete_task() dereference it. One
unsolicited NOP-In is enough; a Text Response carrying the same ITT
crashes in iscsi_complete_task() instead.

Require the task to be in flight and not a SCSI command, the way
iscsi_itt_to_ctask() does for the command opcodes.

[    6.298634] Oops: general protection fault, probably for non-canonical address 0xdffffc000000000c: 0000 [#1] SMP KASAN NOPTI
[    6.298642] KASAN: null-ptr-deref in range [0x0000000000000060-0x0000000000000067]
[    6.298652] CPU: 1 UID: 0 PID: 111 Comm: iscsistart Not tainted 7.2.0-rc5-ISCSI1-gf5098b6bae76 #1 PREEMPT(lazy)
[    6.298654] Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[    6.298656] RIP: 0010:iscsi_nop_out_rsp.constprop.0+0x46/0x160
[    6.298691] Code: c1 ea 03 48 83 ec 08 80 3c 02 00 0f 85 f5 00 00 00 48 b8 00 00 00 00 00 fc ff df 48 8b 6b 58 48 8d 7d 60 48 89 fa 48 c1 ea 03 <80> 3c 02 00 0f 85 c0 00 00 00 48 8b 45 60 48 39 c3 74 50 48 b8 00
[    6.298698] RSP: 0018:ffff88806c907be8 EFLAGS: 00010206
[    6.298701] RAX: dffffc0000000000 RBX: ffff888006116800 RCX: 0000000000000020
[    6.298702] RDX: 000000000000000c RSI: ffff88800525d578 RDI: 0000000000000060
[    6.298703] RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000
[    6.298706] R10: 0000000000000020 R11: 0000000000000000 R12: 0000000000000000
[    6.298706] R13: 000000000000002e R14: ffff8880056eb440 R15: ffff888006116800
[    6.298707] FS:  00007fc02d1c2740(0000) GS:ffff8880b29bc000(0000) knlGS:0000000000000000
[    6.298710] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[    6.298711] CR2: 000055fe3b56ddf8 CR3: 00000000053b9004 CR4: 0000000000770ef0
[    6.298712] PKRU: 55555554
[    6.298713] Call Trace:
[    6.298714]  <IRQ>
[    6.298714]  __iscsi_complete_pdu+0x13a8/0x22a0
[    6.298758]  iscsi_complete_pdu+0x54/0xa0
[    6.298759]  iscsi_tcp_hdr_recv_done+0x870/0x2c80
[    6.298778]  iscsi_tcp_recv_skb+0x31e/0xec0
[    6.298800]  iscsi_sw_tcp_recv+0x12f/0x390
[    6.298804]  __tcp_read_sock+0x1ab/0x810
[    6.298812]  iscsi_sw_tcp_data_ready+0x18b/0x510
[    6.298814]  tcp_rcv_established+0x1f56/0x3a00
[    6.298842]  tcp_v4_do_rcv+0x449/0x960
[    6.298847]  tcp_v4_rcv+0x2245/0x3bc0

Fixes: 7996a778ff8c ("[SCSI] iscsi: add libiscsi")
Cc: stable@vger.kernel.org
Reviewed-by: Mike Christie <michael.christie@oracle.com>
Signed-off-by: Yehyeong Lee <yhlee@isslab.korea.ac.kr>
Link: https://patch.msgid.link/20261007015842.634893-4-yhlee@isslab.korea.ac.kr
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/scsi/libiscsi.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1286,7 +1286,7 @@ int __iscsi_complete_pdu(struct iscsi_co
 	case ISCSI_OP_SCSI_TMFUNC_RSP:
 	case ISCSI_OP_NOOP_IN:
 		task = iscsi_itt_to_task(conn, hdr->itt);
-		if (!task)
+		if (!task || task->state == ISCSI_TASK_FREE || task->sc)
 			return ISCSI_ERR_BAD_ITT;
 		break;
 	default:



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 087/247] drm/amdgpu/sdma3: Work around POLL_REGMEM / FENCE hang
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (85 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 086/247] scsi: libiscsi: Validate the task named by a management response Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 088/247] drm/amdgpu: dont drop the runtime PM reference twice in amdgpu_gpr Greg Kroah-Hartman
                   ` (167 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Alex Deucher, Timur Kristóf

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Timur Kristóf <timur.kristof@gmail.com>

commit 752480ad62964edf0254e151110d3e53a7cb37de upstream.

SDMA can randomly hang on Polaris 10. Hard to reproduce,
but has been occurring sporadically in the Mesa CI
on the RADV Polaris 10 job even when Mesa isn't using
the SDMA engine.

When Mesa actually uses the SDMA on Polaris, the hang
becomes more frequent and the reproduction rate goes up
significantly in the CI system.

We don't know why the hangs occur, but it seems
that inserting a single NOP packet before each
POLL_REGMEM and FENCE packet works around it.
At the moment it's unclear which GPUs are affected,
so let's apply this to SDMA 3.x for now.

Note that this issue is not documented or acknowledged by AMD.

Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit c343a27ed90823d08de125f7c447d96d056b75d9)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c |   25 +++++++++++++++++++++----
 1 file changed, 21 insertions(+), 4 deletions(-)

--- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
@@ -455,6 +455,9 @@ static void sdma_v3_0_ring_emit_hdp_flus
 	else
 		ref_and_mask = REG_SET_FIELD(ref_and_mask, GPU_HDP_FLUSH_DONE, SDMA1, 1);
 
+	/* Hang workaround */
+	amdgpu_ring_write(ring, SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP));
+
 	amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_POLL_REGMEM) |
 			  SDMA_PKT_POLL_REGMEM_HEADER_HDP_FLUSH(1) |
 			  SDMA_PKT_POLL_REGMEM_HEADER_FUNC(3)); /* == */
@@ -482,6 +485,10 @@ static void sdma_v3_0_ring_emit_fence(st
 				      unsigned flags)
 {
 	bool write64bit = flags & AMDGPU_FENCE_FLAG_64BIT;
+
+	/* Hang workaround */
+	amdgpu_ring_write(ring, SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP));
+
 	/* write the fence */
 	amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_FENCE));
 	amdgpu_ring_write(ring, lower_32_bits(addr));
@@ -490,7 +497,11 @@ static void sdma_v3_0_ring_emit_fence(st
 
 	/* optionally write high bits as well */
 	if (write64bit) {
+		/* Hang workaround */
+		amdgpu_ring_write(ring, SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP));
+
 		addr += 4;
+
 		amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_FENCE));
 		amdgpu_ring_write(ring, lower_32_bits(addr));
 		amdgpu_ring_write(ring, upper_32_bits(addr));
@@ -1031,6 +1042,9 @@ static void sdma_v3_0_ring_emit_pipeline
 	uint32_t seq = ring->fence_drv.sync_seq;
 	uint64_t addr = ring->fence_drv.gpu_addr;
 
+	/* Hang workaround */
+	amdgpu_ring_write(ring, SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP));
+
 	/* wait for idle */
 	amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_POLL_REGMEM) |
 			  SDMA_PKT_POLL_REGMEM_HEADER_HDP_FLUSH(0) |
@@ -1059,6 +1073,9 @@ static void sdma_v3_0_ring_emit_vm_flush
 {
 	amdgpu_gmc_emit_flush_gpu_tlb(ring, vmid, pd_addr);
 
+	/* Hang workaround */
+	amdgpu_ring_write(ring, SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP));
+
 	/* wait for flush */
 	amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_POLL_REGMEM) |
 			  SDMA_PKT_POLL_REGMEM_HEADER_HDP_FLUSH(0) |
@@ -1568,11 +1585,11 @@ static const struct amdgpu_ring_funcs sd
 	.get_wptr = sdma_v3_0_ring_get_wptr,
 	.set_wptr = sdma_v3_0_ring_set_wptr,
 	.emit_frame_size =
-		6 + /* sdma_v3_0_ring_emit_hdp_flush */
+		6 + 1 + /* sdma_v3_0_ring_emit_hdp_flush */
 		3 + /* hdp invalidate */
-		6 + /* sdma_v3_0_ring_emit_pipeline_sync */
-		VI_FLUSH_GPU_TLB_NUM_WREG * 3 + 6 + /* sdma_v3_0_ring_emit_vm_flush */
-		10 + 10 + 10, /* sdma_v3_0_ring_emit_fence x3 for user fence, vm fence */
+		6 + 1 + /* sdma_v3_0_ring_emit_pipeline_sync */
+		VI_FLUSH_GPU_TLB_NUM_WREG * 3 + 6 + 1 + /* sdma_v3_0_ring_emit_vm_flush */
+		(10 + 1) * 3, /* sdma_v3_0_ring_emit_fence x3 for user fence, vm fence */
 	.emit_ib_size = 7 + 6, /* sdma_v3_0_ring_emit_ib */
 	.emit_ib = sdma_v3_0_ring_emit_ib,
 	.emit_fence = sdma_v3_0_ring_emit_fence,



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 088/247] drm/amdgpu: dont drop the runtime PM reference twice in amdgpu_gpr
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (86 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 087/247] drm/amdgpu/sdma3: Work around POLL_REGMEM / FENCE hang Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 089/247] drm/exec: dont immediately add prelocked obj to array of locked objs Greg Kroah-Hartman
                   ` (166 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Alex Deucher, Jesse Zhang

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Jesse Zhang <Jesse.Zhang@amd.com>

commit de9f6bcdb44f0e410031002e2f103826ea6b6259 upstream.

amdgpu_debugfs_gpr_read() drops its runtime PM reference right after
reading the wave registers. When copying them to userspace fails, it
jumps to the err label, which drops the reference a second time. A read
into a bad buffer on Navi31 either steals a reference somebody else
holds (power/runtime_usage goes from 1 to 0) or underflows the count:

  amdgpu 0000:03:00.0: Runtime PM usage count underflow!

The registers are already in the kernel buffer at that point, so finish
the hardware access first and copy the buffer with a single
copy_to_user() instead of the put_user() loop with its own error path.

Fixes: 9eee152aab56 ("drm/amdgpu/debugfs: fix ref count leak when pm_runtime_get_sync fails")
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Jesse Zhang <Jesse.Zhang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 31035bbd74f7c3e10c163db875b8e67f8b50ee6a)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c |   21 +++------------------
 1 file changed, 3 insertions(+), 18 deletions(-)

--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
@@ -1164,7 +1164,6 @@ static ssize_t amdgpu_debugfs_gpr_read(s
 {
 	struct amdgpu_device *adev = f->f_inode->i_private;
 	int r;
-	ssize_t result = 0;
 	uint32_t offset, se, sh, cu, wave, simd, thread, bank, *data;
 
 	if (size > 4096 || size & 3 || *pos & 3)
@@ -1209,25 +1208,11 @@ static ssize_t amdgpu_debugfs_gpr_read(s
 
 	pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
 	pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
+	amdgpu_virt_disable_access_debugfs(adev);
 
-	while (size) {
-		uint32_t value;
-
-		value = data[result >> 2];
-		r = put_user(value, (uint32_t *)buf);
-		if (r) {
-			amdgpu_virt_disable_access_debugfs(adev);
-			goto err;
-		}
-
-		result += 4;
-		buf += 4;
-		size -= 4;
-	}
-
+	r = copy_to_user(buf, data, size) ? -EFAULT : size;
 	kfree(data);
-	amdgpu_virt_disable_access_debugfs(adev);
-	return result;
+	return r;
 
 err:
 	pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 089/247] drm/exec: dont immediately add prelocked obj to array of locked objs
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (87 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 088/247] drm/amdgpu: dont drop the runtime PM reference twice in amdgpu_gpr Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 090/247] tracing: Fix the shift out of bounds in the log2 histogram modifier Greg Kroah-Hartman
                   ` (165 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Christian König, Vitaly Prosyak

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Christian König <ckoenig.leichtzumerken@gmail.com>

commit 26401a4999f1596a515b2e704e7066ac09306488 upstream.

When a contention is detected the drm_exec object grabs a reference to
the contended object, unlocks all other objects and pre-locks the
contended one before anything else.

The problem is that it is possible that this pre-locked object was about
to be destroyed and drm_exec is now holding the last reference to it.

So we never actually see this pre-locked object again to be explicitly
locked and so also never reserve a slot for a dma_fence object on it.

Should the driver now use drm_exec_for_each_locked_object() to add a new
fence to all locked objects we eventually see a warning or even a
BUG_ON() to prevent random memory corruption.

Fix this by keeping the prelocked object out of the array of locked objs
until it was explicitly mentioned by the driver again.

If the prelocked object is never mentioned again by the driver
just unlock and drop the reference at the end of the locking loop.

Signed-off-by: Christian König <christian.koenig@amd.com>
Reported-by: Vitaly Prosyak <vitaly.prosyak@amd.com>
Reviewed-by: Vitaly Prosyak <vitaly.prosyak@amd.com>
Tested-by: Vitaly Prosyak <vitaly.prosyak@amd.com>
Fixes: 09593216bff1 ("drm: execution context for GEM buffers v7")
CC: stable@vger.kernel.org # v6.6+
Link: https://lore.kernel.org/r/20261007124657.9664-1-christian.koenig@amd.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/gpu/drm/drm_exec.c |   75 ++++++++++++++++++++++++++-------------------
 include/drm/drm_exec.h     |   15 +++++----
 2 files changed, 53 insertions(+), 37 deletions(-)

--- a/drivers/gpu/drm/drm_exec.c
+++ b/drivers/gpu/drm/drm_exec.c
@@ -49,6 +49,16 @@
 /* Dummy value used to initially enter the retry loop */
 #define DRM_EXEC_DUMMY ((void *)~0)
 
+/* Unlock and put the prelocked obj */
+static void drm_exec_drop_prelocked(struct drm_exec *exec)
+{
+	if (exec->prelocked) {
+		dma_resv_unlock(exec->prelocked->resv);
+		drm_gem_object_put(exec->prelocked);
+		exec->prelocked = NULL;
+	}
+}
+
 /* Unlock all objects and drop references */
 static void drm_exec_unlock_all(struct drm_exec *exec)
 {
@@ -59,8 +69,7 @@ static void drm_exec_unlock_all(struct d
 		drm_gem_object_put(obj);
 	}
 
-	drm_gem_object_put(exec->prelocked);
-	exec->prelocked = NULL;
+	drm_exec_drop_prelocked(exec);
 }
 
 /**
@@ -119,6 +128,14 @@ EXPORT_SYMBOL(drm_exec_fini);
 bool drm_exec_cleanup(struct drm_exec *exec)
 {
 	if (likely(!exec->contended)) {
+
+		/*
+		 * The contended and prelocked object might never be passed to
+		 * drm_exec_lock_obj() again. This can happen when the object
+		 * is about to be cleaned up and we now hold the last reference
+		 * to it. Make sure that we don't unnecessarily keep it around.
+		 */
+		drm_exec_drop_prelocked(exec);
 		ww_acquire_done(&exec->ticket);
 		return false;
 	}
@@ -176,16 +193,16 @@ static int drm_exec_lock_contended(struc
 		dma_resv_lock_slow(obj->resv, &exec->ticket);
 	}
 
-	ret = drm_exec_obj_locked(exec, obj);
-	if (unlikely(ret))
-		goto error_unlock;
+	/*
+	 * It is perfectly possible that we see another contention before the
+	 * first one is fully handled.
+	 */
+	drm_exec_drop_prelocked(exec);
 
+	/* We move the reference from contended to prelocked here */
 	exec->prelocked = obj;
 	return 0;
 
-error_unlock:
-	dma_resv_unlock(obj->resv);
-
 error_dropref:
 	drm_gem_object_put(obj);
 	return ret;
@@ -213,35 +230,31 @@ int drm_exec_lock_obj(struct drm_exec *e
 	if (exec->prelocked == obj) {
 		drm_gem_object_put(exec->prelocked);
 		exec->prelocked = NULL;
-		return 0;
-	}
+	} else {
+		if (exec->flags & DRM_EXEC_INTERRUPTIBLE_WAIT)
+			ret = dma_resv_lock_interruptible(obj->resv,
+							  &exec->ticket);
+		else
+			ret = dma_resv_lock(obj->resv, &exec->ticket);
+
+		if (unlikely(ret == -EDEADLK)) {
+			drm_gem_object_get(obj);
+			exec->contended = obj;
+			return -EDEADLK;
+		}
+
+		if (unlikely(ret == -EALREADY) &&
+		    exec->flags & DRM_EXEC_IGNORE_DUPLICATES)
+			return 0;
 
-	if (exec->flags & DRM_EXEC_INTERRUPTIBLE_WAIT)
-		ret = dma_resv_lock_interruptible(obj->resv, &exec->ticket);
-	else
-		ret = dma_resv_lock(obj->resv, &exec->ticket);
-
-	if (unlikely(ret == -EDEADLK)) {
-		drm_gem_object_get(obj);
-		exec->contended = obj;
-		return -EDEADLK;
+		if (unlikely(ret))
+			return ret;
 	}
 
-	if (unlikely(ret == -EALREADY) &&
-	    exec->flags & DRM_EXEC_IGNORE_DUPLICATES)
-		return 0;
-
-	if (unlikely(ret))
-		return ret;
-
 	ret = drm_exec_obj_locked(exec, obj);
 	if (ret)
-		goto error_unlock;
-
-	return 0;
+		dma_resv_unlock(obj->resv);
 
-error_unlock:
-	dma_resv_unlock(obj->resv);
 	return ret;
 }
 EXPORT_SYMBOL(drm_exec_lock_obj);
--- a/include/drm/drm_exec.h
+++ b/include/drm/drm_exec.h
@@ -67,13 +67,15 @@ drm_exec_obj(struct drm_exec *exec, unsi
 
 /* Helper for drm_exec_for_each_locked_object(). Internal use only. */
 #define __drm_exec_for_each_locked_object(exec, obj, __index)		\
-	for (unsigned long __index = 0; ((obj) = drm_exec_obj(exec, __index)); ++__index)
+	for (unsigned long __index = 0; ((obj) = drm_exec_obj(exec, __index)); \
+	     ++__index)
 /**
  * drm_exec_for_each_locked_object - iterate over all the locked objects
  * @exec: drm_exec object
  * @obj: the current GEM object
  *
- * Iterate over all the locked GEM objects inside the drm_exec object.
+ * Iterate over all the explicitly locked GEM objects inside the drm_exec
+ * container, except for the contended and implicit prelocked one.
  */
 #define drm_exec_for_each_locked_object(exec, obj)			\
 	__drm_exec_for_each_locked_object(exec, obj, __UNIQUE_ID(drm_exec))
@@ -88,12 +90,13 @@ drm_exec_obj(struct drm_exec *exec, unsi
  * @exec: drm_exec object
  * @obj: the current GEM object
  *
- * Iterate over all the locked GEM objects inside the drm_exec object in
- * reverse locking order. Note that the internal index may wrap around,
- * but that will be caught by drm_exec_obj(), returning a NULL object.
+ * Iterate over all the explicitly locked GEM objects inside the drm_exec
+ * container in reverse locking order. Note that the internal index may wrap
+ * around, but that will be caught by drm_exec_obj(), returning a NULL object.
  */
 #define drm_exec_for_each_locked_object_reverse(exec, obj)		\
-	__drm_exec_for_each_locked_object_reverse(exec, obj, __UNIQUE_ID(drm_exec))
+	__drm_exec_for_each_locked_object_reverse(exec, obj,		\
+						  __UNIQUE_ID(drm_exec))
 
 /**
  * drm_exec_until_all_locked - loop until all GEM objects are locked



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 090/247] tracing: Fix the shift out of bounds in the log2 histogram modifier
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (88 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 089/247] drm/exec: dont immediately add prelocked obj to array of locked objs Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 091/247] tracing: Take trace_types_lock when dropping the buffer_meta reference Greg Kroah-Hartman
                   ` (164 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Donggeun Yoo, Steven Rostedt

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Donggeun Yoo <donggeunyoo.kernel@gmail.com>

commit 647c2f97fcb94bc642cefe6db004999974563f06 upstream.

The .log2 key modifier files a value under its base-2 order:

  # echo 'hist:keys=bytes_req.log2' > events/kmem/kmalloc/trigger

hist_field_log2() computes that as ilog2(roundup_pow_of_two(val)). The
out-of-line form of roundup_pow_of_two() is

	return 1UL << fls_long(n - 1);

which shifts by 64 on a 64-bit kernel both when n is 0, where n - 1
wraps to ULONG_MAX, and when n is above 2^63. Both are ordinary keys,
because the field fetch hands every value over as a u64: a syscall
argument of 0 reaches the first, and one above 2^63 reaches the second.

Keying sys_enter_lseek on offset.log2 and passing 0, 1, 2, 3, 1000,
2^63+1 and U64_MAX gives

  { offset: ~ 2^1  } hitcount:          1
  { offset: ~ 2^10 } hitcount:          1
  { offset: ~ 2^2  } hitcount:          1
  { offset: ~ 2^0  } hitcount:          4

Keys above 2^63 land in the lowest bucket. With CONFIG_UBSAN_SHIFT=y
the shift is also reported:

  UBSAN: shift-out-of-bounds in include/linux/log2.h:57:13
  shift exponent 64 is too large for 64-bit type 'long unsigned int'
   __ubsan_handle_shift_out_of_bounds.cold+0xdd/0x1cb
   hist_fn_call.cold+0x8b/0xd9
   event_hist_trigger+0x1cc/0x790
   ftrace_syscall_enter+0x197/0x360
   do_syscall_64+0x402/0x4b0

Use order_base_2(), which is ilog2(n - 1) + 1 for n > 1 and 0 below
that. It returns what the old expression returned on every input the
old one was defined for. Where it was not, 0 stays in bucket 0, which
is where x86_64 had been putting it, and the keys above 2^63 move into
bucket 64.

Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20260916002735.808520-1-donggeunyoo.kernel@gmail.com
Fixes: 4b94f5b7b4a5 ("tracing: Add hist trigger 'log2' modifier")
Signed-off-by: Donggeun Yoo <donggeunyoo.kernel@gmail.com>
Assisted-by: Claude:claude-fable-5
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 kernel/trace/trace_events_hist.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/kernel/trace/trace_events_hist.c
+++ b/kernel/trace/trace_events_hist.c
@@ -283,7 +283,7 @@ static u64 hist_field_log2(struct hist_f
 
 	u64 val = hist_fn_call(operand, elt, buffer, rbe, event);
 
-	return (u64) ilog2(roundup_pow_of_two(val));
+	return order_base_2(val);
 }
 
 static u64 hist_field_bucket(struct hist_field *hist_field,



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 091/247] tracing: Take trace_types_lock when dropping the buffer_meta reference
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (89 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 090/247] tracing: Fix the shift out of bounds in the log2 histogram modifier Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 092/247] tracing: Check operator stack capacity before pushing Greg Kroah-Hartman
                   ` (163 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, David Carlier, Steven Rostedt

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: David Carlier <devnexen@gmail.com>

commit 2afe7575fb24b9d0476ae4a3a9862f7997216aa4 upstream.

tracing_buffer_meta_open() drops the trace_array reference with
__trace_array_put() when ring_buffer_meta_seq_init() fails, without
holding trace_types_lock. Use trace_array_put() like every other open
error path.

Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20260914133506.4865-2-devnexen@gmail.com
Fixes: 950032ffcee7 ("ring-buffer: Add output of ring buffer meta page")
Signed-off-by: David Carlier <devnexen@gmail.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 kernel/trace/trace.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -6839,7 +6839,7 @@ static int tracing_buffer_meta_open(stru
 
 	ret = ring_buffer_meta_seq_init(filp, tr->array_buffer.buffer, cpu);
 	if (ret < 0)
-		__trace_array_put(tr);
+		trace_array_put(tr);
 	return ret;
 }
 



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 092/247] tracing: Check operator stack capacity before pushing
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (90 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 091/247] tracing: Take trace_types_lock when dropping the buffer_meta reference Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 093/247] tracing: Do not initialize tracefs work if tracing is disabled Greg Kroah-Hartman
                   ` (162 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Taeyang Lee, Steven Rostedt

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Taeyang Lee <0wn@theori.io>

commit c47a7b11bcb3d45e29723afcf6336866476b1d08 upstream.

predicate_parse() uses the first operator stack entry before processing
any opening parentheses. A push then increments top before writing.
The existing check still permits that write when top already points to
the last allocated entry, which can access beyond the operator stack.

Reject the push when top reaches the last allocated entry.

Cc: stable@vger.kernel.org
Fixes: 39f7c41c908b ("tracing/filters: Enable filtering a cpumask field by another cpumask")
Link: https://patch.msgid.link/atELO9L0I9kg5CpC@Taeyangs-MacBook-Pro.local
Signed-off-by: Taeyang Lee <0wn@theori.io>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 kernel/trace/trace_events_filter.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/kernel/trace/trace_events_filter.c
+++ b/kernel/trace/trace_events_filter.c
@@ -512,7 +512,7 @@ predicate_parse(const char *str, int nr_
 
 		switch (*next) {
 		case '(':					/* #2 */
-			if (top - op_stack > nr_parens) {
+			if (top - op_stack >= nr_parens - 1) {
 				ret = -EINVAL;
 				goto out_free;
 			}



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 093/247] tracing: Do not initialize tracefs work if tracing is disabled
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (91 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 092/247] tracing: Check operator stack capacity before pushing Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 094/247] tracing: Fix hist trigger timestamps for buffered events Greg Kroah-Hartman
                   ` (161 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Michal Suchánek, Amit Machhiwal,
	Masami Hiramatsu (Google), Steven Rostedt

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Amit Machhiwal <amachhiw@linux.ibm.com>

commit b3b974008388ab59e44d764ba7a63c988fec2524 upstream.

If trace buffer allocation fails during early boot (e.g.  in
early_trace_init() -> allocate_trace_buffers()), tracing_disabled is
left set to 1 and the global trace array events list remains
uninitialized.

Later during boot, tracer_init_tracefs() (invoked via fs_initcall)
queues tracerfs_init_work asynchronously without checking if tracing was
disabled.  When tracer_init_tracefs_work_func() runs, it calls
event_trace_init() and init_tracer_tracefs(&global_trace, NULL)
unconditionally.  This leads to __find_event_file() dereferencing an
uninitialized tr->events list, causing an early boot NULL pointer
dereference Oops:

  BUG: Kernel NULL pointer dereference on read at 0x00000010
  Faulting instruction address: 0xc000000000485be0
  Oops: Kernel access of bad area, sig: 7 [#1]
  ...
  NIP [c000000000485be0] __find_event_file+0x70/0x3c0
  LR  [c000000000448874] init_tracer_tracefs+0x274/0xc80
  Call Trace:
   init_tracer_tracefs+0x274/0xc80
   tracer_init_tracefs_work_func+0x50/0x320
   process_one_work+0x1e8/0x5c0
   worker_thread+0x1dc/0x3d0
   kthread+0x194/0x1b0
   start_kernel_thread+0x14/0x18

Check tracing_disabled at the beginning of tracer_init_tracefs_work_func()
and return immediately if tracing is disabled or failed to initialize,
preventing the crash.

Cc: stable@vger.kernel.org
Fixes: 6621a7004684 ("tracing: make tracer_init_tracefs initcall asynchronous")
Link: https://patch.msgid.link/20261009163557.88467-2-amachhiw@linux.ibm.com
Reported-by: Michal Suchánek <msuchanek@suse.de>
Closes: https://lore.kernel.org/all/arYskzbiaNzBR9MD@kunlun.suse.cz/
Signed-off-by: Amit Machhiwal <amachhiw@linux.ibm.com>
Tested-by: Michal Suchánek <msuchanek@suse.de>
Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 kernel/trace/trace.c |    6 ++++++
 1 file changed, 6 insertions(+)

--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -10005,6 +10005,12 @@ static struct notifier_block trace_modul
 
 static __init void tracer_init_tracefs_work_func(struct work_struct *work)
 {
+	/*
+	 * Do not attempt to initialize tracefs if tracing was disabled or
+	 * failed to allocate
+	 */
+	if (tracing_disabled)
+		return;
 
 	event_trace_init();
 



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 094/247] tracing: Fix hist trigger timestamps for buffered events
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (92 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 093/247] tracing: Do not initialize tracefs work if tracing is disabled Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 095/247] wifi: p54: validate firmware record lengths Greg Kroah-Hartman
                   ` (160 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Tengda Wu, Steven Rostedt

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Tengda Wu <wutengda@huaweicloud.com>

commit 9414ca3b99e5a7f1f3bf51c2a01b383e1b355dd0 upstream.

Syzkaller triggered a WARN_ON_ONCE(!nest) warning:

  WARNING: kernel/trace/ring_buffer.c:821 at ring_buffer_event_time_stamp
  Call trace:
    ring_buffer_event_time_stamp
    hist_field_timestamp
    hist_fn_call
    event_hist_trigger
    event_triggers_call
    __event_trigger_test_discard
    trace_event_buffer_commit
    do_trace_event_raw_event_sched_switch
    trace_event_raw_event_sched_switch

The warning is probabilistically reproducible and is related to syzkaller
executing the following commands:

  echo 'prev_pid == 999999' > events/sched/sched_switch/filter
  echo 'hist:keys=common_timestamp' > events/sched/sched_switch/trigger

The specific triggering process is as follows:

CPU 0                                           CPU 1
(context switching)                             (echo 'hist:keys=common_timestamp' > \
                                                        events/sched/sched_switch/trigger)
do_trace_event_raw_event_##call
  trace_event_buffer_lock_reserve
    if (!tr->no_filter_buffering_ref &&
        trace_file->flags & EVENT_FILE_FL_FILTERED)
        return entry;  // return directly
                                                event_hist_trigger_parse
                                                  hist_register_trigger
                                                    tracing_set_filter_buffering(file->tr, true);
                                                      tr->no_filter_buffering_ref++;
    __trace_buffer_lock_reserve
      rb_start_commit
        local_inc(&cpu_buffer->committing);  // skipped and not executed
  trace_event_buffer_commit
    __event_trigger_test_discard
      event_triggers_call
        event_hist_trigger
          hist_fn_call
            hist_field_timestamp
              ring_buffer_event_time_stamp
                nest = local_read(&cpu_buffer->committing);
                WARN_ON_ONCE(!nest)  // trigger warning

The root cause is that when an event file has a filter attached and the
hist trigger has not yet been attached, trace_event_buffer_lock_reserve()
writes the event into the per-CPU trace_buffered_event temp buffer instead
of reserving it in the ring buffer, so cpu_buffer->committing is not
incremented. When the event is later processed at commit time by a hist
trigger, hist_field_timestamp() -> ring_buffer_event_time_stamp() sees a
zero committing count, triggering WARN_ON_ONCE(!nest).

tracing_event_time_stamp() was added by commit d8279bfc5e959 ("tracing:
Add tracing_event_time_stamp() API") for exactly this case: if the event
is the per-CPU trace_buffered_event, it returns the current ring buffer
timestamp. But it never gained a caller. Use it in hist_field_timestamp(),
so that a hist trigger that races onto a buffered event records the
current time, which is only marginally later than when the event was
recorded, instead of warning and recording a bogus timestamp.

Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20260929104015.1689921-1-wutengda@huaweicloud.com
Fixes: b94bc80df648 ("tracing: Use a no_filter_buffering_ref to stop using the filter buffer")
Signed-off-by: Tengda Wu <wutengda@huaweicloud.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 kernel/trace/trace_events_hist.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/kernel/trace/trace_events_hist.c
+++ b/kernel/trace/trace_events_hist.c
@@ -866,7 +866,7 @@ static u64 hist_field_timestamp(struct h
 	struct hist_trigger_data *hist_data = hist_field->hist_data;
 	struct trace_array *tr = hist_data->event_file->tr;
 
-	u64 ts = ring_buffer_event_time_stamp(buffer, rbe);
+	u64 ts = tracing_event_time_stamp(buffer, rbe);
 
 	if (hist_data->attrs->ts_in_usecs && trace_clock_in_ns(tr))
 		ts = ns2usecs(ts);



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 095/247] wifi: p54: validate firmware record lengths
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (93 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 094/247] tracing: Fix hist trigger timestamps for buffered events Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 096/247] tcp: fix use-after-free in do_tcp_getsockopt(TCP_CONGESTION) Greg Kroah-Hartman
                   ` (159 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Heyang Tan, Christian Lamparter,
	Johannes Berg

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Heyang Tan <thy15333007817@163.com>

commit db7b86bd97b380ece8fa39cfdd7502a9fd35e56f upstream.

The p54 firmware parser accesses component ID and component version
records without checking that their lengths cover the fields being read.
A malformed record can therefore make the parser read past the record.

Validate the component ID and component version record lengths before
accessing their data. The descriptor record is also checked against the
shortest descriptor length found in the supported firmware images.

Reject descriptor values that underflow the RX offset or produce an empty
RX range before updating the driver state.

Assisted-by: LLM Codex
Signed-off-by: Heyang Tan <thy15333007817@163.com>
Tested-by: Christian Lamparter <chunkeey@gmail.com>
Link: https://patch.msgid.link/20260918083349.891-1-thy15333007817@163.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/net/wireless/intersil/p54/fwio.c |   42 +++++++++++++++++++++++++++----
 1 file changed, 37 insertions(+), 5 deletions(-)

--- a/drivers/net/wireless/intersil/p54/fwio.c
+++ b/drivers/net/wireless/intersil/p54/fwio.c
@@ -52,6 +52,13 @@ int p54_parse_firmware(struct ieee80211_
 		u32 code = le32_to_cpu(bootrec->code);
 		switch (code) {
 		case BR_CODE_COMPONENT_ID:
+			if (len < sizeof(struct bootrec_comp_id) /
+				sizeof(*bootrec->data)) {
+				wiphy_err(priv->hw->wiphy,
+					  "firmware component ID is too short\n");
+				return -EINVAL;
+			}
+
 			priv->fw_interface = be32_to_cpup((__be32 *)
 					     bootrec->data);
 			switch (priv->fw_interface) {
@@ -72,16 +79,41 @@ int p54_parse_firmware(struct ieee80211_
 			}
 			break;
 		case BR_CODE_COMPONENT_VERSION:
+			if (len < DIV_ROUND_UP(sizeof(struct bootrec_comp_ver),
+					       sizeof(*bootrec->data))) {
+				wiphy_err(priv->hw->wiphy,
+					  "firmware component version is too short\n");
+				return -EINVAL;
+			}
+
 			/* 24 bytes should be enough for all firmwares */
-			if (strnlen((unsigned char *) bootrec->data, 24) < 24)
-				fw_version = (unsigned char *) bootrec->data;
+			if (strnlen((unsigned char *)bootrec->data,
+				    sizeof(struct bootrec_comp_ver)) <
+				    sizeof(struct bootrec_comp_ver))
+				fw_version = (unsigned char *)bootrec->data;
 			break;
 		case BR_CODE_DESCR: {
 			struct bootrec_desc *desc =
 				(struct bootrec_desc *)bootrec->data;
-			priv->rx_start = le32_to_cpu(desc->rx_start);
-			/* FIXME add sanity checking */
-			priv->rx_end = le32_to_cpu(desc->rx_end) - 0x3500;
+			u32 rx_start, rx_end;
+
+			/* 0xa is the shortest descriptor in supported firmware. */
+			if (len < 0xa) {
+				wiphy_err(priv->hw->wiphy,
+					  "firmware descriptor is too short\n");
+				return -EINVAL;
+			}
+
+			rx_start = le32_to_cpu(desc->rx_start);
+			rx_end = le32_to_cpu(desc->rx_end);
+			if (rx_end < 0x3500 || rx_end - 0x3500 <= rx_start) {
+				wiphy_err(priv->hw->wiphy,
+					  "firmware descriptor has invalid RX range\n");
+				return -EINVAL;
+			}
+
+			priv->rx_start = rx_start;
+			priv->rx_end = rx_end - 0x3500;
 			priv->headroom = desc->headroom;
 			priv->tailroom = desc->tailroom;
 			priv->privacy_caps = desc->privacy_caps;



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 096/247] tcp: fix use-after-free in do_tcp_getsockopt(TCP_CONGESTION)
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (94 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 095/247] wifi: p54: validate firmware record lengths Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 097/247] tcp: fix use-after-free in do_tcp_getsockopt(TCP_CC_INFO) Greg Kroah-Hartman
                   ` (158 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Eric Dumazet, Xiang Mei (Microsoft),
	AutonomousCodeSecurity, Cen Zhang (Microsoft Security FORGE Labs),
	Jiayuan Chen, Matthieu Baerts (NGI0), Breno Leitao,
	Jakub Kicinski

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Cen Zhang (Microsoft Security FORGE Labs) <blbllhy@gmail.com>

commit 5271b79b7ad68dcb222e893773f92bdabf7750f3 upstream.

do_tcp_getsockopt() reads icsk->icsk_ca_ops->name without holding
rcu_read_lock(). Since commit 0baf26b0fcd7 ("bpf: tcp: Support
tcp_congestion_ops in bpf"), icsk_ca_ops can point to dynamically
allocated BPF struct_ops memory that may be freed concurrently via
setsockopt(TCP_CONGESTION), leading to a use-after-free.

  BUG: KASAN: slab-use-after-free in _copy_to_user+0x37/0x60
  Read of size 16 at addr ffff888013505260 by task exploit/149
   _copy_to_user+0x37/0x60
   do_tcp_getsockopt+0x158a/0x2460 (net/ipv4/tcp.c:4585)
   tcp_getsockopt+0x91/0xf0
   __sys_getsockopt+0xf7/0x170

Fix this by holding rcu_read_lock() around the ca_ops->name access,
using READ_ONCE() to load icsk_ca_ops, and copying the name to a
stack buffer before releasing the lock. Also annotate the relevant
icsk_ca_ops stores with WRITE_ONCE() to fix the accompanying KCSAN
data-race issue.

Fixes: 0baf26b0fcd7 ("bpf: tcp: Support tcp_congestion_ops in bpf")
Suggested-by: Eric Dumazet <edumazet@google.com>
Reported-by: Xiang Mei (Microsoft) <xmei5@asu.edu>
Link: https://lore.kernel.org/all/20260821182449.79785-2-blbllhy@gmail.com/
Cc: AutonomousCodeSecurity@microsoft.com
Cc: stable@vger.kernel.org
Reviewed-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Cen Zhang (Microsoft Security FORGE Labs) <blbllhy@gmail.com>
Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>
Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Reviewed-by: Breno Leitao <leitao@debian.org>
Link: https://patch.msgid.link/d3f97f1acbf0010898148be6e6406e4b8b4a5c84.1787870710.git.blbllhy@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 net/ipv4/tcp.c           |   14 +++++++++++---
 net/ipv4/tcp_cong.c      |    4 ++--
 net/ipv4/tcp_dctcp.c     |    2 +-
 net/ipv4/tcp_minisocks.c |    2 +-
 net/ipv4/tcp_output.c    |    2 +-
 5 files changed, 16 insertions(+), 8 deletions(-)

--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -4418,16 +4418,24 @@ int do_tcp_getsockopt(struct sock *sk, i
 		val = !inet_csk_in_pingpong_mode(sk);
 		break;
 
-	case TCP_CONGESTION:
+	case TCP_CONGESTION: {
+		char ca_name[TCP_CA_NAME_MAX] = {};
+
 		if (copy_from_sockptr(&len, optlen, sizeof(int)))
 			return -EFAULT;
 		len = min_t(unsigned int, len, TCP_CA_NAME_MAX);
 		if (copy_to_sockptr(optlen, &len, sizeof(int)))
 			return -EFAULT;
-		if (copy_to_sockptr(optval, icsk->icsk_ca_ops->name, len))
+
+		rcu_read_lock();
+		memcpy(ca_name, READ_ONCE(icsk->icsk_ca_ops)->name,
+		       sizeof(ca_name));
+		rcu_read_unlock();
+
+		if (copy_to_sockptr(optval, ca_name, len))
 			return -EFAULT;
 		return 0;
-
+	}
 	case TCP_ULP:
 		if (copy_from_sockptr(&len, optlen, sizeof(int)))
 			return -EFAULT;
--- a/net/ipv4/tcp_cong.c
+++ b/net/ipv4/tcp_cong.c
@@ -222,7 +222,7 @@ void tcp_assign_congestion_control(struc
 	ca = rcu_dereference(net->ipv4.tcp_congestion_control);
 	if (unlikely(!bpf_try_module_get(ca, ca->owner)))
 		ca = &tcp_reno;
-	icsk->icsk_ca_ops = ca;
+	WRITE_ONCE(icsk->icsk_ca_ops, ca);
 	rcu_read_unlock();
 
 	memset(icsk->icsk_ca_priv, 0, sizeof(icsk->icsk_ca_priv));
@@ -252,7 +252,7 @@ static void tcp_reinit_congestion_contro
 	struct inet_connection_sock *icsk = inet_csk(sk);
 
 	tcp_cleanup_congestion_control(sk);
-	icsk->icsk_ca_ops = ca;
+	WRITE_ONCE(icsk->icsk_ca_ops, ca);
 	icsk->icsk_ca_setsockopt = 1;
 	memset(icsk->icsk_ca_priv, 0, sizeof(icsk->icsk_ca_priv));
 
--- a/net/ipv4/tcp_dctcp.c
+++ b/net/ipv4/tcp_dctcp.c
@@ -111,7 +111,7 @@ __bpf_kfunc static void dctcp_init(struc
 	/* No ECN support? Fall back to Reno. Also need to clear
 	 * ECT from sk since it is set during 3WHS for DCTCP.
 	 */
-	inet_csk(sk)->icsk_ca_ops = &dctcp_reno;
+	WRITE_ONCE(inet_csk(sk)->icsk_ca_ops, &dctcp_reno);
 	INET_ECN_dontxmit(sk);
 }
 
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -468,7 +468,7 @@ void tcp_ca_openreq_child(struct sock *s
 		ca = tcp_ca_find_key(ca_key);
 		if (likely(ca && bpf_try_module_get(ca, ca->owner))) {
 			icsk->icsk_ca_dst_locked = tcp_ca_dst_locked(dst);
-			icsk->icsk_ca_ops = ca;
+			WRITE_ONCE(icsk->icsk_ca_ops, ca);
 			ca_got_dst = true;
 		}
 		rcu_read_unlock();
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -3888,7 +3888,7 @@ static void tcp_ca_dst_init(struct sock
 	if (likely(ca && bpf_try_module_get(ca, ca->owner))) {
 		bpf_module_put(icsk->icsk_ca_ops, icsk->icsk_ca_ops->owner);
 		icsk->icsk_ca_dst_locked = tcp_ca_dst_locked(dst);
-		icsk->icsk_ca_ops = ca;
+		WRITE_ONCE(icsk->icsk_ca_ops, ca);
 	}
 	rcu_read_unlock();
 }



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 097/247] tcp: fix use-after-free in do_tcp_getsockopt(TCP_CC_INFO)
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (95 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 096/247] tcp: fix use-after-free in do_tcp_getsockopt(TCP_CONGESTION) Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 098/247] cgroup: fix spurious SIGKILL of CLONE_INTO_CGROUP children Greg Kroah-Hartman
                   ` (157 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Eric Dumazet, AutonomousCodeSecurity,
	Cen Zhang (Microsoft Security FORGE Labs), Jiayuan Chen,
	Matthieu Baerts (NGI0), Jakub Kicinski

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Cen Zhang (Microsoft Security FORGE Labs) <blbllhy@gmail.com>

commit 385e474086c2e7e29e2dded690be40dc273e20ee upstream.

do_tcp_getsockopt() reads icsk->icsk_ca_ops and dereferences the
get_info function pointer without rcu_read_lock(). With BPF struct_ops
congestion control, ca_ops can point to dynamically allocated memory
that is freed concurrently, resulting in a use-after-free when the
kernel dereferences or calls through the stale pointer.

  BUG: KASAN: slab-use-after-free in do_tcp_getsockopt+0x2037/0x23e0
  Read of size 8 at addr ffff888013701258 by task exploit/149
   do_tcp_getsockopt+0x2037/0x23e0 (net/ipv4/tcp.c:4564)
   tcp_getsockopt+0x91/0xf0
   __sys_getsockopt+0xf7/0x170

Fix this by wrapping the ca_ops load and get_info call within
rcu_read_lock()/rcu_read_unlock(), and using READ_ONCE() to load
the icsk_ca_ops pointer.

Fixes: 0baf26b0fcd7 ("bpf: tcp: Support tcp_congestion_ops in bpf")
Suggested-by: Eric Dumazet <edumazet@google.com>
Cc: AutonomousCodeSecurity@microsoft.com
Cc: stable@vger.kernel.org
Reviewed-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Cen Zhang (Microsoft Security FORGE Labs) <blbllhy@gmail.com>
Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>
Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/65fd3816ed5d541d9edd4bf4fcf97104a2cf907a.1787870710.git.blbllhy@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 net/ipv4/tcp.c       |    4 +++-
 net/ipv4/tcp_dctcp.c |    2 +-
 2 files changed, 4 insertions(+), 2 deletions(-)

--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -4403,9 +4403,11 @@ int do_tcp_getsockopt(struct sock *sk, i
 		if (copy_from_sockptr(&len, optlen, sizeof(int)))
 			return -EFAULT;
 
-		ca_ops = icsk->icsk_ca_ops;
+		rcu_read_lock();
+		ca_ops = READ_ONCE(icsk->icsk_ca_ops);
 		if (ca_ops && ca_ops->get_info)
 			sz = ca_ops->get_info(sk, ~0U, &attr, &info);
+		rcu_read_unlock();
 
 		len = min_t(unsigned int, len, sz);
 		if (copy_to_sockptr(optlen, &len, sizeof(int)))
--- a/net/ipv4/tcp_dctcp.c
+++ b/net/ipv4/tcp_dctcp.c
@@ -224,7 +224,7 @@ static size_t dctcp_get_info(struct sock
 	if (ext & (1 << (INET_DIAG_DCTCPINFO - 1)) ||
 	    ext & (1 << (INET_DIAG_VEGASINFO - 1))) {
 		memset(&info->dctcp, 0, sizeof(info->dctcp));
-		if (inet_csk(sk)->icsk_ca_ops != &dctcp_reno) {
+		if (READ_ONCE(inet_csk(sk)->icsk_ca_ops) != &dctcp_reno) {
 			info->dctcp.dctcp_enabled = 1;
 			info->dctcp.dctcp_ce_state = (u16) ca->ce_state;
 			info->dctcp.dctcp_alpha = ca->dctcp_alpha;



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 098/247] cgroup: fix spurious SIGKILL of CLONE_INTO_CGROUP children
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (96 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 097/247] tcp: fix use-after-free in do_tcp_getsockopt(TCP_CC_INFO) Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 099/247] dm cache: fix demotion stats in passthrough mode Greg Kroah-Hartman
                   ` (156 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Shakeel Butt, Etienne Perot,
	Tejun Heo

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Etienne Perot <eperot@google.com>

commit 8e359920216689b3b79e0fe8961a77fe312a511f upstream.

Since commit b69bb476dee9 ("cgroup: fix race between fork and
cgroup.kill"), the fork path snapshots the kill_seq of the child's
future cgroup into kargs->kill_seq, and cgroup_post_fork() SIGKILLs
the child if that cgroup's kill_seq has changed in the meantime, to
catch forks racing with a cgroup.kill sweep.

For CLONE_INTO_CGROUP, however, the snapshot in cgroup_css_set_fork()
is taken before the target cgroup has been resolved: kargs->cgrp is
always NULL at this point (it is only set at the end of the function).
So the "if (kargs->cgrp)" branch is dead code and the snapshot always
records the kill_seq of the parent's cgroup. cgroup_post_fork() then
compares it with the kill_seq of the target cgroup, so the child gets
SIGKILLed whenever the two cgroups have been killed a different number
of times.

As a result, once cgroup.kill has been written to a cgroup, every
child subsequently cloned into it with clone3(CLONE_INTO_CGROUP) is
killed on the spot, for as long as the cgroup exists: kill_seq is not
exposed to userspace and never resets.

Re-snapshot kill_seq from the target cgroup once it has been resolved,
and drop the dead branch at the early snapshot site.

This does not reopen the race fixed by b69bb476dee9. For
CLONE_INTO_CGROUP, everything from the snapshot to the check in
cgroup_post_fork() runs with cgroup_mutex held, and kill_seq is
only ever incremented under cgroup_mutex.

tj: Updated the comment above kill_seq to reflect the new serialization
rules as suggested by Shakeel Butt.

Fixes: b69bb476dee9 ("cgroup: fix race between fork and cgroup.kill")
Cc: stable@vger.kernel.org
Cc: Shakeel Butt <shakeel.butt@linux.dev>
Assisted-by: LLM
Signed-off-by: Etienne Perot <eperot@google.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 include/linux/cgroup-defs.h |    5 ++++-
 kernel/cgroup/cgroup.c      |    6 ++----
 2 files changed, 6 insertions(+), 5 deletions(-)

--- a/include/linux/cgroup-defs.h
+++ b/include/linux/cgroup-defs.h
@@ -458,7 +458,10 @@ struct cgroup {
 
 	int nr_threaded_children;	/* # of live threaded child cgroups */
 
-	/* sequence number for cgroup.kill, serialized by css_set_lock. */
+	/*
+	 * Sequence number for cgroup.kill. Incremented with both cgroup_mutex
+	 * and css_set_lock held. Readers hold either one.
+	 */
 	unsigned int kill_seq;
 
 	struct kernfs_node *kn;		/* cgroup kernfs entry */
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -6602,10 +6602,7 @@ static int cgroup_css_set_fork(struct ke
 	spin_lock_irq(&css_set_lock);
 	cset = task_css_set(current);
 	get_css_set(cset);
-	if (kargs->cgrp)
-		kargs->kill_seq = kargs->cgrp->kill_seq;
-	else
-		kargs->kill_seq = cset->dfl_cgrp->kill_seq;
+	kargs->kill_seq = cset->dfl_cgrp->kill_seq;
 	spin_unlock_irq(&css_set_lock);
 
 	if (!(kargs->flags & CLONE_INTO_CGROUP)) {
@@ -6670,6 +6667,7 @@ static int cgroup_css_set_fork(struct ke
 	put_css_set(cset);
 	fput(f);
 	kargs->cgrp = dst_cgrp;
+	kargs->kill_seq = dst_cgrp->kill_seq;
 	return ret;
 
 err:



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 099/247] dm cache: fix demotion stats in passthrough mode
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (97 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 098/247] cgroup: fix spurious SIGKILL of CLONE_INTO_CGROUP children Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 100/247] dm cache: fix issue with background work locking Greg Kroah-Hartman
                   ` (155 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Ben Marzinski, Ming-Hung Tsai,
	Mikulas Patocka

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Ming-Hung Tsai <mtsai@redhat.com>

commit 2ccb8878c149443c6acf628b438c9c942c20abb2 upstream.

The demotion counter is incremented per incoming write bio before the
invalidation begins, causing the demotion count to exceed the actual
number of cached blocks when multiple bios target the same cached
block. Additionally, the counter is incremented unconditionally
regardless of invalidation failure.

Reproduce steps:

1. Create a cache device consisting of 512 cache entries

modprobe brd rd_size=262144
dmsetup create cmeta --table "0 8192 linear /dev/ram0 0"
dmsetup create cdata --table "0 65536 linear /dev/ram0 8192"
dmsetup create corig --table "0 65536 linear /dev/ram0 262144"
dd if=/dev/zero of=/dev/mapper/cmeta bs=4k count=1 oflag=direct
dmsetup create cache --table "0 65536 cache /dev/mapper/cmeta \
/dev/mapper/cdata /dev/mapper/corig 128 2 metadata2 writethrough smq 0"

2. Populate the cache, and record the number of cached blocks

fio --name=populate --filename=/dev/mapper/cache --rw=randwrite --bs=4k \
--direct=1 --ioengine=libaio --iodepth=32 --io_size=2048m
nr_cached=$(dmsetup status cache | awk '{split($7, a, "/"); print a[1]}')

3. Reload the cache into passthrough mode

dmsetup suspend cache
dmsetup reload cache --table "0 65536 cache /dev/mapper/cmeta \
/dev/mapper/cdata /dev/mapper/corig 128 2 metadata2 passthrough smq 0"
dmsetup resume cache

4. Write to the passthrough cache with multiple jobs to trigger
   multiple bios hitting the same cached block.

fio --filename=/dev/mapper/cache --name=test --rw=write --bs=4k \
--direct=1 --ioengine=libaio --iodepth=32 --numjobs=4

5. Check if demoted matches cached block count. These numbers should
   match but may differ due to overcounting per bio.

nr_demoted=$(dmsetup status cache | awk '{print $12}')
echo "$nr_cached, $nr_demoted"

Fix by moving the demotion counter increment into invalidate_complete(),
gated on the success flag.

Reported-by: Ben Marzinski <bmarzins@redhat.com>
Fixes: b29d4986d0da ("dm cache: significant rework to leverage dm-bio-prison-v2")
Cc: stable@vger.kernel.org
Signed-off-by: Ming-Hung Tsai <mtsai@redhat.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/md/dm-cache-target.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

--- a/drivers/md/dm-cache-target.c
+++ b/drivers/md/dm-cache-target.c
@@ -1461,6 +1461,9 @@ static void invalidate_complete(struct d
 	struct bio_list bios;
 	struct cache *cache = mg->cache;
 
+	if (success)
+		atomic_inc(&cache->stats.demotion);
+
 	bio_list_init(&bios);
 	if (mg->cell) {
 		if (dm_cell_unlock_v2(cache->prison, mg->cell, &bios))
@@ -1732,7 +1735,6 @@ static int map_bio(struct cache *cache,
 		if (passthrough_mode(cache)) {
 			if (bio_data_dir(bio) == WRITE) {
 				bio_drop_shared_lock(cache, bio);
-				atomic_inc(&cache->stats.demotion);
 				invalidate_start(cache, cblock, block, bio);
 				return DM_MAPIO_SUBMITTED;
 			} else



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 100/247] dm cache: fix issue with background work locking
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (98 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 099/247] dm cache: fix demotion stats in passthrough mode Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 101/247] dm-crypt: fix a tiny race condition in crypt_dec_pending Greg Kroah-Hartman
                   ` (154 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Benjamin Marzinski, Matthew Sakai,
	Ming-Hung Tsai, Mikulas Patocka

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Benjamin Marzinski <bmarzins@redhat.com>

commit bc9781c0247de107876f32929f1637db93a42b34 upstream.

dm cache used a rw_semaphore for background_work_lock. Write locks on
rw_semaphores have strict owner semantics, but there was no guarantee
that the process that locked background_work_lock was the same process
that unlocked it. This can be easily seen using a kernel compiled with
CONFIG_DEBUG_RWSEMS. Given a dm cache device <cache>, run: 'dmsetup
suspend <cache> && dmsetup resume <cache>'. This will trigger a kernel
warning:

DEBUG_RWSEMS_WARN_ON((rwsem_owner(sem) != current) && !rwsem_test_oflags(sem, RWSEM_NONSPINNABLE))

triggered by cache_resume(). To fix this, switch from a rw_semaphore to
a spinlock and a wait queue. dm cache already has a wait queue and
associated counter, migration_wait and nr_allocated_migrations, that was
getting woken up when background work was getting completed, but wasn't
actually used by anything. This is replaced by the background_work queue
and counter.

Fixes: b29d4986d0da ("dm cache: significant rework to leverage dm-bio-prison-v2")
Cc: stable@vger.kernel.org
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Matthew Sakai <msakai@redhat.com>
Reviewed-by: Ming-Hung Tsai <mtsai@redhat.com>
Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/md/dm-cache-target.c |   55 +++++++++++++++++++++----------------------
 1 file changed, 28 insertions(+), 27 deletions(-)

--- a/drivers/md/dm-cache-target.c
+++ b/drivers/md/dm-cache-target.c
@@ -339,8 +339,6 @@ struct cache {
 	struct list_head invalidation_requests;
 
 	sector_t migration_threshold;
-	wait_queue_head_t migration_wait;
-	atomic_t nr_allocated_migrations;
 
 	/*
 	 * The number of in flight migrations that are performing
@@ -396,7 +394,11 @@ struct cache {
 	bool loaded_mappings:1;
 	bool loaded_discards:1;
 
-	struct rw_semaphore background_work_lock;
+	/* background work management */
+	bool background_work_allowed;
+	unsigned background_work_nr;
+	spinlock_t background_work_lock;
+	wait_queue_head_t background_work_wait;
 
 	struct batcher committer;
 	struct work_struct commit_ws;
@@ -487,19 +489,13 @@ static struct dm_cache_migration *alloc_
 	memset(mg, 0, sizeof(*mg));
 
 	mg->cache = cache;
-	atomic_inc(&cache->nr_allocated_migrations);
 
 	return mg;
 }
 
 static void free_migration(struct dm_cache_migration *mg)
 {
-	struct cache *cache = mg->cache;
-
-	if (atomic_dec_and_test(&cache->nr_allocated_migrations))
-		wake_up(&cache->migration_wait);
-
-	mempool_free(mg, &cache->migration_pool);
+	mempool_free(mg, &mg->cache->migration_pool);
 }
 
 /*----------------------------------------------------------------*/
@@ -1029,34 +1025,39 @@ static void calc_discard_block_range(str
 
 static void prevent_background_work(struct cache *cache)
 {
-	lockdep_off();
-	down_write(&cache->background_work_lock);
-	lockdep_on();
+	spin_lock_irq(&cache->background_work_lock);
+	cache->background_work_allowed = false;
+	wait_event_lock_irq(cache->background_work_wait,
+			    cache->background_work_nr == 0,
+			    cache->background_work_lock);
+	spin_unlock_irq(&cache->background_work_lock);
 }
 
 static void allow_background_work(struct cache *cache)
 {
-	lockdep_off();
-	up_write(&cache->background_work_lock);
-	lockdep_on();
+	spin_lock_irq(&cache->background_work_lock);
+	cache->background_work_allowed = true;
+	spin_unlock_irq(&cache->background_work_lock);
 }
 
 static bool background_work_begin(struct cache *cache)
 {
 	bool r;
 
-	lockdep_off();
-	r = down_read_trylock(&cache->background_work_lock);
-	lockdep_on();
-
+	spin_lock_irq(&cache->background_work_lock);
+	r = cache->background_work_allowed;
+	if (r)
+		cache->background_work_nr++;
+	spin_unlock_irq(&cache->background_work_lock);
 	return r;
 }
 
 static void background_work_end(struct cache *cache)
 {
-	lockdep_off();
-	up_read(&cache->background_work_lock);
-	lockdep_on();
+	spin_lock_irq(&cache->background_work_lock);
+	if (--cache->background_work_nr == 0)
+		wake_up(&cache->background_work_wait);
+	spin_unlock_irq(&cache->background_work_lock);
 }
 
 /*----------------------------------------------------------------*/
@@ -2515,9 +2516,7 @@ static int cache_create(struct cache_arg
 
 	spin_lock_init(&cache->lock);
 	bio_list_init(&cache->deferred_bios);
-	atomic_set(&cache->nr_allocated_migrations, 0);
 	atomic_set(&cache->nr_io_migrations, 0);
-	init_waitqueue_head(&cache->migration_wait);
 
 	r = -ENOMEM;
 	atomic_set(&cache->nr_dirty, 0);
@@ -2599,8 +2598,10 @@ static int cache_create(struct cache_arg
 		     issue_op, cache, cache->wq);
 	dm_iot_init(&cache->tracker);
 
-	init_rwsem(&cache->background_work_lock);
-	prevent_background_work(cache);
+	init_waitqueue_head(&cache->background_work_wait);
+	spin_lock_init(&cache->background_work_lock);
+	cache->background_work_allowed = false;
+	cache->background_work_nr = 0;
 
 	*result = cache;
 	return 0;



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 101/247] dm-crypt: fix a tiny race condition in crypt_dec_pending
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (99 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 100/247] dm cache: fix issue with background work locking Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 102/247] dm-ebs: fix incorrect device offset check in ebs_ctr() Greg Kroah-Hartman
                   ` (153 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Jose Fernandez (Anthropic),
	Ben Cressey, Mikulas Patocka

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Ben Cressey <ben@cressey.dev>

commit 148845aa1921d95ef5dc851c76e6a284f6657df6 upstream.

crypt_dec_pending reads io->error before calling atomic_dec_and_test.
Another context, for example crypt_endio called from an interrupt, may
set io->error and drop its reference between the read and the
decrement. crypt_dec_pending then drops the last reference and completes
the bio with the stale status - so a read that failed and was never
decrypted, or a write that failed, is reported as successful.

The read was placed before the decrement by commit b35f8caa0890 ("dm
crypt: wait for endio to complete before destruction"), because that
commit freed dm_crypt_io before calling bio_endio. This is no longer the
case, dm_crypt_io lives in the per-bio data now.

Read io->error after atomic_dec_and_test instead. atomic_dec_and_test is
fully ordered, so no additional barrier is needed.

Fixes: b35f8caa0890 ("dm crypt: wait for endio to complete before destruction")
Cc: stable@vger.kernel.org
Reviewed-by: Jose Fernandez (Anthropic) <jose.fernandez@linux.dev>
Signed-off-by: Ben Cressey <ben@cressey.dev>
Assisted-by: Claude:unspecified
Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/md/dm-crypt.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -1837,7 +1837,6 @@ static void crypt_dec_pending(struct dm_
 {
 	struct crypt_config *cc = io->cc;
 	struct bio *base_bio = io->base_bio;
-	blk_status_t error = io->error;
 
 	if (!atomic_dec_and_test(&io->io_pending))
 		return;
@@ -1859,7 +1858,7 @@ static void crypt_dec_pending(struct dm_
 	else
 		kfree(io->integrity_metadata);
 
-	base_bio->bi_status = error;
+	base_bio->bi_status = io->error;
 
 	bio_endio(base_bio);
 }



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 102/247] dm-ebs: fix incorrect device offset check in ebs_ctr()
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (100 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 101/247] dm-crypt: fix a tiny race condition in crypt_dec_pending Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 103/247] dm-integrity: fix infinite loop on discard with large tag size Greg Kroah-Hartman
                   ` (152 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Genjian Zhang, Mikulas Patocka

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Genjian Zhang <zhanggenjian@kylinos.cn>

commit 7ac81e2d2240f2c57bd073b0733e0b2abca38e82 upstream.

<offset> is a backing-device sector offset; ti->len is the virtual
target length. Comparing them rejects valid tables, e.g.:

  dmsetup create ebs0 --table "0 1048576 ebs /dev/sda 2097152 1 8"
  -> ebs: Invalid device offset sector (-EINVAL)

Drop the check. Bounds against the backing device are already
enforced later by device_area_is_invalid() via ebs_iterate_devices().

Cc: stable@vger.kernel.org
Fixes: d3c7b35c20d6 ("dm: add emulated block size target")
Signed-off-by: Genjian Zhang <zhanggenjian@kylinos.cn>
Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/md/dm-ebs-target.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

--- a/drivers/md/dm-ebs-target.c
+++ b/drivers/md/dm-ebs-target.c
@@ -265,8 +265,7 @@ static int ebs_ctr(struct dm_target *ti,
 
 	r = -EINVAL;
 	if (sscanf(argv[1], "%llu%c", &tmp, &dummy) != 1 ||
-	    tmp != (sector_t)tmp ||
-	    (sector_t)tmp >= ti->len) {
+	    tmp != (sector_t)tmp) {
 		ti->error = "Invalid device offset sector";
 		goto bad;
 	}



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 103/247] dm-integrity: fix infinite loop on discard with large tag size
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (101 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 102/247] dm-ebs: fix incorrect device offset check in ebs_ctr() Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 104/247] dm-integrity: require stable writes for internal hash modes Greg Kroah-Hartman
                   ` (151 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Jose Fernandez (Anthropic),
	Ben Cressey, Mikulas Patocka

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Ben Cressey <ben@cressey.dev>

commit 18d80c77b4c7dd20699e81cedfbbff4e9d198f28 upstream.

When integrity_metadata handles a discard, it fills a buffer with
DISCARD_FILLER and writes it over the tags, max_blocks blocks at a
time. If the kmalloc fails, the buffer is the on-stack array
checksums_onstack and max_size is set to HASH_MAX_DIGESTSIZE. So if the
tag size is larger than HASH_MAX_DIGESTSIZE, max_blocks is zero, bi_size
is never decremented and the loop never terminates.

Fix this by using sizeof(checksums_onstack) as max_size. The array has
MAX_TAG_SIZE bytes since commit b93b6643e9b5 ("dm integrity: fix a
crash with unusually large tag size"), so max_blocks is at least 1.

Fixes: 84597a44a9d8 ("dm integrity: add optional discard support")
Cc: stable@vger.kernel.org
Reviewed-by: Jose Fernandez (Anthropic) <jose.fernandez@linux.dev>
Signed-off-by: Ben Cressey <ben@cressey.dev>
Assisted-by: Claude:unspecified
Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/md/dm-integrity.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/drivers/md/dm-integrity.c
+++ b/drivers/md/dm-integrity.c
@@ -1856,7 +1856,7 @@ static void integrity_metadata(struct wo
 
 		if (unlikely(dio->op == REQ_OP_DISCARD)) {
 			unsigned int bi_size = dio->bio_details.bi_iter.bi_size;
-			unsigned int max_size = likely(checksums != checksums_onstack) ? PAGE_SIZE : HASH_MAX_DIGESTSIZE;
+			unsigned int max_size = likely(checksums != checksums_onstack) ? PAGE_SIZE : sizeof(checksums_onstack);
 			unsigned int max_blocks = (max_size - extra_space) / ic->tag_size;
 			sector_t sector = dio->range.logical_sector;
 



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 104/247] dm-integrity: require stable writes for internal hash modes
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (102 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 103/247] dm-integrity: fix infinite loop on discard with large tag size Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 105/247] mac802154: fix data race and NULL deref on local->assoc_dev Greg Kroah-Hartman
                   ` (150 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Sun Yangkai, Chen Cheng,
	Mikulas Patocka

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Chen Cheng <chencheng@fnnas.com>

commit b2fd92f016e9d692fd3c8c08d0ee014e9212279d upstream.

dm-integrity direct, bitmap and inline internal-hash modes compute
integrity tags from the pages carried by the write bio.  The lower data
write also uses those pages, so the tag and the data write depend on the
same memory contents staying unchanged while writeback is in flight.

Without stable writes, a buffered writer can modify a writeback folio
after dm-integrity has submitted the data bio and before the lower device
has consumed the data.  After a crash, this can leave data from the later
contents with a tag calculated from the earlier contents, causing
permanent checksum failures on read.

Set BLK_FEAT_STABLE_WRITES for internal-hash D, B and I modes so
filesystems wait for writeback folios to become stable before modifying
them again.  Journal mode is left unchanged because it copies data into
the journal before computing and persisting the tag.

Tested using dm-delay over a virtio-blk test disk, dm-integrity
internal_hash:crc32c and no-journal ext4.  The D and B reproducers both
failed with checksum errors before this change and completed with
READ_RC=0 and zero mismatches after it.

Fixes: 7eada909bfd7 ("dm: add integrity target")
Cc: stable@vger.kernel.org
Reported-by: Sun Yangkai <sunyangkai@fygo.io>
Link: https://github.com/chencheng-fnnas/reproducer/blob/main/dm-integrity-writeback-race.py
Signed-off-by: Chen Cheng <chencheng@fnnas.com>
Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/md/dm-integrity.c |    4 ++++
 1 file changed, 4 insertions(+)

--- a/drivers/md/dm-integrity.c
+++ b/drivers/md/dm-integrity.c
@@ -3979,6 +3979,10 @@ static void dm_integrity_io_hints(struct
 		limits->discard_granularity = ic->sectors_per_block << SECTOR_SHIFT;
 	}
 
+	if (ic->internal_hash &&
+	    (ic->mode == 'D' || ic->mode == 'B' || ic->mode == 'I'))
+		limits->features |= BLK_FEAT_STABLE_WRITES;
+
 	if (!ic->internal_hash) {
 		struct blk_integrity *bi = &limits->integrity;
 



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 105/247] mac802154: fix data race and NULL deref on local->assoc_dev
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (103 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 104/247] dm-integrity: require stable writes for internal hash modes Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 106/247] net/iucv: fix the recvmsg window update Greg Kroah-Hartman
                   ` (149 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Miquel Raynal, Xuanqiang Luo,
	Kaiwen Shi, Xuanqiang Luo, Paolo Abeni

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Kaiwen Shi <skwkevin@mail.ustc.edu.cn>

commit c037915f80c4db47f7d061d68e703ffd551b1a34 upstream.

local->assoc_dev is shared between the association path and the
association-response worker without common synchronization.

mac802154_perform_association() stores the coordinator pointer and waits
for a response. Its timeout and error paths clear the pointer and return
to mac802154_associate(), which may then free the coordinator object.
Meanwhile, mac802154_rx_mac_cmd_worker() may observe the associating bit
and enter mac802154_process_association_resp(), which dereferences
assoc_dev.

The worker's bit test and the handler's pointer dereference are not
atomic with respect to cleanup. Cleanup can clear assoc_dev between them,
causing a NULL dereference, or free the coordinator while the response
handler still uses the pointer.

The recorded result is exposed to the same window. assoc_status and
assoc_addr are written by the handler but read by the association path
while the associating bit is still set, so a second response for the same
request - a malicious one, for instance - can replace them between those
reads and leave the caller with an incoherent status and address pair.

The response handler only needs the coordinator extended address.
Replace assoc_dev with a cached address, removing the pointer lifetime
dependency. Protect the cached address and the associating bit with a
dedicated spinlock. A READ_ONCE()/WRITE_ONCE() pair would not guarantee
an atomic __le64 access on all 32-bit architectures.

wpan_dev->association_lock cannot be reused here: nl802154_associate()
holds it across rdev_associate(), hence for the whole of
mac802154_perform_association() including the wait for the response.
A response handler taking that lock would only get it once the
association has already given up.

Reset the completion, publish the cached address, and set the associating
bit while holding the lock. The response handler takes the lock, rechecks
the bit and the cached address, records the response, clears the bit, and
only then completes the waiter. Thus cleanup cannot pass the handler
between its state check and completion, and the cached 64-bit value
cannot tear.

The handler clears the bit before completing, not the woken waiter:
otherwise complete() is issued under the lock and a second (e.g.
malicious) response can reacquire it before the waiter and replace the
result. So a wait that returns success implies the bit is already clear,
and the success and negative-response paths return directly. The
transmit-error and timeout paths still clear it under assoc_lock, which
serializes any racing response against the cleanup while the call returns
the error it already selected. Both paths snapshot assoc_status and
assoc_addr under the same lock.

Both users run in process context, so a plain spinlock is sufficient.
The lock is not held while waiting for the completion.

Suggested-by: Miquel Raynal <miquel.raynal@bootlin.com>
Suggested-by: Xuanqiang Luo <xuanqiang.luo@linux.dev>
Fixes: fefd19807fe9 ("mac802154: Handle associating")
Cc: stable@vger.kernel.org
Signed-off-by: Kaiwen Shi <skwkevin@mail.ustc.edu.cn>
Reviewed-by: Xuanqiang Luo <luoxuanqiang@kylinos.cn>
Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
Link: https://patch.msgid.link/20260829230551.1787432-1-skwkevin@mail.ustc.edu.cn
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 net/mac802154/ieee802154_i.h |    7 +++++
 net/mac802154/main.c         |    1 
 net/mac802154/scan.c         |   51 ++++++++++++++++++++++++++++++++-----------
 3 files changed, 45 insertions(+), 14 deletions(-)

--- a/net/mac802154/ieee802154_i.h
+++ b/net/mac802154/ieee802154_i.h
@@ -80,7 +80,12 @@ struct ieee802154_local {
 	spinlock_t rx_lock;
 
 	/* Association */
-	struct ieee802154_pan_device *assoc_dev;
+	/* assoc_lock protects assoc_dev_extended_addr, assoc_addr,
+	 * assoc_status, the assoc_done reinit/complete pairing and the
+	 * IEEE802154_IS_ASSOCIATING bit in @ongoing.
+	 */
+	spinlock_t assoc_lock;
+	__le64 assoc_dev_extended_addr;
 	struct completion assoc_done;
 	__le16 assoc_addr;
 	u8 assoc_status;
--- a/net/mac802154/main.c
+++ b/net/mac802154/main.c
@@ -105,6 +105,7 @@ ieee802154_alloc_hw(size_t priv_data_len
 	INIT_WORK(&local->rx_mac_cmd_work, mac802154_rx_mac_cmd_worker);
 
 	init_completion(&local->assoc_done);
+	spin_lock_init(&local->assoc_lock);
 
 	/* init supported flags with 802.15.4 default ranges */
 	phy->supported.max_minbe = 8;
--- a/net/mac802154/scan.c
+++ b/net/mac802154/scan.c
@@ -532,7 +532,9 @@ int mac802154_perform_association(struct
 	struct ieee802154_association_req_frame frame = {};
 	struct ieee802154_local *local = sdata->local;
 	struct wpan_dev *wpan_dev = &sdata->wpan_dev;
+	__le16 resp_short_addr;
 	struct sk_buff *skb;
+	u8 resp_status;
 	int ret;
 
 	frame.mhr.fc.type = IEEE802154_FC_TYPE_MAC_CMD;
@@ -574,9 +576,11 @@ int mac802154_perform_association(struct
 		return ret;
 	}
 
-	local->assoc_dev = coord;
+	spin_lock(&local->assoc_lock);
 	reinit_completion(&local->assoc_done);
+	local->assoc_dev_extended_addr = coord->extended_addr;
 	set_bit(IEEE802154_IS_ASSOCIATING, &local->ongoing);
+	spin_unlock(&local->assoc_lock);
 
 	ret = ieee802154_mlme_tx_one_locked(local, sdata, skb);
 	if (ret) {
@@ -595,25 +599,37 @@ int mac802154_perform_association(struct
 		goto clear_assoc;
 	}
 
-	if (local->assoc_status != IEEE802154_ASSOCIATION_SUCCESSFUL) {
-		if (local->assoc_status == IEEE802154_PAN_AT_CAPACITY)
+	/* The association is complete: mac802154_process_association_resp()
+	 * cleared the associating bit before waking us, so a second (e.g.
+	 * malicious) ASSOC RESP can no longer pass the recheck and overwrite
+	 * the result.  Snapshot assoc_status/assoc_addr under the lock.
+	 */
+	spin_lock(&local->assoc_lock);
+	resp_status = local->assoc_status;
+	resp_short_addr = local->assoc_addr;
+	spin_unlock(&local->assoc_lock);
+
+	if (resp_status != IEEE802154_ASSOCIATION_SUCCESSFUL) {
+		if (resp_status == IEEE802154_PAN_AT_CAPACITY)
 			ret = -ERANGE;
 		else
 			ret = -EPERM;
 
 		dev_warn(&sdata->dev->dev,
 			 "Negative ASSOC RESP received from %8phC: %s\n", &ceaddr,
-			 local->assoc_status == IEEE802154_PAN_AT_CAPACITY ?
+			 resp_status == IEEE802154_PAN_AT_CAPACITY ?
 			 "PAN at capacity" : "access denied");
-		goto clear_assoc;
+		return ret;
 	}
 
-	ret = 0;
-	*short_addr = local->assoc_addr;
+	*short_addr = resp_short_addr;
+
+	return 0;
 
 clear_assoc:
+	spin_lock(&local->assoc_lock);
 	clear_bit(IEEE802154_IS_ASSOCIATING, &local->ongoing);
-	local->assoc_dev = NULL;
+	spin_unlock(&local->assoc_lock);
 
 	return ret;
 }
@@ -635,19 +651,28 @@ int mac802154_process_association_resp(s
 		     dest->mode != IEEE802154_EXTENDED_ADDRESSING))
 		return -EINVAL;
 
-	if (unlikely(dest->extended_addr != wpan_dev->extended_addr ||
-		     src->extended_addr != local->assoc_dev->extended_addr))
+	spin_lock(&local->assoc_lock);
+	if (unlikely(!test_bit(IEEE802154_IS_ASSOCIATING, &local->ongoing) ||
+		     dest->extended_addr != wpan_dev->extended_addr ||
+		     src->extended_addr != local->assoc_dev_extended_addr)) {
+		spin_unlock(&local->assoc_lock);
 		return -ENODEV;
+	}
 
 	memcpy(&resp_pl, skb->data, sizeof(resp_pl));
 	local->assoc_addr = resp_pl.short_addr;
 	local->assoc_status = resp_pl.status;
+	/* Clear the associating bit before waking the waiter: once the result
+	 * is saved, any subsequent (e.g. malicious) ASSOC RESP must fail the
+	 * test_bit() recheck above and can no longer overwrite the result.
+	 */
+	clear_bit(IEEE802154_IS_ASSOCIATING, &local->ongoing);
+	complete(&local->assoc_done);
+	spin_unlock(&local->assoc_lock);
 
 	dev_dbg(&skb->dev->dev,
 		"ASSOC RESP 0x%x received from %8phC, getting short address %04x\n",
-		local->assoc_status, &deaddr, local->assoc_addr);
-
-	complete(&local->assoc_done);
+		resp_pl.status, &deaddr, resp_pl.short_addr);
 
 	return 0;
 }



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 106/247] net/iucv: fix the recvmsg window update
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (104 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 105/247] mac802154: fix data race and NULL deref on local->assoc_dev Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 107/247] xfs: fix capability check in xfs Greg Kroah-Hartman
                   ` (148 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Aswin Karuvally, Bryam Vargas,
	Alexandra Winter, Jakub Kicinski

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Bryam Vargas <hexlabsecurity@proton.me>

commit fa5acd038ea657ad5033713d6916214cbd349151 upstream.

iucv_sock_recvmsg() sends the HiperSockets-only AF_IUCV_FLAG_WIN without
testing the transport, so on a classic z/VM socket iucv_send_ctrl() sizes
the skb through a NULL iucv->hs_dev. SO_MSGLIMIT accepts 1, so msglimit / 2
is zero and one recvmsg() on its own socket is enough for an unprivileged
process to take a spurious disconnect.

It also calls iucv_send_ctrl() under spin_lock_bh(&message_q.lock), which
allocates GFP_KERNEL inside a section the code treats as atomic. Sending
outside that lock lets two recvmsg() reach afiucv_hs_send() at once, where
msg_recv is sampled for the advertised window and subtracted after
dev_queue_xmit() -- and sendmsg reaches that counter under lock_sock()
while recvmsg holds no socket lock, so both can subtract the same value,
the counter goes negative and the credit reaches the peer twice.

Test the transport, claim the credit with atomic_xchg() after the last
error exit and hand it back if the transmit fails, and send once the lock
is dropped.

Fixes: 3881ac441f64 ("af_iucv: add HiperSockets transport")
Fixes: 238965b71b96 ("net/af_iucv: build proper skbs for HiperTransport")
Cc: stable@vger.kernel.org
Tested-by: Aswin Karuvally <aswin@linux.ibm.com>
Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
Reviewed-by: Alexandra Winter <wintera@linux.ibm.com>
Link: https://patch.msgid.link/20260828-b4-disp-33fac0ed-v3-1-e6d061880ee0@proton.me
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 net/iucv/af_iucv.c |   42 +++++++++++++++++++++++++-----------------
 1 file changed, 25 insertions(+), 17 deletions(-)

--- a/net/iucv/af_iucv.c
+++ b/net/iucv/af_iucv.c
@@ -207,12 +207,6 @@ static int afiucv_hs_send(struct iucv_me
 	phs_hdr->flags = flags;
 	if (flags == AF_IUCV_FLAG_SYN)
 		phs_hdr->window = iucv->msglimit;
-	else if ((flags == AF_IUCV_FLAG_WIN) || !flags) {
-		confirm_recv = atomic_read(&iucv->msg_recv);
-		phs_hdr->window = confirm_recv;
-		if (confirm_recv)
-			phs_hdr->flags = phs_hdr->flags | AF_IUCV_FLAG_WIN;
-	}
 	memcpy(phs_hdr->destUserID, iucv->dst_user_id, 8);
 	memcpy(phs_hdr->destAppName, iucv->dst_name, 8);
 	memcpy(phs_hdr->srcUserID, iucv->src_user_id, 8);
@@ -247,13 +241,22 @@ static int afiucv_hs_send(struct iucv_me
 	}
 	skb->protocol = cpu_to_be16(ETH_P_AF_IUCV);
 
+	/* Claim the receive credit here, not while building the header: every
+	 * way this frame can be dropped has now been ruled out, so the window
+	 * is zeroed only for as long as the transmit itself takes.
+	 */
+	if (flags == AF_IUCV_FLAG_WIN || !flags) {
+		confirm_recv = atomic_xchg(&iucv->msg_recv, 0);
+		phs_hdr->window = confirm_recv;
+		if (confirm_recv)
+			phs_hdr->flags = phs_hdr->flags | AF_IUCV_FLAG_WIN;
+	}
+
 	atomic_inc(&iucv->skbs_in_xmit);
 	err = dev_queue_xmit(skb);
 	if (net_xmit_eval(err)) {
 		atomic_dec(&iucv->skbs_in_xmit);
-	} else {
-		atomic_sub(confirm_recv, &iucv->msg_recv);
-		WARN_ON(atomic_read(&iucv->msg_recv) < 0);
+		atomic_add(confirm_recv, &iucv->msg_recv);
 	}
 	return net_xmit_eval(err);
 
@@ -1237,6 +1240,7 @@ static int iucv_sock_recvmsg(struct sock
 	struct iucv_sock *iucv = iucv_sk(sk);
 	unsigned int copied, rlen;
 	struct sk_buff *skb, *rskb, *cskb;
+	bool send_win = false;
 	int err = 0;
 	u32 offset;
 
@@ -1327,16 +1331,20 @@ static int iucv_sock_recvmsg(struct sock
 		if (skb_queue_empty(&iucv->backlog_skb_q)) {
 			if (!list_empty(&iucv->message_q.list))
 				iucv_process_message_q(sk);
-			if (atomic_read(&iucv->msg_recv) >=
-							iucv->msglimit / 2) {
-				err = iucv_send_ctrl(sk, AF_IUCV_FLAG_WIN);
-				if (err) {
-					sk->sk_state = IUCV_DISCONN;
-					sk->sk_state_change(sk);
-				}
-			}
+			if (iucv->transport == AF_IUCV_TRANS_HIPER &&
+			    atomic_read(&iucv->msg_recv) >=
+							iucv->msglimit / 2)
+				send_win = true;
 		}
 		spin_unlock_bh(&iucv->message_q.lock);
+
+		if (send_win) {
+			err = iucv_send_ctrl(sk, AF_IUCV_FLAG_WIN);
+			if (err) {
+				sk->sk_state = IUCV_DISCONN;
+				sk->sk_state_change(sk);
+			}
+		}
 	}
 
 done:



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 107/247] xfs: fix capability check in xfs
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (105 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 106/247] net/iucv: fix the recvmsg window update Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 108/247] workqueue: Use raise_softirq() to trigger softirq in irq_work handler Greg Kroah-Hartman
                   ` (147 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Dr. Thomas Orgis, Carlos Maiolino,
	Darrick J. Wong, Serge Hallyn, Christoph Hellwig, Carlos Maiolino

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Carlos Maiolino <cem@kernel.org>

commit e2f62a9744ebad3bcb6347a648e615026e9efeff upstream.

An user reported a bug where he managed to evade group's quota
by changing a file's gid to a different group id the same user
belonged to, even though quotas were enforced on both gids and the
file's size was big enough to exceed the quota's hardlimit.

Commit eba0549bc7d1 replaced a capable() call by a
has_capability_noaudit() to prevent unnecessary selinux audit messages.
Turns out that both calls have slightly different semantics even though
their documentation seems similar. Where in a nutshell:

capable() - Tests the task's effective credentials
has_ns_capability_noaudit() - Tests the task's real credentials

This most of the time has no practical difference but in some cases like
changing attrs (specifically group id in this case) through a NFS client
this will allow the quota code to use XFS_QMOPT_FORCE_RES, effectively
bypassing quota accounting checks.

Using instead ns_capable_noaudit() should fix this issue and prevent
selinux audit messages.

This also fix the remaining calls to has_capability_noaudit()

Fixes: eba0549bc7d1 ("xfs: don't generate selinux audit messages for capability testing")
Cc: stable@vger.kernel.org # v5.18
Reported-by: Dr. Thomas Orgis <thomas.orgis@uni-hamburg.de>
Signed-off-by: Carlos Maiolino <cmaiolino@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Serge Hallyn <sergeh@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 fs/xfs/xfs_fsmap.c |    2 +-
 fs/xfs/xfs_ioctl.c |    2 +-
 fs/xfs/xfs_iops.c  |    2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

--- a/fs/xfs/xfs_fsmap.c
+++ b/fs/xfs/xfs_fsmap.c
@@ -916,7 +916,7 @@ xfs_getfsmap(
 		return -EINVAL;
 
 	use_rmap = xfs_has_rmapbt(mp) &&
-		   has_capability_noaudit(current, CAP_SYS_ADMIN);
+		   ns_capable_noaudit(&init_user_ns, CAP_SYS_ADMIN);
 	head->fmh_entries = 0;
 
 	/* Set up our device handlers. */
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -573,7 +573,7 @@ xfs_ioctl_setattr_get_trans(
 		goto out_error;
 
 	error = xfs_trans_alloc_ichange(ip, NULL, NULL, pdqp,
-			has_capability_noaudit(current, CAP_FOWNER), &tp);
+			ns_capable_noaudit(&init_user_ns, CAP_FOWNER), &tp);
 	if (error)
 		goto out_error;
 
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -735,7 +735,7 @@ xfs_setattr_nonsize(
 	}
 
 	error = xfs_trans_alloc_ichange(ip, udqp, gdqp, NULL,
-			has_capability_noaudit(current, CAP_FOWNER), &tp);
+			ns_capable_noaudit(&init_user_ns, CAP_FOWNER), &tp);
 	if (error)
 		goto out_dqrele;
 



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 108/247] workqueue: Use raise_softirq() to trigger softirq in irq_work handler
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (106 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 107/247] xfs: fix capability check in xfs Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 109/247] tipc: protect node reset trace dump with node lock Greg Kroah-Hartman
                   ` (146 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Zqiang, Tejun Heo

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Zqiang <qiang.zhang@linux.dev>

commit 7e2f2a377ac9f50296ad60bd331f0d4def7aee51 upstream.

bh_pool_kick_normal() and bh_pool_kick_highpri() are registered via
init_irq_work() without the IRQ_WORK_HARD_IRQ flag. On PREEMPT_RT, such
irq_work items are processed by the per-CPU irq_workd kthread in preemptible
task context with IRQs enabled. However, raise_softirq_irqoff() requires
IRQs to be disabled. Calling it from irq_workd trips the lockdep assertion
in __raise_softirq_irqoff() and the non-atomic update of the softirq pending
mask can lose bits raised by an interrupt on the same CPU. Replace
raise_softirq_irqoff() with raise_softirq() in the irq_work handlers.

Fixes: 2f34d7337d98 ("workqueue: Fix queue_work_on() with BH workqueues")
Cc: stable@vger.kernel.org # v6.9+
Signed-off-by: Zqiang <qiang.zhang@linux.dev>
Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 kernel/workqueue.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -7738,12 +7738,12 @@ static inline void wq_watchdog_init(void
 
 static void bh_pool_kick_normal(struct irq_work *irq_work)
 {
-	raise_softirq_irqoff(TASKLET_SOFTIRQ);
+	raise_softirq(TASKLET_SOFTIRQ);
 }
 
 static void bh_pool_kick_highpri(struct irq_work *irq_work)
 {
-	raise_softirq_irqoff(HI_SOFTIRQ);
+	raise_softirq(HI_SOFTIRQ);
 }
 
 static void __init restrict_unbound_cpumask(const char *name, const struct cpumask *mask)



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 109/247] tipc: protect node reset trace dump with node lock
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (107 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 108/247] workqueue: Use raise_softirq() to trigger softirq in irq_work handler Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 110/247] sctp: validate chunk length in the inqueue parser Greg Kroah-Hartman
                   ` (145 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Chengfeng Ye, Tung Nguyen,
	Jakub Kicinski

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Chengfeng Ye <nicoyip.dev@gmail.com>

commit dddf197f29ba5e47a476dde82bf542ca2e0d5e5e upstream.

The tipc_node_reset_links trace event asks tipc_node_dump() to walk the
node's link entries. Unlike the other node events that request link data,
this event runs without the node lock.

This permits bearer teardown to free a link while the trace callback is
dumping it:

  CPU 0                                CPU 1
  trace_tipc_node_reset_links()
    tipc_node_dump()
      l = n->links[0].link
                                       tipc_node_write_lock()
                                       kfree(l)
                                       n->links[0].link = NULL
                                       tipc_node_write_unlock()
      tipc_link_dump(l)

tipc_link_dump() then dereferences the stale pointer. KASAN reported:

  BUG: KASAN: slab-use-after-free in tipc_link_dump
  Read of size 4 by task poc/115
  Call Trace:
   tipc_link_dump+0x10cb/0x16b0
   tipc_node_dump+0x4bb/0x740
   trace_event_raw_event_tipc_node_class+0x258/0x360
   tipc_node_reset_links+0x14d/0x1a0
   tipc_rcv+0x13f5/0x3030
   tipc_udp_recv+0x4e3/0x670
  Allocated by task 0:
   tipc_link_create+0x1e1/0x1020
   tipc_node_check_dest+0x7d2/0x11a0
   tipc_disc_rcv+0xdbf/0x1430
  Freed by task 89:
   kfree+0x131/0x3c0
   tipc_node_link_down+0x267/0x4b0
   tipc_node_delete_links+0xec/0x160
   bearer_disable+0x107/0x260

Take the node write lock around the trace event. This serializes the
dump against tipc_node_link_down(delete=true), which frees the link
under the same write lock.

Fixes: eb18a510b5cd ("tipc: add trace_events for tipc node")
Cc: stable@vger.kernel.org
Signed-off-by: Chengfeng Ye <nicoyip.dev@gmail.com>
Reviewed-by: Tung Nguyen <tung.quang.nguyen@est.tech>
Link: https://patch.msgid.link/20260825190141.242219-1-nicoyip.dev@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 net/tipc/node.c |    2 ++
 1 file changed, 2 insertions(+)

--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -1333,7 +1333,9 @@ static void tipc_node_reset_links(struct
 
 	pr_warn("Resetting all links to %x\n", n->addr);
 
+	tipc_node_write_lock(n);
 	trace_tipc_node_reset_links(n, true, " ");
+	tipc_node_write_unlock_fast(n);
 	for (i = 0; i < MAX_BEARERS; i++) {
 		tipc_node_link_down(n, i, false);
 	}



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 110/247] sctp: validate chunk length in the inqueue parser
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (108 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 109/247] tipc: protect node reset trace dump with node lock Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 111/247] page_pool: keep frag_offset aligned for odd-sized requests Greg Kroah-Hartman
                   ` (144 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Charles Vosburgh, Xin Long,
	Jakub Kicinski

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Charles Vosburgh <theminershive@gmail.com>

commit 6cfc1b90cb86f4aabc69fb8e30128e07e2cdfa3a upstream.

SCTP chunks always include a four-byte generic header, but
sctp_inq_pop() currently accepts shorter declared lengths. A zero-length
chunk leaves chunk_end at the current header.

When ASCONF is covered by the association's SCTP-AUTH policy,
sctp_assoc_bh_rcv() can continue before the state machine performs its
normal chunk-length check. sctp_inq_pop() then returns the same malformed
chunk repeatedly and the receive softirq can lock up.

A remote SCTP peer can trigger this after establishing an association on
a kernel built with CONFIG_IP_SCTP and configured with
net.sctp.addip_enable=1 and net.sctp.auth_enable=1. The reproducer did
not require application credentials, a shared SCTP AUTH key, or
net.sctp.addip_noauth_enable=1.

On commit f967455fb2a5 ("seg6: reset IP6CB after IPv6 decapsulation"),
one zero-length ASCONF caused repeated
watchdog soft-lockup reports in a two-vCPU KVM guest. All 3 pre-trigger
health probes succeeded, while 36 of 37 post-trigger probes failed. With
this change, all 37 post-trigger probes succeeded and no equivalent
soft-lockup signature appeared.

Reject chunks shorter than the generic SCTP header at the shared inqueue
parser boundary. Mark the packet for discard before either caller can
continue processing it, while preserving the four-byte generic minimum.
Declared-length 1 through 4 controls and kernel-generated ASCONF traffic
remained healthy. The patched sctp_hello selftest passed for IPv4 and
IPv6.

The complete private reproducer and validation evidence are available
directly to maintainers on request.

Fixes: bbd0d59809f9 ("[SCTP]: Implement the receive and verification of AUTH chunk")
Cc: stable@vger.kernel.org
Signed-off-by: Charles Vosburgh <theminershive@gmail.com>
Acked-by: Xin Long <lucien.xin@gmail.com>
Link: https://patch.msgid.link/20260827-sctp-zero-chunk-inqueue-v2-1-2e7669c6a6cb@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 net/sctp/inqueue.c |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

--- a/net/sctp/inqueue.c
+++ b/net/sctp/inqueue.c
@@ -212,8 +212,10 @@ new_skb:
 	chunk->chunk_end = ((__u8 *)ch) + SCTP_PAD4(ntohs(ch->length));
 	skb_pull(chunk->skb, sizeof(*ch));
 	chunk->subh.v = NULL; /* Subheader is no longer valid.  */
-
-	if (chunk->chunk_end + sizeof(*ch) <= skb_tail_pointer(chunk->skb)) {
+	if (unlikely(ntohs(ch->length) < sizeof(*ch))) {
+		chunk->pdiscard = 1;
+	} else if (chunk->chunk_end + sizeof(*ch) <=
+		   skb_tail_pointer(chunk->skb)) {
 		/* This is not a singleton */
 		chunk->singleton = 0;
 	} else if (chunk->chunk_end > skb_tail_pointer(chunk->skb)) {



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 111/247] page_pool: keep frag_offset aligned for odd-sized requests
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (109 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 110/247] sctp: validate chunk length in the inqueue parser Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 112/247] s390/ctcm: Prevent XID null dereference Greg Kroah-Hartman
                   ` (143 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Florian Schauer,
	Jesper Dangaard Brouer, Eric Dumazet, Jakub Kicinski

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Florian Schauer <florian@schauer.to>

commit dc0df5a0c62ccea1d0e08d39a4dc9064de81d411 upstream.

page_pool_alloc_frag_netmem() rounds the requested fragment size with

	size = ALIGN(size, dma_get_cache_alignment());

dma_get_cache_alignment() returns 1 unless the architecture defines
ARCH_DMA_MINALIGN, which DMA-coherent architectures such as x86 do not.
There the ALIGN() is a no-op and pool->frag_offset advances by the raw,
unrounded size.

A single caller asking for an odd size then leaves frag_offset misaligned
for every fragment carved out of that page afterwards.  The pool is shared,
so the damage is not confined to the caller that caused it.

The per-cpu system_page_pool used by generic XDP hits this.
skb_pp_cow_data() allocates its fragments with the raw packet length:

	size = min_t(u32, len, PAGE_SIZE);
	truesize = size;
	page = page_pool_dev_alloc(pool, &page_off, &truesize);

leaving frag_offset odd for whatever is carved out of that page next.  Its
own head allocation is already aligned -- SKB_HEAD_ALIGN(size) plus the
XDP_PACKET_HEADROOM its callers pass -- so it is a later user of the shared
pool that pays: page_pool_dev_alloc_va() returns a misaligned buffer,
napi_build_skb() installs it as skb->head, and skb_shinfo(skb) ==
skb->head + skb->end is misaligned with it.

skb_shinfo()->dataref is a 4-byte atomic_t at offset 0x20, so the
atomic_inc() in __skb_clone() straddles a cache line.  On x86 with split
lock detection -- fatal for kernel split locks by default -- this panics
the machine:

  Oops: Split lock detected
  RIP: 0010:skb_clone+0x154/0x1e0
  Call Trace:
   <IRQ>
   raw_local_deliver+0x1ed/0x2c0
   ip_protocol_deliver_rcu+0x54/0x1c0
   ip_local_deliver_finish+0x85/0x100
   ip_local_deliver+0x67/0x100
   __netif_receive_skb_one_core+0x85/0xa0
   process_backlog+0x87/0x130

Reproduced by attaching any generic-mode XDP program to loopback and
opening a RAW IPPROTO_UDP socket, which makes raw_local_deliver() clone
every locally delivered UDP packet; ordinary DNS traffic then triggers it,
roughly once per 2500 clones.  Observed on 6.12.101 and 7.1.8.

Tracing page_pool_alloc_frag_netmem() over one such run shows the
amplification -- two odd-sized requests, nine misaligned offsets:

  requested size & 7:   0: 17035    5: 1    7: 1
  frag_offset & 7:      0: 17028    3: 1    4: 1    5: 1    6: 1    7: 5

and skb_pp_cow_data() returning heads that were aligned on entry:

  head 0xffff8f4c86aeac00 -> 0xffff8f4c53a9a9c4 (&7=4)
  head 0xffff8f4d6a8a42c0 -> 0xffff8f4c4f7b7a45 (&7=5)

Round the fragment size up to at least the alignment struct skb_shared_info
requires, so fragments are always suitably aligned for the objects callers
build on them.  Architectures needing a larger DMA alignment keep it.

This also makes the remainder computed in page_pool_alloc_netmem(),

	*size = max_size - *offset;

aligned, since max_size is a power of two -- which fixes the matching
misalignment of skb->end.

Verified with a controlled A/B under QEMU/KVM: same tree, same config,
same compiler, same rootfs and identical traffic, differing only by this
patch.  A SEC("xdp.frags") XDP_PASS program on lo plus UDP datagrams
larger than max_head_size drives skb_pp_cow_data()'s fragment loop, which
passes raw packet lengths to the pool.  Measured at the return of
skb_pp_cow_data():

                          unpatched   patched
  skb_pp_cow_data calls       40800     40800
  misaligned skb->head         1120         0
  dataref at line offset >60     80         0

The last row counts the accesses that actually fault:
skb_shinfo()->dataref sits at head+end+0x20 and is a 4-byte atomic, so
`lock incl` splits a 64-byte cache line only when that address lands at
offset 61..63.  All 80 occurrences were at offset 61; the panic reported
above was at offset 62.  Eliminating the misalignment removes every one
of them.

Same class of bug as commit 3bed3cc4156e ("net: Do not allocate page
fragments that are not skb aligned"), which fixed the older
netdev_alloc_frag()/napi_alloc_frag() allocators.

Fixes: 53e0961da1c7 ("page_pool: add frag page recycling support in page pool")
Cc: stable@vger.kernel.org
Signed-off-by: Florian Schauer <florian@schauer.to>
Acked-by: Jesper Dangaard Brouer <hawk@kernel.org>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20260828060822.2628276-1-florian@schauer.to
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 net/core/page_pool.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

--- a/net/core/page_pool.c
+++ b/net/core/page_pool.c
@@ -1040,7 +1040,8 @@ netmem_ref page_pool_alloc_frag_netmem(s
 	if (WARN_ON(size > max_size))
 		return 0;
 
-	size = ALIGN(size, dma_get_cache_alignment());
+	size = ALIGN(size, max_t(unsigned int, dma_get_cache_alignment(),
+				 __alignof__(struct skb_shared_info)));
 	*offset = pool->frag_offset;
 
 	if (netmem && *offset + size > max_size) {



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 112/247] s390/ctcm: Prevent XID null dereference
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (110 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 111/247] page_pool: keep frag_offset aligned for odd-sized requests Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 113/247] s390/pci: Fix leak of uninitialized kernel data in SCLP report Greg Kroah-Hartman
                   ` (142 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Aswin Karuvally, Jakub Kicinski

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Aswin Karuvally <aswin@linux.ibm.com>

commit b264d8422779d69febce914efc47a92a85cc382c upstream.

The mpc_validate_xid() function sets grp->saved_xid2->xid2_flag2 to 0x40
to signal XID validation error. If peer XID is NULL or r/w channel
pairing mismatch happens, grp->saved_xid2 is never initialized. An
attempt to set the flag in such case leads to NULL dereference.

Fix this by using the always available priv->xid->xid2_flag2 instead of
grp->saved_xid2->xid2_flag2 for validation errors.

Fixes: 293d984f0e36 ("ctcm: infrastructure for replaced ctc driver")
Cc: stable@vger.kernel.org
Signed-off-by: Aswin Karuvally <aswin@linux.ibm.com>
Link: https://patch.msgid.link/20260827063408.2168914-1-aswin@linux.ibm.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/s390/net/ctcm_mpc.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

--- a/drivers/s390/net/ctcm_mpc.c
+++ b/drivers/s390/net/ctcm_mpc.c
@@ -826,7 +826,7 @@ static void mpc_action_go_ready(fsm_inst
 
 	fsm_deltimer(&grp->timer);
 
-	if (grp->saved_xid2->xid2_flag2 == 0x40) {
+	if (priv->xid->xid2_flag2 == 0x40) {
 		priv->xid->xid2_flag2 = 0x00;
 		if (grp->estconnfunc) {
 			grp->estconnfunc(grp->port_num, 1,
@@ -1636,7 +1636,6 @@ done:
 			"The XID used in the MPC protocol is not valid, "
 			"rc = %d\n", rc);
 		priv->xid->xid2_flag2 = 0x40;
-		grp->saved_xid2->xid2_flag2 = 0x40;
 	}
 
 	return rc;



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 113/247] s390/pci: Fix leak of uninitialized kernel data in SCLP report
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (111 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 112/247] s390/ctcm: Prevent XID null dereference Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 114/247] ipv4: avoid divide by zero in fib_rebalance Greg Kroah-Hartman
                   ` (141 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Niklas Schnelle, Benjamin Block,
	Vasily Gorbik, Heiko Carstens

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Niklas Schnelle <schnelle@linux.ibm.com>

commit 8ac60ae2a307a50b599bf5d300b448d638f3ba29 upstream.

While report_error_write() checks that the provided buffer is at least
as large as the header struct, but not that it is large enough to
contain the report with the length claimed by report->length. If
user-space provides a short buffer, meaning a larger report->length than
the actually written payload, up to around 4K of kernel data from past
the kmalloc(len + 1) sized buffer allocated in kernfs_fop_write_iter()
will leak into the SCLP report.

However, as the entity processing the SCLP is privileged and able to
access at least the page including the report, this does not leak data
that entity could not access but it is still an out of bounds read and
a malformed error report that should be rejected.

Fixes: 368704a65be8 ("s390/pci: add report_error attribute")
Cc: stable@vger.kernel.org
Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
Reviewed-by: Benjamin Block <bblock@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 arch/s390/pci/pci_sysfs.c |    3 +++
 1 file changed, 3 insertions(+)

--- a/arch/s390/pci/pci_sysfs.c
+++ b/arch/s390/pci/pci_sysfs.c
@@ -150,6 +150,9 @@ static ssize_t report_error_write(struct
 	if (off || (count < sizeof(*report)))
 		return -EINVAL;
 
+	if (count < (report->length + sizeof(*report)))
+		return -EINVAL;
+
 	ret = sclp_pci_report(report, zdev->fh, zdev->fid);
 
 	return ret ? ret : count;



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 114/247] ipv4: avoid divide by zero in fib_rebalance
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (112 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 113/247] s390/pci: Fix leak of uninitialized kernel data in SCLP report Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 115/247] drm/amdgpu: Fix VCE 3 ring align_mask Greg Kroah-Hartman
                   ` (140 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Vega, Zihan Xi, Eric Dumazet,
	Ido Schimmel, Jakub Kicinski

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Zihan Xi <zihanx@nebusec.ai>

commit 5046d2880fec7d49ebed2fd2866747ee1d06ad71 upstream.

fib_rebalance() computes the total eligible nexthop weight in one pass
and programs upper bounds in a second pass. A concurrent change to
ignore_routes_with_linkdown can make the first pass return zero while
the second pass sees an eligible nexthop, resulting in division by zero.

If the first pass reports a zero total, set each nexthop upper bound to
-1 and skip the division. This matches the IPv6 fix in commit
d2c26c2911dd ("ipv6: avoid divide by zero in rt6_multipath_rebalance")
and preserves the lock-free rebalance path.

Fixes: 0e884c78ee19 ("ipv4: L3 hash-based multipath")
Cc: stable@vger.kernel.org
Reported-by: Vega <vega@nebusec.ai>
Signed-off-by: Zihan Xi <zihanx@nebusec.ai>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Link: https://patch.msgid.link/20260827182514.4667-2-zihanx@nebusec.ai
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 net/ipv4/fib_semantics.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -856,7 +856,7 @@ static void fib_rebalance(struct fib_inf
 	change_nexthops(fi) {
 		int upper_bound;
 
-		if (nexthop_nh->fib_nh_flags & RTNH_F_DEAD) {
+		if (!total || nexthop_nh->fib_nh_flags & RTNH_F_DEAD) {
 			upper_bound = -1;
 		} else if (ip_ignore_linkdown(nexthop_nh->fib_nh_dev) &&
 			   nexthop_nh->fib_nh_flags & RTNH_F_LINKDOWN) {



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 115/247] drm/amdgpu: Fix VCE 3 ring align_mask
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (113 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 114/247] ipv4: avoid divide by zero in fib_rebalance Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 116/247] mm, madvise: fix potential workingset node list_lru leaks Greg Kroah-Hartman
                   ` (139 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Alex Deucher, David Rosca,
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: David Rosca <david.rosca@amd.com>

[ Upstream commit 2ee9836545e690c9e66ec203445d7705959fd7a8 ]

The largest frame is 20 dwords, so 0xf mask is too small.
This was always wrong, but we were lucky with the VCE_CMD_END
commands inserted after fence and vm_flush.

Fixes: 8897ea8c761b ("drm/amdgpu: Implement insert_end for VCE 3")
Cc: stable@vger.kernel.org
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: David Rosca <david.rosca@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/gpu/drm/amd/amdgpu/vce_v3_0.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
index ff0b7438ac76f..4c7f6c2e1adee 100644
--- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
@@ -959,7 +959,7 @@ static const struct amdgpu_ring_funcs vce_v3_0_ring_phys_funcs = {
 
 static const struct amdgpu_ring_funcs vce_v3_0_ring_vm_funcs = {
 	.type = AMDGPU_RING_TYPE_VCE,
-	.align_mask = 0xf,
+	.align_mask = 0x1f,
 	.nop = VCE_CMD_NO_OP,
 	.support_64bit_ptrs = false,
 	.no_user_fence = true,
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 116/247] mm, madvise: fix potential workingset node list_lru leaks
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (114 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 115/247] drm/amdgpu: Fix VCE 3 ring align_mask Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 117/247] mm/huge_memory: initialise workingset state before folio split Greg Kroah-Hartman
                   ` (138 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, syzbot+38a0cbd267eff2d286ff,
	Kairui Song, Chengming Zhou, Johannes Weiner,
	Matthew Wilcox (Oracle), Michal Hocko, Muchun Song, Qi Zheng,
	Roman Gushchin, Sasha Levin, Shakeel Butt, Yu Zhao, Andrew Morton

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Kairui Song <kasong@tencent.com>

[ Upstream commit 62e72d2cf702a5e2fb53d9c46ed900d9384e4a06 ]

Since commit 5abc1e37afa0 ("mm: list_lru: allocate list_lru_one only when
needed"), all list_lru users need to allocate the items using the new
infrastructure that provides list_lru info for slab allocation, ensuring
that the corresponding memcg list_lru is allocated before use.

For workingset shadow nodes (which are xa_node), users are converted to
use the new infrastructure by commit 9bbdc0f32409 ("xarray: use
kmem_cache_alloc_lru to allocate xa_node").  The xas->xa_lru will be set
correctly for filemap users.  However, there is a missing case: xa_node
allocations caused by madvise(..., MADV_COLLAPSE).

madvise(..., MADV_COLLAPSE) will also read in the absent parts of file
map, and there will be xa_nodes allocated for the caller's memcg (assuming
it's not rootcg).  However, these allocations won't trigger memcg list_lru
allocation because the proper xas info was not set.

If nothing else has allocated other xa_nodes for that memcg to trigger
list_lru creation, and memory pressure starts to evict file pages,
workingset_update_node will try to add these xa_nodes to their
corresponding memcg list_lru, and it does not exist (NULL).  So they will
be added to rootcg's list_lru instead.

This shouldn't be a significant issue in practice, but it is indeed
unexpected behavior, and these xa_nodes will not be reclaimed effectively.
And may lead to incorrect counting of the list_lru->nr_items counter.

This problem wasn't exposed until recent commit 28e98022b31ef
("mm/list_lru: simplify reparenting and initial allocation") added a
sanity check: only dying memcg could have a NULL list_lru when
list_lru_{add,del} is called.  This problem triggered this WARNING.

So make madvise(..., MADV_COLLAPSE) also call xas_set_lru() to pass the
list_lru which we may want to insert xa_node into later.  And move
mapping_set_update to mm/internal.h, and turn into a macro to avoid
including extra headers in mm/internal.h.

Link: https://lkml.kernel.org/r/20241222122936.67501-1-ryncsn@gmail.com
Fixes: 9bbdc0f32409 ("xarray: use kmem_cache_alloc_lru to allocate xa_node")
Reported-by: syzbot+38a0cbd267eff2d286ff@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/lkml/675d01e9.050a0220.37aaf.00be.GAE@google.com/
Signed-off-by: Kairui Song <kasong@tencent.com>
Cc: Chengming Zhou <chengming.zhou@linux.dev>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Qi Zheng <zhengqi.arch@bytedance.com>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: Sasha Levin <sashal@kernel.org>
Cc: Shakeel Butt <shakeel.butt@linux.dev>
Cc: Yu Zhao <yuzhao@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Stable-dep-of: aca1f2d5de17 ("mm/huge_memory: initialise workingset state before folio split")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 mm/filemap.c    | 9 ---------
 mm/internal.h   | 6 ++++++
 mm/khugepaged.c | 3 +++
 3 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/mm/filemap.c b/mm/filemap.c
index c2287a1d1c6b7..64c2325b92389 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -125,15 +125,6 @@
  *    ->private_lock		(zap_pte_range->block_dirty_folio)
  */
 
-static void mapping_set_update(struct xa_state *xas,
-		struct address_space *mapping)
-{
-	if (dax_mapping(mapping) || shmem_mapping(mapping))
-		return;
-	xas_set_update(xas, workingset_update_node);
-	xas_set_lru(xas, &shadow_nodes);
-}
-
 static void page_cache_delete(struct address_space *mapping,
 				   struct folio *folio, void *shadow)
 {
diff --git a/mm/internal.h b/mm/internal.h
index 9d277bc2c26e9..7aca909c54052 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -1526,6 +1526,12 @@ static inline void shrinker_debugfs_remove(struct dentry *debugfs_entry,
 /* Only track the nodes of mappings with shadow entries */
 void workingset_update_node(struct xa_node *node);
 extern struct list_lru shadow_nodes;
+#define mapping_set_update(xas, mapping) do {			\
+	if (!dax_mapping(mapping) && !shmem_mapping(mapping)) {	\
+		xas_set_update(xas, workingset_update_node);	\
+		xas_set_lru(xas, &shadow_nodes);		\
+	}							\
+} while (0)
 
 /* mremap.c */
 unsigned long move_page_tables(struct vm_area_struct *vma,
diff --git a/mm/khugepaged.c b/mm/khugepaged.c
index 84bacd7e19620..769e2f9f99920 100644
--- a/mm/khugepaged.c
+++ b/mm/khugepaged.c
@@ -20,6 +20,7 @@
 #include <linux/rcupdate_wait.h>
 #include <linux/swapops.h>
 #include <linux/shmem_fs.h>
+#include <linux/dax.h>
 #include <linux/ksm.h>
 
 #include <asm/tlb.h>
@@ -1823,6 +1824,8 @@ static int collapse_file(struct mm_struct *mm, unsigned long addr,
 	if (result != SCAN_SUCCEED)
 		goto out;
 
+	mapping_set_update(&xas, mapping);
+
 	__folio_set_locked(new_folio);
 	if (is_shmem)
 		__folio_set_swapbacked(new_folio);
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 117/247] mm/huge_memory: initialise workingset state before folio split
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (115 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 116/247] mm, madvise: fix potential workingset node list_lru leaks Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 118/247] Revert "s390/mm: Add missing secure storage access fixups for donated memory" Greg Kroah-Hartman
                   ` (137 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Matt Fleming,
	syzbot+c5b060ce82921a2fd500, Zi Yan, David Hildenbrand (Arm),
	Baolin Wang, Barry Song, Dave Chinner, Dev Jain, Kairui Song,
	Lance Yang, Liam Howlett, Lorenzo Stoakes,
	Matthew Wilcox (Oracle), Muchun Song, Nico Pache, Roman Gushchin,
	Ryan Roberts, Shakeel Butt, Andrew Morton, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Matt Fleming <mfleming@cloudflare.com>

[ Upstream commit aca1f2d5de17e138bc6c4859126b77e516b82541 ]

xas_try_split() adds __GFP_ACCOUNT for page-cache xa_nodes, but
__folio_split() leaves the xa_state's xa_lru unset.  That lets a live,
memcg-charged xa_node exist without being linked into the mapping's
shadow_nodes list_lru; when reclaim later walks the list_lru it trips
VM_WARN_ON(!css_is_dying()).

Use mapping_set_update() to install both the workingset update callback
and the shadow_nodes list_lru on the xa_state.

Link: https://lore.kernel.org/20260725101419.3938406-1-matt@readmodwrite.com
Fixes: 58729c04cf10 ("mm/huge_memory: add buddy allocator like (non-uniform) folio_split()")
Signed-off-by: Matt Fleming <mfleming@cloudflare.com>
Reported-by: syzbot+c5b060ce82921a2fd500@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=c5b060ce82921a2fd500
Reviewed-by: Zi Yan <ziy@nvidia.com>
Acked-by: David Hildenbrand (Arm) <david@kernel.org>
Cc: Baolin Wang <baolin.wang@linux.alibaba.com>
Cc: Barry Song <baohua@kernel.org>
Cc: Dave Chinner <david@fromorbit.com>
Cc: Dev Jain <dev.jain@arm.com>
Cc: Kairui Song <ryncsn@gmail.com>
Cc: Lance Yang <lance.yang@linux.dev>
Cc: Liam Howlett <liam@infradead.org>
Cc: Lorenzo Stoakes <ljs@kernel.org>
Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Nico Pache <npache@redhat.com>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: Ryan Roberts <ryan.roberts@arm.com>
Cc: Shakeel Butt <shakeel.butt@linux.dev>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 mm/huge_memory.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 348fb144e63be..f6ba19b57265b 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -3532,6 +3532,8 @@ int split_huge_page_to_list_to_order(struct page *page, struct list_head *list,
 			goto out;
 		}
 
+		mapping_set_update(&xas, mapping);
+
 		xas_split_alloc(&xas, folio, folio_order(folio), gfp);
 		if (xas_error(&xas)) {
 			ret = xas_error(&xas);
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 118/247] Revert "s390/mm: Add missing secure storage access fixups for donated memory"
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (116 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 117/247] mm/huge_memory: initialise workingset state before folio split Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 119/247] netfilter: nft_byteorder: remove multi-register support Greg Kroah-Hartman
                   ` (136 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, kernelci.org bot, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

This reverts commit 74ccc099f1baa9236b8fb600406457a0870c83a9.

Reported-by: kernelci.org bot <bot@kernelci.org>
Link: https://lore.kernel.org/all/179258034449.241924.15241097267562754477@kernelci.org/
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 arch/s390/mm/fault.c | 11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 2d03af60ed88f..f907e916aa20d 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -443,17 +443,10 @@ void do_secure_storage_access(struct pt_regs *regs)
 		folio = phys_to_folio(addr);
 		if (unlikely(!folio_try_get(folio)))
 			return;
-		rc = uv_convert_from_secure(folio_to_phys(folio));
-		if (!rc)
-			clear_bit(PG_arch_1, &folio->flags.f);
+		rc = arch_make_folio_accessible(folio);
 		folio_put(folio);
-		/*
-		 * There are some valid fixup types for kernel
-		 * accesses to donated secure memory. zeropad is one
-		 * of them.
-		 */
 		if (rc)
-			return handle_fault_error_nolock(regs, 0);
+			BUG();
 	} else {
 		if (faulthandler_disabled())
 			return handle_fault_error_nolock(regs, 0);
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 119/247] netfilter: nft_byteorder: remove multi-register support
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (117 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 118/247] Revert "s390/mm: Add missing secure storage access fixups for donated memory" Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 120/247] mm/huge_memory: bypass THP tuneables for huge pfnmap mappings Greg Kroah-Hartman
                   ` (135 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Michal Kubecek, Florian Westphal,
	Pablo Neira Ayuso, Sasha Levin, stable+noautosel

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Florian Westphal <fw@strlen.de>

[ Upstream commit bb061d3de41707415269be75ebf700efb03ec212 ]

64bit byteorder conversion is broken when several registers need to be
converted because the source register array advances in steps for 4 bytes
instead of 8:

  for (i = ...
      src64 = nft_reg_load64(&src[i]);
                             ~~~~~ u32 *src
      nft_reg_store64(&dst64[i],

Remove the multi-register support, it has other issues as well:

Pablo points out that commit
caf3ef7468f7 ("netfilter: nf_tables: prevent OOB access in nft_byteorder_eval")
alters semantics: before the loop operated on registers, i.e.
 for ( ... )
   dst32[i] = htons((u16)src32[i])

 .. but after the patch it will operate on bytes, which makes this
 useless to convert e.g. concatenations, which store each compound
 in its own register.

Multi-convert of u32 has one theoretical application:

ct mark . meta mark . tcp dport @intervalset

Because ct mark and meta mark are host byte order, use with
intervals has to convert the byteorder for ct/meta mark value
to network byte order (bigendian).

nftables emits this:
 [ meta load mark => reg 1 ]
 [ byteorder reg 1 = hton(reg 1, 4, 4) ]
 [ ct load mark => reg 9 ]
 [ byteorder reg 9 = hton(reg 9, 4, 4) ]
 ...

I.e. two separate calls.  Theoretically it could be changed to do:
 [ meta load mark => reg 1 ]
 [ ct load mark => reg 9 ]
 [ byteorder reg 1 = htonl(reg 1, 4, 8) ]
 ...

But then all it would take to change the set to
meta mark . tcp dport . ct mark

... and we'd be back to two "byteorder" calls. IOW, support to
convert a range of registers is both dysfunctional and dubious.

Simplify this: remove the feature.

Pablo Neira Ayuso points out that nftables before 1.1.0 can generate
incorrect byteorder conversions, see 9fe58952c45a,
"evaluate: skip byteorder conversion for selector smaller than 2 bytes"
in nftables.git).  Affected rulesets fail to load with this change and
old userspace due to 'len != size' check.

Fixes: c301f0981fdd ("netfilter: nf_tables: fix pointer math issue in nft_byteorder_eval()")
Cc: <stable+noautosel@kernel.org> # may break rule load with old nftables versions
Reported-by: Michal Kubecek <mkubecek@suse.cz>
Link: https://lore.kernel.org/netfilter-devel/20240206104336.ctigqpkunom2ufmn@lion.mk-sys.cz/
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/netfilter/nft_byteorder.c | 51 ++++++++++++++---------------------
 1 file changed, 20 insertions(+), 31 deletions(-)

diff --git a/net/netfilter/nft_byteorder.c b/net/netfilter/nft_byteorder.c
index 74548b4c114b9..391aade36ef3c 100644
--- a/net/netfilter/nft_byteorder.c
+++ b/net/netfilter/nft_byteorder.c
@@ -19,7 +19,6 @@ struct nft_byteorder {
 	u8			sreg;
 	u8			dreg;
 	enum nft_byteorder_ops	op:8;
-	u8			len;
 	u8			size;
 };
 
@@ -28,13 +27,8 @@ void nft_byteorder_eval(const struct nft_expr *expr,
 			const struct nft_pktinfo *pkt)
 {
 	const struct nft_byteorder *priv = nft_expr_priv(expr);
-	u32 *src = &regs->data[priv->sreg];
+	const u32 *src = &regs->data[priv->sreg];
 	u32 *dst = &regs->data[priv->dreg];
-	u16 *s16, *d16;
-	unsigned int i;
-
-	s16 = (void *)src;
-	d16 = (void *)dst;
 
 	switch (priv->size) {
 	case 8: {
@@ -43,18 +37,14 @@ void nft_byteorder_eval(const struct nft_expr *expr,
 
 		switch (priv->op) {
 		case NFT_BYTEORDER_NTOH:
-			for (i = 0; i < priv->len / 8; i++) {
-				src64 = nft_reg_load64(&src[i]);
-				nft_reg_store64(&dst64[i],
-						be64_to_cpu((__force __be64)src64));
-			}
+			src64 = nft_reg_load64(src);
+
+			nft_reg_store64(dst64, be64_to_cpu((__force __be64)src64));
 			break;
 		case NFT_BYTEORDER_HTON:
-			for (i = 0; i < priv->len / 8; i++) {
-				src64 = (__force __u64)
-					cpu_to_be64(nft_reg_load64(&src[i]));
-				nft_reg_store64(&dst64[i], src64);
-			}
+			src64 = (__force __u64)cpu_to_be64(nft_reg_load64(src));
+
+			nft_reg_store64(dst64, src64);
 			break;
 		}
 		break;
@@ -62,24 +52,20 @@ void nft_byteorder_eval(const struct nft_expr *expr,
 	case 4:
 		switch (priv->op) {
 		case NFT_BYTEORDER_NTOH:
-			for (i = 0; i < priv->len / 4; i++)
-				dst[i] = ntohl((__force __be32)src[i]);
+			*dst = ntohl((__force __be32)*src);
 			break;
 		case NFT_BYTEORDER_HTON:
-			for (i = 0; i < priv->len / 4; i++)
-				dst[i] = (__force __u32)htonl(src[i]);
+			*dst = (__force __u32)htonl(*src);
 			break;
 		}
 		break;
 	case 2:
 		switch (priv->op) {
 		case NFT_BYTEORDER_NTOH:
-			for (i = 0; i < priv->len / 2; i++)
-				d16[i] = ntohs((__force __be16)s16[i]);
+			nft_reg_store16(dst, ntohs(nft_reg_load_be16(src)));
 			break;
 		case NFT_BYTEORDER_HTON:
-			for (i = 0; i < priv->len / 2; i++)
-				d16[i] = (__force __u16)htons(s16[i]);
+			nft_reg_store_be16(dst, htons(nft_reg_load16(src)));
 			break;
 		}
 		break;
@@ -137,20 +123,22 @@ static int nft_byteorder_init(const struct nft_ctx *ctx,
 	if (err < 0)
 		return err;
 
-	priv->len = len;
+	/* no longer support multi-reg conversions */
+	if (len != size)
+		return -EOPNOTSUPP;
 
 	err = nft_parse_register_load(ctx, tb[NFTA_BYTEORDER_SREG], &priv->sreg,
-				      priv->len);
+				      len);
 	if (err < 0)
 		return err;
 
 	err = nft_parse_register_store(ctx, tb[NFTA_BYTEORDER_DREG],
 				       &priv->dreg, NULL, NFT_DATA_VALUE,
-				       priv->len);
+				       len);
 	if (err < 0)
 		return err;
 
-	if (nft_reg_overlap(priv->sreg, priv->dreg, priv->len))
+	if (nft_reg_overlap(priv->sreg, priv->dreg, len))
 		return -EINVAL;
 
 	return 0;
@@ -167,10 +155,11 @@ static int nft_byteorder_dump(struct sk_buff *skb,
 		goto nla_put_failure;
 	if (nla_put_be32(skb, NFTA_BYTEORDER_OP, htonl(priv->op)))
 		goto nla_put_failure;
-	if (nla_put_be32(skb, NFTA_BYTEORDER_LEN, htonl(priv->len)))
-		goto nla_put_failure;
 	if (nla_put_be32(skb, NFTA_BYTEORDER_SIZE, htonl(priv->size)))
 		goto nla_put_failure;
+	/* compatibility for old userspace which permitted size != len */
+	if (nla_put_be32(skb, NFTA_BYTEORDER_LEN, htonl(priv->size)))
+		goto nla_put_failure;
 	return 0;
 
 nla_put_failure:
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 120/247] mm/huge_memory: bypass THP tuneables for huge pfnmap mappings
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (118 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 119/247] netfilter: nft_byteorder: remove multi-register support Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 121/247] KVM: x86/mmu: Preserve nested TDP shadow page tables if they are used as roots Greg Kroah-Hartman
                   ` (134 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Lorenzo Stoakes (ARM), Zi Yan,
	Cedric Le Goater, Saravanan D, Lance Yang, SJ Park, Baolin Wang,
	Andrew Morton, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Lorenzo Stoakes (ARM) <ljs@kernel.org>

[ Upstream commit e384abeb559d10d6505aec053ede9368d81d4c71 ]

The sysfs THP tuneables at /sys/kernel/mm/transparent_huge_pages/ rather
confusingly only control the behaviour of THP in some instances.

They are not applicable to MADV_COLLAPSE operations, nor to DAX mappings.

Long-term, THP is predicated upon compaction being able to obtain large
folios to populate THP ranges.

However, vm_normal_folio() returns NULL for PFN map mappings, thus their
reference count is maintained by the driver, not core mm.

As a consequence, the folios are not subject to reclaim nor compaction, so
are not truly part of the THP mechanism at all.

However, since commit 5dd40721f147 ("mm: allow THP orders for PFNMAPs")
introduced the ability to establish huge PFN maps, they have been subject
to THP tuneables.

This is incorrect - if a huge PFN map is available (defined by
vma->vm_ops->huge_fault being non-NULL for a VM_PFNMAP VMA), then it
should be mapped huge upon fault-in.

Correct this by explicitly checking for this while ensuring that smaps
continues to accurately report THPeligible statistics.

While here, abstract the entire file-backed THP check in
vma_can_map_huge_file(), with sensible separation of logic into helper
functions.

Failing to map huge PFN maps has resulted in significant real-world
performance degradation, see links for details.

[ziy@nvidia.com: rename some functions]
  Link: https://lore.kernel.org/DL1HIHWYJ7TB.1CY76SJS0V03L@nvidia.com
Fixes: 5dd40721f147 ("mm: allow THP orders for PFNMAPs")
Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
Signed-off-by: Zi Yan <ziy@nvidia.com>
Reported-by: Cedric Le Goater <clg@redhat.com>
Closes: https://lore.kernel.org/linux-mm/20260805055544.1568534-1-clg@redhat.com/
Reported-by: Saravanan D <saravanand@crusoe.ai>
Closes: https://lore.kernel.org/linux-mm/20260821070520.25759-1-saravanand@crusoe.ai/
Reviewed-by: Zi Yan <ziy@nvidia.com>
Tested-by: Saravanan D <saravanand@crusoe.ai>
Tested-by: Lance Yang <lance.yang@linux.dev>
Reviewed-by: SJ Park <sj@kernel.org>
Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
[ ljs - Converted to tva_flags, made file_thp_enabled() const in huge_mm.h
   + other smaller changes. Updated commit msg to reflect. ]
Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 include/linux/huge_mm.h |  2 +-
 mm/huge_memory.c        | 79 ++++++++++++++++++++++++++++++-----------
 2 files changed, 59 insertions(+), 22 deletions(-)

diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h
index bd34b70dd0cf9..10e41e8b16349 100644
--- a/include/linux/huge_mm.h
+++ b/include/linux/huge_mm.h
@@ -254,7 +254,7 @@ static inline unsigned long thp_vma_suitable_orders(struct vm_area_struct *vma,
 	return orders;
 }
 
-static inline bool file_thp_enabled(struct vm_area_struct *vma)
+static inline bool file_thp_enabled(const struct vm_area_struct *vma)
 {
 	struct inode *inode;
 
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index f6ba19b57265b..d175e93988a92 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -86,6 +86,62 @@ unsigned long huge_anon_orders_madvise __read_mostly;
 unsigned long huge_anon_orders_inherit __read_mostly;
 static bool anon_orders_configured __initdata;
 
+static bool vma_file_bypass_thp_tuneables(const struct vm_area_struct *vma,
+		unsigned long tva_flags)
+{
+	const bool has_huge_fault = vma->vm_ops->huge_fault;
+
+	/* MADV_COLLAPSE ignores tuneables. */
+	if (!(tva_flags & TVA_ENFORCE_SYSFS))
+		return true;
+	/* Huge PFN mappings are uncompactable so the policy doesn't apply. */
+	if ((vma->vm_flags & VM_PFNMAP) && has_huge_fault)
+		return true;
+	return false;
+}
+
+static bool vma_file_allow_thp_tuneables(vm_flags_t vm_flags)
+{
+	/* THP=always? */
+	if (hugepage_global_always())
+		return true;
+	/* THP=madvise and marked MADV_HUGEPAGE? */
+	if (hugepage_global_enabled() && (vm_flags & VM_HUGEPAGE))
+		return true;
+	return false;
+}
+
+static bool vma_file_check_thp_tuneables(const struct vm_area_struct *vma,
+		vm_flags_t vm_flags, unsigned long tva_flags)
+{
+	return vma_file_bypass_thp_tuneables(vma, tva_flags) ||
+		vma_file_allow_thp_tuneables(vm_flags);
+}
+
+static bool vma_can_map_huge_file(const struct vm_area_struct *vma,
+		vm_flags_t vm_flags, unsigned long tva_flags)
+{
+	const bool has_huge_fault = vma->vm_ops->huge_fault;
+
+	/*
+	 * Enforce THP collapse requirements as necessary. Anonymous vmas
+	 * were already handled in thp_vma_allowable_orders().
+	 */
+	if (!vma_file_check_thp_tuneables(vma, vm_flags, tva_flags))
+		return false;
+
+	/*
+	 * Trust that ->huge_fault() handlers know what they are doing
+	 * in fault path.
+	 */
+	if (tva_flags & TVA_IN_PF)
+		return has_huge_fault;
+	if ((tva_flags & TVA_SMAPS) && has_huge_fault)
+		return true;
+	/* Only regular file is valid in collapse path. */
+	return file_thp_enabled(vma);
+}
+
 unsigned long __thp_vma_allowable_orders(struct vm_area_struct *vma,
 					 unsigned long vm_flags,
 					 unsigned long tva_flags,
@@ -158,27 +214,8 @@ unsigned long __thp_vma_allowable_orders(struct vm_area_struct *vma,
 						   vma, vma->vm_pgoff, 0,
 						   !enforce_sysfs);
 
-	if (!vma_is_anonymous(vma)) {
-		/*
-		 * Enforce sysfs THP requirements as necessary. Anonymous vmas
-		 * were already handled in thp_vma_allowable_orders().
-		 */
-		if (enforce_sysfs &&
-		    (!hugepage_global_enabled() || (!(vm_flags & VM_HUGEPAGE) &&
-						    !hugepage_global_always())))
-			return 0;
-
-		/*
-		 * Trust that ->huge_fault() handlers know what they are doing
-		 * in fault path.
-		 */
-		if (((in_pf || smaps)) && vma->vm_ops->huge_fault)
-			return orders;
-		/* Only regular file is valid in collapse path */
-		if (((!in_pf || smaps)) && file_thp_enabled(vma))
-			return orders;
-		return 0;
-	}
+	if (!vma_is_anonymous(vma))
+		return vma_can_map_huge_file(vma, vm_flags, tva_flags) ? orders : 0;
 
 	if (vma_is_temporary_stack(vma))
 		return 0;
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 121/247] KVM: x86/mmu: Preserve nested TDP shadow page tables if they are used as roots
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (119 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 120/247] mm/huge_memory: bypass THP tuneables for huge pfnmap mappings Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 122/247] fs: get rid of __FMODE_NONOTIFY kludge Greg Kroah-Hartman
                   ` (133 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Hyunwoo Kim, Paolo Bonzini,
	Sean Christopherson, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Hyunwoo Kim <imv4bel@gmail.com>

[ Upstream commit 7a2c70e777a00c32ebafd376a6fe31ebb91c5b20 ]

kvm_mmu_zap_oldest_mmu_pages() excludes a shadow page whose root_count
is non-zero from top-level reclaim, because such a page cannot be
freed. The path in mmu_page_zap_pte() that recursively zaps a parentless
nested TDP child has no such check. As a result, a shadow page can
be zapped even if the page itself can't be freed; as the comment in
kvm_mmu_zap_oldest_mmu_pages() notes, zapping it will just force vCPUs
to rebuild the page.

As in top-level reclaim, do not recursively prepare zapping of a
nested TDP child whose root_count is non-zero.

Fixes: 2de4085cccea ("KVM: x86/MMU: Recursively zap nested TDP SPs when zapping last/only parent")
Signed-off-by: Hyunwoo Kim <imv4bel@gmail.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
[sean: resolve minor conflict due to lack of lockless aging in 6.12]
Signed-off-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 arch/x86/kvm/mmu/mmu.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
index ab6d3f565b0a1..1dfc568631e29 100644
--- a/arch/x86/kvm/mmu/mmu.c
+++ b/arch/x86/kvm/mmu/mmu.c
@@ -2500,7 +2500,9 @@ static int mmu_page_zap_pte(struct kvm *kvm, struct kvm_mmu_page *sp,
 			 * avoids retaining a large number of stale nested SPs.
 			 */
 			if (tdp_enabled && invalid_list &&
-			    child->role.guest_mode && !child->parent_ptes.val)
+			    child->role.guest_mode &&
+			    !child->root_count &&
+			    !child->parent_ptes.val)
 				return kvm_mmu_prepare_zap_page(kvm, child,
 								invalid_list);
 		}
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 122/247] fs: get rid of __FMODE_NONOTIFY kludge
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (120 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 121/247] KVM: x86/mmu: Preserve nested TDP shadow page tables if they are used as roots Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 17:56   ` Amir Goldstein
  2026-10-28 16:58 ` [PATCH 6.12 123/247] net: bridge: mcast: dont truncate the port group walk on teardown Greg Kroah-Hartman
                   ` (132 subsequent siblings)
  254 siblings, 1 reply; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Al Viro, Amir Goldstein, Jan Kara,
	Guenter Roeck

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Al Viro <viro@zeniv.linux.org.uk>

commit ebe559609d7829b52c6642b581860760984faf9d upstream.

All it takes to get rid of the __FMODE_NONOTIFY kludge is switching
fanotify from anon_inode_getfd() to anon_inode_getfile_fmode() and adding
a dentry_open_nonotify() helper to be used by fanotify on the other path.
That's it - no more weird shit in OPEN_FMODE(), etc.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Link: https://lore.kernel.org/linux-fsdevel/20241113043003.GH3387508@ZenIV/
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Jan Kara <jack@suse.cz>
Link: https://patch.msgid.link/d1231137e7b661a382459e79a764259509a4115d.1731684329.git.josef@toxicpanda.com
Cc: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 fs/fcntl.c                         |    4 ++--
 fs/notify/fanotify/fanotify_user.c |   25 ++++++++++++++++---------
 fs/open.c                          |   23 +++++++++++++++++++----
 include/linux/fs.h                 |    6 +++---
 include/uapi/asm-generic/fcntl.h   |    1 -
 5 files changed, 40 insertions(+), 19 deletions(-)

--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -1166,10 +1166,10 @@ static int __init fcntl_init(void)
 	 * Exceptions: O_NONBLOCK is a two bit define on parisc; O_NDELAY
 	 * is defined as O_NONBLOCK on some platforms and not on others.
 	 */
-	BUILD_BUG_ON(21 - 1 /* for O_RDONLY being 0 */ !=
+	BUILD_BUG_ON(20 - 1 /* for O_RDONLY being 0 */ !=
 		HWEIGHT32(
 			(VALID_OPEN_FLAGS & ~(O_NONBLOCK | O_NDELAY)) |
-			__FMODE_EXEC | __FMODE_NONOTIFY));
+			__FMODE_EXEC));
 
 	fasync_cache = kmem_cache_create("fasync_cache",
 					 sizeof(struct fasync_struct), 0,
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -100,8 +100,7 @@ static void __init fanotify_sysctls_init
  *
  * Internal and external open flags are stored together in field f_flags of
  * struct file. Only external open flags shall be allowed in event_f_flags.
- * Internal flags like FMODE_NONOTIFY, FMODE_EXEC, FMODE_NOCMTIME shall be
- * excluded.
+ * Internal flags like FMODE_EXEC shall be excluded.
  */
 #define	FANOTIFY_INIT_ALL_EVENT_F_BITS				( \
 		O_ACCMODE	| O_APPEND	| O_NONBLOCK	| \
@@ -258,12 +257,11 @@ static int create_fd(struct fsnotify_gro
 		return client_fd;
 
 	/*
-	 * we need a new file handle for the userspace program so it can read even if it was
-	 * originally opened O_WRONLY.
+	 * We provide an fd for the userspace program, so it could access the
+	 * file without generating fanotify events itself.
 	 */
-	new_file = dentry_open(path,
-			       group->fanotify_data.f_flags | __FMODE_NONOTIFY,
-			       current_cred());
+	new_file = dentry_open_nonotify(path, group->fanotify_data.f_flags,
+					current_cred());
 	if (IS_ERR(new_file)) {
 		put_unused_fd(client_fd);
 		client_fd = PTR_ERR(new_file);
@@ -1400,6 +1398,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned
 	unsigned int fid_mode = flags & FANOTIFY_FID_BITS;
 	unsigned int class = flags & FANOTIFY_CLASS_BITS;
 	unsigned int internal_flags = 0;
+	struct file *file;
 
 	pr_debug("%s: flags=%x event_f_flags=%x\n",
 		 __func__, flags, event_f_flags);
@@ -1468,7 +1467,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned
 	    (!(fid_mode & FAN_REPORT_NAME) || !(fid_mode & FAN_REPORT_FID)))
 		return -EINVAL;
 
-	f_flags = O_RDWR | __FMODE_NONOTIFY;
+	f_flags = O_RDWR;
 	if (flags & FAN_CLOEXEC)
 		f_flags |= O_CLOEXEC;
 	if (flags & FAN_NONBLOCK)
@@ -1546,10 +1545,18 @@ SYSCALL_DEFINE2(fanotify_init, unsigned
 			goto out_destroy_group;
 	}
 
-	fd = anon_inode_getfd("[fanotify]", &fanotify_fops, group, f_flags);
+	fd = get_unused_fd_flags(f_flags);
 	if (fd < 0)
 		goto out_destroy_group;
 
+	file = anon_inode_getfile_fmode("[fanotify]", &fanotify_fops, group,
+					f_flags, FMODE_NONOTIFY);
+	if (IS_ERR(file)) {
+		fd = PTR_ERR(file);
+		put_unused_fd(fd);
+		goto out_destroy_group;
+	}
+	fd_install(fd, file);
 	return fd;
 
 out_destroy_group:
--- a/fs/open.c
+++ b/fs/open.c
@@ -1124,6 +1124,23 @@ struct file *dentry_open(const struct pa
 }
 EXPORT_SYMBOL(dentry_open);
 
+struct file *dentry_open_nonotify(const struct path *path, int flags,
+				  const struct cred *cred)
+{
+	struct file *f = alloc_empty_file(flags, cred);
+	if (!IS_ERR(f)) {
+		int error;
+
+		f->f_mode |= FMODE_NONOTIFY;
+		error = vfs_open(path, f);
+		if (error) {
+			fput(f);
+			f = ERR_PTR(error);
+		}
+	}
+	return f;
+}
+
 /**
  * dentry_create - Create and open a file
  * @path: path to create
@@ -1221,7 +1238,7 @@ inline struct open_how build_open_how(in
 inline int build_open_flags(const struct open_how *how, struct open_flags *op)
 {
 	u64 flags = how->flags;
-	u64 strip = __FMODE_NONOTIFY | O_CLOEXEC;
+	u64 strip = O_CLOEXEC;
 	int lookup_flags = 0;
 	int acc_mode = ACC_MODE(flags);
 
@@ -1229,9 +1246,7 @@ inline int build_open_flags(const struct
 			 "struct open_flags doesn't yet handle flags > 32 bits");
 
 	/*
-	 * Strip flags that either shouldn't be set by userspace like
-	 * FMODE_NONOTIFY or that aren't relevant in determining struct
-	 * open_flags like O_CLOEXEC.
+	 * Strip flags that aren't relevant in determining struct open_flags.
 	 */
 	flags &= ~strip;
 
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2784,6 +2784,8 @@ static inline struct file *file_open_roo
 }
 struct file *dentry_open(const struct path *path, int flags,
 			 const struct cred *creds);
+struct file *dentry_open_nonotify(const struct path *path, int flags,
+				  const struct cred *cred);
 struct file *dentry_create(const struct path *path, int flags, umode_t mode,
 			   const struct cred *cred);
 struct path *backing_file_user_path(const struct file *f);
@@ -3719,11 +3721,9 @@ struct ctl_table;
 int __init list_bdev_fs_names(char *buf, size_t size);
 
 #define __FMODE_EXEC		((__force int) FMODE_EXEC)
-#define __FMODE_NONOTIFY	((__force int) FMODE_NONOTIFY)
 
 #define ACC_MODE(x) ("\004\002\006\006"[(x)&O_ACCMODE])
-#define OPEN_FMODE(flag) ((__force fmode_t)(((flag + 1) & O_ACCMODE) | \
-					    (flag & __FMODE_NONOTIFY)))
+#define OPEN_FMODE(flag) ((__force fmode_t)((flag + 1) & O_ACCMODE))
 
 static inline bool is_sxid(umode_t mode)
 {
--- a/include/uapi/asm-generic/fcntl.h
+++ b/include/uapi/asm-generic/fcntl.h
@@ -6,7 +6,6 @@
 
 /*
  * FMODE_EXEC is 0x20
- * FMODE_NONOTIFY is 0x4000000
  * These cannot be used by userspace O_* until internal and external open
  * flags are split.
  * -Eric Paris



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 123/247] net: bridge: mcast: dont truncate the port group walk on teardown
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (121 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 122/247] fs: get rid of __FMODE_NONOTIFY kludge Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 124/247] ksmbd: fill in FileSysIdentifier in FS_POSIX_INFORMATION Greg Kroah-Hartman
                   ` (131 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Nikolay Aleksandrov,
	TencentOS Corvus AI, Jun Yang, Jakub Kicinski

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Jun Yang <littleddfu@gmail.com>

commit 5a3f7a683aee56e1f15c9d53041f3236767eaae7 upstream.

__br_multicast_disable_port_ctx() and br_multicast_del_port() walk
port->mglist with hlist_for_each_entry_safe(). However,
br_multicast_find_del_pg() can also delete other entries from the same
list through br_multicast_fwd_src_remove() or __fwd_del_star_excl().

If such an entry is the iterator's saved next node, hlist_del_init()
clears its ->next and terminates the walk early. The reproducer triggers
this in both teardown walks, leaving port groups in the bridge mdb with
a dangling ->key.port after del_nbp() frees the port:

  BUG: KASAN: slab-use-after-free in __mdb_fill_info+0x1191/0x1320
   __mdb_fill_info+0x1191/0x1320
   br_mdb_dump+0x594/0xe40
   rtnl_mdb_dump+0x1cf/0x5d0

Use hlist_del_init_rcu() to unlink the group while preserving ->next.
br_multicast_del_pg() and the teardown walks run under
br->multicast_lock. The GC worker must acquire the same lock before
detaching the group for destruction, so the node remains alive while
the walk uses the preserved pointer.

Preserving ->next means a walk can now reach a group that an earlier
iteration already deleted as a side effect. That group is off mp->ports,
so br_multicast_find_del_pg() would fall through its port scan and hit
the trailing WARN_ON(1). Skip such groups at the top of that helper: a
port group is put on port->mglist when it is created and only unlinked
when it is deleted, so hlist_unhashed() identifies exactly this case.

Fixes: b08123684bd5 ("net: bridge: mcast: install S,G entries automatically based on reports")
Cc: stable@vger.kernel.org
Suggested-by: Nikolay Aleksandrov <razor@blackwall.org>
Reported-by: TencentOS Corvus AI <corvus@tencent.com>
Signed-off-by: Jun Yang <junvyyang@tencent.com>
Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org>
Link: https://patch.msgid.link/20260831111330.199543-1-junvyyang@tencent.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 net/bridge/br_multicast.c |   13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -813,7 +813,11 @@ static void __br_multicast_del_pg(struct
 	struct hlist_node *tmp;
 
 	rcu_assign_pointer(*pp, pg->next);
-	hlist_del_init(&pg->mglist);
+	/* Keep ->next (held under multicast_lock, freed later by the GC work):
+	 * a port->mglist teardown walk may have latched this node as its next,
+	 * and deleting other groups of the same port must not truncate it.
+	 */
+	hlist_del_init_rcu(&pg->mglist);
 	br_multicast_eht_clean_sets(pg);
 	hlist_for_each_entry_safe(ent, tmp, &pg->src_list, node)
 		br_multicast_del_group_src(ent, false);
@@ -848,6 +852,13 @@ static void br_multicast_find_del_pg(str
 	struct net_bridge_mdb_entry *mp;
 	struct net_bridge_port_group *p;
 
+	/* A teardown walk over port->mglist can reach a group that an earlier
+	 * iteration already deleted as a side effect. It is off mp->ports by
+	 * now, so skip it instead of falling through to the WARN_ON() below.
+	 */
+	if (hlist_unhashed(&pg->mglist))
+		return;
+
 	mp = br_mdb_ip_get(br, &pg->key.addr);
 	if (WARN_ON(!mp))
 		return;



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 124/247] ksmbd: fill in FileSysIdentifier in FS_POSIX_INFORMATION
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (122 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 123/247] net: bridge: mcast: dont truncate the port group walk on teardown Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 125/247] ksmbd: initialize FileSystemControlFlags in FS_CONTROL_INFORMATION Greg Kroah-Hartman
                   ` (130 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Aleksandr Khromov, Namjae Jeon

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Aleksandr Khromov <haa@amicon.ru>

commit db2267b27c054a6c2151ff7fbb67927e784f31d6 upstream.

smb2_get_info_filesystem() reports 56 bytes for FS_POSIX_INFORMATION,
that is the whole of FILE_SYSTEM_POSIX_INFO, but never assigns
FileSysIdentifier.  Those eight bytes go to the client as they are found
in the response buffer.

The buffer is zeroed on allocation, so a standalone request leaks
nothing.  A compound request can leak: the offset of the next response
is advanced by the length pinned for the previous one, so a reply that
was written into the buffer and then dropped in favour of the short
error response of smb2_set_err_rsp() stays there, and the next reply is
laid over it with only the header cleared.

Report the file system id statfs() returned, which is what the field is
for.  FileSysIdentifier is __le64 and f_fsid is a pair of ints, so
assemble the value first, val[0] as the low half, and convert it on the
way out.

Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3")
Cc: stable@vger.kernel.org
Signed-off-by: Aleksandr Khromov <haa@amicon.ru>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 fs/smb/server/smb2pdu.c |    3 +++
 1 file changed, 3 insertions(+)

--- a/fs/smb/server/smb2pdu.c
+++ b/fs/smb/server/smb2pdu.c
@@ -5774,6 +5774,9 @@ static int smb2_get_info_filesystem(stru
 			info->UserBlocksAvail = cpu_to_le64(stfs.f_bavail);
 			info->TotalFileNodes = cpu_to_le64(stfs.f_files);
 			info->FreeFileNodes = cpu_to_le64(stfs.f_ffree);
+			info->FileSysIdentifier =
+				cpu_to_le64((u64)(u32)stfs.f_fsid.val[1] << 32 |
+					    (u32)stfs.f_fsid.val[0]);
 			rsp->OutputBufferLength = cpu_to_le32(56);
 			fixed_len = 56;
 		}



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 125/247] ksmbd: initialize FileSystemControlFlags in FS_CONTROL_INFORMATION
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (123 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 124/247] ksmbd: fill in FileSysIdentifier in FS_POSIX_INFORMATION Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 126/247] ksmbd: zero the FS_OBJECT_ID_INFORMATION buffer before filling it in Greg Kroah-Hartman
                   ` (129 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Aleksandr Khromov, Namjae Jeon

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Aleksandr Khromov <haa@amicon.ru>

commit c0cd3fc6824122014da2b3b0cb7ddeaa2946ec8e upstream.

smb2_get_info_filesystem() reports 48 bytes for FS_CONTROL_INFORMATION,
that is the whole of struct smb2_fs_control_info, but never assigns
FileSystemControlFlags.  Those four bytes go to the client as they are
found in the response buffer.

The buffer is zeroed on allocation, so a standalone request leaks
nothing.  A compound request can leak: the offset of the next response
is advanced by the length pinned for the previous one, so a reply that
was written into the buffer and then dropped in favour of the short
error response of smb2_set_err_rsp() stays there, and the next reply is
laid over it with only the header cleared.

ksmbd does not implement quota tracking, so report no control flags.

Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3")
Cc: stable@vger.kernel.org
Signed-off-by: Aleksandr Khromov <haa@amicon.ru>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 fs/smb/server/smb2pdu.c |    1 +
 1 file changed, 1 insertion(+)

--- a/fs/smb/server/smb2pdu.c
+++ b/fs/smb/server/smb2pdu.c
@@ -5752,6 +5752,7 @@ static int smb2_get_info_filesystem(stru
 		info->FreeSpaceStopFiltering = 0;
 		info->DefaultQuotaThreshold = cpu_to_le64(SMB2_NO_FID);
 		info->DefaultQuotaLimit = cpu_to_le64(SMB2_NO_FID);
+		info->FileSystemControlFlags = 0;
 		info->Padding = 0;
 		rsp->OutputBufferLength = cpu_to_le32(48);
 		fixed_len = 48;



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 126/247] ksmbd: zero the FS_OBJECT_ID_INFORMATION buffer before filling it in
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (124 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 125/247] ksmbd: initialize FileSystemControlFlags in FS_CONTROL_INFORMATION Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 127/247] net/sched: cls_flower: validate mask pointer after nla_next() Greg Kroah-Hartman
                   ` (128 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, ChenXiaoSong, Aleksandr Khromov,
	Namjae Jeon

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Aleksandr Khromov <haa@amicon.ru>

commit 399aa12450a61a5c73dc77e73f069ece9687c95d upstream.

smb2_get_info_filesystem() reports 64 bytes for FS_OBJECT_ID_INFORMATION,
that is the whole of struct object_id_info, but writes only 46 of them:

 - objid[] is 16 bytes, and when the volume UUID is not available only
   sizeof(stfs.f_fsid) (8) bytes are copied into it;
 - extended_info.version_string[] is STRING_LENGTH (28) bytes, and only
   strlen("1.1.0") (5) bytes are copied into it.

The response buffer is zeroed on allocation (kvzalloc() in
smb2_allocate_rsp_buf()), so for a standalone request the remaining 31
bytes are zero.  In a compound request they need not be.  The offset of
the next response is advanced by the length pinned for the previous one,
so if a preceding command wrote its reply into the buffer and then
failed, smb2_set_err_rsp() pins only the short error response and the
next reply lands inside the area that has already been written.  Only
the header is cleared there:

	memset((char *)rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);

The client then receives up to 31 bytes of a response it was not meant
to see, including one that failed with an access denied error.

Clear the structure before filling it in.  As a side effect
version_string is now NUL terminated.

Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3")
Suggested-by: ChenXiaoSong <chenxiaosong@chenxiaosong.com>
Cc: stable@vger.kernel.org
Signed-off-by: Aleksandr Khromov <haa@amicon.ru>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 fs/smb/server/smb2pdu.c |    1 +
 1 file changed, 1 insertion(+)

--- a/fs/smb/server/smb2pdu.c
+++ b/fs/smb/server/smb2pdu.c
@@ -5698,6 +5698,7 @@ static int smb2_get_info_filesystem(stru
 		struct object_id_info *info;
 
 		info = (struct object_id_info *)(rsp->Buffer);
+		memset(info, 0, sizeof(*info));
 
 		if (path.mnt->mnt_sb->s_uuid_len == 16)
 			memcpy(info->objid, path.mnt->mnt_sb->s_uuid.b,



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 127/247] net/sched: cls_flower: validate mask pointer after nla_next()
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (125 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 126/247] ksmbd: zero the FS_OBJECT_ID_INFORMATION buffer before filling it in Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 128/247] smb: client: fix heap overflow in cifs_do_set_acl() Greg Kroah-Hartman
                   ` (127 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, TencentOS Corvus AI, Aohan Mei,
	Jakub Kicinski

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Aohan Mei <henrymei@tencent.com>

commit fee10655709c5c597e8e9f722f3035d9ea31ff3a upstream.

fl_set_enc_opt() iterates the key's nested tunnel-option attributes
with nla_for_each_attr() while advancing a single mask pointer via
nla_next() at the bottom of each loop, so the mask cursor is driven
by the number of key attributes rather than by the mask's own
attributes.  The nla_ok() added by commit c96adff956191 ("cls_flower:
call nla_ok() before nla_next()") only validates the mask pointer
that was just consumed; the pointer produced by nla_next() is used by
the next iteration (fl_set_geneve_opt() and siblings) without any
validation.

The mask's nested attributes are validated with NL_VALIDATE_LIBERAL,
which merely warns on trailing bytes that do not form a complete
attribute.  A mask carrying one valid attribute plus 1-3 residue
bytes (or a non-aligned attribute length making msk_depth negative)
therefore reaches the next iteration with msk_depth != 0, so neither
the !msk_depth check in fl_set_enc_opt() nor the !depth check in the
per-type helpers fires.  nla_type() then reads past the mask payload
and nla_parse_nested_deprecated() iterates with an nla_len taken
from those bytes, reading well beyond the mask attribute (KASAN:
slab-out-of-bounds read in __nla_validate_parse from fl_change()).

Validate the advanced mask pointer as well: when the mask is not
legitimately exhausted (msk_depth != 0) and the new pointer fails
nla_ok(), reject the filter with -EINVAL.  An exactly exhausted mask
still skips the check, preserving exact-match behaviour for the
remaining key attributes.

Fixes: c96adff95619 ("cls_flower: call nla_ok() before nla_next()")
Reported-by: TencentOS Corvus AI <corvus@tencent.com>
Cc: stable@vger.kernel.org
Signed-off-by: Aohan Mei <henrymei@tencent.com>
Link: https://patch.msgid.link/20260826025123.62758-1-ljp1205831794@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 net/sched/cls_flower.c |    5 +++++
 1 file changed, 5 insertions(+)

--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -1707,6 +1707,11 @@ static int fl_set_enc_opt(struct nlattr
 			return -EINVAL;
 		}
 		nla_opt_msk = nla_next(nla_opt_msk, &msk_depth);
+
+		if (msk_depth && !nla_ok(nla_opt_msk, msk_depth)) {
+			NL_SET_ERR_MSG(extack, "A mask attribute is invalid");
+			return -EINVAL;
+		}
 	}
 
 	return 0;



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 128/247] smb: client: fix heap overflow in cifs_do_set_acl()
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (126 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 127/247] net/sched: cls_flower: validate mask pointer after nla_next() Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 129/247] smb: client: fix multiuser mount with krb5 Greg Kroah-Hartman
                   ` (126 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Frank Sorenson, Paulo Alcantara

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Frank Sorenson <sorenson@redhat.com>

commit 1dac61e2c29d1a71784604b48cf3b1234a65ec29 upstream.

cifs_set_acl() validates ACL size using posix_acl_xattr_size():

        4 + (count * 8)  // 4-byte header + 8 bytes per ACE

cifs_do_set_acl() then calls posix_acl_to_cifs() to write the CIFS
wire format into the same buffer:

        6 + (count * 10)  // 6-byte header + 10 bytes per ACE

An ACL that passes the xattr-based check in cifs_set_acl() can
overflow the heap when posix_acl_to_cifs() writes the larger CIFS
format.

Validate the CIFS format size against the remaining buffer space and
USHRT_MAX before converting--data_count is __u16, so sizes above
USHRT_MAX truncate the on-wire packet length, causing the server to
apply a partial ACL.  Replace MaxDataCount = 1000 with
min(CIFSMaxBufSize, USHRT_MAX).

Fixes: dc1af4c4b4721 ("cifs: implement set acl method")
Cc: stable@vger.kernel.org
Signed-off-by: Frank Sorenson <sorenson@redhat.com>
Signed-off-by: Paulo Alcantara <pc@manguebit.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 fs/smb/client/cifssmb.c |   13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

--- a/fs/smb/client/cifssmb.c
+++ b/fs/smb/client/cifssmb.c
@@ -3188,6 +3188,7 @@ int cifs_do_set_acl(const unsigned int x
 	int rc = 0;
 	int bytes_returned = 0;
 	__u16 params, byte_count, data_count, param_offset, offset;
+	size_t cifs_acl_size, bytes_available;
 
 	cifs_dbg(FYI, "In SetPosixACL (Unix) for path %s\n", fileName);
 setAclRetry:
@@ -3206,8 +3207,7 @@ setAclRetry:
 	}
 	params = 6 + name_len;
 	pSMB->MaxParameterCount = cpu_to_le16(2);
-	/* BB find max SMB size from sess */
-	pSMB->MaxDataCount = cpu_to_le16(1000);
+	pSMB->MaxDataCount = cpu_to_le16(min_t(unsigned int, CIFSMaxBufSize, USHRT_MAX));
 	pSMB->MaxSetupCount = 0;
 	pSMB->Reserved = 0;
 	pSMB->Flags = 0;
@@ -3219,6 +3219,15 @@ setAclRetry:
 	parm_data = ((char *)pSMB) + sizeof(pSMB->hdr.smb_buf_length) + offset;
 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
 
+	/* make sure we can fit the larger cifs_posix_aces in the buffer */
+	cifs_acl_size = sizeof(struct cifs_posix_acl) +
+		       (acl->a_count * sizeof(struct cifs_posix_ace));
+	bytes_available = (CIFSMaxBufSize + MAX_HEADER_SIZE(tcon->ses->server)) - offset;
+	if (cifs_acl_size > bytes_available || cifs_acl_size > USHRT_MAX) {
+		rc = -E2BIG;
+		goto setACLerrorExit;
+	}
+
 	/* convert to on the wire format for POSIX ACL */
 	data_count = posix_acl_to_cifs(parm_data, acl, acl_type);
 



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 129/247] smb: client: fix multiuser mount with krb5
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (127 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 128/247] smb: client: fix heap overflow in cifs_do_set_acl() Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 130/247] scsi: st: Fix use-after-free race between st_remove() and st_open() Greg Kroah-Hartman
                   ` (125 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Jacob Shivers, Ronnie Sahlberg,
	Shyam Prasad N, Tom Talpey, Bharath SM, Namjae Jeon,
	Paulo Alcantara

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Paulo Alcantara <pc@manguebit.org>

commit 69499395867332364ed4ac8b546537eb3bab6ebb upstream.

Customer reported that they could no longer mount their SMB shares
with multiuser mount option and krb5.  Turned out that the client
wasn't duplicating username option when creating multiuser
connections, therefore failing to retrieve credentials as
cifs.upcall(8) couldn't find them in keytab.

Fix this by duplicating username option (if set) from original fs
context before creating multiuser connections with krb5.

Reproducer:

  ```
  $ ktutil
  ktutil:  add_entry -password -p testuser -k 1 -e aes256-cts
  Password for testuser@ZELDA.TEST:
  ktutil:  write_kt /etc/krb5.keytab
  ktutil:  quit
  $ klist -ke
  Keytab name: FILE:/etc/krb5.keytab
  KVNO Principal
   ---- ----------------------------------------------------------------
     1 testuser@ZELDA.TEST (aes256-cts-hmac-sha1-96)
  $ mount.cifs //w22-root2/scratch /mnt/1 -o \
      	uid=1000,sec=krb5,username=testuser@ZELDA.TEST,multiuser
  mount error(13): Permission denied
  Refer to the mount.cifs(8) manual page (e.g. man mount.cifs) and
  kernel log messages (dmesg)
  ```

Reported-by: Jacob Shivers <jshivers@redhat.com>
Fixes: 12b4c5d98cd7 ("smb: client: fix krb5 mount with username option")
Cc: Ronnie Sahlberg <ronniesahlberg@gmail.com>
Cc: Shyam Prasad N <sprasad@microsoft.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Bharath SM <bharathsm@microsoft.com>
Cc: Namjae Jeon <linkinjeon@kernel.org>
Cc: stable@vger.kernel.org
Reviewed-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Paulo Alcantara <pc@manguebit.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 fs/smb/client/connect.c |   21 ++++++++++++++++-----
 1 file changed, 16 insertions(+), 5 deletions(-)

--- a/fs/smb/client/connect.c
+++ b/fs/smb/client/connect.c
@@ -4151,14 +4151,25 @@ cifs_setup_session(const unsigned int xi
 	return rc;
 }
 
-static int
-cifs_set_vol_auth(struct smb3_fs_context *ctx, struct cifs_ses *ses)
+static int set_fs_context_auth(struct smb3_fs_context *ctx,
+			       struct cifs_ses *ses)
 {
 	ctx->sectype = ses->sectype;
 
-	/* krb5 is special, since we don't need username or pw */
-	if (ctx->sectype == Kerberos)
+	/*
+	 * krb5 is special as we might need to pass username (passwordless) down
+	 * to cifs.upcall(8) for keytab.
+	 */
+	if (ctx->sectype == Kerberos) {
+		if (ses->user_name && ses->user_name[0]) {
+			ctx->username = kstrndup(ses->user_name,
+						 CIFS_MAX_USERNAME_LEN,
+						 GFP_KERNEL);
+			if (!ctx->username)
+				return -ENOMEM;
+		}
 		return 0;
+	}
 
 	return cifs_set_cifscreds(ctx, ses);
 }
@@ -4197,7 +4208,7 @@ cifs_construct_tcon(struct cifs_sb_info
 	ctx->witness = master_tcon->use_witness;
 	ctx->dfs_root_ses = master_tcon->ses->dfs_root_ses;
 
-	rc = cifs_set_vol_auth(ctx, master_tcon->ses);
+	rc = set_fs_context_auth(ctx, master_tcon->ses);
 	if (rc) {
 		tcon = ERR_PTR(rc);
 		goto out;



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 130/247] scsi: st: Fix use-after-free race between st_remove() and st_open()
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (128 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 129/247] smb: client: fix multiuser mount with krb5 Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 131/247] perf: Track the perf mlock gift separately Greg Kroah-Hartman
                   ` (124 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Dingisoul, Laurence Oberman,
	Martin K. Petersen (Oracle), Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Laurence Oberman <loberman@redhat.com>

commit 71caf7f84bd62a4bf91cc95abd2de690afb8d15f upstream.

st_remove() drops the probe reference on the scsi_tape with kref_put()
and only afterwards removes its index from st_index_idr. If that was the
last reference, scsi_tape_release() frees the structure while it is
still published in the idr.

scsi_tape_get(), called from st_open(), looks up the tape in
st_index_idr and takes a reference under st_ref_mutex and
st_index_lock. remove_cdevs() does not wait for opens that are already
past chrdev_open(), so an open that is blocked on st_ref_mutex while
st_remove() holds it can take the mutex as soon as st_remove() drops it,
find the freed tpnt in the idr and call kref_get() on it:

  BUG: KASAN: slab-use-after-free in st_open
  Write of size 4 ...
   st_open (drivers/scsi/st.c:254 drivers/scsi/st.c:1291)
   chrdev_open
  ...
  Freed by task ...:
   kfree
   st_remove (drivers/scsi/st.c:4512)

Remove the index from the idr before dropping the reference, all under
st_ref_mutex. A concurrent scsi_tape_get() now either runs first and
holds a valid reference that keeps the tape alive, or runs afterwards
and finds nothing, so st_open() fails with -ENXIO.

This restores the ordering st_remove() had before the conversion to
st_index_idr, where the tape was unpublished from scsi_tapes[] before
the final kref_put().

Fixes: 6c648d95a6af ("[SCSI] st: get rid of scsi_tapes array")
Cc: stable@vger.kernel.org
Reported-by: Dingisoul <dingiso.kernel@gmail.com>
Closes: https://lore.kernel.org/linux-scsi/20261007211520.1428497-1-dingiso.kernel@gmail.com/
Tested-by: Dingisoul <dingiso.kernel@gmail.com>
Signed-off-by: Laurence Oberman <loberman@redhat.com>
Link: https://patch.msgid.link/20261013202548.249628-1-loberman@redhat.com
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
[ loberman: st_remove() still returns int in 6.12; context adjusted ]
Signed-off-by: Laurence Oberman <loberman@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/scsi/st.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 95da0d15e0490..53d37c8497714 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -4448,11 +4448,11 @@ static int st_remove(struct device *dev)
 	remove_cdevs(tpnt);
 
 	mutex_lock(&st_ref_mutex);
-	kref_put(&tpnt->kref, scsi_tape_release);
-	mutex_unlock(&st_ref_mutex);
 	spin_lock(&st_index_lock);
 	idr_remove(&st_index_idr, index);
 	spin_unlock(&st_index_lock);
+	kref_put(&tpnt->kref, scsi_tape_release);
+	mutex_unlock(&st_ref_mutex);
 	return 0;
 }
 
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 131/247] perf: Track the perf mlock gift separately
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (129 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 130/247] scsi: st: Fix use-after-free race between st_remove() and st_open() Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 132/247] eventfs: fix SRCU read lock leak in eventfs_iterate() Greg Kroah-Hartman
                   ` (123 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Ameer Hamza, Lorenzo Stoakes (ARM),
	Peter Zijlstra (Intel), Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Lorenzo Stoakes (ARM) <ljs@kernel.org>

commit 78436f3882fb8d848c823bf8cf754988202c5ca5 upstream.

The locked_vm field in struct user_struct was originally introduced by
commit 789f90fcf6b0 ("perf_counter: per user mlock gift") to provide an
mlock-like budget for perf measured against mm->pinned_vm (since 2011).

perf grants each user a 'gift' of perf_event_mlock_kb * online CPUs of
buffer pages which is charged to user->locked_vm without any RLIMIT_MEMLOCK
check.

Only pages beyond the gift are checked against RLIMIT_MEMLOCK, per-mm, via
mm->pinned_vm, which makes it different from the standard mlock() check,
which is per-mm and made against RLIMIT_MEMLOCK.

However, since this was introduced, a number of other components have
utilised this field where a shared resource needed to be limited against
RLIMIT_MEMLOCK.

The other users are currently MSG_ZEROCOPY, io_uring, AF_XDP, iommufd,
s390 KVM zPCI and most recently, secretmem in commit 97d34aa65c29
("mm/secretmem: properly account locked pages").

This field is shared between all of these, but because the gift is not
checked against RLIMIT_MEMLOCK, user->locked_vm alone can exceed it - 16
CPUs * 516 KiB is already more than the default 8 MiB - after which every
other user of the field fails unconditionally.

This was reported by a user who saw secretmem failing while running a
simultaneous perf record.

Resolve the issue by simply giving perf its own field separate from the
rest.

BPF used user->locked_vm up until commit 80ee81e0403c ("bpf: Eliminate
rlimit-based memory accounting infra for bpf maps") which landed in 5.11.

Thus also eliminate the now-defunct ifdef for CONFIG_BPF_SYSCALL for
user->locked_vm.

This issue exists between all of the components which use user->locked_vm
and perf, however secretmem is the first user who has caused a report over
many years and has been backported, so target the fix at that.

Fixes: 97d34aa65c29 ("mm/secretmem: properly account locked pages")
Closes: https://lore.kernel.org/20261002175651.811343-1-ameer.hamza@truenas.com
Reported-by: Ameer Hamza <ameer.hamza@truenas.com>
Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: stable@vger.kernel.org
[ ljs - Applied to open-coded accounting in perf_mmap()/perf_mmap_close(). ]
Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 include/linux/sched/user.h |  8 +++++---
 kernel/events/core.c       | 12 ++++++------
 2 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/include/linux/sched/user.h b/include/linux/sched/user.h
index 8d7e5521f7cdd..ec262b605437c 100644
--- a/include/linux/sched/user.h
+++ b/include/linux/sched/user.h
@@ -23,11 +23,13 @@ struct user_struct {
 	struct hlist_node uidhash_node;
 	kuid_t uid;
 
-#if defined(CONFIG_PERF_EVENTS) || defined(CONFIG_BPF_SYSCALL) || \
-	defined(CONFIG_NET) || defined(CONFIG_IO_URING) || \
+#if defined(CONFIG_NET) || defined(CONFIG_IO_URING) || \
 	defined(CONFIG_VFIO_PCI_ZDEV_KVM) || IS_ENABLED(CONFIG_IOMMUFD) || \
 	defined(CONFIG_SECRETMEM)
-	atomic_long_t locked_vm;
+	atomic_long_t locked_vm;	/* pinned pages charged to RLIMIT_MEMLOCK */
+#endif
+#ifdef CONFIG_PERF_EVENTS
+	atomic_long_t perf_mlock;	/* perf buffer pages within perf_event_mlock_kb */
 #endif
 #ifdef CONFIG_WATCH_QUEUE
 	atomic_t nr_watches;	/* The number of watches this user currently has */
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 5f02d85957637..d14cf23a16a63 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -6534,7 +6534,7 @@ static void perf_mmap_close(struct vm_area_struct *vma)
 		perf_pmu_output_stop(event);
 
 		/* now it's safe to free the pages */
-		atomic_long_sub(rb->aux_nr_pages - rb->aux_mmap_locked, &mmap_user->locked_vm);
+		atomic_long_sub(rb->aux_nr_pages - rb->aux_mmap_locked, &mmap_user->perf_mlock);
 		atomic64_sub(rb->aux_mmap_locked, &vma->vm_mm->pinned_vm);
 
 		/* this has to be the last one */
@@ -6609,7 +6609,7 @@ static void perf_mmap_close(struct vm_area_struct *vma)
 	 */
 
 	atomic_long_sub((size >> PAGE_SHIFT) + 1 - mmap_locked,
-			&mmap_user->locked_vm);
+			&mmap_user->perf_mlock);
 	atomic64_sub(mmap_locked, &vma->vm_mm->pinned_vm);
 	free_uid(mmap_user);
 
@@ -6769,11 +6769,11 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma)
 	 */
 	user_lock_limit *= num_online_cpus();
 
-	user_locked = atomic_long_read(&user->locked_vm);
+	user_locked = atomic_long_read(&user->perf_mlock);
 
 	/*
 	 * sysctl_perf_event_mlock may have changed, so that
-	 *     user->locked_vm > user_lock_limit
+	 *     user->perf_mlock > user_lock_limit
 	 */
 	if (user_locked > user_lock_limit)
 		user_locked = user_lock_limit;
@@ -6781,7 +6781,7 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma)
 
 	if (user_locked > user_lock_limit) {
 		/*
-		 * charge locked_vm until it hits user_lock_limit;
+		 * charge perf_mlock until it hits user_lock_limit;
 		 * charge the rest from pinned_vm
 		 */
 		extra = user_locked - user_lock_limit;
@@ -6833,7 +6833,7 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma)
 
 unlock:
 	if (!ret) {
-		atomic_long_add(user_extra, &user->locked_vm);
+		atomic_long_add(user_extra, &user->perf_mlock);
 		atomic64_add(extra, &vma->vm_mm->pinned_vm);
 
 		atomic_inc(&event->mmap_count);
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 132/247] eventfs: fix SRCU read lock leak in eventfs_iterate()
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (130 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 131/247] perf: Track the perf mlock gift separately Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 133/247] net: call getsockopt_iter if available Greg Kroah-Hartman
                   ` (122 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Joseph Qi, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Joseph Qi <joseph.qi@linux.alibaba.com>

Commit 1b95382da85c ("eventfs: Use children field for rcu head and add
memory barriers") added an early bail out to the ei->children loop:

	smp_rmb();
	if (ei->is_freed)
		return -EINVAL;

Upstream wraps eventfs_iterate() in guard(srcu)(&eventfs_srcu), so that
return still drops the read lock. The 6.12.y backport instead brackets the
function with srcu_read_lock() and a shared "out" label that calls
srcu_read_unlock(), so this path returns while still holding eventfs_srcu
for reading.

The unbalanced reader prevents the grace period from ever completing, so
the call_srcu() callback queued by free_ei() never runs and the
eventfs_inode is leaked. Every readdir that races with removal adds
another reader.

Set ret and jump to "out" like the other bail out paths in this function
do.

Fixes: 1b95382da85c ("eventfs: Use children field for rcu head and add memory barriers")
Signed-off-by: Joseph Qi <joseph.qi@linux.alibaba.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 fs/tracefs/event_inode.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/fs/tracefs/event_inode.c b/fs/tracefs/event_inode.c
index a992c2919f79a..e060dfe7cdac5 100644
--- a/fs/tracefs/event_inode.c
+++ b/fs/tracefs/event_inode.c
@@ -678,8 +678,10 @@ static int eventfs_iterate(struct file *file, struct dir_context *ctx)
 		 * Matches the smp_wmb() in free_ei()
 		 */
 		smp_rmb();
-		if (ei->is_freed)
-			return -EINVAL;
+		if (ei->is_freed) {
+			ret = -EINVAL;
+			goto out;
+		}
 
 		if (c > 0) {
 			c--;
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 133/247] net: call getsockopt_iter if available
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (131 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 132/247] eventfs: fix SRCU read lock leak in eventfs_iterate() Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 134/247] kernel/watch_queue: Use pipe_buf() to retrieve the pipe buffer Greg Kroah-Hartman
                   ` (121 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Breno Leitao, Stanislav Fomichev,
	Jakub Kicinski, Emanuele Ghidoli, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Breno Leitao <leitao@debian.org>

commit 5bd0dec150f56b6307d599132dcb7c01007bbecc upstream.

Update do_sock_getsockopt() to use the new getsockopt_iter callback
when available. Add do_sock_getsockopt_iter() helper that:

1. Reads optlen from user/kernel space
2. Initializes a sockopt_t with the appropriate iov_iter (kvec for
   kernel, ubuf for user buffers) and sets opt.optlen
3. Calls the protocol's getsockopt_iter callback
4. Writes opt.optlen back to user/kernel space

The optlen is always written back, even on failure. Some protocols
(e.g. CAN raw) return -ERANGE and set optlen to the required buffer
size so userspace knows how much to allocate.

The callback is responsible for setting opt.optlen to indicate the
returned data size.

Important to say that  iov_out does not need to be copied back in
do_sock_getsockopt().

When optval is not kernel (the userspace path), sockptr_to_sockopt()
sets up opt->iter_out as a ITER_DEST ubuf iterator pointing directly at
the userspace buffer (optval.user). So when getsockopt_iter
implementations call copy_to_iter(..., &opt->iter_out), the data is
written directly to userspace — no intermediate kernel buffer is
involved.

When optval.is_kernel is true (the in-kernel path, e.g. from io_uring),
the kvec points at the already-provided kernel buffer (optval.kernel),
so the data lands in the caller's buffer directly via the kvec-backed
iterator.

In both cases the iterator writes to the final destination in-place at
protocol callback. There's nothing to copy back — only optlen needs to
be written back.

Signed-off-by: Breno Leitao <leitao@debian.org>
Acked-by: Stanislav Fomichev <sdf@fomichev.me>
Link: https://patch.msgid.link/20260408-getsockopt-v3-2-061bb9cb355d@debian.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Emanuele Ghidoli <emanuele.ghidoli@toradex.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/socket.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 51 insertions(+), 3 deletions(-)

diff --git a/net/socket.c b/net/socket.c
index 723bc3a1ba5cd..b8d662e193103 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -77,6 +77,7 @@
 #include <linux/mount.h>
 #include <linux/pseudo_fs.h>
 #include <linux/security.h>
+#include <linux/uio.h>
 #include <linux/syscalls.h>
 #include <linux/compat.h>
 #include <linux/kmod.h>
@@ -2345,11 +2346,45 @@ SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
 INDIRECT_CALLABLE_DECLARE(bool tcp_bpf_bypass_getsockopt(int level,
 							 int optname));
 
+/*
+ * Initialize a sockopt_t from sockptr optval/optlen, setting up iov_iter
+ * for both input and output directions.
+ * It is important to remember that both iov points to the same data, but,
+ * .iter_in is read-only and .iter_out is write-only by the protocol callbacks
+ */
+static int sockptr_to_sockopt(sockopt_t *opt, sockptr_t optval,
+			      sockptr_t optlen, struct kvec *kvec)
+{
+	int koptlen;
+
+	if (copy_from_sockptr(&koptlen, optlen, sizeof(int)))
+		return -EFAULT;
+
+	if (koptlen < 0)
+		return -EINVAL;
+
+	if (optval.is_kernel) {
+		kvec->iov_base = optval.kernel;
+		kvec->iov_len = koptlen;
+		iov_iter_kvec(&opt->iter_out, ITER_DEST, kvec, 1, koptlen);
+		iov_iter_kvec(&opt->iter_in, ITER_SOURCE, kvec, 1, koptlen);
+	} else {
+		iov_iter_ubuf(&opt->iter_out, ITER_DEST, optval.user, koptlen);
+		iov_iter_ubuf(&opt->iter_in, ITER_SOURCE, optval.user,
+			      koptlen);
+	}
+	opt->optlen = koptlen;
+
+	return 0;
+}
+
 int do_sock_getsockopt(struct socket *sock, bool compat, int level,
 		       int optname, sockptr_t optval, sockptr_t optlen)
 {
 	int max_optlen __maybe_unused = 0;
 	const struct proto_ops *ops;
+	struct kvec kvec;
+	sockopt_t opt;
 	int err;
 
 	err = security_socket_getsockopt(sock, level, optname);
@@ -2362,15 +2397,28 @@ int do_sock_getsockopt(struct socket *sock, bool compat, int level,
 	ops = READ_ONCE(sock->ops);
 	if (level == SOL_SOCKET) {
 		err = sk_getsockopt(sock->sk, level, optname, optval, optlen);
-	} else if (unlikely(!ops->getsockopt)) {
-		err = -EOPNOTSUPP;
-	} else {
+	} else if (ops->getsockopt_iter) {
+		err = sockptr_to_sockopt(&opt, optval, optlen, &kvec);
+		if (err)
+			return err;
+
+		err = ops->getsockopt_iter(sock, level, optname, &opt);
+
+		/* Always write back optlen, even on failure. Some protocols
+		 * (e.g. CAN raw) return -ERANGE and set optlen to the
+		 * required buffer size so userspace can discover it.
+		 */
+		if (copy_to_sockptr(optlen, &opt.optlen, sizeof(int)))
+			return -EFAULT;
+	} else if (ops->getsockopt) {
 		if (WARN_ONCE(optval.is_kernel || optlen.is_kernel,
 			      "Invalid argument type"))
 			return -EOPNOTSUPP;
 
 		err = ops->getsockopt(sock, level, optname, optval.user,
 				      optlen.user);
+	} else {
+		err = -EOPNOTSUPP;
 	}
 
 	if (!compat)
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 134/247] kernel/watch_queue: Use pipe_buf() to retrieve the pipe buffer
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (132 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 133/247] net: call getsockopt_iter if available Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 135/247] watch_queue: Fix note pool publication race in watch_queue_set_size() Greg Kroah-Hartman
                   ` (120 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Oleg Nesterov, K Prateek Nayak,
	Christian Brauner, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: K Prateek Nayak <kprateek.nayak@amd.com>

[ Upstream commit 547476063e123e73fc3aea8432104ab092ffea84 ]

Use pipe_buf() helper to retrieve the pipe buffer in
post_one_notification() replacing the open-coded the logic.

Suggested-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: K Prateek Nayak <kprateek.nayak@amd.com>
Link: https://lore.kernel.org/r/20250307052919.34542-3-kprateek.nayak@amd.com
Signed-off-by: Christian Brauner <brauner@kernel.org>
Stable-dep-of: 5e531d62f1f8 ("watch_queue: Fix note pool publication race in watch_queue_set_size()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 kernel/watch_queue.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/kernel/watch_queue.c b/kernel/watch_queue.c
index 6d1936fb8ff02..5da67a1047d00 100644
--- a/kernel/watch_queue.c
+++ b/kernel/watch_queue.c
@@ -101,12 +101,11 @@ static bool post_one_notification(struct watch_queue *wqueue,
 	struct pipe_inode_info *pipe = wqueue->pipe;
 	struct pipe_buffer *buf;
 	struct page *page;
-	unsigned int head, tail, mask, note, offset, len;
+	unsigned int head, tail, note, offset, len;
 	bool done = false;
 
 	spin_lock_irq(&pipe->rd_wait.lock);
 
-	mask = pipe->ring_size - 1;
 	head = pipe->head;
 	tail = pipe->tail;
 	if (pipe_full(head, tail, pipe->ring_size))
@@ -124,7 +123,7 @@ static bool post_one_notification(struct watch_queue *wqueue,
 	memcpy(p + offset, n, len);
 	kunmap_atomic(p);
 
-	buf = &pipe->bufs[head & mask];
+	buf = pipe_buf(pipe, head);
 	buf->page = page;
 	buf->private = (unsigned long)wqueue;
 	buf->ops = &watch_queue_pipe_buf_ops;
@@ -147,7 +146,7 @@ static bool post_one_notification(struct watch_queue *wqueue,
 	return done;
 
 lost:
-	buf = &pipe->bufs[(head - 1) & mask];
+	buf = pipe_buf(pipe, head - 1);
 	buf->flags |= PIPE_BUF_FLAG_LOSS;
 	goto out;
 }
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 135/247] watch_queue: Fix note pool publication race in watch_queue_set_size()
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (133 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 134/247] kernel/watch_queue: Use pipe_buf() to retrieve the pipe buffer Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:58 ` [PATCH 6.12 136/247] ntfs3: free the sbi after a grace period Greg Kroah-Hartman
                   ` (119 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Dae R. Jeong, AutonomousCodeSecurity,
	Cen Zhang (Microsoft), Bradley Morgan,
	Christian Brauner (Amutable), Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Cen Zhang (Microsoft) <cenzhang@linux.microsoft.com>

[ Upstream commit 5e531d62f1f8834faf7a4eed0d41105cf6570a8f ]

There is a race between watch_queue_set_size() and post_one_notification().
watch_queue_set_size() publishes wqueue->notes, notes_bitmap, nr_pages and
nr_notes with plain stores, and post_one_notification() reads them with
plain loads under a different lock, so nothing orders the four stores
against the poster's loads: depending on the build, notes can be stored
last (gcc 14 on x86-64 does this).  Since keyctl_watch_key() lets a watch
attach to a queue before it is sized, post_one_notification() can already
be running on another CPU at that moment: it reads nr_notes > 0, passes
its bounds check, and then reads notes while it is still NULL,
dereferencing notes[0].

An unprivileged user triggers this reliably by watching one of its own
keys through a notification pipe and racing ioctl(IOC_WATCH_QUEUE_SET_SIZE)
on that pipe against keyctl(KEYCTL_SETPERM) on the key from another CPU,
triggering:

  BUG: kernel NULL pointer dereference, address: 0000000000000000
  RIP: 0010:post_one_notification.isra.0+0xa2/0x1e0
  Call Trace:
   __post_watch_notification+0x148/0x180
   keyctl_setperm_key+0x119/0x130
   do_syscall_64+0x108/0x4c0
   entry_SYSCALL_64_after_hwframe+0x77/0x7f
  Kernel panic - not syncing: Fatal exception in interrupt

Fix this by publishing nr_notes last with smp_store_release(), and by
reading it once with smp_load_acquire() in post_one_notification() before
the bitmap and the page array are touched.  A poster that observes a
non-zero nr_notes then also observes the pool behind it; one that observes
zero drops the notification as before.

Fixes: c73be61cede5 ("pipe: Add general notification queue support")
Reported-by: Dae R. Jeong <threeearcat@gmail.com>
Closes: https://lore.kernel.org/all/ZT-S8Q7tyutcvu_q@dragonet/
Reported-by: AutonomousCodeSecurity@microsoft.com
Suggested-by: Dae R. Jeong <threeearcat@gmail.com>
Signed-off-by: Cen Zhang (Microsoft) <cenzhang@linux.microsoft.com>
Link: https://patch.msgid.link/20261009224715.46121-1-cenzhang@linux.microsoft.com
Reviewed-by: Bradley Morgan <brads@mainlining.org>
Cc: <stable@vger.kernel.org>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 kernel/watch_queue.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/kernel/watch_queue.c b/kernel/watch_queue.c
index 5da67a1047d00..8f809cc60c036 100644
--- a/kernel/watch_queue.c
+++ b/kernel/watch_queue.c
@@ -101,7 +101,7 @@ static bool post_one_notification(struct watch_queue *wqueue,
 	struct pipe_inode_info *pipe = wqueue->pipe;
 	struct pipe_buffer *buf;
 	struct page *page;
-	unsigned int head, tail, note, offset, len;
+	unsigned int head, tail, note, offset, len, nr_notes;
 	bool done = false;
 
 	spin_lock_irq(&pipe->rd_wait.lock);
@@ -111,8 +111,10 @@ static bool post_one_notification(struct watch_queue *wqueue,
 	if (pipe_full(head, tail, pipe->ring_size))
 		goto lost;
 
-	note = find_first_bit(wqueue->notes_bitmap, wqueue->nr_notes);
-	if (note >= wqueue->nr_notes)
+	/* Pairs with the smp_store_release() in watch_queue_set_size(). */
+	nr_notes = smp_load_acquire(&wqueue->nr_notes);
+	note = find_first_bit(wqueue->notes_bitmap, nr_notes);
+	if (note >= nr_notes)
 		goto lost;
 
 	page = wqueue->notes[note / WATCH_QUEUE_NOTES_PER_PAGE];
@@ -297,7 +299,8 @@ long watch_queue_set_size(struct pipe_inode_info *pipe, unsigned int nr_notes)
 	wqueue->notes = pages;
 	wqueue->notes_bitmap = bitmap;
 	wqueue->nr_pages = nr_pages;
-	wqueue->nr_notes = nr_notes;
+	/* Pairs with the smp_load_acquire() in post_one_notification(). */
+	smp_store_release(&wqueue->nr_notes, nr_notes);
 	return 0;
 
 error_p:
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 136/247] ntfs3: free the sbi after a grace period
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (134 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 135/247] watch_queue: Fix note pool publication race in watch_queue_set_size() Greg Kroah-Hartman
@ 2026-10-28 16:58 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 137/247] ext4: " Greg Kroah-Hartman
                   ` (118 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:58 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Christian Brauner (Amutable),
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Christian Brauner <brauner@kernel.org>

[ Upstream commit c01b091b06412d3b1b53d8c2925f6de586c8a2fc ]

If the "nocase" mount option ntfs3 uses custom hash and dentry compare
functions. Both access ntfs3 superblock private information in rcu
pathwalk. ntfs_put_super() and ntfs3_kill_sb() drop the info without any
rcu delay. A lookup that's still inside the filesystem when the last
reference to the mount is dropped causes a UAF. With a pathwalk held up
in ntfs_d_hash() while the last reference to the mount goes away:

  BUG: KASAN: slab-use-after-free in ntfs_nls_to_utf16+0x752/0x940
  Read of size 8 at addr ff1100010453c850 by task walker/99
  Call Trace:
   <TASK>
   ntfs_nls_to_utf16+0x752/0x940
   ntfs_d_hash+0x22b/0x500
   link_path_walk+0x11ad/0x1d30
   path_lookupat+0x63/0xb00
   filename_lookup+0x1f1/0x5b0
   vfs_statx+0xd7/0x3b0
  [...]
  Allocated by task 95:
   __kmalloc_cache_noprof+0x249/0x560
   ntfs_init_fs_context+0x2db/0x5a0
   alloc_fs_context+0x52e/0xc70
  [...]
  Freed by task 98:
   kfree+0x1db/0x5b0
   deactivate_locked_super+0x9c/0xf0
   cleanup_mnt+0x9f/0x130
   task_work_run+0x131/0x250

The bug is currently masked by the grace period in namespace_unlock()
for umount(2). Keep the necessary information until the filesystem
private info is freed and free it with an rcu delay.

ntfs3_free_sbi() now runs from an rcu callback and drops the upcase
table via ntfs_put_shared(). So switch s_shared_lock over to
spin_lock_bh(). Otherwise the callback can deadlock against a task
holding the lock on the same cpu.

Fixes: a3a956c78efa ("fs/ntfs3: Add option "nocase"")
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20261009-work-fixes-rcu-v1-7-7446d2d335e6@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
[ sashal: Adjusted ntfs_put_super() context because the early mount-options cleanup block was already absent. ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 fs/ntfs3/ntfs_fs.h |  1 +
 fs/ntfs3/super.c   | 29 ++++++++++++++++++++++-------
 2 files changed, 23 insertions(+), 7 deletions(-)

diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h
index 11be9a6f041cf..934dcb136d6da 100644
--- a/fs/ntfs3/ntfs_fs.h
+++ b/fs/ntfs3/ntfs_fs.h
@@ -209,6 +209,7 @@ struct ntfs_index {
 /* Ntfs file system in-core superblock data. */
 struct ntfs_sb_info {
 	struct super_block *sb;
+	struct rcu_head rcu;
 
 	u32 discard_granularity;
 	u64 discard_granularity_mask_inv; // ~(discard_granularity_mask_inv-1)
diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c
index 4b1941e3f3a67..c7c1896acc2c5 100644
--- a/fs/ntfs3/super.c
+++ b/fs/ntfs3/super.c
@@ -187,7 +187,7 @@ void *ntfs_set_shared(void *ptr, u32 bytes)
 	void *ret = NULL;
 	int i, j = -1;
 
-	spin_lock(&s_shared_lock);
+	spin_lock_bh(&s_shared_lock);
 	for (i = 0; i < ARRAY_SIZE(s_shared); i++) {
 		if (!s_shared[i].cnt) {
 			j = i;
@@ -205,7 +205,7 @@ void *ntfs_set_shared(void *ptr, u32 bytes)
 		s_shared[j].cnt = 1;
 		ret = ptr;
 	}
-	spin_unlock(&s_shared_lock);
+	spin_unlock_bh(&s_shared_lock);
 
 	return ret;
 }
@@ -222,7 +222,7 @@ void *ntfs_put_shared(void *ptr)
 	void *ret = ptr;
 	int i;
 
-	spin_lock(&s_shared_lock);
+	spin_lock_bh(&s_shared_lock);
 	for (i = 0; i < ARRAY_SIZE(s_shared); i++) {
 		if (s_shared[i].cnt && s_shared[i].ptr == ptr) {
 			if (--s_shared[i].cnt)
@@ -230,7 +230,7 @@ void *ntfs_put_shared(void *ptr)
 			break;
 		}
 	}
-	spin_unlock(&s_shared_lock);
+	spin_unlock_bh(&s_shared_lock);
 
 	return ret;
 }
@@ -630,6 +630,8 @@ static noinline void ntfs3_put_sbi(struct ntfs_sb_info *sbi)
 
 static void ntfs3_free_sbi(struct ntfs_sb_info *sbi)
 {
+	if (sbi->options)
+		put_mount_options(sbi->options);
 	kfree(sbi->new_rec);
 	kvfree(ntfs_put_shared(sbi->upcase));
 	kvfree(sbi->def_table);
@@ -641,6 +643,11 @@ static void ntfs3_free_sbi(struct ntfs_sb_info *sbi)
 	kfree(sbi);
 }
 
+static void ntfs3_free_sbi_rcu(struct rcu_head *head)
+{
+	ntfs3_free_sbi(container_of(head, struct ntfs_sb_info, rcu));
+}
+
 static void ntfs_put_super(struct super_block *sb)
 {
 	struct ntfs_sb_info *sbi = sb->s_fs_info;
@@ -657,6 +664,12 @@ static void ntfs_put_super(struct super_block *sb)
 
 	/* Mark rw ntfs as clear, if possible. */
 	ntfs_set_state(sbi, NTFS_DIRTY_CLEAR);
+
+	/*
+	 * The mount options stay until the sbi is freed: ->d_hash() and
+	 * ->d_compare() of a pathwalk in rcu mode read the nls table through
+	 * them.
+	 */
 	ntfs3_put_sbi(sbi);
 }
 
@@ -1806,9 +1819,11 @@ static void ntfs3_kill_sb(struct super_block *sb)
 
 	kill_block_super(sb);
 
-	if (sbi->options)
-		put_mount_options(sbi->options);
-	ntfs3_free_sbi(sbi);
+	/*
+	 * A pathwalk in rcu mode may still be in ->d_hash() or ->d_compare()
+	 * and read the upcase table and the nls table through the sbi.
+	 */
+	call_rcu(&sbi->rcu, ntfs3_free_sbi_rcu);
 }
 
 // clang-format off
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 137/247] ext4: free the sbi after a grace period
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (135 preceding siblings ...)
  2026-10-28 16:58 ` [PATCH 6.12 136/247] ntfs3: free the sbi after a grace period Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 138/247] ASoC: SOF: ipc4-topology: Fix shift-out-of-bounds for aggregated ALH capture Greg Kroah-Hartman
                   ` (117 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Christian Brauner (Amutable),
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Christian Brauner <brauner@kernel.org>

[ Upstream commit c17b44266a1f9fcb49b894d4611d1254bf1aa313 ]

ext4_get_link() follows a symlink that keeps its target in a data block
in rcu pathwalk mode with ext4_getblk(EXT4_GET_BLOCKS_CACHED_NOWAIT).
That reads s_mount_state in the ASSERT() of ext4_getblk() and again in
ext4_es_lookup_extent(), and the lookup bumps the extent status hit or
miss counter, all through sb->s_fs_info.

ext4_put_super() destroys those counters, clears sb->s_fs_info and frees
the sbi without waiting for a grace period. A pathwalk that is still in
ext4_get_link() when the last reference to the mount goes away then
dereferences a NULL s_fs_info, the freed sbi or the destroyed percpu
counters.

With a pathwalk held up in ext4_get_link() while the last reference
goes away:

  KASAN: null-ptr-deref in range [0x00000000000000a8-0x00000000000000af]
  RIP: 0010:ext4_getblk+0xf0/0x640
  Call Trace:
   <TASK>
   ext4_get_link+0x26c/0x410
   pick_link+0xf96/0x1780
   step_into_slowpath+0x9b8/0x1250
   path_lookupat+0x484/0xb00
   filename_lookup+0x1f1/0x5b0
   vfs_statx+0xd7/0x3b0
   vfs_fstatat+0x4d/0x90
   __do_sys_newfstatat+0xa0/0x100
   do_syscall_64+0x10e/0x5e0
   entry_SYSCALL_64_after_hwframe+0x77/0x7f

So far that has been hard to hit. umount(2) waits for a grace period in
namespace_unlock() before it drops the mount, so only a mount whose last
reference goes away elsewhere, like the close of a file or a chdir out of
a lazily unmounted directory, can race a walker.

Keep sb->s_fs_info and free the sbi together with the extent status
counters after a grace period. Split the counters out of
ext4_es_unregister_shrinker() for that. The shrinker still gets wasted
in ext4_put_super(), the counters go with the sbi.

Fixes: 6493792d3299 ("ext4: convert symlink external data block mapping to bdev")
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20261009-work-fixes-rcu-v1-1-7446d2d335e6@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
[ sashal: omitted ext4_es_destroy_stats() integration with the extent KUnit tests ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 fs/ext4/ext4.h           |  2 ++
 fs/ext4/extents_status.c |  7 ++++++-
 fs/ext4/extents_status.h |  1 +
 fs/ext4/super.c          | 13 +++++++++++--
 4 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 21de942bb6fb3..3e0c29434ae38 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1663,6 +1663,8 @@ struct ext4_sb_info {
 	struct list_head s_es_list;	/* List of inodes with reclaimable extents */
 	long s_es_nr_inode;
 	struct ext4_es_stats s_es_stats;
+	/* ext4_get_link() reads the sbi in rcu pathwalk */
+	struct rcu_head s_rcu;
 	struct mb_cache *s_ea_block_cache;
 	struct mb_cache *s_ea_inode_cache;
 	spinlock_t s_es_lock ____cacheline_aligned_in_smp;
diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
index c786691dabd3d..425a613683c0a 100644
--- a/fs/ext4/extents_status.c
+++ b/fs/ext4/extents_status.c
@@ -1766,12 +1766,17 @@ int ext4_es_register_shrinker(struct ext4_sb_info *sbi)
 }
 
 void ext4_es_unregister_shrinker(struct ext4_sb_info *sbi)
+{
+	shrinker_free(sbi->s_es_shrinker);
+}
+
+/* ext4_get_link() bumps the hit and miss counters in rcu pathwalk */
+void ext4_es_destroy_stats(struct ext4_sb_info *sbi)
 {
 	percpu_counter_destroy(&sbi->s_es_stats.es_stats_cache_hits);
 	percpu_counter_destroy(&sbi->s_es_stats.es_stats_cache_misses);
 	percpu_counter_destroy(&sbi->s_es_stats.es_stats_all_cnt);
 	percpu_counter_destroy(&sbi->s_es_stats.es_stats_shk_cnt);
-	shrinker_free(sbi->s_es_shrinker);
 }
 
 /*
diff --git a/fs/ext4/extents_status.h b/fs/ext4/extents_status.h
index 4424232de2989..c1e45f6ab6647 100644
--- a/fs/ext4/extents_status.h
+++ b/fs/ext4/extents_status.h
@@ -237,6 +237,7 @@ static inline void ext4_es_store_pblock_status(struct extent_status *es,
 
 extern int ext4_es_register_shrinker(struct ext4_sb_info *sbi);
 extern void ext4_es_unregister_shrinker(struct ext4_sb_info *sbi);
+extern void ext4_es_destroy_stats(struct ext4_sb_info *sbi);
 
 extern int ext4_seq_es_shrinker_info_show(struct seq_file *seq, void *v);
 
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 08f84ed65ad1c..25aae8165f070 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1289,6 +1289,14 @@ static void ext4_flex_groups_free(struct ext4_sb_info *sbi)
 	}
 }
 
+static void ext4_put_sbi_rcu(struct rcu_head *head)
+{
+	struct ext4_sb_info *sbi = container_of(head, struct ext4_sb_info, s_rcu);
+
+	ext4_es_destroy_stats(sbi);
+	kfree(sbi);
+}
+
 static void ext4_put_super(struct super_block *sb)
 {
 	struct ext4_sb_info *sbi = EXT4_SB(sb);
@@ -1381,7 +1389,6 @@ static void ext4_put_super(struct super_block *sb)
 	ext4_stop_mmpd(sbi);
 
 	brelse(sbi->s_sbh);
-	sb->s_fs_info = NULL;
 	/*
 	 * Now that we are completely done shutting down the
 	 * superblock, we need to actually destroy the kobject.
@@ -1396,7 +1403,8 @@ static void ext4_put_super(struct super_block *sb)
 #if IS_ENABLED(CONFIG_UNICODE)
 	utf8_unload(sb->s_encoding);
 #endif
-	kfree(sbi);
+	/* ext4_get_link() reads the sbi and the counters in rcu pathwalk */
+	call_rcu(&sbi->s_rcu, ext4_put_sbi_rcu);
 }
 
 static struct kmem_cache *ext4_inode_cachep;
@@ -5659,6 +5667,7 @@ failed_mount8: __maybe_unused
 	}
 failed_mount3a:
 	ext4_es_unregister_shrinker(sbi);
+	ext4_es_destroy_stats(sbi);
 failed_mount3:
 	/* flush s_sb_upd_work before sbi destroy */
 	flush_work(&sbi->s_sb_upd_work);
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 138/247] ASoC: SOF: ipc4-topology: Fix shift-out-of-bounds for aggregated ALH capture
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (136 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 137/247] ext4: " Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 139/247] drm/xe: Bump LRU for external objects on exec and rebind Greg Kroah-Hartman
                   ` (116 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Peter Ujfalusi, Bard Liao,
	Mark Brown, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>

[ Upstream commit 746de48c3a250f0c264105dcbfcdf0c5001e970b ]

When ch_count is smaller than blob->alh_cfg.device_count (e.g. a mono
capture stream, such as a SmartMic, aggregated across multiple SDW
links), step = ch_count / blob->alh_cfg.device_count truncates to 0.
The subsequent GENMASK(step - 1, 0) then underflows step - 1 (u32) to
UINT_MAX, causing GENMASK()'s internal shift to use an out-of-bounds
exponent:

  UBSAN: shift-out-of-bounds in sound/soc/sof/ipc4-topology.c:2363:13
  shift exponent 18446744069414584384 is too large for 64-bit type 'long unsigned int'

Treat ch_count < device_count the same way as the existing "channels
equal to output reference channels" case: apply the same ch_mask to
every aggregated device instead of trying to split channels that
can't be evenly divided.

Fixes: 0390a102cc18 ("ASoC: SOF: ipc4-topology: use different channel mask for each sdw amp feedback")
Cc: stable@vger.kernel.org
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Link: https://patch.msgid.link/20261008090130.15135-1-peter.ujfalusi@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
[ sashal: used a standalone condition because the playback-specific channel check is absent ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 sound/soc/sof/ipc4-topology.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c
index 6af0cc154f3d7..5cf272fe93ff6 100644
--- a/sound/soc/sof/ipc4-topology.c
+++ b/sound/soc/sof/ipc4-topology.c
@@ -1973,8 +1973,20 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
 				ch_map >>= 4;
 			}
 
-			step = ch_count / blob->alh_cfg.device_count;
-			mask =  GENMASK(step - 1, 0);
+			if (ch_count < blob->alh_cfg.device_count) {
+				/*
+				 * When there are fewer channels than aggregated devices
+				 * (e.g. a mono capture stream split across multiple links),
+				 * set step = 0 to ensure all the ch_mask is applied to all
+				 * alh mappings.
+				 */
+				mask = ch_mask;
+				step = 0;
+			} else {
+				step = ch_count / blob->alh_cfg.device_count;
+				mask =  GENMASK(step - 1, 0);
+			}
+
 			/*
 			 * Set each gtw_cfg.node_id to blob->alh_cfg.mapping[]
 			 * for all widgets with the same stream name
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 139/247] drm/xe: Bump LRU for external objects on exec and rebind
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (137 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 138/247] ASoC: SOF: ipc4-topology: Fix shift-out-of-bounds for aggregated ALH capture Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 140/247] tracing: Keep the predicate limit separate from program capacity Greg Kroah-Hartman
                   ` (115 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Matthew Auld, Matthew Brost,
	Thomas Hellström, Rodrigo Vivi, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Thomas Hellström <thomas.hellstrom@linux.intel.com>

[ Upstream commit d2ce8fcd778ee6d92748c92d23a56d4416c29d86 ]

The VM's private BOs get their LRU position refreshed in bulk via
ttm_lru_bulk_move_tail() on vm->lru_bulk_move, both after a successful
non-LR exec and after the LR preempt-fence rebind worker runs. External
objects (BOs potentially shared across VMs) are never added to that
per-VM bulk move list, so their LRU position is never refreshed by
either path. This makes external objects in active use look more
evictable than they are.

Add xe_vm_bump_lru(), which, under a single lru_lock critical section,
performs the bulk move of the VM's private BOs and bumps each external
object locked by the drm_exec transaction. Use it from both the non-LR
exec path and the LR rebind worker, replacing the open-coded bulk move.

Fixes: d490ecf57790 ("drm/xe: Rework xe_exec and the VM rebind worker to use the drm_exec helper")
Cc: Matthew Auld <matthew.auld@intel.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: <stable@vger.kernel.org> # v6.8+
Assisted-by: LLM
Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
Reviewed-by: Matthew Auld <matthew.auld@intel.com>
Link: https://patch.msgid.link/20261012132607.21387-1-thomas.hellstrom@linux.intel.com
(cherry picked from commit 324ba30cca180c2e1d02090743dd78ccb15b9e4a)
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
[ sashal: Adjusted header context to accommodate missing xe_vm_bind_kernel_bo() and xe_vm_resume_rebind_worker() declarations. ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/gpu/drm/xe/xe_exec.c |  7 ++-----
 drivers/gpu/drm/xe/xe_vm.c   | 31 ++++++++++++++++++++++++++++---
 drivers/gpu/drm/xe/xe_vm.h   |  2 ++
 3 files changed, 32 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_exec.c b/drivers/gpu/drm/xe/xe_exec.c
index 04a88c16d8358..03af3704ee68d 100644
--- a/drivers/gpu/drm/xe/xe_exec.c
+++ b/drivers/gpu/drm/xe/xe_exec.c
@@ -330,11 +330,8 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
 	xe_sched_job_push(job);
 	xe_vm_reactivate_rebind(vm);
 
-	if (!err && !xe_vm_in_lr_mode(vm)) {
-		spin_lock(&xe->ttm.lru_lock);
-		ttm_lru_bulk_move_tail(&vm->lru_bulk_move);
-		spin_unlock(&xe->ttm.lru_lock);
-	}
+	if (!err && !xe_vm_in_lr_mode(vm))
+		xe_vm_bump_lru(vm, exec);
 
 	if (mode == EXEC_MODE_LR)
 		xe_hw_engine_group_resume_faulting_lr_jobs(group);
diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index da148df421057..d53cb4e625172 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -439,6 +439,33 @@ int xe_vm_validate_rebind(struct xe_vm *vm, struct drm_exec *exec,
 	return 0;
 }
 
+/**
+ * xe_vm_bump_lru() - Bump the LRU position of BOs used by a submission
+ * @vm: The vm for which we are bumping LRUs.
+ * @exec: The struct drm_exec with the locked GEM objects.
+ *
+ * Move the VM's private BOs, and all external objects locked by @exec,
+ * to the LRU tail. Private BOs are moved in bulk using @vm's
+ * &xe_vm.lru_bulk_move. External objects, which may be shared with other
+ * VMs, are not part of that bulk move and are bumped individually.
+ */
+void xe_vm_bump_lru(struct xe_vm *vm, struct drm_exec *exec)
+{
+	spinlock_t *lru_lock = &vm->xe->ttm.lru_lock;
+	struct drm_gem_object *obj;
+
+	spin_lock(lru_lock);
+	ttm_lru_bulk_move_tail(&vm->lru_bulk_move);
+	drm_exec_for_each_locked_object(exec, obj) {
+		if (!drm_gpuvm_is_extobj(&vm->gpuvm, obj))
+			continue;
+
+		ttm_bo_move_to_lru_tail(&gem_to_xe_bo(obj)->ttm);
+		cond_resched_lock(lru_lock);
+	}
+	spin_unlock(lru_lock);
+}
+
 static int xe_preempt_work_begin(struct drm_exec *exec, struct xe_vm *vm,
 				 bool *done)
 {
@@ -552,9 +579,7 @@ static void preempt_rebind_work_func(struct work_struct *w)
 
 #undef retry_required
 
-	spin_lock(&vm->xe->ttm.lru_lock);
-	ttm_lru_bulk_move_tail(&vm->lru_bulk_move);
-	spin_unlock(&vm->xe->ttm.lru_lock);
+	xe_vm_bump_lru(vm, &exec);
 
 	/* Point of no return. */
 	arm_preempt_fences(vm, &preempt_fences);
diff --git a/drivers/gpu/drm/xe/xe_vm.h b/drivers/gpu/drm/xe/xe_vm.h
index d2406532fcc50..b0a864618eccc 100644
--- a/drivers/gpu/drm/xe/xe_vm.h
+++ b/drivers/gpu/drm/xe/xe_vm.h
@@ -248,6 +248,8 @@ int xe_vm_lock_vma(struct drm_exec *exec, struct xe_vma *vma);
 int xe_vm_validate_rebind(struct xe_vm *vm, struct drm_exec *exec,
 			  unsigned int num_fences);
 
+void xe_vm_bump_lru(struct xe_vm *vm, struct drm_exec *exec);
+
 /**
  * xe_vm_resv() - Return's the vm's reservation object
  * @vm: The vm
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 140/247] tracing: Keep the predicate limit separate from program capacity
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (138 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 139/247] drm/xe: Bump LRU for external objects on exec and rebind Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 141/247] io_uring/cancel: dont spin on local work the task cant run Greg Kroah-Hartman
                   ` (114 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Taeyang Lee, Steven Rostedt,
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Taeyang Lee <0wn@theori.io>

[ Upstream commit 803aa6fc2dbea25ab9d3ed19eca1c96d0ab17445 ]

predicate_parse() adds two to nr_preds to reserve the terminal TRUE
and FALSE entries. It also uses that increased value as the limit for
parsed predicates. If the initial count is smaller than the number
actually parsed, the program can fill the allocation and subsequent
accesses can go past its end.

Keep nr_preds as the predicate limit and use a separate value for the
allocation size. This leaves space for both terminal entries and a
zeroed entry when parsing stops at the limit.

Cc: stable@vger.kernel.org
Fixes: 39f7c41c908b ("tracing/filters: Enable filtering a cpumask field by another cpumask")
Link: https://patch.msgid.link/atELCd1XjKVhrkFL@Taeyangs-MacBook-Pro.local
Signed-off-by: Taeyang Lee <0wn@theori.io>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
[ sashal: adapted the allocation change to use kcalloc() instead of kzalloc_objs(). ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 kernel/trace/trace_events_filter.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
index ada02ae893c20..cd89fbf2fb208 100644
--- a/kernel/trace/trace_events_filter.c
+++ b/kernel/trace/trace_events_filter.c
@@ -482,18 +482,17 @@ predicate_parse(const char *str, int nr_parens, int nr_preds,
 	int len;
 	int N = 0;
 	int i;
-
-	nr_preds += 2; /* For TRUE and FALSE */
+	int nr_preds_alloc = nr_preds + 2; /* For TRUE and FALSE */
 
 	op_stack = kmalloc_array(nr_parens, sizeof(*op_stack), GFP_KERNEL);
 	if (!op_stack)
 		return ERR_PTR(-ENOMEM);
-	prog_stack = kcalloc(nr_preds, sizeof(*prog_stack), GFP_KERNEL);
+	prog_stack = kcalloc(nr_preds_alloc, sizeof(*prog_stack), GFP_KERNEL);
 	if (!prog_stack) {
 		parse_error(pe, -ENOMEM, 0);
 		goto out_free;
 	}
-	inverts = kmalloc_array(nr_preds, sizeof(*inverts), GFP_KERNEL);
+	inverts = kmalloc_array(nr_preds_alloc, sizeof(*inverts), GFP_KERNEL);
 	if (!inverts) {
 		parse_error(pe, -ENOMEM, 0);
 		goto out_free;
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 141/247] io_uring/cancel: dont spin on local work the task cant run
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (139 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 140/247] tracing: Keep the predicate limit separate from program capacity Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 142/247] virtio: set skb owner of virtio_transport_reset_no_sock() reply Greg Kroah-Hartman
                   ` (113 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, AutonomousCodeSecurity,
	Cen Zhang (Microsoft Security FORGE Labs), Jens Axboe,
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Cen Zhang (Microsoft Security FORGE Labs) <cenzhang@linux.microsoft.com>

[ Upstream commit fddcf4c5321b3ea5f72166c3fd36a9d1c34f80c7 ]

io_uring_cancel_generic() refuses to sleep while any ring on the exiting
task's tctx has local work pending. It assumes the task is that ring's
submitter and that the next io_uring_try_cancel_requests() pass will run
the work. This does not hold for a ring that was still
IORING_SETUP_R_DISABLED when the task got its tctx node from
io_uring_create() or io_ringfd_register(). The submitter is set later by
IORING_REGISTER_ENABLE_RINGS, possibly from another task, and only the
submitter may run local work on an IORING_SETUP_DEFER_TASKRUN ring. To
the exiting task the work stays pending forever, the loop never reaches
schedule(), and the task trips the WARN_ON_ONCE() once and then spins in
do_exit().

An unprivileged user can set this up at will by creating a disabled
ring, having a child enable it and stop, posting to the ring with
IORING_OP_MSG_RING and exiting with a request in flight that only the
child can complete. The exiting thread burns a CPU until the child runs
or dies, and with panic_on_warn set the WARN panics the kernel.

Fix by skipping the sleep only when io_allowed_defer_tw_run() allows the
task to run the work. This is reasonable since work it cannot run cannot
complete any of its requests either, so nothing is lost by sleeping.
Drop the WARN_ON_ONCE() since handing a disabled ring to another thread
is a supported scenario, not a bug state.

Fixes: 360cd42c4e95 ("io_uring: optimise io_req_local_work_add")
Reported-by: AutonomousCodeSecurity@microsoft.com
Signed-off-by: Cen Zhang (Microsoft Security FORGE Labs) <cenzhang@linux.microsoft.com>
Link: https://patch.msgid.link/20261008191602.45101-1-cenzhang@linux.microsoft.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
[ sashal: Used !llist_empty(&node->ctx->work_llist) instead of the unavailable io_local_work_pending() helper. ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 io_uring/io_uring.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
index 0076c7599c947..68a21552a186f 100644
--- a/io_uring/io_uring.c
+++ b/io_uring/io_uring.c
@@ -3190,12 +3190,11 @@ __cold void io_uring_cancel_generic(bool cancel_all, struct io_sq_data *sqd)
 		prepare_to_wait(&tctx->wait, &wait, TASK_INTERRUPTIBLE);
 		io_run_task_work();
 		io_uring_drop_tctx_refs(current);
+		/* only skip the sleep for local work this task may run */
 		xa_for_each(&tctx->xa, index, node) {
-			if (!llist_empty(&node->ctx->work_llist)) {
-				WARN_ON_ONCE(node->ctx->submitter_task &&
-					     node->ctx->submitter_task != current);
+			if (!llist_empty(&node->ctx->work_llist) &&
+			    io_allowed_defer_tw_run(node->ctx))
 				goto end_wait;
-			}
 		}
 		/*
 		 * If we've seen completions, retry without waiting. This
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 142/247] virtio: set skb owner of virtio_transport_reset_no_sock() reply
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (140 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 141/247] io_uring/cancel: dont spin on local work the task cant run Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 143/247] vsock/virtio: validate packet source for connected sockets Greg Kroah-Hartman
                   ` (112 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Stefano Garzarella, Bobby Eshleman,
	Michael S. Tsirkin, Paolo Abeni, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Bobby Eshleman <bobbyeshleman@meta.com>

[ Upstream commit a6ae12a599e0f16bc01a38bcfe8d0278a26b5ee0 ]

Associate reply packets with the sending socket. When vsock must reply
with an RST packet and there exists a sending socket (e.g., for
loopback), setting the skb owner to the socket correctly handles
reference counting between the skb and sk (i.e., the sk stays alive
until the skb is freed).

This allows the net namespace to be used for socket lookups for the
duration of the reply skb's lifetime, preventing race conditions between
the namespace lifecycle and vsock socket search using the namespace
pointer.

Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
Signed-off-by: Bobby Eshleman <bobbyeshleman@meta.com>
Link: https://patch.msgid.link/20260121-vsock-vmtest-v16-2-2859a7512097@meta.com
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Stable-dep-of: dee44f41f206 ("vsock/virtio: validate packet source for connected sockets")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/vmw_vsock/virtio_transport_common.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c
index 8552173aafe16..75df280bcc81f 100644
--- a/net/vmw_vsock/virtio_transport_common.c
+++ b/net/vmw_vsock/virtio_transport_common.c
@@ -1313,6 +1313,12 @@ static int virtio_transport_reset_no_sock(const struct virtio_transport *t,
 		.op = VIRTIO_VSOCK_OP_RST,
 		.type = le16_to_cpu(hdr->type),
 		.reply = true,
+
+		/* Set sk owner to socket we are replying to (may be NULL for
+		 * non-loopback). This keeps a reference to the sock and
+		 * sock_net(sk) until the reply skb is freed.
+		 */
+		.vsk = vsock_sk(skb->sk),
 	};
 	struct sk_buff *reply;
 
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 143/247] vsock/virtio: validate packet source for connected sockets
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (141 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 142/247] virtio: set skb owner of virtio_transport_reset_no_sock() reply Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 144/247] ipv4: udp: Create exceptions before socket matching Greg Kroah-Hartman
                   ` (111 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Stefano Garzarella, Bobby Eshleman,
	Daehyeon Ko, Jakub Kicinski, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Daehyeon Ko <4ncienth@gmail.com>

[ Upstream commit dee44f41f206becb41c492899c1996cfd7f82a1b ]

virtio_transport_recv_pkt() looks up sockets first by the full source and
destination tuple, then by destination only in the bound table. The
fallback is needed for listening and connecting sockets, but sockets remain
in the bound table after connect(), so it can also return a non-listening
socket.

The fallback does not validate the source address. In TCP_SYN_SENT, a
RESPONSE from an unrelated source can transition the victim socket to
TCP_ESTABLISHED while its stored remote address remains unchanged.
Subsequent RW packets from that source are delivered through the same
destination-only fallback.

This was reproduced with capability-empty processes under different UIDs.
The attacker discovered the target tuple through unprivileged AF_VSOCK
sock_diag and caused the victim socket to read 16 attacker-chosen bytes;
the intended peer-side socket read 0 of those 16 bytes.

Add vsock_check_source() to validate the transport, source port and source
CID against the peer stored in a non-listening socket. The local transport
is the CID exception because its packets are generated internally with
VMADDR_CID_LOCAL as their source, including connections using CID aliases.

Use the helper after lock_sock() in the virtio receive path.

Fixes: 06a8fc78367d ("VSOCK: Introduce virtio_vsock_common.ko")
Closes: https://lore.kernel.org/netdev/20260813121236.2328599-1-4ncienth@gmail.com/
Cc: stable@vger.kernel.org
Suggested-by: Stefano Garzarella <sgarzare@redhat.com>
Reviewed-by: Bobby Eshleman <bobbyeshleman@meta.com>
Signed-off-by: Daehyeon Ko <4ncienth@gmail.com>
Link: https://patch.msgid.link/20260826003929.966160-2-4ncienth@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
[ sashal: adjusted context for socket lookup and reset helpers without network namespace parameters ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 include/net/af_vsock.h                  |  3 +++
 net/vmw_vsock/af_vsock.c                | 32 +++++++++++++++++++++++++
 net/vmw_vsock/virtio_transport_common.c |  3 ++-
 3 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/include/net/af_vsock.h b/include/net/af_vsock.h
index 70302c92d329f..20bbe02d2cfc5 100644
--- a/include/net/af_vsock.h
+++ b/include/net/af_vsock.h
@@ -216,6 +216,9 @@ void vsock_remove_connected(struct vsock_sock *vsk);
 struct sock *vsock_find_bound_socket(struct sockaddr_vm *addr);
 struct sock *vsock_find_connected_socket(struct sockaddr_vm *src,
 					 struct sockaddr_vm *dst);
+bool vsock_check_source(const struct vsock_sock *vsk,
+			const struct vsock_transport *transport,
+			const struct sockaddr_vm *src);
 void vsock_remove_sock(struct vsock_sock *vsk);
 void vsock_for_each_connected_socket(struct vsock_transport *transport,
 				     void (*fn)(struct sock *sk));
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
index 228e45bf2d769..999cccb323f79 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -335,6 +335,38 @@ struct sock *vsock_find_connected_socket(struct sockaddr_vm *src,
 }
 EXPORT_SYMBOL_GPL(vsock_find_connected_socket);
 
+/**
+ * vsock_check_source - validate a packet source against a socket peer
+ * @vsk: socket receiving the packet
+ * @transport: transport receiving the packet
+ * @src: source address from the packet
+ *
+ * Return: true if the packet arrived on the socket's assigned transport and
+ * its source matches the stored peer. Loopback packets are generated
+ * internally and always use the local CID as their source, including
+ * connections using a valid CID alias.
+ *
+ * The caller must hold the socket lock and must not call this for listening
+ * sockets, which accept packets from any source and have no assigned
+ * transport.
+ */
+bool vsock_check_source(const struct vsock_sock *vsk,
+			const struct vsock_transport *transport,
+			const struct sockaddr_vm *src)
+{
+	if (vsk->transport != transport)
+		return false;
+
+	if (src->svm_port != vsk->remote_addr.svm_port)
+		return false;
+
+	if (src->svm_cid == vsk->remote_addr.svm_cid)
+		return true;
+
+	return transport->get_local_cid() == VMADDR_CID_LOCAL;
+}
+EXPORT_SYMBOL_GPL(vsock_check_source);
+
 void vsock_remove_sock(struct vsock_sock *vsk)
 {
 	/* Transport reassignment must not remove the binding. */
diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c
index 75df280bcc81f..cf7f3dcc075c7 100644
--- a/net/vmw_vsock/virtio_transport_common.c
+++ b/net/vmw_vsock/virtio_transport_common.c
@@ -1837,7 +1837,8 @@ void virtio_transport_recv_pkt(struct virtio_transport *t,
 	 * lock_sock (note: listener sockets are not assigned to any transport)
 	 */
 	if (sock_flag(sk, SOCK_DONE) ||
-	    (sk->sk_state != TCP_LISTEN && vsk->transport != &t->transport)) {
+	    (sk->sk_state != TCP_LISTEN &&
+	     !vsock_check_source(vsk, &t->transport, &src))) {
 		(void)virtio_transport_reset_no_sock(t, skb);
 		release_sock(sk);
 		sock_put(sk);
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 144/247] ipv4: udp: Create exceptions before socket matching
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (142 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 143/247] vsock/virtio: validate packet source for connected sockets Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 145/247] workqueue: release pwq pools by pool type Greg Kroah-Hartman
                   ` (110 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Amit Klein, Noam Caspi, Ido Schimmel,
	David Ahern, Jakub Kicinski, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Ido Schimmel <idosch@nvidia.com>

[ Upstream commit 4c3499f79f8c7e8561266bcc220a18538cec0458 ]

Currently, when ICMP Fragmentation Needed and Redirect Message packets
are locally delivered and quote a UDP packet, a FIB nexthop exception
(FNHE) is only created if the kernel can match the UDP packet to an
existing socket.

This behavior allows off-path attackers to conduct a side-channel attack
on the FNHE cache in order to discover the ephemeral port used by a
connected UDP socket.

Commit 6457378fe796 ("ipv4: use siphash instead of Jenkins in
fnhe_hashfun()") and commit 67d6d681e15b ("ipv4: make exception cache
less predictible") tried to mitigate such attacks by making it harder
for attackers to discover hash collisions in the FNHE cache and by
randomizing the number of exceptions a hash bucket can hold,
respectively. Unfortunately, both of the mitigations can be bypassed.

Instead, mitigate such attacks by always creating a FNHE, even before
trying to find a matching socket. Do that by calling ipv4_update_pmtu()
and ipv4_redirect(), the helpers used when the quoted packet did not
originate from a socket.

This means that guesses (right or wrong) from an off-path attacker will
always result in a FNHE being created or updated in the cache that the
attacker can observe.

Pass an oif of 0, in a similar fashion to icmp_err(). This is also the
oif used by the socket path for sockets that are not bound to a device.

Note that this does not allow attackers to create FNHEs that they could
not create before, as both helpers can already be reached with little to
no validation. For example, by sending an ICMP error that quotes an ICMP
Echo Reply or one that quotes a UDP source port that matches a wildcard
socket.

Also note that in the good case (matched socket) the above scheme comes
at the cost of an extra route lookup, as the no socket helpers perform
their own lookup before the one performed by ipv4_sk_update_pmtu() /
ipv4_sk_redirect(). When the two resolve to different nexthops, it also
results in two exceptions being created for the same destination IP. One
in the FNHE cache of the nexthop resolved by the no socket helpers and
another in the FNHE cache of the nexthop used by the socket.

Fixes: 4895c771c7f0 ("ipv4: Add FIB nexthop exceptions.")
Cc: stable@vger.kernel.org
Reported-by: Amit Klein <aksecurity@gmail.com>
Reported-by: Noam Caspi <noam.caspi@mail.huji.ac.il>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
Link: https://patch.msgid.link/20260828192344.2596928-3-idosch@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
[ sashal: inlined udp_err_update_exception() in the udp_err() wrapper. ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/ipv4/udp.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 69e6897337417..22eee4fdd5d8d 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -869,7 +869,16 @@ int __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable)
 
 int udp_err(struct sk_buff *skb, u32 info)
 {
-	return __udp4_lib_err(skb, info, dev_net(skb->dev)->ipv4.udp_table);
+	const int type = icmp_hdr(skb)->type;
+	const int code = icmp_hdr(skb)->code;
+	struct net *net = dev_net(skb->dev);
+
+	if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED)
+		ipv4_update_pmtu(skb, net, info, 0, IPPROTO_UDP);
+	else if (type == ICMP_REDIRECT)
+		ipv4_redirect(skb, net, 0, IPPROTO_UDP);
+
+	return __udp4_lib_err(skb, info, net->ipv4.udp_table);
 }
 
 /*
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 145/247] workqueue: release pwq pools by pool type
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (143 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 144/247] ipv4: udp: Create exceptions before socket matching Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 146/247] workqueue: Fix unbound pool lifetime for pending pwqs Greg Kroah-Hartman
                   ` (109 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Breno Leitao, Tejun Heo, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Breno Leitao <leitao@debian.org>

[ Upstream commit 3180ee71b676845603274c66f6bb5528939cf470 ]

Add is_percpu_pool() and test the pool directly for per cpu. Convert the
other open-coded pool->cpu checks -- in put_unbound_pool(),
pool_allowed_cpus() and the workqueue watchdog -- to the same helper.

No functional change.

Signed-off-by: Breno Leitao <leitao@debian.org>
Signed-off-by: Tejun Heo <tj@kernel.org>

Use a single-evaluation macro for is_percpu_pool() so the predicate
conversion does not add a function. Keep the existing watchdog stall
accounting; only its pool-type check needs to change. This preserves
the release-path context needed by the pending-pwq lifetime fix.

Stable-dep-of: cf9c8aaea0d4 ("workqueue: Fix unbound pool lifetime for pending pwqs")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 kernel/workqueue.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 329394830c40f..14a3d1775c2ff 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -1559,6 +1559,8 @@ work_func_t wq_worker_last_func(struct task_struct *task)
 	return worker->last_func;
 }
 
+#define is_percpu_pool(pool) ((pool)->cpu >= 0)
+
 /**
  * wq_node_nr_active - Determine wq_node_nr_active to use
  * @wq: workqueue of interest
@@ -2683,7 +2685,7 @@ static struct worker *alloc_worker(int node)
 
 static cpumask_t *pool_allowed_cpus(struct worker_pool *pool)
 {
-	if (pool->cpu < 0 && pool->attrs->affn_strict)
+	if (!is_percpu_pool(pool) && pool->attrs->affn_strict)
 		return pool->attrs->__pod_cpumask;
 	else
 		return pool->attrs->cpumask;
@@ -4969,7 +4971,7 @@ static void put_unbound_pool(struct worker_pool *pool)
 		return;
 
 	/* sanity checks */
-	if (WARN_ON(!(pool->cpu < 0)) ||
+	if (WARN_ON(is_percpu_pool(pool)) ||
 	    WARN_ON(!list_empty(&pool->worklist)))
 		return;
 
@@ -5121,7 +5123,7 @@ static void pwq_release_workfn(struct kthread_work *work)
 		mutex_unlock(&wq->mutex);
 	}
 
-	if (wq->flags & WQ_UNBOUND) {
+	if (!is_percpu_pool(pool)) {
 		mutex_lock(&wq_pool_mutex);
 		put_unbound_pool(pool);
 		mutex_unlock(&wq_pool_mutex);
@@ -7639,7 +7641,7 @@ static void wq_watchdog_timer_fn(struct timer_list *unused)
 		/* did we stall? */
 		if (time_after(now, ts + thresh)) {
 			lockup_detected = true;
-			if (pool->cpu >= 0 && !(pool->flags & POOL_BH)) {
+			if (is_percpu_pool(pool) && !(pool->flags & POOL_BH)) {
 				pool->cpu_stall = true;
 				cpu_pool_stall = true;
 			}
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 146/247] workqueue: Fix unbound pool lifetime for pending pwqs
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (144 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 145/247] workqueue: release pwq pools by pool type Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 147/247] i2c: viai2c-wmt: Replace dev_err() with dev_err_probe() in probe function Greg Kroah-Hartman
                   ` (108 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Yao Kai, Tejun Heo, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Yao Kai <yaokai34@huawei.com>

[ Upstream commit cf9c8aaea0d47410df8708bec195889f3a85cd3c ]

KASAN reports a use-after-free of an unbound worker_pool in
node_activate_pending_pwq():

  BUG: KASAN: slab-use-after-free in _raw_spin_trylock+0x6d/0x120
  Read of size 4 at addr ffff8880089ce000 by task kworker/u22:0/318

  CPU: 1 UID: 0 PID: 318 Comm: kworker/u22:0 Not tainted 7.2.0 #1 PREEMPT(lazy)
  Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
  Workqueue:  0x0 (flush-8:0)
  Call Trace:
   <TASK>
   dump_stack_lvl+0x53/0x70
   print_report+0xce/0x610
   kasan_report+0xce/0x100
   _raw_spin_trylock+0x6d/0x120
   pwq_dec_nr_in_flight+0x4b4/0xcb0
   process_one_work+0x921/0x11a0
   worker_thread+0x4d0/0xd20
   kthread+0x2de/0x3c0
   ret_from_fork+0x3aa/0x620
   ret_from_fork_asm+0x1a/0x30
   </TASK>

  Allocated by task 311:
   alloc_pwq+0x439/0xca0
   apply_wqattrs_prepare+0x75e/0xd10
   apply_workqueue_attrs_locked+0x44/0xa0
   wq_nice_store+0x350/0x450

  Freed by task 0:
   kfree+0x127/0x3b0
   rcu_core+0x523/0x1780
   handle_softirqs+0x1b3/0x610

  Last potentially related work creation:
   put_unbound_pool+0x3f3/0x7d0
   pwq_release_workfn+0x494/0x8e0
   kthread_worker_fn+0x1ff/0x790

Canceling the last inactive work skips pwq_dec_nr_active(), so an empty
pwq can remain on pending_pwqs when its refcnt reaches zero.
pwq_release_workfn() currently puts the pool before removing that pwq.
If this drops the last pool reference, the pool can be RCU-freed while
the pwq remains reachable, and node_activate_pending_pwq() may trylock
the freed pool->lock.

Remove the pwq from pending_pwqs before putting the pool.

Fixes: 5797b1c18919 ("workqueue: Implement system-wide nr_active enforcement for unbound workqueues")
Cc: stable@vger.kernel.org
Signed-off-by: Yao Kai <yaokai34@huawei.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 kernel/workqueue.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 14a3d1775c2ff..f6dde83c9466f 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -5123,12 +5123,6 @@ static void pwq_release_workfn(struct kthread_work *work)
 		mutex_unlock(&wq->mutex);
 	}
 
-	if (!is_percpu_pool(pool)) {
-		mutex_lock(&wq_pool_mutex);
-		put_unbound_pool(pool);
-		mutex_unlock(&wq_pool_mutex);
-	}
-
 	if (!list_empty(&pwq->pending_node)) {
 		struct wq_node_nr_active *nna =
 			wq_node_nr_active(pwq->wq, pwq->pool->node);
@@ -5138,6 +5132,12 @@ static void pwq_release_workfn(struct kthread_work *work)
 		raw_spin_unlock_irq(&nna->lock);
 	}
 
+	if (!is_percpu_pool(pool)) {
+		mutex_lock(&wq_pool_mutex);
+		put_unbound_pool(pool);
+		mutex_unlock(&wq_pool_mutex);
+	}
+
 	kfree_rcu(pwq, rcu);
 
 	/*
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 147/247] i2c: viai2c-wmt: Replace dev_err() with dev_err_probe() in probe function
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (145 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 146/247] workqueue: Fix unbound pool lifetime for pending pwqs Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 148/247] i2c: viai2c-wmt: Fix clock leak in wmt_i2c_probe() Greg Kroah-Hartman
                   ` (107 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Enrico Zanda, Andi Shyti,
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Enrico Zanda <e.zanda1@gmail.com>

[ Upstream commit 3b7d8d151a7ebebc5257766110c102ab173b5844 ]

This simplifies the code while improving log.

Signed-off-by: Enrico Zanda <e.zanda1@gmail.com>
Link: https://lore.kernel.org/r/20250513210246.528370-2-e.zanda1@gmail.com
Signed-off-by: Andi Shyti <andi@smida.it>
Stable-dep-of: aaabefc79b0f ("i2c: viai2c-wmt: Fix clock leak in wmt_i2c_probe()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/i2c/busses/i2c-viai2c-wmt.c | 20 +++++++-------------
 1 file changed, 7 insertions(+), 13 deletions(-)

diff --git a/drivers/i2c/busses/i2c-viai2c-wmt.c b/drivers/i2c/busses/i2c-viai2c-wmt.c
index 3415683dab91c..133dc41fe387b 100644
--- a/drivers/i2c/busses/i2c-viai2c-wmt.c
+++ b/drivers/i2c/busses/i2c-viai2c-wmt.c
@@ -44,16 +44,13 @@ static int wmt_i2c_reset_hardware(struct viai2c *i2c)
 	int err;
 
 	err = clk_prepare_enable(i2c->clk);
-	if (err) {
-		dev_err(i2c->dev, "failed to enable clock\n");
-		return err;
-	}
+	if (err)
+		return dev_err_probe(i2c->dev, err, "failed to enable clock\n");
 
 	err = clk_set_rate(i2c->clk, 20000000);
 	if (err) {
-		dev_err(i2c->dev, "failed to set clock = 20Mhz\n");
 		clk_disable_unprepare(i2c->clk);
-		return err;
+		return dev_err_probe(i2c->dev, err, "failed to set clock = 20Mhz\n");
 	}
 
 	writew(0, i2c->base + VIAI2C_REG_CR);
@@ -121,10 +118,9 @@ static int wmt_i2c_probe(struct platform_device *pdev)
 				"failed to request irq %i\n", i2c->irq);
 
 	i2c->clk = of_clk_get(np, 0);
-	if (IS_ERR(i2c->clk)) {
-		dev_err(&pdev->dev, "unable to request clock\n");
-		return PTR_ERR(i2c->clk);
-	}
+	if (IS_ERR(i2c->clk))
+		return dev_err_probe(&pdev->dev, PTR_ERR(i2c->clk),
+				     "unable to request clock\n");
 
 	err = of_property_read_u32(np, "clock-frequency", &clk_rate);
 	if (!err && clk_rate == I2C_MAX_FAST_MODE_FREQ)
@@ -139,10 +135,8 @@ static int wmt_i2c_probe(struct platform_device *pdev)
 	adap->dev.of_node = pdev->dev.of_node;
 
 	err = wmt_i2c_reset_hardware(i2c);
-	if (err) {
-		dev_err(&pdev->dev, "error initializing hardware\n");
+	if (err)
 		return err;
-	}
 
 	err = i2c_add_adapter(adap);
 	if (err)
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 148/247] i2c: viai2c-wmt: Fix clock leak in wmt_i2c_probe()
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (146 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 147/247] i2c: viai2c-wmt: Replace dev_err() with dev_err_probe() in probe function Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 149/247] futex: Fix mm reuse handling for FUT_OFF_MMSHARED Greg Kroah-Hartman
                   ` (106 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Wentao Liang, Andi Shyti,
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Wentao Liang <vulab@iscas.ac.cn>

[ Upstream commit aaabefc79b0ff0018e8e3832169bbe359d0551fc ]

In wmt_i2c_probe(), i2c->clk is acquired using of_clk_get(). If any
subsequent operation fails or when the module is unloaded, the clock
reference count is never decremented via clk_put(), leading to a
resource leak.

Switch to devm_clk_get() so that the clock is automatically managed
and released.

Fixes: 560746eb79d3 ("i2c: vt8500: Add support for I2C bus on Wondermedia SoCs")
Cc: stable@vger.kernel.org
Signed-off-by: Wentao Liang <vulab@iscas.ac.cn>
Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
Link: https://patch.msgid.link/20260916070631.1965713-1-vulab@iscas.ac.cn
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/i2c/busses/i2c-viai2c-wmt.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-viai2c-wmt.c b/drivers/i2c/busses/i2c-viai2c-wmt.c
index 133dc41fe387b..029473ef3fc50 100644
--- a/drivers/i2c/busses/i2c-viai2c-wmt.c
+++ b/drivers/i2c/busses/i2c-viai2c-wmt.c
@@ -117,7 +117,7 @@ static int wmt_i2c_probe(struct platform_device *pdev)
 		return dev_err_probe(&pdev->dev, err,
 				"failed to request irq %i\n", i2c->irq);
 
-	i2c->clk = of_clk_get(np, 0);
+	i2c->clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(i2c->clk))
 		return dev_err_probe(&pdev->dev, PTR_ERR(i2c->clk),
 				     "unable to request clock\n");
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 149/247] futex: Fix mm reuse handling for FUT_OFF_MMSHARED
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (147 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 148/247] i2c: viai2c-wmt: Fix clock leak in wmt_i2c_probe() Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 150/247] drm/i915/dmc: Harden DMC firmware payload parsing Greg Kroah-Hartman
                   ` (105 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Jann Horn, Peter Zijlstra (Intel),
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Jann Horn <jannh@google.com>

[ Upstream commit 3267512ad1c2cc0c7768c5b014dc2cceb398a801 ]

A FUT_OFF_MMSHARED futex is a shared futex that refers to an MM.
It is possible for a process to wait on a shared futex with a different MM
because a FUT_OFF_INODE waiter can be requeued onto a FUT_OFF_MMSHARED
futex by another process.
This can cause FUT_OFF_MMSHARED waiters on a freed MM to consume
wakeups intended for a newly allocated MM at the same address.

Fix it by keying FUT_OFF_MMSHARED using a unique 64-bit per-MM ID.
Leave private futexes as before to avoid influencing the performance of the
hotpath.

(Multi-threaded processes typically implicitly use FUT_OFF_MMSHARED by
setting clear_child_tid such that it points into anonymous memory, which
causes mm_release() in a multi-threaded mm to perform FUTEX_WAKE.)

Fixes: 222993395ed3 ("futex: Remove pointless mmgrap() + mmdrop()")
Closes: https://lore.kernel.org/r/CAG48ez0dLBpc3QtbAhMMVNHwHL94iHh2G+h-=BVFR4dDuzZr1g@mail.gmail.com/
Signed-off-by: Jann Horn <jannh@google.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://patch.msgid.link/20260929-futex-mmshared-fix-v1-1-262b1ffeb3d0@google.com
Cc: stable@vger.kernel.org
[ sashal: Replaced futex_mm_data infrastructure with a direct mm_struct field initialized in mm_init(). ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 include/linux/futex.h    | 14 +++++++-----
 include/linux/mm_types.h |  3 +++
 kernel/fork.c            |  3 +++
 kernel/futex/core.c      | 47 ++++++++++++++++++++--------------------
 4 files changed, 39 insertions(+), 28 deletions(-)

diff --git a/include/linux/futex.h b/include/linux/futex.h
index b70df27d7e85c..09f757f14d01f 100644
--- a/include/linux/futex.h
+++ b/include/linux/futex.h
@@ -23,26 +23,30 @@ struct task_struct;
  *  01 : Shared futex (PTHREAD_PROCESS_SHARED)
  *	mapped on a file (reference on the underlying inode)
  *  10 : Shared futex (PTHREAD_PROCESS_SHARED)
- *       (but private mapping on an mm, and reference taken on it)
+ *       (but private mapping on an mm)
 */
 
-#define FUT_OFF_INODE    1 /* We set bit 0 if key has a reference on inode */
-#define FUT_OFF_MMSHARED 2 /* We set bit 1 if key has a reference on mm */
+#define FUT_OFF_INODE    1 /* We set bit 0 if shared key identifies an inode */
+#define FUT_OFF_MMSHARED 2 /* We set bit 1 if shared key identifies an mm */
 
 union futex_key {
+	/* For FUT_OFF_INODE */
 	struct {
 		u64 i_seq;
 		unsigned long pgoff;
 		unsigned int offset;
 	} shared;
+
+	/* For FUT_OFF_MMSHARED or private */
 	struct {
 		union {
-			struct mm_struct *mm;
-			u64 __tmp;
+			struct mm_struct *mm; /* for private */
+			u64 mm_seq; /* for FUT_OFF_MMSHARED */
 		};
 		unsigned long address;
 		unsigned int offset;
 	} private;
+
 	struct {
 		u64 ptr;
 		unsigned long word;
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index f9a280a27e5ca..3deb3f1d5ad26 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -945,6 +945,9 @@ struct mm_struct {
 		 */
 		seqcount_t mm_lock_seq;
 #endif
+#ifdef CONFIG_FUTEX
+		atomic64_t futex_unique_id;
+#endif
 
 
 		unsigned long hiwater_rss; /* High-watermark of RSS usage */
diff --git a/kernel/fork.c b/kernel/fork.c
index c0ecb097aa1d2..81a8a7d3a5bd3 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1304,6 +1304,9 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p,
 #endif
 	mm_init_uprobes_state(mm);
 	hugetlb_count_init(mm);
+#ifdef CONFIG_FUTEX
+	atomic64_set(&mm->futex_unique_id, 0);
+#endif
 
 	if (current->mm) {
 		mm->flags = mmf_init_flags(current->mm->flags);
diff --git a/kernel/futex/core.c b/kernel/futex/core.c
index c37d2263c21fe..fa6ea7e235b13 100644
--- a/kernel/futex/core.c
+++ b/kernel/futex/core.c
@@ -153,39 +153,27 @@ futex_setup_timer(ktime_t *time, struct hrtimer_sleeper *timeout,
 }
 
 /*
- * Generate a machine wide unique identifier for this inode.
+ * Generate a machine wide unique identifier for this object (inode or mm).
  *
  * This relies on u64 not wrapping in the life-time of the machine; which with
  * 1ns resolution means almost 585 years.
- *
- * This further relies on the fact that a well formed program will not unmap
- * the file while it has a (shared) futex waiting on it. This mapping will have
- * a file reference which pins the mount and inode.
- *
- * If for some reason an inode gets evicted and read back in again, it will get
- * a new sequence number and will _NOT_ match, even though it is the exact same
- * file.
- *
- * It is important that futex_match() will never have a false-positive, esp.
- * for PI futexes that can mess up the state. The above argues that false-negatives
- * are only possible for malformed programs.
  */
-static u64 get_inode_sequence_number(struct inode *inode)
+static u64 get_object_id(atomic64_t *object_seq)
 {
-	static atomic64_t i_seq;
+	static atomic64_t last_assigned_seq;
 	u64 old;
 
-	/* Does the inode already have a sequence number? */
-	old = atomic64_read(&inode->i_sequence);
+	/* Does the object already have a sequence number? */
+	old = atomic64_read(object_seq);
 	if (likely(old))
 		return old;
 
 	for (;;) {
-		u64 new = atomic64_add_return(1, &i_seq);
+		u64 new = atomic64_add_return(1, &last_assigned_seq);
 		if (WARN_ON_ONCE(!new))
 			continue;
 
-		old = atomic64_cmpxchg_relaxed(&inode->i_sequence, 0, new);
+		old = atomic64_cmpxchg_relaxed(object_seq, 0, new);
 		if (old)
 			return old;
 		return new;
@@ -208,7 +196,7 @@ static u64 get_inode_sequence_number(struct inode *inode)
  *
  *   ( inode->i_sequence, page->index, offset_within_page )
  *
- * [ also see get_inode_sequence_number() ]
+ * [ also see get_object_id() ]
  *
  * For private mappings (or when !@fshared), the key is:
  *
@@ -362,8 +350,8 @@ int get_futex_key(u32 __user *uaddr, unsigned int flags, union futex_key *key,
 			goto out;
 		}
 
-		key->both.offset |= FUT_OFF_MMSHARED; /* ref taken on mm */
-		key->private.mm = mm;
+		key->both.offset |= FUT_OFF_MMSHARED;
+		key->private.mm_seq = get_object_id(&mm->futex_unique_id);
 		key->private.address = address;
 
 	} else {
@@ -398,7 +386,20 @@ int get_futex_key(u32 __user *uaddr, unsigned int flags, union futex_key *key,
 		}
 
 		key->both.offset |= FUT_OFF_INODE; /* inode-based key */
-		key->shared.i_seq = get_inode_sequence_number(inode);
+		/*
+		 * This relies on the fact that a well formed program will not unmap
+		 * the file while it has a (shared) futex waiting on it. This mapping will have
+		 * a file reference which pins the mount and inode.
+		 *
+		 * If for some reason an inode gets evicted and read back in again, it will get
+		 * a new sequence number and will _NOT_ match, even though it is the exact same
+		 * file.
+		 *
+		 * It is important that futex_match() will never have a false-positive, esp.
+		 * for PI futexes that can mess up the state. The above argues that false-negatives
+		 * are only possible for malformed programs.
+		 */
+		key->shared.i_seq = get_object_id(&inode->i_sequence);
 		key->shared.pgoff = folio->index + folio_page_idx(folio, page);
 		rcu_read_unlock();
 	}
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 150/247] drm/i915/dmc: Harden DMC firmware payload parsing
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (148 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 149/247] futex: Fix mm reuse handling for FUT_OFF_MMSHARED Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 151/247] tracing: Fix ignored return value of resize_buffer_duplicate_size() Greg Kroah-Hartman
                   ` (104 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Dibin Moolakadan Subrahmanian,
	Mitul Golani, Ankit Nautiyal, Joonas Lahtinen, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Dibin Moolakadan Subrahmanian <dibin.moolakadan.subrahmanian@intel.com>

[ Upstream commit 8bb1858db453cd4250e3b633f5d2d09206024ca6 ]

Validate the conversion of the DMC firmware size from dwords to bytes
using check_mul_overflow() before calculating the firmware payload size.

Reject zero-length payloads and zero MMIO counts in the DMC firmware
header so malformed firmware is caught early. Also set dmc_fw_size only
after the payload allocation succeeds.

Fixes: eb805623d8b1 ("drm/i915/skl: Add support to load SKL CSR firmware.")
Cc: stable@vger.kernel.org
Assisted-by: Claude-Code:Sonnet-5
Signed-off-by: Dibin Moolakadan Subrahmanian <dibin.moolakadan.subrahmanian@intel.com>
Reviewed-by: Mitul Golani<mitulkumar.ajitkumar.golani@intel.com>
Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
Link: https://patch.msgid.link/20260922133535.3180973-5-dibin.moolakadan.subrahmanian@intel.com
(cherry picked from commit efde6601a1f1daedfe3dcc2816c934ddb44e3eef)
Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
[ sashal: Changed logging arguments from `display->drm` to `&i915->drm`. ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/gpu/drm/i915/display/intel_dmc.c | 21 ++++++++++++++++-----
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c
index 7c756d5ba2a22..641dabf275e73 100644
--- a/drivers/gpu/drm/i915/display/intel_dmc.c
+++ b/drivers/gpu/drm/i915/display/intel_dmc.c
@@ -796,7 +796,7 @@ static u32 parse_dmc_fw_header(struct intel_dmc *dmc,
 	}
 
 	/* Cache the dmc header info. */
-	if (mmio_count > mmio_count_max) {
+	if (!mmio_count || mmio_count > mmio_count_max) {
 		drm_err(&i915->drm, "DMC firmware has wrong mmio count %u\n", mmio_count);
 		return 0;
 	}
@@ -819,13 +819,21 @@ static u32 parse_dmc_fw_header(struct intel_dmc *dmc,
 			    disable_dmc_evt(i915, dmc_id, dmc_info->mmioaddr[i],
 					    dmc_info->mmiodata[i]) ? " (disabling)" : "");
 	}
-	dmc_info->mmio_count = mmio_count;
-	dmc_info->start_mmioaddr = start_mmioaddr;
 
 	rem_size -= header_len_bytes;
 
 	/* fw_size is in dwords, so multiplied by 4 to convert into bytes. */
-	payload_size = dmc_header->fw_size * 4;
+	if (check_mul_overflow(dmc_header->fw_size, 4u, &payload_size)) {
+		drm_err(&i915->drm, "DMC fw_size too large (%u dwords)\n",
+			dmc_header->fw_size);
+		return 0;
+	}
+
+	if (!payload_size) {
+		drm_err(&i915->drm, "DMC firmware has empty payload\n");
+		return 0;
+	}
+
 	if (rem_size < payload_size)
 		goto error_truncated;
 
@@ -833,12 +841,15 @@ static u32 parse_dmc_fw_header(struct intel_dmc *dmc,
 		drm_err(&i915->drm, "DMC FW too big (%u bytes)\n", payload_size);
 		return 0;
 	}
-	dmc_info->dmc_fw_size = dmc_header->fw_size;
 
 	dmc_info->payload = kmalloc(payload_size, GFP_KERNEL);
 	if (!dmc_info->payload)
 		return 0;
 
+	dmc_info->mmio_count = mmio_count;
+	dmc_info->start_mmioaddr = start_mmioaddr;
+	dmc_info->dmc_fw_size = dmc_header->fw_size;
+
 	payload = (u8 *)(dmc_header) + header_len_bytes;
 	memcpy(dmc_info->payload, payload, payload_size);
 
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 151/247] tracing: Fix ignored return value of resize_buffer_duplicate_size()
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (149 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 150/247] drm/i915/dmc: Harden DMC firmware payload parsing Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 152/247] drm/amdgpu: free the userptr ranges when a CS fails after parser_bos Greg Kroah-Hartman
                   ` (103 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Dmitry Kandybka, Steven Rostedt,
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Dmitry Kandybka <d.kandybka@gmail.com>

[ Upstream commit 3110d09bb98e3ac66482a7b257548a1683ec6c1a ]

When tr->allocated_snapshot is true, resize_buffer_duplicate_size() is
called to update the snapshot buffer size. However, its return value was
not checked. In case of a failed resize this could lead next snapshot
being incomplete.

Add resize_buffer_duplicate_size() result check and return error if
resize fails.

Compile tested only.

Found by Linux Verification Center (linuxtesting.org) with SVACE.

Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20260928152634.4354-1-d.kandybka@gmail.com
Fixes: 180e4e390978 ("tracing: Add snapshot refcount")
Signed-off-by: Dmitry Kandybka <d.kandybka@gmail.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
[ sashal: Adapted the resize call to use max_buffer instead of snapshot_buffer. ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 kernel/trace/trace.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 7936e8cd7811e..2816708932d6a 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -7275,9 +7275,12 @@ tracing_snapshot_write(struct file *filp, const char __user *ubuf, size_t cnt,
 		if (iter->cpu_file != RING_BUFFER_ALL_CPUS)
 			return -EINVAL;
 #endif
-		if (tr->allocated_snapshot)
+		if (tr->allocated_snapshot) {
 			ret = resize_buffer_duplicate_size(&tr->max_buffer,
 					&tr->array_buffer, iter->cpu_file);
+			if (ret < 0)
+				return ret;
+		}
 
 		ret = tracing_arm_snapshot_locked(tr);
 		if (ret)
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 152/247] drm/amdgpu: free the userptr ranges when a CS fails after parser_bos
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (150 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 151/247] tracing: Fix ignored return value of resize_buffer_duplicate_size() Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 153/247] sched_ext: Fix stall when a task enqueued with SCX_ENQ_LAST lands back on its CPUs local DSQ Greg Kroah-Hartman
                   ` (102 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Alex Deucher, Jesse Zhang,
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Jesse Zhang <Jesse.Zhang@amd.com>

[ Upstream commit 1b4da805a0ba354a549ce07459c871c17dd94fe0 ]

amdgpu_cs_parser_bos() allocates an HMM range for every userptr entry of
the BO list and looks up the user pages. Those ranges are only freed when
amdgpu_cs_parser_bos() itself fails or when amdgpu_cs_submit() checks
them under the notifier lock. If amdgpu_cs_patch_jobs(),
amdgpu_cs_vm_handling(), amdgpu_cs_sync_rings() or the early part of
amdgpu_cs_submit() fails, nothing frees them: neither
amdgpu_cs_parser_fini() nor amdgpu_bo_list_free() touch e->range.

Each such CS then leaks the range, its hmm_pfns array (8 bytes per page
of the userptr BO) and the BO reference the range holds. An IB on a ring
that patches the CS in place (e.g. VCN) with an unmapped va_start fails
in amdgpu_cs_patch_ibs() and takes this path.

Free the ranges on those error paths. Ranges amdgpu_cs_submit() already
dropped are NULL, so freeing them again is a no-op.

Fixes: fec8fdb54e8f ("drm/amdgpu: fix userptr HMM range handling v2")
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Jesse Zhang <Jesse.Zhang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit c52a9542ed7cfd527feb938bd0accada2ac8d267)
Cc: stable@vger.kernel.org
[ sashal: Adapted cleanup to use amdgpu_ttm_tt_get_user_pages_done() in the existing error_backoff path. ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
index eb5f528459ecd..528f0aeac36c6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -1449,6 +1449,7 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser)
 int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
 {
 	struct amdgpu_device *adev = drm_to_adev(dev);
+	struct amdgpu_bo_list_entry *e;
 	struct amdgpu_cs_parser parser;
 	int r;
 
@@ -1503,6 +1504,11 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
 	return 0;
 
 error_backoff:
+	/* amdgpu_cs_submit() only drops the ranges once it got that far. */
+	amdgpu_bo_list_for_each_userptr_entry(e, parser.bo_list) {
+		amdgpu_ttm_tt_get_user_pages_done(e->bo->tbo.ttm, e->range);
+		e->range = NULL;
+	}
 	mutex_unlock(&parser.bo_list->bo_list_mutex);
 
 error_fini:
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 153/247] sched_ext: Fix stall when a task enqueued with SCX_ENQ_LAST lands back on its CPUs local DSQ
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (151 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 152/247] drm/amdgpu: free the userptr ranges when a CS fails after parser_bos Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 154/247] cifs: add revalidation on FSCTL failure in smb2_duplicate_extents() Greg Kroah-Hartman
                   ` (101 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Xiangyu Bu, Tejun Heo,
	Dan Schatzberg, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Tejun Heo <tj@kernel.org>

[ Upstream commit 7a9df76679633cf26e0fea882a684012c6ec245a ]

With SCX_OPS_ENQ_LAST, the last runnable task on a CPU is passed to
ops.enqueue() instead of being kept running. Exiting tasks without
SCX_OPS_ENQ_EXITING, migration disabled tasks without
SCX_OPS_ENQ_MIGRATION_DISABLED and tasks on an offline rq skip ops.enqueue()
and go straight to the local DSQ. This happens in put_prev_task_scx() after
the pick has settled on idle, so nothing reschedules the CPU, which idles
with the task queued until an unrelated wakeup lands on it or the watchdog
fires.

scx_mitosis, which sets SCX_OPS_ENQ_LAST without SCX_OPS_ENQ_EXITING, hit
this during mass cgroup teardown: exiting tasks stuck in exit_mmap() for
over 40 seconds.

A task put on the local DSQ runs, as anywhere else. If the SCX_ENQ_LAST
enqueue left the task on this CPU's local DSQ, set need_resched on the task
being switched in, as proxy_resched_idle() does. resched_curr() would flag
the task being put instead, and __schedule() clears that right after the
pick.

Fixes: f0e1a0643a59 ("sched_ext: Implement BPF extensible scheduler class")
Cc: stable@vger.kernel.org # v6.12+
Reported-by: Xiangyu Bu <xbu@meta.com>
Link: https://github.com/sched-ext/scx/pull/3870
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Dan Schatzberg <schatzberg.dan@gmail.com>
[ sashal: Relocated the hunks from separate source and header files into the monolithic sched_ext source file. ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 kernel/sched/ext.c | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c
index 876adf5568ed1..ded7a0dd2e533 100644
--- a/kernel/sched/ext.c
+++ b/kernel/sched/ext.c
@@ -730,8 +730,9 @@ enum scx_enq_flags {
 	 * %SCX_OPS_ENQ_LAST is specified, they're ops.enqueue()'d with the
 	 * %SCX_ENQ_LAST flag set.
 	 *
-	 * The BPF scheduler is responsible for triggering a follow-up
-	 * scheduling event. Otherwise, Execution may stall.
+	 * If the task is queued on the local DSQ of the CPU it was running on,
+	 * it continues to run. Otherwise, the CPU goes idle. A scheduler that
+	 * wants a full dispatch cycle on the CPU should kick it.
 	 */
 	SCX_ENQ_LAST		= 1LLU << 41,
 
@@ -3083,8 +3084,7 @@ static void put_prev_task_scx(struct rq *rq, struct task_struct *p,
 		/*
 		 * If @p is runnable but we're about to enter a lower
 		 * sched_class, %SCX_OPS_ENQ_LAST must be set. Tell
-		 * ops.enqueue() that @p is the only one available for this cpu,
-		 * which should trigger an explicit follow-up scheduling event.
+		 * ops.enqueue() that @p is the only one available for this cpu.
 		 *
 		 * Core scheduling can force this CPU idle while @p stays
 		 * runnable. @p's cookie then won't match the core's, so skip
@@ -3094,6 +3094,16 @@ static void put_prev_task_scx(struct rq *rq, struct task_struct *p,
 			WARN_ON_ONCE(sched_cpu_cookie_match(rq, p) &&
 				     !static_branch_unlikely(&scx_ops_enq_last));
 			do_enqueue_task(rq, p, SCX_ENQ_LAST, -1);
+
+			/*
+			 * A task put on the local DSQ runs, as anywhere else.
+			 * Here the insert can't reschedule on its own: the pick
+			 * has settled on @next and @p is still curr, so
+			 * resched_curr() would flag @p and __schedule() clears
+			 * that right after the pick. Flag @next instead.
+			 */
+			if (p->scx.dsq == &rq->scx.local_dsq)
+				set_tsk_need_resched(next);
 		} else {
 			do_enqueue_task(rq, p, 0, -1);
 		}
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 154/247] cifs: add revalidation on FSCTL failure in smb2_duplicate_extents()
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (152 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 153/247] sched_ext: Fix stall when a task enqueued with SCX_ENQ_LAST lands back on its CPUs local DSQ Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 155/247] xfs: dont hold buffer locks across sync transaction commit in xfs_sync_sb_buf Greg Kroah-Hartman
                   ` (100 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Frank Sorenson, Paulo Alcantara,
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Frank Sorenson <sorenson@redhat.com>

[ Upstream commit 53676a5e28231186c9f56d87b7998b640699bc15 ]

smb2_duplicate_extents() has no handling for
FSCTL_DUPLICATE_EXTENTS_TO_FILE failure: when the FSCTL fails, local
inode metadata may be stale from the pre-extension or from concurrent
remote writes, but is never refreshed.

Force revalidation on FSCTL failure and use i_size_read() for the
pre-extension check.

Fixes: cfc63fc8126a ("smb3: fix cached file size problems in duplicate extents (reflink)")
Cc: stable@vger.kernel.org
Signed-off-by: Frank Sorenson <sorenson@redhat.com>
Signed-off-by: Paulo Alcantara <pc@manguebit.org>
[ sashal: Used a standalone failure block because the upstream success branch is absent. ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 fs/smb/client/smb2ops.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
index 6ef0fcd9a05c2..7cd2e88a86b72 100644
--- a/fs/smb/client/smb2ops.c
+++ b/fs/smb/client/smb2ops.c
@@ -2292,7 +2292,7 @@ smb2_duplicate_extents(const unsigned int xid,
 			       trgtfile->fid.volatile_fid, tcon->tid,
 			       tcon->ses->Suid, src_off, dest_off, len);
 	inode = d_inode(trgtfile->dentry);
-	if (inode->i_size < dest_off + len) {
+	if (i_size_read(inode) < dest_off + len) {
 		rc = smb2_set_file_size(xid, tcon, trgtfile, dest_off + len, false);
 		if (rc)
 			goto duplicate_extents_out;
@@ -2318,6 +2318,11 @@ smb2_duplicate_extents(const unsigned int xid,
 	if (ret_data_len > 0)
 		cifs_dbg(FYI, "Non-zero response length in duplicate extents\n");
 
+	if (rc) {
+		CIFS_I(inode)->time = 0; /* force reval */
+		cifs_invalidate_cache(inode, 0);
+	}
+
 duplicate_extents_out:
 	if (rc)
 		trace_smb3_clone_err(xid, srcfile->fid.volatile_fid,
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 155/247] xfs: dont hold buffer locks across sync transaction commit in xfs_sync_sb_buf
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (153 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 154/247] cifs: add revalidation on FSCTL failure in smb2_duplicate_extents() Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 156/247] rose: clear stale N(R)/N(S) before (re)transmitting a data frame Greg Kroah-Hartman
                   ` (99 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, syzbot+837bcd54843dd6262f2f,
	Yun Zhou, Christoph Hellwig, Carlos Maiolino, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Yun Zhou <yun.zhou@windriver.com>

[ Upstream commit 41a28c865d1d5843f8cb9e0af17a8f4d9e2961ff ]

xfs_sync_sb_buf() holds sb/rtsb buffer locks across a synchronous
xfs_trans_commit(), which flushes the CIL push workqueue internally.
If shutdown occurs during the CIL push, xfs_buf_item_unpin() needs to
lock these buffers to fail them, causing a deadlock:

  setlabel:          holds buf lock -> flush_workqueue(xfs-cil)
  CIL push worker:   xfs_buf_item_unpin -> xfs_buf_lock(same buf)

Remove the xfs_trans_bhold() calls so that commit releases the buffer
locks normally.  After the sync commit, re-acquire the buffers via
mp->m_sb_bp / mp->m_rtsb_bp for the on-disk writeback.

Fixes: f7664b31975b ("xfs: implement online get/set fs label")
Reported-by: syzbot+837bcd54843dd6262f2f@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=837bcd54843dd6262f2f
Cc: stable@vger.kernel.org
Signed-off-by: Yun Zhou <yun.zhou@windriver.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
[ sashal: Omitted realtime-superblock changes because the corresponding support is absent. ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 fs/xfs/libxfs/xfs_sb.c | 17 +++++++----------
 1 file changed, 7 insertions(+), 10 deletions(-)

diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c
index eb46712e27d9f..de10b1adbf8a5 100644
--- a/fs/xfs/libxfs/xfs_sb.c
+++ b/fs/xfs/libxfs/xfs_sb.c
@@ -1186,26 +1186,23 @@ xfs_sync_sb_buf(
 	struct xfs_mount	*mp)
 {
 	struct xfs_trans	*tp;
-	struct xfs_buf		*bp;
 	int			error;
 
 	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_sb, 0, 0, 0, &tp);
 	if (error)
 		return error;
 
-	bp = xfs_trans_getsb(tp);
 	xfs_log_sb(tp);
-	xfs_trans_bhold(tp, bp);
 	xfs_trans_set_sync(tp);
 	error = xfs_trans_commit(tp);
 	if (error)
-		goto out;
-	/*
-	 * write out the sb buffer to get the changes to disk
-	 */
-	error = xfs_bwrite(bp);
-out:
-	xfs_buf_relse(bp);
+		return error;
+
+	/* Re-acquire and write the sb to disk. */
+	xfs_buf_lock(mp->m_sb_bp);
+	error = xfs_bwrite(mp->m_sb_bp);
+	xfs_buf_unlock(mp->m_sb_bp);
+
 	return error;
 }
 
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 156/247] rose: clear stale N(R)/N(S) before (re)transmitting a data frame
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (154 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 155/247] xfs: dont hold buffer locks across sync transaction commit in xfs_sync_sb_buf Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 157/247] netrom: linearize and validate lengths in nr_rx_frame() Greg Kroah-Hartman
                   ` (98 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Bernard Pidoux <bernard.f6bvp@gmail.com>

rose_kick() transmits a skb_clone() of each data frame and keeps the
original on ack_queue. The clone shares its data buffer with the
original, so the sequence numbers that rose_send_iframe() ORs into
byte 2 of the header are also left in the queued original.

After a RESET, rose_requeue_frames() puts those originals back on the
write queue and rose_kick() sends them again with vs/vr restarted at
zero. rose_send_iframe() only ORs the new values into byte 2, so the
retransmitted frame carries the bitwise OR of the old and new N(R) and
N(S). The peer rejects the invalid N(R) with a new RESET REQUEST, the
frames are requeued again, and the two nodes reset each other forever.

This was observed on a live FPAC network: a White Pages circuit between
two nodes looping on RESET REQUEST / RESET CONFIRMATION / DATA at about
2000 frames per second, with DATA frames resent as "R3 S7" right after
a reset instead of "R0 S0", until the application was restarted.

Clear everything but the M bit before setting the sequence numbers, as
x25_send_iframe() does for modulo 8 circuits.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
(cherry picked from commit b16b091aeb78faac22cf2b850246826d23f4a335)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/rose/rose_out.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/net/rose/rose_out.c b/net/rose/rose_out.c
index 9050e33c96042..6672fc65a7651 100644
--- a/net/rose/rose_out.c
+++ b/net/rose/rose_out.c
@@ -34,6 +34,7 @@ static void rose_send_iframe(struct sock *sk, struct sk_buff *skb)
 	if (skb == NULL)
 		return;
 
+	skb->data[2] &= ROSE_M_BIT;
 	skb->data[2] |= (rose->vr << 5) & 0xE0;
 	skb->data[2] |= (rose->vs << 1) & 0x0E;
 
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 157/247] netrom: linearize and validate lengths in nr_rx_frame()
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (155 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 156/247] rose: clear stale N(R)/N(S) before (re)transmitting a data frame Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 158/247] netrom: require full NET/ROM headers in nr_route_frame() Greg Kroah-Hartman
                   ` (97 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Eric Dumazet, Stanislav Fort,
	Bernard Pidoux, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Stanislav Fort <disclosure@aisle.com>

Linearize skb and add targeted length checks in nr_rx_frame() to
prevent out-of-bounds reads when processing malformed NET/ROM frames.

- Require skb to be linear and at least NR_NETWORK_LEN +
  NR_TRANSPORT_LEN (20 bytes) before reading network/transport fields.
- For the existing sockets path, ensure NR_CONNACK includes the window
  byte (>= 21 bytes), which nr_state1_machine() reads.
- For CONNREQ handling, ensure window (byte 20) and user address
  (bytes 21-27) are present (>= 28 bytes), and do so before
  nr_find_listener() so no listener reference can leak.
- Preserve existing BPQ extension handling:
  - NR_CONNACK len == 22 -> 1 extra byte (TTL)
  - NR_CONNREQ len == 37 -> 2 extra bytes (timeout)

nr_route_frame() only guarantees 15 bytes before handing a frame
addressed to a local node to nr_rx_frame(), so a short frame received
from any AX.25 neighbour is enough to trigger the over-read.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Suggested-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Stanislav Fort <disclosure@aisle.com>
[F6BVP: v4 never reached mainline (whitespace-damaged posting, subsystem
 removed in 7.1); rebased onto mod-orphan, added comments. Tested on a
 two-VM QEMU bench (6.12.94, mkiss link): an AX.25 peer sends CONNREQ
 frames truncated to 20 and 27 bytes; without this patch both are
 accepted as connections, the user callsign being read past the end of
 the frame; with it only the complete 35-byte CONNREQ is accepted.
 v2: apply the CONNACK length check to a plain CONNACK only, so that
 20-byte CONNACK|CHOKE refusals and resets are no longer dropped
 (reported by Sasha Levin). Same fix submitted to mod-orphan.]
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
(cherry picked from commit db51201afd46992c9206fa79878badb2236bb7d3)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/netrom/af_netrom.c | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index 6ee148f0e6d04..4dac5ee58adc9 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -885,6 +885,11 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev)
 	 *	skb->data points to the netrom frame start
 	 */
 
+	if (skb_linearize(skb))
+		return 0;
+	if (skb->len < NR_NETWORK_LEN + NR_TRANSPORT_LEN)
+		return 0;
+
 	src  = (ax25_address *)(skb->data + 0);
 	dest = (ax25_address *)(skb->data + 7);
 
@@ -927,6 +932,17 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev)
 	}
 
 	if (sk != NULL) {
+		/*
+		 * nr_state1_machine() reads the window size at byte 20, but
+		 * only for a plain CONNACK. A CONNACK with the choke flag set
+		 * is a refusal or a reset, sent as a 20-byte frame by
+		 * __nr_transmit_reply(), and must not be dropped here.
+		 */
+		if (frametype == NR_CONNACK && !flags &&
+		    skb->len < NR_NETWORK_LEN + NR_TRANSPORT_LEN + 1) {
+			sock_put(sk);
+			return 0;
+		}
 		bh_lock_sock(sk);
 		skb_reset_transport_header(skb);
 
@@ -961,10 +977,14 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev)
 		return 0;
 	}
 
-	sk = nr_find_listener(dest);
+	/* Need window (byte 20) and user address (bytes 21-27) */
+	if (skb->len < NR_NETWORK_LEN + NR_TRANSPORT_LEN + 1 + AX25_ADDR_LEN)
+		return 0;
 
 	user = (ax25_address *)(skb->data + 21);
 
+	sk = nr_find_listener(dest);
+
 	if (sk == NULL || sk_acceptq_is_full(sk) ||
 	    (make = nr_make_new(sk)) == NULL) {
 		nr_transmit_refusal(skb, 0);
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 158/247] netrom: require full NET/ROM headers in nr_route_frame()
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (156 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 157/247] netrom: linearize and validate lengths in nr_rx_frame() Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 159/247] net: netrom: validate source address in nr_find_socket() Greg Kroah-Hartman
                   ` (96 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

nr_route_frame() only checked that an incoming frame was long enough
for the two network layer addresses and the time-to-live byte, and did
so against skb->len without making sure the bytes were in the linear
part of the skb.

A valid NET/ROM network frame always carries the 5-byte transport
header as well, so anything shorter than NR_NETWORK_LEN +
NR_TRANSPORT_LEN (20 bytes) is malformed, whether it is for this node
or in transit. Use pskb_may_pull() for that length, as suggested in
review, so the header fields are also guaranteed to be linear before
they are read here or later in nr_rx_frame().

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
[F6BVP: taken from the nr_route.c part of Greg's "netrom: do some
basic forms of validation on incoming frames"; the nr_rx_frame() part
is handled separately. Switched from a skb->len test to
pskb_may_pull() following Simon Horman's review.]
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
(cherry picked from commit dc06212ff6bb781fad2b5082e3ecb7cc93336da0)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/netrom/nr_route.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c
index 9cc29ae85b06f..7f55030e4b166 100644
--- a/net/netrom/nr_route.c
+++ b/net/netrom/nr_route.c
@@ -755,10 +755,11 @@ int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25)
 	struct sk_buff *nskb, *oskb;
 
 	/*
-	 * Reject malformed packets early. Check that it contains at least 2
-	 * addresses and 1 byte more for Time-To-Live
+	 * Reject malformed packets early. Check that it contains at least
+	 * the network and transport headers (20 bytes), and that they are
+	 * in the linear part of the skb.
 	 */
-	if (skb->len < 2 * sizeof(ax25_address) + 1)
+	if (!pskb_may_pull(skb, NR_NETWORK_LEN + NR_TRANSPORT_LEN))
 		return 0;
 
 	nr_src  = (ax25_address *)(skb->data + 0);
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 159/247] net: netrom: validate source address in nr_find_socket()
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (157 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 158/247] netrom: require full NET/ROM headers in nr_route_frame() Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 160/247] netrom: bound fragment reassembly in nr_queue_rx_frame() Greg Kroah-Hartman
                   ` (95 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Mashiro Chen, Bernard Pidoux,
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Mashiro Chen <mashiro.chen@mailbox.org>

nr_find_socket() dispatches incoming NR_INFO frames into a connected
socket by matching the frame's circuit index/id pair (bytes[15-16])
against the socket's my_index/my_id.  It performs no validation of
the frame's source callsign against the socket's dest_addr.

This means any node on the network can craft an NR_INFO frame with
a guessed or brute-forced circuit index/id pair and have it accepted
into an arbitrary STATE_3 connection as if it came from the legitimate
peer.  Circuit IDs are assigned sequentially starting at (1,1), making
them predictable in practice.

Combined with other receive path bugs, this lets a third party feed
frames into a circuit it does not own. nr_find_peer() already checks
the source address for CONNREQ; do the same for the other frame types.

Fix by adding a source address parameter to nr_find_socket() and
requiring it to match the socket's recorded dest_addr for all
frame-dispatch lookups.  The internal nr_find_next_circuit() caller,
which only checks for circuit ID availability, passes NULL to skip
the source check.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Signed-off-by: Mashiro Chen <mashiro.chen@mailbox.org>
[F6BVP: rebased on mod-orphan; dropped the reference to an unassigned
CVE from the changelog. Checked that every caller other than
nr_find_next_circuit() is in nr_rx_frame() for non-CONNREQ frames,
whose network source is the remote node recorded in dest_addr.]
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
(cherry picked from commit 70bf32b0eda85781a416cb929b7c6b4761abd2a8)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/netrom/af_netrom.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index 4dac5ee58adc9..fc7bd19ad0e37 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -162,7 +162,8 @@ static struct sock *nr_find_listener(ax25_address *addr)
 /*
  *	Find a connected NET/ROM socket given my circuit IDs.
  */
-static struct sock *nr_find_socket(unsigned char index, unsigned char id)
+static struct sock *nr_find_socket(unsigned char index, unsigned char id,
+				   const ax25_address *src)
 {
 	struct sock *s;
 
@@ -170,7 +171,8 @@ static struct sock *nr_find_socket(unsigned char index, unsigned char id)
 	sk_for_each(s, &nr_list) {
 		struct nr_sock *nr = nr_sk(s);
 
-		if (nr->my_index == index && nr->my_id == id) {
+		if (nr->my_index == index && nr->my_id == id &&
+		    (!src || !ax25cmp(&nr->dest_addr, src))) {
 			sock_hold(s);
 			goto found;
 		}
@@ -219,7 +221,8 @@ static unsigned short nr_find_next_circuit(void)
 		j = id % 256;
 
 		if (i != 0 && j != 0) {
-			if ((sk=nr_find_socket(i, j)) == NULL)
+			sk = nr_find_socket(i, j, NULL);
+			if (!sk)
 				break;
 			sock_put(sk);
 		}
@@ -928,7 +931,7 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev)
 		if (frametype == NR_CONNREQ)
 			sk = nr_find_peer(circuit_index, circuit_id, src);
 		else
-			sk = nr_find_socket(circuit_index, circuit_id);
+			sk = nr_find_socket(circuit_index, circuit_id, src);
 	}
 
 	if (sk != NULL) {
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 160/247] netrom: bound fragment reassembly in nr_queue_rx_frame()
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (158 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 159/247] net: netrom: validate source address in nr_find_socket() Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 161/247] ax25: fix OOB read after address header strip in ax25_rcv() Greg Kroah-Hartman
                   ` (94 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Mashiro Chen, Bernard Pidoux,
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Bernard Pidoux <bernard.f6bvp@gmail.com>

nr_sock.fraglen is an unsigned short, but nr_sendmsg() accepts messages
of up to 65536 bytes, which nr_output() then splits into NR_INFO frames
with the MORE flag. Reassembling such a message on the receiving side
makes fraglen wrap to 0, so alloc_skb() returns a buffer far smaller
than the data copied into it just after. The same happens with any
stream of MORE fragments that adds up to more than 65535 bytes.

Mashiro Chen proposed rejecting fragments once the total would exceed
USHRT_MAX by returning 1 to the caller. Review pointed out that this
return value makes nr_state3_machine() put the frame back on the
resequencing queue after nr_queue_rx_frame() has already pulled its
headers, and that the limit would reject a legitimate 65536-byte
message.

Instead:
- make fraglen an unsigned int, so a full 64 KiB message fits;
- when a message would grow beyond 65536 bytes, drop what has been
  gathered so far, consume the frame and return 0, so the caller does
  not retry it;
- discard the remaining fragments of that message up to its last
  fragment, using a new NR_COND_FRAG_DISCARD condition bit, rather
  than delivering its tail as a separate message.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Reported-by: Mashiro Chen <mashiro.chen@mailbox.org>
Closes: https://patchwork.kernel.org/project/netdevbpf/patch/20260407171600.102988-2-mashiro.chen@mailbox.org/
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
(cherry picked from commit 6ad8be739b22495d6edc3f6d7b916098ceb3fdf0)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 include/net/netrom.h |  3 ++-
 net/netrom/nr_in.c   | 26 ++++++++++++++++++++++++++
 2 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/include/net/netrom.h b/include/net/netrom.h
index f0565a5987d1b..30ecf812b4ab4 100644
--- a/include/net/netrom.h
+++ b/include/net/netrom.h
@@ -46,6 +46,7 @@ enum {
 #define	NR_COND_REJECT			0x02
 #define	NR_COND_PEER_RX_BUSY		0x04
 #define	NR_COND_OWN_RX_BUSY		0x08
+#define	NR_COND_FRAG_DISCARD		0x10
 
 #define NR_DEFAULT_T1			120000		/* Outstanding frames - 120 seconds */
 #define NR_DEFAULT_T2			5000		/* Response delay     - 5 seconds */
@@ -74,7 +75,7 @@ struct nr_sock {
 	unsigned short		vs, vr, va, vl;
 	unsigned char		n2, n2count;
 	unsigned long		t1, t2, t4, idle;
-	unsigned short		fraglen;
+	unsigned int		fraglen;
 	struct timer_list	t1timer;
 	struct timer_list	t2timer;
 	struct timer_list	t4timer;
diff --git a/net/netrom/nr_in.c b/net/netrom/nr_in.c
index 97944db6b5ac6..b90a47dcf165e 100644
--- a/net/netrom/nr_in.c
+++ b/net/netrom/nr_in.c
@@ -26,6 +26,9 @@
 #include <linux/interrupt.h>
 #include <net/netrom.h>
 
+/* nr_sendmsg() never sends more than this in one message */
+#define NR_MAX_REASM_LEN	65536
+
 static int nr_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more)
 {
 	struct sk_buff *skbo, *skbn = skb;
@@ -35,6 +38,29 @@ static int nr_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more)
 
 	nr_start_idletimer(sk);
 
+	/* Rest of a message already found to be too long: drop it */
+	if (nr->condition & NR_COND_FRAG_DISCARD) {
+		if (!more)
+			nr->condition &= ~NR_COND_FRAG_DISCARD;
+		kfree_skb(skb);
+		return 0;
+	}
+
+	/*
+	 * Give up on a message that would grow beyond what a peer may
+	 * send. The frame is consumed rather than handed back to the
+	 * caller, which would queue it again after skb_pull().
+	 */
+	if ((more || nr->fraglen > 0) &&
+	    nr->fraglen + skb->len > NR_MAX_REASM_LEN) {
+		skb_queue_purge(&nr->frag_queue);
+		nr->fraglen = 0;
+		if (more)
+			nr->condition |= NR_COND_FRAG_DISCARD;
+		kfree_skb(skb);
+		return 0;
+	}
+
 	if (more) {
 		nr->fraglen += skb->len;
 		skb_queue_tail(&nr->frag_queue, skb);
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 161/247] ax25: fix OOB read after address header strip in ax25_rcv()
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (159 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 160/247] netrom: bound fragment reassembly in nr_queue_rx_frame() Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 162/247] ax25: check frame length in ax25_decode() and ax25_rx_iframe() Greg Kroah-Hartman
                   ` (93 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Ashutosh Desai, Bernard Pidoux,
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Ashutosh Desai <ashutoshdesai993@gmail.com>

A crafted AX.25 frame with a valid address header but no control byte
causes skb->len to reach zero after skb_pull() strips the header.
The subsequent reads of skb->data[0] (control) and skb->data[1] (PID)
are then out of bounds.

Linearize the skb after confirming the device is an AX.25 interface.
Guard with skb->len < 1 after the pull - one byte suffices for LAPB
control frames which have no PID byte. Add a separate skb->len < 2
check inside the UI branch before accessing the PID byte.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Signed-off-by: Ashutosh Desai <ashutoshdesai993@gmail.com>
[F6BVP: v5 as posted on netdev; the author withdrew it only because the
subsystem was being removed from the kernel that day. Applied unchanged.]
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
(cherry picked from commit e653f27001ca2a31a445ee20d9f90be65b85d7e3)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/ax25/ax25_in.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/net/ax25/ax25_in.c b/net/ax25/ax25_in.c
index f2d66af863595..f105e638611fa 100644
--- a/net/ax25/ax25_in.c
+++ b/net/ax25/ax25_in.c
@@ -199,6 +199,9 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev,
 	if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL)
 		goto free;
 
+	if (skb_linearize(skb))
+		goto free;
+
 	/*
 	 *	Parse the address header.
 	 */
@@ -217,6 +220,9 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev,
 	 */
 	skb_pull(skb, ax25_addr_size(&dp));
 
+	if (skb->len < 1)
+		goto free;
+
 	/* For our port addresses ? */
 	if (ax25cmp(&dest, dev_addr) == 0 && dp.lastrepeat + 1 == dp.ndigi)
 		mine = 1;
@@ -227,6 +233,9 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev,
 
 	/* UI frame - bypass LAPB processing */
 	if ((*skb->data & ~0x10) == AX25_UI && dp.lastrepeat + 1 == dp.ndigi) {
+		if (skb->len < 2)
+			goto free;
+
 		skb_set_transport_header(skb, 2); /* skip control and pid */
 
 		ax25_send_to_raw(&dest, skb, skb->data[1]);
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 162/247] ax25: check frame length in ax25_decode() and ax25_rx_iframe()
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (160 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 161/247] ax25: fix OOB read after address header strip in ax25_rcv() Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 163/247] net: ax25: fix integer overflow in ax25_rx_fragment() Greg Kroah-Hartman
                   ` (92 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Bernard Pidoux <bernard.f6bvp@gmail.com>

Two more reads on the receive path assume bytes that a short frame
does not have:

- On a connection set up with SABME (modulo 128), ax25_decode() reads
  a two-byte control field for I and S frames (frame[1]) without
  checking that the second byte is there.
- ax25_rx_iframe() reads the PID byte of an I frame without checking
  that anything is left after the control field, so an I frame made of
  its control field alone is dispatched on a byte past its end. The
  same function also receives reassembled segments.

Return AX25_ILLEGAL from ax25_decode() when the control field is
incomplete, which the state machines already handle as a malformed
frame, and drop an I frame that has no PID byte. The first check in
ax25_decode() also covers an empty frame on its own, independently of
the length check proposed for ax25_rcv().

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
(cherry picked from commit 5b010290c0e627fd09b92eb8d690f0726d7cfe7c)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/ax25/ax25_in.c   | 4 ++++
 net/ax25/ax25_subr.c | 7 +++++++
 2 files changed, 11 insertions(+)

diff --git a/net/ax25/ax25_in.c b/net/ax25/ax25_in.c
index f105e638611fa..217f9a9b07631 100644
--- a/net/ax25/ax25_in.c
+++ b/net/ax25/ax25_in.c
@@ -104,6 +104,10 @@ int ax25_rx_iframe(ax25_cb *ax25, struct sk_buff *skb)
 
 	if (skb == NULL) return 0;
 
+	/* An I frame must at least carry its PID byte */
+	if (skb->len < 1)
+		return 0;
+
 	ax25_start_idletimer(ax25);
 
 	pid = *skb->data;
diff --git a/net/ax25/ax25_subr.c b/net/ax25/ax25_subr.c
index 9ff98f46dc6be..d0719267e5484 100644
--- a/net/ax25/ax25_subr.c
+++ b/net/ax25/ax25_subr.c
@@ -102,6 +102,9 @@ int ax25_decode(ax25_cb *ax25, struct sk_buff *skb, int *ns, int *nr, int *pf)
 	frame = skb->data;
 	*ns = *nr = *pf = 0;
 
+	if (skb->len < 1)
+		return frametype;
+
 	if (ax25->modulus == AX25_MODULUS) {
 		if ((frame[0] & AX25_S) == 0) {
 			frametype = AX25_I;			/* I frame - carries NR/NS/PF */
@@ -118,6 +121,10 @@ int ax25_decode(ax25_cb *ax25, struct sk_buff *skb, int *ns, int *nr, int *pf)
 		}
 		skb_pull(skb, 1);
 	} else {
+		/* I and S frames carry a two-byte control field here */
+		if ((frame[0] & AX25_U) != 3 && skb->len < 2)
+			return frametype;
+
 		if ((frame[0] & AX25_S) == 0) {
 			frametype = AX25_I;			/* I frame - carries NR/NS/PF */
 			*ns = (frame[0] >> 1) & 0x7F;
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 163/247] net: ax25: fix integer overflow in ax25_rx_fragment()
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (161 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 162/247] ax25: check frame length in ax25_decode() and ax25_rx_iframe() Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 164/247] netrom: use a single lock for the node and neighbour lists Greg Kroah-Hartman
                   ` (91 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Mashiro Chen, Bernard Pidoux,
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Mashiro Chen <mashiro.chen@mailbox.org>

ax25_rx_fragment() accumulates fragment lengths into ax25_cb->fraglen,
which is an unsigned short. When the total exceeds 65535, fraglen wraps
around to a small value. The subsequent alloc_skb(fraglen) allocates a
too-small buffer, and skb_put() in the copy loop triggers skb_over_panic().

Add pskb_may_pull(skb, 1) at function entry to ensure the segmentation
header byte is in the linear data area before dereferencing skb->data.
This also rejects zero-length skbs, which the original code did not
check for.

Two issues in the overflow error path are also fixed:
First, the current skb, after skb_pull(skb, 1), is neither enqueued
nor freed before returning 1, leaking it. Add kfree_skb(skb) before
the return.
Second, ax25->fraglen is not reset after skb_queue_purge(). Add
ax25->fraglen = 0 to restore a consistent state.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Mashiro Chen <mashiro.chen@mailbox.org>
[F6BVP: v4 as posted on netdev; it was set aside only because the
subsystem was being removed from the kernel. Applied unchanged.]
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
(cherry picked from commit 0674e0f082be20adb8e7eb03718d85e71d8b05de)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/ax25/ax25_in.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/net/ax25/ax25_in.c b/net/ax25/ax25_in.c
index 217f9a9b07631..18e15c3c26e46 100644
--- a/net/ax25/ax25_in.c
+++ b/net/ax25/ax25_in.c
@@ -35,12 +35,22 @@ static int ax25_rx_fragment(ax25_cb *ax25, struct sk_buff *skb)
 {
 	struct sk_buff *skbn, *skbo;
 
+	if (!pskb_may_pull(skb, 1))
+		return 0;
+
 	if (ax25->fragno != 0) {
 		if (!(*skb->data & AX25_SEG_FIRST)) {
 			if ((ax25->fragno - 1) == (*skb->data & AX25_SEG_REM)) {
 				/* Enqueue fragment */
 				ax25->fragno = *skb->data & AX25_SEG_REM;
 				skb_pull(skb, 1);	/* skip fragno */
+				if (ax25->fraglen + skb->len > USHRT_MAX) {
+					kfree_skb(skb);
+					skb_queue_purge(&ax25->frag_queue);
+					ax25->fragno = 0;
+					ax25->fraglen = 0;
+					return 1;
+				}
 				ax25->fraglen += skb->len;
 				skb_queue_tail(&ax25->frag_queue, skb);
 
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 164/247] netrom: use a single lock for the node and neighbour lists
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (162 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 163/247] net: ax25: fix integer overflow in ax25_rx_fragment() Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 165/247] netrom: look up and update routes in one critical section Greg Kroah-Hartman
                   ` (90 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Jakub Kicinski, Bernard Pidoux,
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Bernard Pidoux <bernard.f6bvp@gmail.com>

NET/ROM routing uses three kinds of locks: nr_node_list_lock,
nr_neigh_list_lock and a lock in every nr_node. They are taken in
opposite orders on different paths:

- nr_del_node() and nr_dec_obs() take the node list lock, then a node
  lock, then the neighbour list lock (through nr_remove_neigh());
- nr_add_node(), called for every frame received from a neighbour,
  holds a node lock and takes the neighbour list lock;
- nr_rt_device_down() takes the neighbour list lock, then the node
  list lock, then each node lock.

Taking an interface down while routes are being changed or frames are
coming in can therefore deadlock, which is what the open syzbot
reports against nr_del_node(), nr_remove_neigh() and
nr_rt_device_down() show. Fixing the order case by case was tried
several times and never covered every combination.

As suggested by Jakub, replace all three with one nr_route_lock that
covers both lists and the routes of every node. The per-node lock goes
away: with the lists and routes[] under the same lock it no longer
protects anything, and routing tables are small and change rarely.
nr_remove_neigh() gets a variant for callers that already hold the
lock. Node refcounting is unchanged apart from the hold/put pair that
nr_node_lock()/nr_node_unlock() used to add around each critical
section.

nr_route_frame() still calls ax25_send_frame() with the lock held, as
it did under the node lock, so the lock is documented as never to be
taken with an AX.25 list lock held; nr_link_failed() is called from
AX.25 with only linkfail_lock held.

No change in behaviour otherwise; the other issues found on the way
(unlocked updates of nr_neigh->ax25 and failed, duplicate entries from
concurrent nr_add_node(), a reference leak in nr_rt_device_down()) are
left for separate patches.

Link: https://patchwork.kernel.org/project/netdevbpf/patch/20260406114904.89088-1-mashiro.chen@mailbox.org/
Suggested-by: Jakub Kicinski <kuba@kernel.org>
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
(cherry picked from commit 602c964d5e3d006cbd6e514aa971c5ab7257d66a)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 include/net/netrom.h  |  15 -----
 net/netrom/nr_route.c | 133 +++++++++++++++++++-----------------------
 2 files changed, 59 insertions(+), 89 deletions(-)

diff --git a/include/net/netrom.h b/include/net/netrom.h
index 30ecf812b4ab4..2b4685d52bd81 100644
--- a/include/net/netrom.h
+++ b/include/net/netrom.h
@@ -115,7 +115,6 @@ struct nr_node {
 	unsigned char		count;
 	struct nr_route		routes[3];
 	refcount_t		refcount;
-	spinlock_t		node_lock;
 };
 
 /*********************************************************************
@@ -145,20 +144,6 @@ static __inline__ void nr_neigh_put(struct nr_neigh *nr_neigh)
 	}
 }
 
-/* nr_node_lock and nr_node_unlock also hold/put the node's refcounter.
- */
-static __inline__ void nr_node_lock(struct nr_node *nr_node)
-{
-	nr_node_hold(nr_node);
-	spin_lock_bh(&nr_node->node_lock);
-}
-
-static __inline__ void nr_node_unlock(struct nr_node *nr_node)
-{
-	spin_unlock_bh(&nr_node->node_lock);
-	nr_node_put(nr_node);
-}
-
 #define nr_neigh_for_each(__nr_neigh, list) \
 	hlist_for_each_entry(__nr_neigh, list, neigh_node)
 
diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c
index 7f55030e4b166..e3effc85d3106 100644
--- a/net/netrom/nr_route.c
+++ b/net/netrom/nr_route.c
@@ -36,24 +36,30 @@
 
 static unsigned int nr_neigh_no = 1;
 
+/*
+ * nr_route_lock protects both lists and the routing data hanging off them:
+ * which, count and routes[] of every node. It is taken with bottom halves
+ * disabled, is never nested with itself, and may be held while calling into
+ * AX.25 (nr_route_frame() -> ax25_send_frame()), so it must never be taken
+ * with an AX.25 list lock held.
+ */
+static DEFINE_SPINLOCK(nr_route_lock);
 static HLIST_HEAD(nr_node_list);
-static DEFINE_SPINLOCK(nr_node_list_lock);
 static HLIST_HEAD(nr_neigh_list);
-static DEFINE_SPINLOCK(nr_neigh_list_lock);
 
 static struct nr_node *nr_node_get(ax25_address *callsign)
 {
 	struct nr_node *found = NULL;
 	struct nr_node *nr_node;
 
-	spin_lock_bh(&nr_node_list_lock);
+	spin_lock_bh(&nr_route_lock);
 	nr_node_for_each(nr_node, &nr_node_list)
 		if (ax25cmp(callsign, &nr_node->callsign) == 0) {
 			nr_node_hold(nr_node);
 			found = nr_node;
 			break;
 		}
-	spin_unlock_bh(&nr_node_list_lock);
+	spin_unlock_bh(&nr_route_lock);
 	return found;
 }
 
@@ -63,7 +69,7 @@ static struct nr_neigh *nr_neigh_get_dev(ax25_address *callsign,
 	struct nr_neigh *found = NULL;
 	struct nr_neigh *nr_neigh;
 
-	spin_lock_bh(&nr_neigh_list_lock);
+	spin_lock_bh(&nr_route_lock);
 	nr_neigh_for_each(nr_neigh, &nr_neigh_list)
 		if (ax25cmp(callsign, &nr_neigh->callsign) == 0 &&
 		    nr_neigh->dev == dev) {
@@ -71,11 +77,11 @@ static struct nr_neigh *nr_neigh_get_dev(ax25_address *callsign,
 			found = nr_neigh;
 			break;
 		}
-	spin_unlock_bh(&nr_neigh_list_lock);
+	spin_unlock_bh(&nr_route_lock);
 	return found;
 }
 
-static void nr_remove_neigh(struct nr_neigh *);
+static void nr_remove_neigh_locked(struct nr_neigh *nr_neigh);
 
 /*      re-sort the routes in quality order.    */
 static void re_sort_routes(struct nr_node *nr_node, int x, int y)
@@ -121,16 +127,14 @@ static int __must_check nr_add_node(ax25_address *nr, const char *mnemonic,
 	if (nr_neigh != NULL && nr_neigh->failed != 0 && quality == 0) {
 		struct nr_node *nr_nodet;
 
-		spin_lock_bh(&nr_node_list_lock);
+		spin_lock_bh(&nr_route_lock);
 		nr_node_for_each(nr_nodet, &nr_node_list) {
-			nr_node_lock(nr_nodet);
 			for (i = 0; i < nr_nodet->count; i++)
 				if (nr_nodet->routes[i].neighbour == nr_neigh)
 					if (i < nr_nodet->which)
 						nr_nodet->which = i;
-			nr_node_unlock(nr_nodet);
 		}
-		spin_unlock_bh(&nr_node_list_lock);
+		spin_unlock_bh(&nr_route_lock);
 	}
 
 	if (nr_neigh != NULL)
@@ -172,10 +176,10 @@ static int __must_check nr_add_node(ax25_address *nr, const char *mnemonic,
 			}
 		}
 
-		spin_lock_bh(&nr_neigh_list_lock);
+		spin_lock_bh(&nr_route_lock);
 		hlist_add_head(&nr_neigh->neigh_node, &nr_neigh_list);
 		nr_neigh_hold(nr_neigh);
-		spin_unlock_bh(&nr_neigh_list_lock);
+		spin_unlock_bh(&nr_route_lock);
 	}
 
 	if (quality != 0 && ax25cmp(nr, ax25) == 0 && !nr_neigh->locked)
@@ -194,7 +198,6 @@ static int __must_check nr_add_node(ax25_address *nr, const char *mnemonic,
 		nr_node->which = 0;
 		nr_node->count = 1;
 		refcount_set(&nr_node->refcount, 1);
-		spin_lock_init(&nr_node->node_lock);
 
 		nr_node->routes[0].quality   = quality;
 		nr_node->routes[0].obs_count = obs_count;
@@ -203,15 +206,15 @@ static int __must_check nr_add_node(ax25_address *nr, const char *mnemonic,
 		nr_neigh_hold(nr_neigh);
 		nr_neigh->count++;
 
-		spin_lock_bh(&nr_node_list_lock);
+		spin_lock_bh(&nr_route_lock);
 		hlist_add_head(&nr_node->node_node, &nr_node_list);
 		/* refcount initialized at 1 */
-		spin_unlock_bh(&nr_node_list_lock);
+		spin_unlock_bh(&nr_route_lock);
 
 		nr_neigh_put(nr_neigh);
 		return 0;
 	}
-	nr_node_lock(nr_node);
+	spin_lock_bh(&nr_route_lock);
 
 	if (quality != 0)
 		strscpy(nr_node->mnemonic, mnemonic);
@@ -246,7 +249,7 @@ static int __must_check nr_add_node(ax25_address *nr, const char *mnemonic,
 				nr_neigh_put(nr_node->routes[2].neighbour);
 
 				if (nr_node->routes[2].neighbour->count == 0 && !nr_node->routes[2].neighbour->locked)
-					nr_remove_neigh(nr_node->routes[2].neighbour);
+					nr_remove_neigh_locked(nr_node->routes[2].neighbour);
 
 				nr_node->routes[2].quality   = quality;
 				nr_node->routes[2].obs_count = obs_count;
@@ -280,33 +283,32 @@ static int __must_check nr_add_node(ax25_address *nr, const char *mnemonic,
 	}
 
 	nr_neigh_put(nr_neigh);
-	nr_node_unlock(nr_node);
+	spin_unlock_bh(&nr_route_lock);
 	nr_node_put(nr_node);
 	return 0;
 }
 
 static void nr_remove_node_locked(struct nr_node *nr_node)
 {
-	lockdep_assert_held(&nr_node_list_lock);
+	lockdep_assert_held(&nr_route_lock);
 
 	hlist_del_init(&nr_node->node_node);
 	nr_node_put(nr_node);
 }
 
-static inline void __nr_remove_neigh(struct nr_neigh *nr_neigh)
+static void nr_remove_neigh_locked(struct nr_neigh *nr_neigh)
 {
+	lockdep_assert_held(&nr_route_lock);
+
 	hlist_del_init(&nr_neigh->neigh_node);
 	nr_neigh_put(nr_neigh);
 }
 
-#define nr_remove_neigh_locked(__neigh) \
-	__nr_remove_neigh(__neigh)
-
 static void nr_remove_neigh(struct nr_neigh *nr_neigh)
 {
-	spin_lock_bh(&nr_neigh_list_lock);
-	__nr_remove_neigh(nr_neigh);
-	spin_unlock_bh(&nr_neigh_list_lock);
+	spin_lock_bh(&nr_route_lock);
+	nr_remove_neigh_locked(nr_neigh);
+	spin_unlock_bh(&nr_route_lock);
 }
 
 /*
@@ -331,15 +333,14 @@ static int nr_del_node(ax25_address *callsign, ax25_address *neighbour, struct n
 		return -EINVAL;
 	}
 
-	spin_lock_bh(&nr_node_list_lock);
-	nr_node_lock(nr_node);
+	spin_lock_bh(&nr_route_lock);
 	for (i = 0; i < nr_node->count; i++) {
 		if (nr_node->routes[i].neighbour == nr_neigh) {
 			nr_neigh->count--;
 			nr_neigh_put(nr_neigh);
 
 			if (nr_neigh->count == 0 && !nr_neigh->locked)
-				nr_remove_neigh(nr_neigh);
+				nr_remove_neigh_locked(nr_neigh);
 			nr_neigh_put(nr_neigh);
 
 			nr_node->count--;
@@ -359,15 +360,13 @@ static int nr_del_node(ax25_address *callsign, ax25_address *neighbour, struct n
 				}
 				nr_node_put(nr_node);
 			}
-			nr_node_unlock(nr_node);
-			spin_unlock_bh(&nr_node_list_lock);
+			spin_unlock_bh(&nr_route_lock);
 
 			return 0;
 		}
 	}
 	nr_neigh_put(nr_neigh);
-	nr_node_unlock(nr_node);
-	spin_unlock_bh(&nr_node_list_lock);
+	spin_unlock_bh(&nr_route_lock);
 	nr_node_put(nr_node);
 
 	return -EINVAL;
@@ -412,10 +411,10 @@ static int __must_check nr_add_neigh(ax25_address *callsign,
 		}
 	}
 
-	spin_lock_bh(&nr_neigh_list_lock);
+	spin_lock_bh(&nr_route_lock);
 	hlist_add_head(&nr_neigh->neigh_node, &nr_neigh_list);
 	/* refcount is initialized at 1 */
-	spin_unlock_bh(&nr_neigh_list_lock);
+	spin_unlock_bh(&nr_route_lock);
 
 	return 0;
 }
@@ -454,9 +453,8 @@ static int nr_dec_obs(void)
 	struct hlist_node *nodet;
 	int i;
 
-	spin_lock_bh(&nr_node_list_lock);
+	spin_lock_bh(&nr_route_lock);
 	nr_node_for_each_safe(s, nodet, &nr_node_list) {
-		nr_node_lock(s);
 		for (i = 0; i < s->count; i++) {
 			switch (s->routes[i].obs_count) {
 			case 0:		/* A locked entry */
@@ -469,7 +467,7 @@ static int nr_dec_obs(void)
 				nr_neigh_put(nr_neigh);
 
 				if (nr_neigh->count == 0 && !nr_neigh->locked)
-					nr_remove_neigh(nr_neigh);
+					nr_remove_neigh_locked(nr_neigh);
 
 				s->count--;
 
@@ -494,9 +492,8 @@ static int nr_dec_obs(void)
 
 		if (s->count <= 0)
 			nr_remove_node_locked(s);
-		nr_node_unlock(s);
 	}
-	spin_unlock_bh(&nr_node_list_lock);
+	spin_unlock_bh(&nr_route_lock);
 
 	return 0;
 }
@@ -511,12 +508,10 @@ void nr_rt_device_down(struct net_device *dev)
 	struct nr_node  *t;
 	int i;
 
-	spin_lock_bh(&nr_neigh_list_lock);
+	spin_lock_bh(&nr_route_lock);
 	nr_neigh_for_each_safe(s, nodet, &nr_neigh_list) {
 		if (s->dev == dev) {
-			spin_lock_bh(&nr_node_list_lock);
 			nr_node_for_each_safe(t, node2t, &nr_node_list) {
-				nr_node_lock(t);
 				for (i = 0; i < t->count; i++) {
 					if (t->routes[i].neighbour == s) {
 						t->count--;
@@ -536,14 +531,12 @@ void nr_rt_device_down(struct net_device *dev)
 
 				if (t->count <= 0)
 					nr_remove_node_locked(t);
-				nr_node_unlock(t);
 			}
-			spin_unlock_bh(&nr_node_list_lock);
 
 			nr_remove_neigh_locked(s);
 		}
 	}
-	spin_unlock_bh(&nr_neigh_list_lock);
+	spin_unlock_bh(&nr_route_lock);
 }
 
 /*
@@ -707,7 +700,7 @@ void nr_link_failed(ax25_cb *ax25, int reason)
 	struct nr_neigh *s, *nr_neigh = NULL;
 	struct nr_node  *nr_node = NULL;
 
-	spin_lock_bh(&nr_neigh_list_lock);
+	spin_lock_bh(&nr_route_lock);
 	nr_neigh_for_each(s, &nr_neigh_list) {
 		if (s->ax25 == ax25) {
 			nr_neigh_hold(s);
@@ -715,7 +708,7 @@ void nr_link_failed(ax25_cb *ax25, int reason)
 			break;
 		}
 	}
-	spin_unlock_bh(&nr_neigh_list_lock);
+	spin_unlock_bh(&nr_route_lock);
 
 	if (nr_neigh == NULL)
 		return;
@@ -727,15 +720,13 @@ void nr_link_failed(ax25_cb *ax25, int reason)
 		nr_neigh_put(nr_neigh);
 		return;
 	}
-	spin_lock_bh(&nr_node_list_lock);
+	spin_lock_bh(&nr_route_lock);
 	nr_node_for_each(nr_node, &nr_node_list) {
-		nr_node_lock(nr_node);
 		if (nr_node->which < nr_node->count &&
 		    nr_node->routes[nr_node->which].neighbour == nr_neigh)
 			nr_node->which++;
-		nr_node_unlock(nr_node);
 	}
-	spin_unlock_bh(&nr_node_list_lock);
+	spin_unlock_bh(&nr_route_lock);
 	nr_neigh_put(nr_neigh);
 }
 
@@ -793,10 +784,10 @@ int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25)
 	nr_node = nr_node_get(nr_dest);
 	if (nr_node == NULL)
 		return 0;
-	nr_node_lock(nr_node);
+	spin_lock_bh(&nr_route_lock);
 
 	if (nr_node->which >= nr_node->count) {
-		nr_node_unlock(nr_node);
+		spin_unlock_bh(&nr_route_lock);
 		nr_node_put(nr_node);
 		return 0;
 	}
@@ -804,7 +795,7 @@ int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25)
 	nr_neigh = nr_node->routes[nr_node->which].neighbour;
 
 	if ((dev = nr_dev_first()) == NULL) {
-		nr_node_unlock(nr_node);
+		spin_unlock_bh(&nr_route_lock);
 		nr_node_put(nr_node);
 		return 0;
 	}
@@ -815,7 +806,7 @@ int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25)
 	nskb = skb_copy_expand(skb, dev->hard_header_len, 0, GFP_ATOMIC);
 
 	if (!nskb) {
-		nr_node_unlock(nr_node);
+		spin_unlock_bh(&nr_route_lock);
 		nr_node_put(nr_node);
 		dev_put(dev);
 		return 0;
@@ -837,7 +828,7 @@ int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25)
 
 	dev_put(dev);
 	ret = (nr_neigh->ax25 != NULL);
-	nr_node_unlock(nr_node);
+	spin_unlock_bh(&nr_route_lock);
 	nr_node_put(nr_node);
 
 	if (ret)
@@ -849,9 +840,9 @@ int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25)
 #ifdef CONFIG_PROC_FS
 
 static void *nr_node_start(struct seq_file *seq, loff_t *pos)
-	__acquires(&nr_node_list_lock)
+	__acquires(&nr_route_lock)
 {
-	spin_lock_bh(&nr_node_list_lock);
+	spin_lock_bh(&nr_route_lock);
 	return seq_hlist_start_head(&nr_node_list, *pos);
 }
 
@@ -861,9 +852,9 @@ static void *nr_node_next(struct seq_file *seq, void *v, loff_t *pos)
 }
 
 static void nr_node_stop(struct seq_file *seq, void *v)
-	__releases(&nr_node_list_lock)
+	__releases(&nr_route_lock)
 {
-	spin_unlock_bh(&nr_node_list_lock);
+	spin_unlock_bh(&nr_route_lock);
 }
 
 static int nr_node_show(struct seq_file *seq, void *v)
@@ -878,7 +869,6 @@ static int nr_node_show(struct seq_file *seq, void *v)
 		struct nr_node *nr_node = hlist_entry(v, struct nr_node,
 						      node_node);
 
-		nr_node_lock(nr_node);
 		seq_printf(seq, "%-9s %-7s  %d %d",
 			ax2asc(buf, &nr_node->callsign),
 			(nr_node->mnemonic[0] == '\0') ? "*" : nr_node->mnemonic,
@@ -891,7 +881,6 @@ static int nr_node_show(struct seq_file *seq, void *v)
 				nr_node->routes[i].obs_count,
 				nr_node->routes[i].neighbour->number);
 		}
-		nr_node_unlock(nr_node);
 
 		seq_puts(seq, "\n");
 	}
@@ -906,9 +895,9 @@ const struct seq_operations nr_node_seqops = {
 };
 
 static void *nr_neigh_start(struct seq_file *seq, loff_t *pos)
-	__acquires(&nr_neigh_list_lock)
+	__acquires(&nr_route_lock)
 {
-	spin_lock_bh(&nr_neigh_list_lock);
+	spin_lock_bh(&nr_route_lock);
 	return seq_hlist_start_head(&nr_neigh_list, *pos);
 }
 
@@ -918,9 +907,9 @@ static void *nr_neigh_next(struct seq_file *seq, void *v, loff_t *pos)
 }
 
 static void nr_neigh_stop(struct seq_file *seq, void *v)
-	__releases(&nr_neigh_list_lock)
+	__releases(&nr_route_lock)
 {
-	spin_unlock_bh(&nr_neigh_list_lock);
+	spin_unlock_bh(&nr_route_lock);
 }
 
 static int nr_neigh_show(struct seq_file *seq, void *v)
@@ -971,12 +960,9 @@ void nr_rt_free(void)
 	struct nr_node  *t = NULL;
 	struct hlist_node *nodet;
 
-	spin_lock_bh(&nr_neigh_list_lock);
-	spin_lock_bh(&nr_node_list_lock);
+	spin_lock_bh(&nr_route_lock);
 	nr_node_for_each_safe(t, nodet, &nr_node_list) {
-		nr_node_lock(t);
 		nr_remove_node_locked(t);
-		nr_node_unlock(t);
 	}
 	nr_neigh_for_each_safe(s, nodet, &nr_neigh_list) {
 		while(s->count) {
@@ -985,6 +971,5 @@ void nr_rt_free(void)
 		}
 		nr_remove_neigh_locked(s);
 	}
-	spin_unlock_bh(&nr_node_list_lock);
-	spin_unlock_bh(&nr_neigh_list_lock);
+	spin_unlock_bh(&nr_route_lock);
 }
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 165/247] netrom: look up and update routes in one critical section
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (163 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 164/247] netrom: use a single lock for the node and neighbour lists Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 166/247] netrom: fix reference count leak in nr_rt_device_down Greg Kroah-Hartman
                   ` (89 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, syzbot+2860e75836a08b172755,
	syzbot+df52f4216bf7b4d768e7, Bernard Pidoux, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Bernard Pidoux <bernard.f6bvp@gmail.com>

nr_add_node(), nr_del_node(), nr_add_neigh() and nr_del_neigh() look up
a node or neighbour with nr_node_get()/nr_neigh_get_dev(), which take
and drop the routing lock, and only then take the lock again to change
the routes. In between, another task can unlink the object they found.
nr_add_node() can then store a neighbour that is no longer on
nr_neigh_list in a node's routes; that route's reference becomes the
last one, and the next time the route is dropped the neighbour is freed
and read again straight away:

	nr_neigh->count--;
	nr_neigh_put(nr_neigh);			/* frees it */
	if (nr_neigh->count == 0 && ...)	/* use after free */

This is what syzbot reports in nr_add_node() (evicting the worst of
three routes) and in nr_dec_obs() through nr_rt_ioctl(). Lizhi Xu
analysed the first race; the fix posted then filtered neighbours by
refcount and was not taken.

Now that one lock covers both lists and the routes, do the lookup and
the update in a single critical section in all four functions, using
new __nr_node_get()/__nr_neigh_get_dev() variants that expect the lock
to be held. A node or neighbour found there stays linked while it is
used, so a route can no longer outlive its neighbour's list entry.
Concurrent additions of the same node or neighbour no longer create
duplicate entries either.

Also factor the "drop one route's use of a neighbour" sequence into
nr_neigh_route_put_locked(), which reads count and locked before
dropping the reference, and use it in nr_add_node(), nr_del_node() and
nr_dec_obs().

nr_add_node() is also called from nr_route_frame() in softirq context,
where the kmemdup(GFP_KERNEL) of the digipeater list could sleep; the
neighbour creation shared with nr_add_neigh() now allocates with
GFP_ATOMIC, like the rest of nr_add_node() already did.

This depends on "netrom: use a single lock for the node and neighbour
lists".

Reported-by: syzbot+2860e75836a08b172755@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=2860e75836a08b172755
Reported-by: syzbot+df52f4216bf7b4d768e7@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=df52f4216bf7b4d768e7
Link: https://patchwork.kernel.org/project/netdevbpf/patch/20251023135032.3759443-1-lizhi.xu@windriver.com/
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
(cherry picked from commit 1292cb18feed7503f861695134206c99347cc7bb)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/netrom/nr_route.c | 264 ++++++++++++++++++++++--------------------
 1 file changed, 138 insertions(+), 126 deletions(-)

diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c
index e3effc85d3106..10294cf068f8a 100644
--- a/net/netrom/nr_route.c
+++ b/net/netrom/nr_route.c
@@ -47,38 +47,44 @@ static DEFINE_SPINLOCK(nr_route_lock);
 static HLIST_HEAD(nr_node_list);
 static HLIST_HEAD(nr_neigh_list);
 
-static struct nr_node *nr_node_get(ax25_address *callsign)
+static struct nr_node *__nr_node_get(ax25_address *callsign)
 {
-	struct nr_node *found = NULL;
 	struct nr_node *nr_node;
 
-	spin_lock_bh(&nr_route_lock);
+	lockdep_assert_held(&nr_route_lock);
+
 	nr_node_for_each(nr_node, &nr_node_list)
 		if (ax25cmp(callsign, &nr_node->callsign) == 0) {
 			nr_node_hold(nr_node);
-			found = nr_node;
-			break;
+			return nr_node;
 		}
+	return NULL;
+}
+
+static struct nr_node *nr_node_get(ax25_address *callsign)
+{
+	struct nr_node *found;
+
+	spin_lock_bh(&nr_route_lock);
+	found = __nr_node_get(callsign);
 	spin_unlock_bh(&nr_route_lock);
 	return found;
 }
 
-static struct nr_neigh *nr_neigh_get_dev(ax25_address *callsign,
-					 struct net_device *dev)
+static struct nr_neigh *__nr_neigh_get_dev(ax25_address *callsign,
+					   struct net_device *dev)
 {
-	struct nr_neigh *found = NULL;
 	struct nr_neigh *nr_neigh;
 
-	spin_lock_bh(&nr_route_lock);
+	lockdep_assert_held(&nr_route_lock);
+
 	nr_neigh_for_each(nr_neigh, &nr_neigh_list)
 		if (ax25cmp(callsign, &nr_neigh->callsign) == 0 &&
 		    nr_neigh->dev == dev) {
 			nr_neigh_hold(nr_neigh);
-			found = nr_neigh;
-			break;
+			return nr_neigh;
 		}
-	spin_unlock_bh(&nr_route_lock);
-	return found;
+	return NULL;
 }
 
 static void nr_remove_neigh_locked(struct nr_neigh *nr_neigh);
@@ -96,6 +102,66 @@ static void re_sort_routes(struct nr_node *nr_node, int x, int y)
 	}
 }
 
+/*
+ * Allocate a neighbour and link it into nr_neigh_list. The list holds one
+ * reference and the caller gets another one. Called with nr_route_lock held.
+ */
+static struct nr_neigh *nr_neigh_create_locked(ax25_address *callsign,
+					       ax25_digi *ax25_digi,
+					       struct net_device *dev,
+					       unsigned int quality,
+					       unsigned char locked)
+{
+	struct nr_neigh *nr_neigh;
+
+	lockdep_assert_held(&nr_route_lock);
+
+	nr_neigh = kmalloc(sizeof(*nr_neigh), GFP_ATOMIC);
+	if (!nr_neigh)
+		return NULL;
+
+	nr_neigh->callsign = *callsign;
+	nr_neigh->digipeat = NULL;
+	nr_neigh->ax25     = NULL;
+	nr_neigh->dev      = dev;
+	nr_neigh->quality  = quality;
+	nr_neigh->locked   = locked;
+	nr_neigh->count    = 0;
+	nr_neigh->number   = nr_neigh_no++;
+	nr_neigh->failed   = 0;
+	refcount_set(&nr_neigh->refcount, 1);
+
+	if (ax25_digi && ax25_digi->ndigi > 0) {
+		nr_neigh->digipeat = kmemdup(ax25_digi, sizeof(*ax25_digi),
+					     GFP_ATOMIC);
+		if (!nr_neigh->digipeat) {
+			kfree(nr_neigh);
+			return NULL;
+		}
+	}
+
+	hlist_add_head(&nr_neigh->neigh_node, &nr_neigh_list);
+	nr_neigh_hold(nr_neigh);
+
+	return nr_neigh;
+}
+
+/*
+ * Drop one route's use of a neighbour. The neighbour is unlinked when no
+ * route uses it any more and it was not added explicitly; count and locked
+ * are read before the route's reference is dropped, since that reference
+ * may be the last one. Called with nr_route_lock held.
+ */
+static void nr_neigh_route_put_locked(struct nr_neigh *nr_neigh)
+{
+	lockdep_assert_held(&nr_route_lock);
+
+	nr_neigh->count--;
+	if (nr_neigh->count == 0 && !nr_neigh->locked)
+		nr_remove_neigh_locked(nr_neigh);
+	nr_neigh_put(nr_neigh);
+}
+
 /*
  *	Add a new route to a node, and in the process add the node and the
  *	neighbour if it is new.
@@ -106,7 +172,7 @@ static int __must_check nr_add_node(ax25_address *nr, const char *mnemonic,
 {
 	struct nr_node  *nr_node;
 	struct nr_neigh *nr_neigh;
-	int i, found;
+	int i, found, ret = 0;
 	struct net_device *odev;
 
 	if ((odev=nr_dev_get(nr)) != NULL) {	/* Can't add routes to ourself */
@@ -114,9 +180,15 @@ static int __must_check nr_add_node(ax25_address *nr, const char *mnemonic,
 		return -EINVAL;
 	}
 
-	nr_node = nr_node_get(nr);
+	/*
+	 * Look up and update under one critical section, so that a node or
+	 * neighbour found here cannot be unlinked before it is used.
+	 */
+	spin_lock_bh(&nr_route_lock);
+
+	nr_node = __nr_node_get(nr);
 
-	nr_neigh = nr_neigh_get_dev(ax25, dev);
+	nr_neigh = __nr_neigh_get_dev(ax25, dev);
 
 	/*
 	 * The L2 link to a neighbour has failed in the past
@@ -127,14 +199,12 @@ static int __must_check nr_add_node(ax25_address *nr, const char *mnemonic,
 	if (nr_neigh != NULL && nr_neigh->failed != 0 && quality == 0) {
 		struct nr_node *nr_nodet;
 
-		spin_lock_bh(&nr_route_lock);
 		nr_node_for_each(nr_nodet, &nr_node_list) {
 			for (i = 0; i < nr_nodet->count; i++)
 				if (nr_nodet->routes[i].neighbour == nr_neigh)
 					if (i < nr_nodet->which)
 						nr_nodet->which = i;
 		}
-		spin_unlock_bh(&nr_route_lock);
 	}
 
 	if (nr_neigh != NULL)
@@ -143,43 +213,19 @@ static int __must_check nr_add_node(ax25_address *nr, const char *mnemonic,
 	if (quality == 0 && nr_neigh != NULL && nr_node != NULL) {
 		nr_neigh_put(nr_neigh);
 		nr_node_put(nr_node);
-		return 0;
+		goto out;
 	}
 
 	if (nr_neigh == NULL) {
-		if ((nr_neigh = kmalloc(sizeof(*nr_neigh), GFP_ATOMIC)) == NULL) {
+		unsigned int q = READ_ONCE(sysctl_netrom_default_path_quality);
+
+		nr_neigh = nr_neigh_create_locked(ax25, ax25_digi, dev, q, 0);
+		if (!nr_neigh) {
 			if (nr_node)
 				nr_node_put(nr_node);
-			return -ENOMEM;
-		}
-
-		nr_neigh->callsign = *ax25;
-		nr_neigh->digipeat = NULL;
-		nr_neigh->ax25     = NULL;
-		nr_neigh->dev      = dev;
-		nr_neigh->quality  = READ_ONCE(sysctl_netrom_default_path_quality);
-		nr_neigh->locked   = 0;
-		nr_neigh->count    = 0;
-		nr_neigh->number   = nr_neigh_no++;
-		nr_neigh->failed   = 0;
-		refcount_set(&nr_neigh->refcount, 1);
-
-		if (ax25_digi != NULL && ax25_digi->ndigi > 0) {
-			nr_neigh->digipeat = kmemdup(ax25_digi,
-						     sizeof(*ax25_digi),
-						     GFP_KERNEL);
-			if (nr_neigh->digipeat == NULL) {
-				kfree(nr_neigh);
-				if (nr_node)
-					nr_node_put(nr_node);
-				return -ENOMEM;
-			}
+			ret = -ENOMEM;
+			goto out;
 		}
-
-		spin_lock_bh(&nr_route_lock);
-		hlist_add_head(&nr_neigh->neigh_node, &nr_neigh_list);
-		nr_neigh_hold(nr_neigh);
-		spin_unlock_bh(&nr_route_lock);
 	}
 
 	if (quality != 0 && ax25cmp(nr, ax25) == 0 && !nr_neigh->locked)
@@ -187,9 +233,9 @@ static int __must_check nr_add_node(ax25_address *nr, const char *mnemonic,
 
 	if (nr_node == NULL) {
 		if ((nr_node = kmalloc(sizeof(*nr_node), GFP_ATOMIC)) == NULL) {
-			if (nr_neigh)
-				nr_neigh_put(nr_neigh);
-			return -ENOMEM;
+			nr_neigh_put(nr_neigh);
+			ret = -ENOMEM;
+			goto out;
 		}
 
 		nr_node->callsign = *nr;
@@ -206,15 +252,12 @@ static int __must_check nr_add_node(ax25_address *nr, const char *mnemonic,
 		nr_neigh_hold(nr_neigh);
 		nr_neigh->count++;
 
-		spin_lock_bh(&nr_route_lock);
 		hlist_add_head(&nr_node->node_node, &nr_node_list);
 		/* refcount initialized at 1 */
-		spin_unlock_bh(&nr_route_lock);
 
 		nr_neigh_put(nr_neigh);
-		return 0;
+		goto out;
 	}
-	spin_lock_bh(&nr_route_lock);
 
 	if (quality != 0)
 		strscpy(nr_node->mnemonic, mnemonic);
@@ -245,11 +288,7 @@ static int __must_check nr_add_node(ax25_address *nr, const char *mnemonic,
 		} else {
 			/* It must be better than the worst */
 			if (quality > nr_node->routes[2].quality) {
-				nr_node->routes[2].neighbour->count--;
-				nr_neigh_put(nr_node->routes[2].neighbour);
-
-				if (nr_node->routes[2].neighbour->count == 0 && !nr_node->routes[2].neighbour->locked)
-					nr_remove_neigh_locked(nr_node->routes[2].neighbour);
+				nr_neigh_route_put_locked(nr_node->routes[2].neighbour);
 
 				nr_node->routes[2].quality   = quality;
 				nr_node->routes[2].obs_count = obs_count;
@@ -283,9 +322,10 @@ static int __must_check nr_add_node(ax25_address *nr, const char *mnemonic,
 	}
 
 	nr_neigh_put(nr_neigh);
-	spin_unlock_bh(&nr_route_lock);
 	nr_node_put(nr_node);
-	return 0;
+out:
+	spin_unlock_bh(&nr_route_lock);
+	return ret;
 }
 
 static void nr_remove_node_locked(struct nr_node *nr_node)
@@ -304,13 +344,6 @@ static void nr_remove_neigh_locked(struct nr_neigh *nr_neigh)
 	nr_neigh_put(nr_neigh);
 }
 
-static void nr_remove_neigh(struct nr_neigh *nr_neigh)
-{
-	spin_lock_bh(&nr_route_lock);
-	nr_remove_neigh_locked(nr_neigh);
-	spin_unlock_bh(&nr_route_lock);
-}
-
 /*
  *	"Delete" a node. Strictly speaking remove a route to a node. The node
  *	is only deleted if no routes are left to it.
@@ -319,28 +352,25 @@ static int nr_del_node(ax25_address *callsign, ax25_address *neighbour, struct n
 {
 	struct nr_node  *nr_node;
 	struct nr_neigh *nr_neigh;
-	int i;
+	int i, ret = -EINVAL;
 
-	nr_node = nr_node_get(callsign);
+	spin_lock_bh(&nr_route_lock);
+
+	nr_node = __nr_node_get(callsign);
 
 	if (nr_node == NULL)
-		return -EINVAL;
+		goto out;
 
-	nr_neigh = nr_neigh_get_dev(neighbour, dev);
+	nr_neigh = __nr_neigh_get_dev(neighbour, dev);
 
 	if (nr_neigh == NULL) {
 		nr_node_put(nr_node);
-		return -EINVAL;
+		goto out;
 	}
 
-	spin_lock_bh(&nr_route_lock);
 	for (i = 0; i < nr_node->count; i++) {
 		if (nr_node->routes[i].neighbour == nr_neigh) {
-			nr_neigh->count--;
-			nr_neigh_put(nr_neigh);
-
-			if (nr_neigh->count == 0 && !nr_neigh->locked)
-				nr_remove_neigh_locked(nr_neigh);
+			nr_neigh_route_put_locked(nr_neigh);
 			nr_neigh_put(nr_neigh);
 
 			nr_node->count--;
@@ -360,16 +390,15 @@ static int nr_del_node(ax25_address *callsign, ax25_address *neighbour, struct n
 				}
 				nr_node_put(nr_node);
 			}
-			spin_unlock_bh(&nr_route_lock);
-
-			return 0;
+			ret = 0;
+			goto out;
 		}
 	}
 	nr_neigh_put(nr_neigh);
-	spin_unlock_bh(&nr_route_lock);
 	nr_node_put(nr_node);
-
-	return -EINVAL;
+out:
+	spin_unlock_bh(&nr_route_lock);
+	return ret;
 }
 
 /*
@@ -379,44 +408,25 @@ static int __must_check nr_add_neigh(ax25_address *callsign,
 	ax25_digi *ax25_digi, struct net_device *dev, unsigned int quality)
 {
 	struct nr_neigh *nr_neigh;
+	int ret = 0;
 
-	nr_neigh = nr_neigh_get_dev(callsign, dev);
+	spin_lock_bh(&nr_route_lock);
+
+	nr_neigh = __nr_neigh_get_dev(callsign, dev);
 	if (nr_neigh) {
 		nr_neigh->quality = quality;
 		nr_neigh->locked  = 1;
-		nr_neigh_put(nr_neigh);
-		return 0;
-	}
-
-	if ((nr_neigh = kmalloc(sizeof(*nr_neigh), GFP_ATOMIC)) == NULL)
-		return -ENOMEM;
-
-	nr_neigh->callsign = *callsign;
-	nr_neigh->digipeat = NULL;
-	nr_neigh->ax25     = NULL;
-	nr_neigh->dev      = dev;
-	nr_neigh->quality  = quality;
-	nr_neigh->locked   = 1;
-	nr_neigh->count    = 0;
-	nr_neigh->number   = nr_neigh_no++;
-	nr_neigh->failed   = 0;
-	refcount_set(&nr_neigh->refcount, 1);
-
-	if (ax25_digi != NULL && ax25_digi->ndigi > 0) {
-		nr_neigh->digipeat = kmemdup(ax25_digi, sizeof(*ax25_digi),
-					     GFP_KERNEL);
-		if (nr_neigh->digipeat == NULL) {
-			kfree(nr_neigh);
-			return -ENOMEM;
-		}
+	} else {
+		nr_neigh = nr_neigh_create_locked(callsign, ax25_digi, dev,
+						  quality, 1);
+		if (!nr_neigh)
+			ret = -ENOMEM;
 	}
+	if (nr_neigh)
+		nr_neigh_put(nr_neigh);
 
-	spin_lock_bh(&nr_route_lock);
-	hlist_add_head(&nr_neigh->neigh_node, &nr_neigh_list);
-	/* refcount is initialized at 1 */
 	spin_unlock_bh(&nr_route_lock);
-
-	return 0;
+	return ret;
 }
 
 /*
@@ -427,17 +437,23 @@ static int nr_del_neigh(ax25_address *callsign, struct net_device *dev, unsigned
 {
 	struct nr_neigh *nr_neigh;
 
-	nr_neigh = nr_neigh_get_dev(callsign, dev);
+	spin_lock_bh(&nr_route_lock);
+
+	nr_neigh = __nr_neigh_get_dev(callsign, dev);
 
-	if (nr_neigh == NULL) return -EINVAL;
+	if (nr_neigh == NULL) {
+		spin_unlock_bh(&nr_route_lock);
+		return -EINVAL;
+	}
 
 	nr_neigh->quality = quality;
 	nr_neigh->locked  = 0;
 
 	if (nr_neigh->count == 0)
-		nr_remove_neigh(nr_neigh);
+		nr_remove_neigh_locked(nr_neigh);
 	nr_neigh_put(nr_neigh);
 
+	spin_unlock_bh(&nr_route_lock);
 	return 0;
 }
 
@@ -463,11 +479,7 @@ static int nr_dec_obs(void)
 			case 1:		/* From 1 -> 0 */
 				nr_neigh = s->routes[i].neighbour;
 
-				nr_neigh->count--;
-				nr_neigh_put(nr_neigh);
-
-				if (nr_neigh->count == 0 && !nr_neigh->locked)
-					nr_remove_neigh_locked(nr_neigh);
+				nr_neigh_route_put_locked(nr_neigh);
 
 				s->count--;
 
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 166/247] netrom: fix reference count leak in nr_rt_device_down
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (164 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 165/247] netrom: look up and update routes in one critical section Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 167/247] netrom: clear nr_neigh->ax25 under the routing lock in nr_link_failed() Greg Kroah-Hartman
                   ` (88 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Junjie Cao, Bernard Pidoux,
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Junjie Cao <junjie.cao@intel.com>

When a device goes down, nr_rt_device_down() clears the routes that
use this device. However, it fails to drop the per-route reference to
the neighbour (nr_neigh): neither nr_neigh->count nor its refcount
is decremented when the route is removed.

Mirror the behaviour of nr_dec_obs() / nr_del_node() by decrementing
nr_neigh->count and calling nr_neigh_put(), so that the neighbour
reference is properly released when a device goes down.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Signed-off-by: Junjie Cao <junjie.cao@intel.com>
[F6BVP: rebased on the single nr_route_lock; the list reference is
still dropped last by nr_remove_neigh_locked(), so the neighbour stays
valid while its routes are removed.]
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
(cherry picked from commit b0f6830b24b75618e299c8e5451367e8742272da)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/netrom/nr_route.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c
index 10294cf068f8a..67d9ed0006b40 100644
--- a/net/netrom/nr_route.c
+++ b/net/netrom/nr_route.c
@@ -526,6 +526,9 @@ void nr_rt_device_down(struct net_device *dev)
 			nr_node_for_each_safe(t, node2t, &nr_node_list) {
 				for (i = 0; i < t->count; i++) {
 					if (t->routes[i].neighbour == s) {
+						s->count--;
+						nr_neigh_put(s);
+
 						t->count--;
 
 						switch (i) {
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 167/247] netrom: clear nr_neigh->ax25 under the routing lock in nr_link_failed()
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (165 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 166/247] netrom: fix reference count leak in nr_rt_device_down Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 168/247] netrom: fix nr_node leak when nr_del_node() removes the last route Greg Kroah-Hartman
                   ` (87 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Bernard Pidoux <bernard.f6bvp@gmail.com>

nr_route_frame() swaps nr_neigh->ax25 for the ax25_cb returned by
ax25_send_frame() and puts the old one while holding nr_route_lock.
nr_link_failed(), called by AX.25 when that link fails, looks the
neighbour up under the lock but then clears nr_neigh->ax25, puts the
ax25_cb and bumps nr_neigh->failed after dropping it. If a frame is
routed to the same neighbour at that moment, both paths can see the
same ax25_cb and put it twice.

Do the whole of nr_link_failed() in one critical section. The
neighbour no longer needs a temporary reference, since it cannot be
unlinked while the lock is held.

This depends on "netrom: use a single lock for the node and neighbour
lists".

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
(cherry picked from commit 6e6f80bff5c901f317c3750cdf375766800ecc1a)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/netrom/nr_route.c | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c
index 67d9ed0006b40..98ba317ada637 100644
--- a/net/netrom/nr_route.c
+++ b/net/netrom/nr_route.c
@@ -715,34 +715,35 @@ void nr_link_failed(ax25_cb *ax25, int reason)
 	struct nr_neigh *s, *nr_neigh = NULL;
 	struct nr_node  *nr_node = NULL;
 
+	/*
+	 * nr_route_frame() replaces nr_neigh->ax25 under nr_route_lock;
+	 * clear it and drop its reference under the same lock, so that the
+	 * two paths cannot both put the same ax25_cb.
+	 */
 	spin_lock_bh(&nr_route_lock);
 	nr_neigh_for_each(s, &nr_neigh_list) {
 		if (s->ax25 == ax25) {
-			nr_neigh_hold(s);
 			nr_neigh = s;
 			break;
 		}
 	}
-	spin_unlock_bh(&nr_route_lock);
 
 	if (nr_neigh == NULL)
-		return;
+		goto out;
 
 	nr_neigh->ax25 = NULL;
 	ax25_cb_put(ax25);
 
-	if (++nr_neigh->failed < READ_ONCE(sysctl_netrom_link_fails_count)) {
-		nr_neigh_put(nr_neigh);
-		return;
-	}
-	spin_lock_bh(&nr_route_lock);
+	if (++nr_neigh->failed < READ_ONCE(sysctl_netrom_link_fails_count))
+		goto out;
+
 	nr_node_for_each(nr_node, &nr_node_list) {
 		if (nr_node->which < nr_node->count &&
 		    nr_node->routes[nr_node->which].neighbour == nr_neigh)
 			nr_node->which++;
 	}
+out:
 	spin_unlock_bh(&nr_route_lock);
-	nr_neigh_put(nr_neigh);
 }
 
 /*
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 168/247] netrom: fix nr_node leak when nr_del_node() removes the last route
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (166 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 167/247] netrom: clear nr_neigh->ax25 under the routing lock in nr_link_failed() Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 169/247] rose: clear through routes when a neighbour is removed from the tables Greg Kroah-Hartman
                   ` (86 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Bernard Pidoux <bernard.f6bvp@gmail.com>

nr_del_node() takes a reference on the node with its lookup. When the
route it deletes is not the last one, it drops that reference before
returning. When it is the last one, it only unlinks the node with
nr_remove_node_locked(), which drops the list's reference, and returns
still holding its own: the unlinked node is never freed.

Seen with kmemleak on a live node after adding and then deleting a
route to a dummy node with nrparms (SIOCADDRT then SIOCDELRT): the
96-byte nr_node allocated by nr_add_node(), callsign and mnemonic of
the dummy node in its hex dump, is reported as unreferenced.

Drop the lookup reference in both cases.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
(cherry picked from commit a4b96115783fdefae9599f9a84a39e24fb288d6b)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/netrom/nr_route.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c
index 98ba317ada637..288c4a91ea9b7 100644
--- a/net/netrom/nr_route.c
+++ b/net/netrom/nr_route.c
@@ -388,8 +388,9 @@ static int nr_del_node(ax25_address *callsign, ax25_address *neighbour, struct n
 				case 2:
 					break;
 				}
-				nr_node_put(nr_node);
 			}
+			/* Drop the reference taken by __nr_node_get() */
+			nr_node_put(nr_node);
 			ret = 0;
 			goto out;
 		}
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 169/247] rose: clear through routes when a neighbour is removed from the tables
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (167 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 168/247] netrom: fix nr_node leak when nr_del_node() removes the last route Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 170/247] rose: restart the link of a neighbour created over a live AX.25 connection Greg Kroah-Hartman
                   ` (85 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Bernard Pidoux <bernard.f6bvp@gmail.com>

When the last route using a neighbour is deleted (SIOCDELRT) or all
routes are cleared (SIOCRSCLRRT), rose_del_node() and
rose_clear_routes() take the neighbour out of rose_neigh_list, but the
through routes in rose_route_list that still use it are left alone.
No frame can reach them any more, so they stay in the table for ever,
holding their neighbour references, and neither end of the relayed
connection is told: the caller and the called station keep a circuit
that goes nowhere. rose_clear_routes() even says it keeps neighbours
with active connections, which it does not.

This shows up on every node that relays traffic when its routing
daemon restarts: FPAC clears and reloads the routes, the neighbours are
recreated under new numbers, and the old through routes remain listed
with neighbours that no longer exist.

Clear them when the neighbour is removed, as rose_link_failed() does
when a link fails, but send the CLEAR to both halves since the removed
neighbour's link may still be up, and cut the local connections using
it. rose_route_list_lock is taken under rose_node_list_lock and
rose_neigh_list_lock, the order rose_route_frame() and
rose_link_failed() already use.

Tested in QEMU with a lockdep and KASAN kernel, three nodes A - B - C
with A calling C through B: before, the through route stays on B after
SIOCDELRT or SIOCRSCLRRT and A is never told; after, the entry is gone
and both A and C get a CLEAR (cause 0x09) within a second. No lockdep,
KASAN or refcount report.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
(cherry picked from commit 065ae03f519c147d5ee7b87acb2d21fe93ae0007)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/rose/rose_route.c | 49 +++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 47 insertions(+), 2 deletions(-)

diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c
index fd196f2e2fd64..87844cc195f8d 100644
--- a/net/rose/rose_route.c
+++ b/net/rose/rose_route.c
@@ -285,6 +285,49 @@ static void rose_remove_route(struct rose_route *rose_route)
 	}
 }
 
+/*
+ *	A neighbour is being removed from the tables while its link may still
+ *	be up (route deleted or routes cleared by the configuration). Clear the
+ *	through routes using it, on both sides since both can still be reached,
+ *	instead of leaving them in rose_route_list for ever: no frame can reach
+ *	them once the neighbour is gone. Local connections using it are cut too,
+ *	as rose_link_failed() does.
+ *
+ *	Caller is holding rose_node_list_lock and rose_neigh_list_lock, taken
+ *	before rose_route_list_lock as in rose_route_frame() and
+ *	rose_link_failed().
+ */
+static void rose_neigh_clear_routes(struct rose_neigh *rose_neigh)
+{
+	struct rose_route *rose_route, *s;
+
+	spin_lock_bh(&rose_route_list_lock);
+
+	rose_route = rose_route_list;
+	while (rose_route != NULL) {
+		s = rose_route->next;
+
+		if (rose_route->neigh1 == rose_neigh ||
+		    rose_route->neigh2 == rose_neigh) {
+			if (rose_route->neigh1 != NULL)
+				rose_transmit_clear_request(rose_route->neigh1,
+							    rose_route->lci1,
+							    ROSE_OUT_OF_ORDER, 0);
+			if (rose_route->neigh2 != NULL)
+				rose_transmit_clear_request(rose_route->neigh2,
+							    rose_route->lci2,
+							    ROSE_OUT_OF_ORDER, 0);
+			rose_remove_route(rose_route);
+		}
+
+		rose_route = s;
+	}
+
+	spin_unlock_bh(&rose_route_list_lock);
+
+	rose_kill_by_neigh(rose_neigh);
+}
+
 /*
  *	"Delete" a node. Strictly speaking remove a route to a node. The node
  *	is only deleted if no routes are left to it.
@@ -333,6 +376,7 @@ static int rose_del_node(struct rose_route_struct *rose_route,
 			rose_neigh_put(rose_neigh);
 
 			if (rose_neigh->count == 0) {
+				rose_neigh_clear_routes(rose_neigh);
 				rose_remove_neigh(rose_neigh);
 				rose_neigh_put(rose_neigh);
 			}
@@ -547,8 +591,8 @@ void rose_route_device_down(struct net_device *dev)
 #endif
 
 /*
- *	Clear all nodes and neighbours out, except for neighbours with
- *	active connections going through them.
+ *	Clear all nodes and neighbours out, with the through routes and
+ *	connections using those neighbours.
  *  Do not clear loopback neighbour and nodes.
  */
 static int rose_clear_routes(void)
@@ -579,6 +623,7 @@ static int rose_clear_routes(void)
 		rose_neigh = rose_neigh->next;
 
 		if (!s->loopback) {
+			rose_neigh_clear_routes(s);
 			rose_remove_neigh(s);
 			rose_neigh_put(s);
 		}
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 170/247] rose: restart the link of a neighbour created over a live AX.25 connection
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (168 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 169/247] rose: clear through routes when a neighbour is removed from the tables Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 171/247] ax25: serialise the transmission of I frames on a connection Greg Kroah-Hartman
                   ` (84 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Bernard Pidoux <bernard.f6bvp@gmail.com>

A new neighbour starts with restarted == 0 and waits for the first frame
sent to it to start the restart procedure. But when a neighbour is
removed from the routing tables and added back (SIOCDELRT then
SIOCADDRT, or SIOCRSCLRRT followed by a reload of the routes), the AX.25
connection to it outlives the old entry. The other end has seen nothing:
it still regards the link as restarted and will not restart it. On this
end rose_get_neigh() only hands out restarted neighbours to through
calls, so no frame is ever sent to the new neighbour and nothing starts
the restart either. Every call relayed through that neighbour is then
refused until one of the two ends happens to originate a call of its own
over the link, or the AX.25 connection drops.

This happens on a relay node each time its routing daemon restarts: FPAC
clears and reloads the routes, the neighbours come back as "restart no"
while /proc/net/ax25 still shows their connections established.

When rose_add_node() creates a neighbour and an AX.25 connection to it
already exists, send the RESTART REQUEST right away and start T0, as
rose_transmit_link() does for the first frame. Nothing changes when
there is no connection yet: the link is still brought up on demand.

Tested in QEMU with a lockdep and KASAN kernel, three nodes A - B - C
with A calling C through B, then B removing and re-adding its route to
C (or clearing and reloading all its routes): before, the neighbour
stays "restart no" on B and A's calls to C are refused for as long as
the test runs; after, the neighbour is restarted within three seconds
and the first call goes through. No lockdep, KASAN or refcount report.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
(cherry picked from commit 411b950c8862277a53f4afc6c6c5b3ab00b814be)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 include/net/rose.h    |  1 +
 net/rose/rose_link.c  | 20 ++++++++++++++++++++
 net/rose/rose_route.c | 10 ++++++++++
 3 files changed, 31 insertions(+)

diff --git a/include/net/rose.h b/include/net/rose.h
index 49140668b3dd0..f5b23c8a11e4d 100644
--- a/include/net/rose.h
+++ b/include/net/rose.h
@@ -237,6 +237,7 @@ void rose_link_rx_restart(struct sk_buff *, struct rose_neigh *,
 			  unsigned short);
 void rose_transmit_clear_request(struct rose_neigh *, unsigned int,
 				 unsigned char, unsigned char);
+void rose_link_restart(struct rose_neigh *neigh);
 void rose_transmit_link(struct sk_buff *, struct rose_neigh *);
 
 /* rose_loopback.c */
diff --git a/net/rose/rose_link.c b/net/rose/rose_link.c
index cbfb11fc3ac52..64ae309441a74 100644
--- a/net/rose/rose_link.c
+++ b/net/rose/rose_link.c
@@ -259,6 +259,26 @@ void rose_transmit_clear_request(struct rose_neigh *neigh, unsigned int lci, uns
 		kfree_skb(skb);
 }
 
+/*
+ * A neighbour has just been created while an AX.25 connection to it is
+ * already up, e.g. it was removed from the routing tables and added back.
+ * The other end still regards the link as restarted and will not restart it,
+ * and through calls only use restarted neighbours, so nothing would ever
+ * restart it from this end either: do it now.
+ */
+void rose_link_restart(struct rose_neigh *neigh)
+{
+	if (neigh->loopback || neigh->restarted || rose_t0timer_running(neigh))
+		return;
+
+	if (!rose_link_up(neigh))
+		return;
+
+	rose_transmit_restart_request(neigh);
+	neigh->dce_mode = 0;
+	rose_start_t0timer(neigh);
+}
+
 void rose_transmit_link(struct sk_buff *skb, struct rose_neigh *neigh)
 {
 	unsigned char *dptr;
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c
index 87844cc195f8d..7ae3552c19267 100644
--- a/net/rose/rose_route.c
+++ b/net/rose/rose_route.c
@@ -53,6 +53,7 @@ static int __must_check rose_add_node(struct rose_route_struct *rose_route,
 {
 	struct rose_node  *rose_node, *rose_tmpn, *rose_tmpp;
 	struct rose_neigh *rose_neigh;
+	bool new_neigh = false;
 	int i, res = 0;
 
 	spin_lock_bh(&rose_node_list_lock);
@@ -125,6 +126,7 @@ static int __must_check rose_add_node(struct rose_route_struct *rose_route,
 
 		rose_neigh->next = rose_neigh_list;
 		rose_neigh_list  = rose_neigh;
+		new_neigh        = true;
 	}
 
 	/*
@@ -192,6 +194,14 @@ static int __must_check rose_add_node(struct rose_route_struct *rose_route,
 	}
 
 out:
+	/*
+	 * The AX.25 connection of a neighbour that was removed from the tables
+	 * outlives it. If it is still there, the other end will not restart
+	 * the link: do it from here.
+	 */
+	if (new_neigh && res == 0)
+		rose_link_restart(rose_neigh);
+
 	spin_unlock_bh(&rose_neigh_list_lock);
 	spin_unlock_bh(&rose_node_list_lock);
 
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 171/247] ax25: serialise the transmission of I frames on a connection
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (169 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 170/247] rose: restart the link of a neighbour created over a live AX.25 connection Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 172/247] rose: process received frames and send with the socket locked Greg Kroah-Hartman
                   ` (83 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Bernard Pidoux <bernard.f6bvp@gmail.com>

ax25_kick() takes frames off the write queue, numbers them from V(S)
and moves them to the ack queue, with no lock. It is called from
process context by the senders (ax25_output()) and from softirq context
by the receive path and the timers. A connection used by ROSE or NET/ROM
carries several circuits, so ax25_output() can run for the same
connection on two CPUs at once, and against the receive path. Both then
read the same V(S) and two different I frames are sent under the same
N(S). The peer keeps the first and rejects the second; the go-back-N
that follows resends whatever the ack queue holds for that number, and
one of the two frames is never sent again while the AX.25 counters look
consistent on both sides. The layer above sees a hole: a ROSE circuit
receives its frames out of sequence, ignores them, and stays frozen
with its window full.

Seen on a live ROSE node relaying several circuits over one AX.25 link:

  fm F6BVP-9 to F6BVP-13 ctl I55^ pid=1(X.25) len 254   LCI 030 DATA S2
  fm F6BVP-9 to F6BVP-13 ctl I55^ pid=1(X.25) len 254   LCI 02E DATA S2
  fm F6BVP-13 to F6BVP-9 ctl REJ6v

Add a lock to the ax25_cb covering V(S), V(A) and the write and ack
queues, taken in ax25_kick(), ax25_frames_acked() and
ax25_requeue_frames(). The frames are not sent with the lock held,
since ax25_transmit_buffer() may end up in ax25_disconnect(): ax25_kick()
puts the numbered frames on a transmit queue which is emptied, in
order, by one context at a time once the lock is dropped.

Tested in QEMU, two 4-CPU nodes with lockdep and KASAN over a KISS
serial link, four ROSE circuits each sending 400 numbered messages at
the same time: before, every circuit freezes and 300 to 600 of the 1600
messages get through; after, no sender is blocked and more than 1500
get through (the ROSE side needs "rose: process received frames and
send with the socket locked" for the rest: 1600/1600 in order on six
runs out of six with both). No lockdep, KASAN or refcount report.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
[F6BVP: v2: in ax25_frames_acked(), loop on what skb_dequeue() returns
 instead of on skb_peek(): ax25_clear_queues() purges the ack queue
 without ax25->lock, so skb_dequeue() could return NULL and
 __skb_queue_tail() dereference it in softirq context (reported by
 Sasha Levin). Same fix submitted to mod-orphan.]
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
(cherry picked from commit 3f42b974059565c9e60229a9ff1ca21d10334671)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 include/net/ax25.h   |  5 ++++
 net/ax25/af_ax25.c   |  2 ++
 net/ax25/ax25_out.c  | 56 ++++++++++++++++++++++++++++++++++++++++----
 net/ax25/ax25_subr.c | 37 ++++++++++++++++++++++-------
 4 files changed, 88 insertions(+), 12 deletions(-)

diff --git a/include/net/ax25.h b/include/net/ax25.h
index a7bba42dde153..0fe92fa6ef075 100644
--- a/include/net/ax25.h
+++ b/include/net/ax25.h
@@ -252,6 +252,11 @@ typedef struct ax25_cb {
 	struct sk_buff_head	reseq_queue;
 	struct sk_buff_head	ack_queue;
 	struct sk_buff_head	frag_queue;
+	/* I frames numbered by ax25_kick(), waiting to go to the device */
+	struct sk_buff_head	xmit_queue;
+	/* serialises V(S)/V(A) and the write, ack and xmit queues */
+	spinlock_t		lock;
+	unsigned char		xmit_running;
 	unsigned char		window;
 	struct timer_list	timer, dtimer;
 	struct sock		*sk;		/* Backlink to socket */
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index 3ee7dba343100..164e9f46f0e77 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -537,6 +537,8 @@ ax25_cb *ax25_create_cb(void)
 	skb_queue_head_init(&ax25->frag_queue);
 	skb_queue_head_init(&ax25->ack_queue);
 	skb_queue_head_init(&ax25->reseq_queue);
+	skb_queue_head_init(&ax25->xmit_queue);
+	spin_lock_init(&ax25->lock);
 
 	ax25_setup_timers(ax25);
 
diff --git a/net/ax25/ax25_out.c b/net/ax25/ax25_out.c
index 8bca2ace98e51..1b9a91b9c9831 100644
--- a/net/ax25/ax25_out.c
+++ b/net/ax25/ax25_out.c
@@ -218,6 +218,11 @@ void ax25_output(ax25_cb *ax25, int paclen, struct sk_buff *skb)
  *  This procedure is passed a buffer descriptor for an iframe. It builds
  *  the rest of the control part of the frame and then writes it out.
  */
+/*
+ *	Number an I frame and queue it for the device. Called by ax25_kick()
+ *	with ax25->lock held: the frame is sent by ax25_run_xmit_queue() once
+ *	the lock is dropped.
+ */
 static void ax25_send_iframe(ax25_cb *ax25, struct sk_buff *skb, int poll_bit)
 {
 	unsigned char *frame;
@@ -245,7 +250,34 @@ static void ax25_send_iframe(ax25_cb *ax25, struct sk_buff *skb, int poll_bit)
 
 	ax25_start_idletimer(ax25);
 
-	ax25_transmit_buffer(ax25, skb, AX25_COMMAND);
+	skb_queue_tail(&ax25->xmit_queue, skb);
+}
+
+/*
+ *	Hand the frames numbered by ax25_kick() to the device, in order. Only
+ *	one context does it at a time, so that frames queued by two senders
+ *	cannot overtake each other; the one already running picks up whatever
+ *	the others have queued. The lock is not held while transmitting.
+ */
+static void ax25_run_xmit_queue(ax25_cb *ax25)
+{
+	struct sk_buff *skb;
+
+	spin_lock_bh(&ax25->lock);
+	if (ax25->xmit_running) {
+		spin_unlock_bh(&ax25->lock);
+		return;
+	}
+	ax25->xmit_running = 1;
+
+	while ((skb = skb_dequeue(&ax25->xmit_queue)) != NULL) {
+		spin_unlock_bh(&ax25->lock);
+		ax25_transmit_buffer(ax25, skb, AX25_COMMAND);
+		spin_lock_bh(&ax25->lock);
+	}
+
+	ax25->xmit_running = 0;
+	spin_unlock_bh(&ax25->lock);
 }
 
 void ax25_kick(ax25_cb *ax25)
@@ -260,14 +292,25 @@ void ax25_kick(ax25_cb *ax25)
 	if (ax25->condition & AX25_COND_PEER_RX_BUSY)
 		return;
 
+	/*
+	 * ax25_kick() is called from process context by the senders and
+	 * from softirq context by the receive path and the timers, possibly
+	 * for several ROSE or NET/ROM circuits sharing this connection. Two
+	 * of them running here at the same time would read the same V(S) and
+	 * send two different frames under the same N(S); the peer keeps one
+	 * and the other is never sent again. Take the frames off the write
+	 * queue and number them under the lock.
+	 */
+	spin_lock_bh(&ax25->lock);
+
 	if (skb_peek(&ax25->write_queue) == NULL)
-		return;
+		goto out;
 
 	start = (skb_peek(&ax25->ack_queue) == NULL) ? ax25->va : ax25->vs;
 	end   = (ax25->va + ax25->window) % ax25->modulus;
 
 	if (start == end)
-		return;
+		goto out;
 
 	/*
 	 * Transmit data until either we're out of data to send or
@@ -281,7 +324,7 @@ void ax25_kick(ax25_cb *ax25)
 	 */
 	skb  = skb_dequeue(&ax25->write_queue);
 	if (!skb)
-		return;
+		goto out;
 
 	ax25->vs = start;
 
@@ -331,6 +374,11 @@ void ax25_kick(ax25_cb *ax25)
 		ax25_calculate_t1(ax25);
 		ax25_start_t1timer(ax25);
 	}
+
+out:
+	spin_unlock_bh(&ax25->lock);
+
+	ax25_run_xmit_queue(ax25);
 }
 
 void ax25_transmit_buffer(ax25_cb *ax25, struct sk_buff *skb, int type)
diff --git a/net/ax25/ax25_subr.c b/net/ax25/ax25_subr.c
index d0719267e5484..fbfeb09784119 100644
--- a/net/ax25/ax25_subr.c
+++ b/net/ax25/ax25_subr.c
@@ -34,6 +34,7 @@ void ax25_clear_queues(ax25_cb *ax25)
 {
 	skb_queue_purge(&ax25->write_queue);
 	skb_queue_purge(&ax25->ack_queue);
+	skb_queue_purge(&ax25->xmit_queue);
 	skb_queue_purge(&ax25->reseq_queue);
 	skb_queue_purge(&ax25->frag_queue);
 }
@@ -45,31 +46,51 @@ void ax25_clear_queues(ax25_cb *ax25)
  */
 void ax25_frames_acked(ax25_cb *ax25, unsigned short nr)
 {
+	struct sk_buff_head acked;
 	struct sk_buff *skb;
 
+	__skb_queue_head_init(&acked);
+
 	/*
-	 * Remove all the ack-ed frames from the ack queue.
+	 * Remove all the ack-ed frames from the ack queue. ax25_kick() may be
+	 * filling it from another CPU: move V(A) and the queue together, and
+	 * free the frames once the lock is dropped.
 	 */
-	if (ax25->va != nr) {
-		while (skb_peek(&ax25->ack_queue) != NULL && ax25->va != nr) {
-			skb = skb_dequeue(&ax25->ack_queue);
-			kfree_skb(skb);
-			ax25->va = (ax25->va + 1) % ax25->modulus;
-		}
+	spin_lock_bh(&ax25->lock);
+	/*
+	 * ax25_clear_queues() purges the ack queue without ax25->lock: test
+	 * what skb_dequeue() returns, not what skb_peek() saw before it.
+	 */
+	while (ax25->va != nr && (skb = skb_dequeue(&ax25->ack_queue)) != NULL) {
+		__skb_queue_tail(&acked, skb);
+		ax25->va = (ax25->va + 1) % ax25->modulus;
 	}
+	spin_unlock_bh(&ax25->lock);
+
+	__skb_queue_purge(&acked);
 }
 
 void ax25_requeue_frames(ax25_cb *ax25)
 {
+	struct sk_buff_head stale;
 	struct sk_buff *skb;
 
+	__skb_queue_head_init(&stale);
+
 	/*
 	 * Requeue all the un-ack-ed frames on the output queue to be picked
 	 * up by ax25_kick called from the timer. This arrangement handles the
-	 * possibility of an empty output queue.
+	 * possibility of an empty output queue. Copies that ax25_kick() has
+	 * numbered but not sent yet are stale: they will be sent again.
 	 */
+	spin_lock_bh(&ax25->lock);
+	while ((skb = skb_dequeue(&ax25->xmit_queue)) != NULL)
+		__skb_queue_tail(&stale, skb);
 	while ((skb = skb_dequeue_tail(&ax25->ack_queue)) != NULL)
 		skb_queue_head(&ax25->write_queue, skb);
+	spin_unlock_bh(&ax25->lock);
+
+	__skb_queue_purge(&stale);
 }
 
 /*
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 172/247] rose: process received frames and send with the socket locked
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (170 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 171/247] ax25: serialise the transmission of I frames on a connection Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 173/247] ax25: dont create two connections for the same link in ax25_send_frame() Greg Kroah-Hartman
                   ` (82 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Bernard Pidoux <bernard.f6bvp@gmail.com>

rose_kick() takes frames off the write queue, numbers them from V(S)
and moves them to the ack queue. It runs from rose_sendmsg() in process
context and from rose_process_rx_frame() in softirq context, and neither
holds the socket lock. When a frame for the socket is received on one
CPU while a process is sending on another, both read the same V(S) and
two different frames go out under the same N(S), or the queues and
V(S)/V(A) are updated by one while the other walks them. The peer drops
the frames it sees as out of sequence, and since ROSE has no REJ and no
retransmission in state 3 the data is lost for good: messages go
missing from the stream, or the window fills and the circuit freezes.

The timers already take the socket lock and retry when a process owns
it. Do the same for the two remaining paths: rose_sendmsg() calls
rose_kick() under lock_sock(), and received frames go through
rose_rcv_frame(), which takes bh_lock_sock() and queues the frame on the
socket backlog when a process owns the socket, as NET/ROM and X.25 do.

Tested in QEMU, two 4-CPU nodes with lockdep and KASAN over a KISS
serial link, four ROSE circuits each sending 400 numbered messages at
the same time (together with the AX.25 fix "ax25: serialise the
transmission of I frames on a connection", without which the same
happens one layer down): before, 60 to 90 of the 1600 messages are
missing from the streams; after, 1600/1600 delivered in order on six
runs out of six. No lockdep, KASAN or refcount report.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
(cherry picked from commit 831b23b977e1fdf14e51dd9652fd27f30965ecb0)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 include/net/rose.h       |  2 ++
 net/rose/af_rose.c       |  5 +++++
 net/rose/rose_in.c       | 31 +++++++++++++++++++++++++++++++
 net/rose/rose_loopback.c |  2 +-
 net/rose/rose_route.c    |  2 +-
 5 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/include/net/rose.h b/include/net/rose.h
index f5b23c8a11e4d..6ce065480a4e6 100644
--- a/include/net/rose.h
+++ b/include/net/rose.h
@@ -227,6 +227,8 @@ void rose_setup(struct net_device *);
 
 /* rose_in.c */
 int rose_process_rx_frame(struct sock *, struct sk_buff *);
+int rose_rcv_frame(struct sock *sk, struct sk_buff *skb);
+int rose_backlog_rcv(struct sock *sk, struct sk_buff *skb);
 
 /* rose_link.c */
 void rose_start_ftimer(struct rose_neigh *);
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index 420408a5ad61c..d8a86006c7448 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -598,6 +598,7 @@ static int rose_create(struct net *net, struct socket *sock, int protocol,
 	rose = rose_sk(sk);
 
 	sock_init_data(sock, sk);
+	sk->sk_backlog_rcv = rose_backlog_rcv;
 
 	skb_queue_head_init(&rose->ack_queue);
 #ifdef M_BIT
@@ -637,6 +638,7 @@ static struct sock *rose_make_new(struct sock *osk)
 	rose = rose_sk(sk);
 
 	sock_init_data(NULL, sk);
+	sk->sk_backlog_rcv = rose_backlog_rcv;
 
 	skb_queue_head_init(&rose->ack_queue);
 #ifdef M_BIT
@@ -1326,7 +1328,10 @@ static int rose_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
 	skb_queue_tail(&sk->sk_write_queue, skb);	/* Shove it onto the queue */
 #endif
 
+	/* The receive path and the timers run rose_kick() too */
+	lock_sock(sk);
 	rose_kick(sk);
+	release_sock(sk);
 
 	return len;
 }
diff --git a/net/rose/rose_in.c b/net/rose/rose_in.c
index 69b2af24e85a6..7a556254ee790 100644
--- a/net/rose/rose_in.c
+++ b/net/rose/rose_in.c
@@ -309,3 +309,34 @@ int rose_process_rx_frame(struct sock *sk, struct sk_buff *skb)
 
 	return queued;
 }
+
+/*
+ * Frames for a socket are processed with the socket locked, as the timers
+ * already do: rose_kick() may be running in rose_sendmsg() on another CPU,
+ * and two of them reading the same V(S) send two different frames under the
+ * same N(S). If a process owns the socket the frame goes to its backlog and
+ * is processed when the socket is released. Returns non-zero if the skb has
+ * been consumed.
+ */
+int rose_rcv_frame(struct sock *sk, struct sk_buff *skb)
+{
+	int queued;
+
+	bh_lock_sock(sk);
+	if (!sock_owned_by_user(sk))
+		queued = rose_process_rx_frame(sk, skb);
+	else
+		queued = !sk_add_backlog(sk, skb, READ_ONCE(sk->sk_rcvbuf) +
+						  READ_ONCE(sk->sk_sndbuf));
+	bh_unlock_sock(sk);
+
+	return queued;
+}
+
+int rose_backlog_rcv(struct sock *sk, struct sk_buff *skb)
+{
+	if (!rose_process_rx_frame(sk, skb))
+		kfree_skb(skb);
+
+	return 0;
+}
diff --git a/net/rose/rose_loopback.c b/net/rose/rose_loopback.c
index fd4e4795776a3..4e4a473910cc8 100644
--- a/net/rose/rose_loopback.c
+++ b/net/rose/rose_loopback.c
@@ -107,7 +107,7 @@ static void rose_loopback_timer(struct timer_list *unused)
 
 		sk = rose_find_socket(lci_o, rose_loopback_neigh);
 		if (sk) {
-			if (rose_process_rx_frame(sk, skb) == 0)
+			if (rose_rcv_frame(sk, skb) == 0)
 				kfree_skb(skb);
 			continue;
 		}
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c
index 7ae3552c19267..883b204121566 100644
--- a/net/rose/rose_route.c
+++ b/net/rose/rose_route.c
@@ -1017,7 +1017,7 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
 		}
 		else {
 			skb_reset_transport_header(skb);
-			res = rose_process_rx_frame(sk, skb);
+			res = rose_rcv_frame(sk, skb);
 			goto out;
 		}
 	}
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 173/247] ax25: dont create two connections for the same link in ax25_send_frame()
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (171 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 172/247] rose: process received frames and send with the socket locked Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 174/247] ax25: read the connections ax25_dev only once when walking ax25_list Greg Kroah-Hartman
                   ` (81 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Bernard Pidoux <bernard.f6bvp@gmail.com>

ax25_send_frame() looks for an existing connection with ax25_find_cb()
and, when there is none, creates one and adds it to the list. The
lookup and the insertion are not done under the same lock, so two
callers sending to a neighbour at the same time both find nothing and
both create a control block: the same link ends up with several
connections, each sending its own SABM, and the frames queued on the
ones that lose are never delivered.

ROSE and NET/ROM call ax25_send_frame() for every frame they send to a
neighbour, from process context and from softirq context, so this
happens as soon as several circuits start together on a link that is
not established yet.

Add ax25_cb_add_unique(), which searches the list and inserts the new
control block under ax25_list_lock, and returns the existing connection
when another sender got there first; ax25_send_frame() then drops its
own control block and queues the frame on that connection. The SABM is
only sent once the control block is known to be the one in the list.

Tested in QEMU, two 4-CPU nodes with lockdep and KASAN over a KISS
serial link, eight ROSE calls started at the same instant with no AX.25
connection up: before, /proc/net/ax25 shows four connections for the
same pair of callsigns on three runs out of three; after, one. No
lockdep, KASAN or refcount report.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
(cherry picked from commit 2649f91b6dd2c48348975d03e8f94d8e6a09cf71)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 include/net/ax25.h  |  1 +
 net/ax25/af_ax25.c  | 49 ++++++++++++++++++++++++++++++++++++++-------
 net/ax25/ax25_out.c | 16 ++++++++++++---
 3 files changed, 56 insertions(+), 10 deletions(-)

diff --git a/include/net/ax25.h b/include/net/ax25.h
index 0fe92fa6ef075..e3c10a9395944 100644
--- a/include/net/ax25.h
+++ b/include/net/ax25.h
@@ -311,6 +311,7 @@ static inline __be16 ax25_type_trans(struct sk_buff *skb, struct net_device *dev
 extern struct hlist_head ax25_list;
 extern spinlock_t ax25_list_lock;
 void ax25_cb_add(ax25_cb *);
+ax25_cb *ax25_cb_add_unique(ax25_cb *ax25);
 struct sock *ax25_find_listener(ax25_address *, int, struct net_device *, int);
 struct sock *ax25_get_socket(ax25_address *, ax25_address *, int);
 ax25_cb *ax25_find_cb(const ax25_address *, ax25_address *, ax25_digi *,
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index 164e9f46f0e77..9f7bda3b511e3 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -222,12 +222,12 @@ struct sock *ax25_get_socket(ax25_address *my_addr, ax25_address *dest_addr,
  *	Find an AX.25 control block given both ends. It will only pick up
  *	floating AX.25 control blocks or non Raw socket bound control blocks.
  */
-ax25_cb *ax25_find_cb(const ax25_address *src_addr, ax25_address *dest_addr,
-	ax25_digi *digi, struct net_device *dev)
+static ax25_cb *__ax25_find_cb(const ax25_address *src_addr,
+			       ax25_address *dest_addr, ax25_digi *digi,
+			       struct net_device *dev)
 {
 	ax25_cb *s;
 
-	spin_lock_bh(&ax25_list_lock);
 	ax25_for_each(s, &ax25_list) {
 		if (s->sk && s->sk->sk_type != SOCK_SEQPACKET)
 			continue;
@@ -243,19 +243,54 @@ ax25_cb *ax25_find_cb(const ax25_address *src_addr, ax25_address *dest_addr,
 				if (s->digipeat != NULL && s->digipeat->ndigi != 0)
 					continue;
 			}
-			ax25_cb_hold(s);
-			spin_unlock_bh(&ax25_list_lock);
-
 			return s;
 		}
 	}
-	spin_unlock_bh(&ax25_list_lock);
 
 	return NULL;
 }
 
+ax25_cb *ax25_find_cb(const ax25_address *src_addr, ax25_address *dest_addr,
+		      ax25_digi *digi, struct net_device *dev)
+{
+	ax25_cb *s;
+
+	spin_lock_bh(&ax25_list_lock);
+	s = __ax25_find_cb(src_addr, dest_addr, digi, dev);
+	if (s)
+		ax25_cb_hold(s);
+	spin_unlock_bh(&ax25_list_lock);
+
+	return s;
+}
+
 EXPORT_SYMBOL(ax25_find_cb);
 
+/*
+ *	Add a new connection to the list unless one already exists for the
+ *	same addresses, path and device. Returns NULL when the control block
+ *	has been added, or the existing one, held, when there is one: looking
+ *	it up and adding it are done under the same lock, so that two senders
+ *	cannot both create a connection for the same link.
+ */
+ax25_cb *ax25_cb_add_unique(ax25_cb *ax25)
+{
+	ax25_cb *s;
+
+	spin_lock_bh(&ax25_list_lock);
+	s = __ax25_find_cb(&ax25->source_addr, &ax25->dest_addr,
+			   ax25->digipeat, ax25->ax25_dev->dev);
+	if (s) {
+		ax25_cb_hold(s);
+	} else {
+		ax25_cb_hold(ax25);
+		hlist_add_head(&ax25->ax25_node, &ax25_list);
+	}
+	spin_unlock_bh(&ax25_list_lock);
+
+	return s;
+}
+
 void ax25_send_to_raw(ax25_address *addr, struct sk_buff *skb, int proto)
 {
 	ax25_cb *s;
diff --git a/net/ax25/ax25_out.c b/net/ax25/ax25_out.c
index 1b9a91b9c9831..eeb2aa1e2186f 100644
--- a/net/ax25/ax25_out.c
+++ b/net/ax25/ax25_out.c
@@ -32,7 +32,7 @@ static DEFINE_SPINLOCK(ax25_frag_lock);
 ax25_cb *ax25_send_frame(struct sk_buff *skb, int paclen, const ax25_address *src, ax25_address *dest, ax25_digi *digi, struct net_device *dev)
 {
 	ax25_dev *ax25_dev;
-	ax25_cb *ax25;
+	ax25_cb *ax25, *existing;
 
 	/*
 	 * Take the default packet length for the device if zero is
@@ -82,6 +82,18 @@ ax25_cb *ax25_send_frame(struct sk_buff *skb, int paclen, const ax25_address *sr
 		}
 	}
 
+	/*
+	 * Another sender may have created the connection since the lookup
+	 * above: the list is searched again and the new control block added
+	 * under one lock. If we lost, use the other one.
+	 */
+	existing = ax25_cb_add_unique(ax25);
+	if (existing) {
+		ax25_cb_put(ax25);
+		ax25_output(existing, paclen, skb);
+		return existing;
+	}
+
 	switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
 	case AX25_PROTO_STD_SIMPLEX:
 	case AX25_PROTO_STD_DUPLEX:
@@ -104,8 +116,6 @@ ax25_cb *ax25_send_frame(struct sk_buff *skb, int paclen, const ax25_address *sr
 	 */
 	ax25_cb_hold(ax25);
 
-	ax25_cb_add(ax25);
-
 	ax25->state = AX25_STATE_1;
 
 	ax25_start_heartbeat(ax25);
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 174/247] ax25: read the connections ax25_dev only once when walking ax25_list
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (172 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 173/247] ax25: dont create two connections for the same link in ax25_send_frame() Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 175/247] ax25: wait for ax25_send_frame() before detaching the connections of a device Greg Kroah-Hartman
                   ` (80 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Bernard Pidoux <bernard.f6bvp@gmail.com>

ax25_kill_by_device() detaches a connection from a device that goes
down by setting s->ax25_dev to NULL. It does so after it has dropped
ax25_list_lock, while the connection is still on ax25_list.

__ax25_find_cb() and ax25_find_listener() walk that list and test
s->ax25_dev against NULL before they dereference it, but they load the
pointer a second time for the dereference. ax25_send_to_raw()
dereferences it without any test. If ax25_kill_by_device() clears the
pointer in between, the walker dereferences NULL:

  Oops: general protection fault, probably for non-canonical address
  KASAN: null-ptr-deref in range [0x0000000000000010-0x0000000000000017]
  RIP: 0010:ax25_find_cb+0x121/0x330 [ax25]
   ax25_send_frame+0xdc/0x980 [ax25]
   rose_send_frame+0xce/0x270 [rose]
   rose_transmit_restart_request+0x1b3/0x260 [rose]
   rose_transmit_link+0x31d/0x560 [rose]
   rose_write_internal+0x3ab/0x15b0 [rose]
   rose_release+0x2b2/0x4b0 [rose]

Load the pointer once in the three walkers and use that value, and add
the missing NULL test to ax25_send_to_raw(). The ax25_dev itself cannot
go away under the walker: ax25_kill_by_device() has to take
ax25_list_lock again, in ax25_cb_del(), before the device teardown gets
as far as freeing it.

The oops above was obtained on 6.12.94 with KASAN, after 382 seconds of
the syzbot C reproducer of the ax25_find_cb() use-after-free report,
with the interface brought up again in a loop, while testing an earlier
version of the next patch. With this series the same test runs for 600
seconds without an oops.

Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
Assisted-by: Claude:claude-opus-5-5
(cherry picked from commit 3696f3cf8690e335a2cc7e8103f018bc205de738)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/ax25/af_ax25.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index 9f7bda3b511e3..0a5cd835d289d 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -91,7 +91,7 @@ static void ax25_kill_by_device(struct net_device *dev)
 			if (!sk) {
 				spin_unlock_bh(&ax25_list_lock);
 				ax25_disconnect(s, ENETUNREACH);
-				s->ax25_dev = NULL;
+				WRITE_ONCE(s->ax25_dev, NULL);
 				ax25_cb_del(s);
 				spin_lock_bh(&ax25_list_lock);
 				goto again;
@@ -100,7 +100,7 @@ static void ax25_kill_by_device(struct net_device *dev)
 			spin_unlock_bh(&ax25_list_lock);
 			lock_sock(sk);
 			ax25_disconnect(s, ENETUNREACH);
-			s->ax25_dev = NULL;
+			WRITE_ONCE(s->ax25_dev, NULL);
 			if (sk->sk_socket) {
 				netdev_put(ax25_dev->dev,
 					   &s->dev_tracker);
@@ -172,6 +172,7 @@ void ax25_cb_add(ax25_cb *ax25)
 struct sock *ax25_find_listener(ax25_address *addr, int digi,
 	struct net_device *dev, int type)
 {
+	ax25_dev *ax25_dev;
 	ax25_cb *s;
 
 	spin_lock(&ax25_list_lock);
@@ -181,7 +182,8 @@ struct sock *ax25_find_listener(ax25_address *addr, int digi,
 		if (s->sk && !ax25cmp(&s->source_addr, addr) &&
 		    s->sk->sk_type == type && s->sk->sk_state == TCP_LISTEN) {
 			/* If device is null we match any device */
-			if (s->ax25_dev == NULL || s->ax25_dev->dev == dev) {
+			ax25_dev = READ_ONCE(s->ax25_dev);
+			if (ax25_dev == NULL || ax25_dev->dev == dev) {
 				sock_hold(s->sk);
 				spin_unlock(&ax25_list_lock);
 				return s->sk;
@@ -226,14 +228,16 @@ static ax25_cb *__ax25_find_cb(const ax25_address *src_addr,
 			       ax25_address *dest_addr, ax25_digi *digi,
 			       struct net_device *dev)
 {
+	ax25_dev *ax25_dev;
 	ax25_cb *s;
 
 	ax25_for_each(s, &ax25_list) {
 		if (s->sk && s->sk->sk_type != SOCK_SEQPACKET)
 			continue;
-		if (s->ax25_dev == NULL)
+		ax25_dev = READ_ONCE(s->ax25_dev);
+		if (ax25_dev == NULL)
 			continue;
-		if (ax25cmp(&s->source_addr, src_addr) == 0 && ax25cmp(&s->dest_addr, dest_addr) == 0 && s->ax25_dev->dev == dev) {
+		if (ax25cmp(&s->source_addr, src_addr) == 0 && ax25cmp(&s->dest_addr, dest_addr) == 0 && ax25_dev->dev == dev) {
 			if (digi != NULL && digi->ndigi != 0) {
 				if (s->digipeat == NULL)
 					continue;
@@ -293,15 +297,17 @@ ax25_cb *ax25_cb_add_unique(ax25_cb *ax25)
 
 void ax25_send_to_raw(ax25_address *addr, struct sk_buff *skb, int proto)
 {
+	ax25_dev *ax25_dev;
 	ax25_cb *s;
 	struct sk_buff *copy;
 
 	spin_lock(&ax25_list_lock);
 	ax25_for_each(s, &ax25_list) {
+		ax25_dev = READ_ONCE(s->ax25_dev);
 		if (s->sk != NULL && ax25cmp(&s->source_addr, addr) == 0 &&
 		    s->sk->sk_type == SOCK_RAW &&
 		    s->sk->sk_protocol == proto &&
-		    s->ax25_dev->dev == skb->dev &&
+		    ax25_dev && ax25_dev->dev == skb->dev &&
 		    atomic_read(&s->sk->sk_rmem_alloc) <= s->sk->sk_rcvbuf) {
 			if ((copy = skb_clone(skb, GFP_ATOMIC)) == NULL)
 				continue;
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 175/247] ax25: wait for ax25_send_frame() before detaching the connections of a device
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (173 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 174/247] ax25: read the connections ax25_dev only once when walking ax25_list Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 176/247] ax25: dont accept frames on a device that is going down Greg Kroah-Hartman
                   ` (79 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, syzbot+caa052a0958a9146870d,
	Bernard Pidoux, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Bernard Pidoux <bernard.f6bvp@gmail.com>

A connection created by ax25_send_frame(), for ROSE, NET/ROM or IP
over AX.25, points to the ax25_dev of its device without holding a
reference on it. It relies on ax25_kill_by_device() to detach it when
the device goes down, before ax25_dev_device_down() frees the ax25_dev.

On NETDEV_DOWN the two run one after the other. In between, the
ax25_dev is still on ax25_dev_list, so ax25_send_frame() still finds
it, creates a connection and adds it to ax25_list after
ax25_kill_by_device() has finished walking that list. The connection is
left with a pointer to an ax25_dev that is freed a moment later, which
ax25_find_cb() and the AX.25 timers then dereference:

  BUG: KASAN: slab-use-after-free in ax25_find_cb+0x2ed/0x330 [ax25]
  Read of size 8 at addr ffff8880031e8c10 by task repro/3287
   ax25_find_cb+0x2ed/0x330 [ax25]
   rose_transmit_link+0xea/0x560 [rose]
   rose_write_internal+0x3ab/0x15b0 [rose]
   rose_release+0x2b2/0x4b0 [rose]
  Allocated by: ax25_dev_device_up, ax25_device_event
  Freed by: kfree_rcu_monitor, queued from ax25_device_event
  The buggy address is located 16 bytes inside of
   freed 256-byte region, cache kmalloc-256

This is the trace of the syzbot report below. An earlier commit, "rose:
use timer_shutdown_sync() for t0timer teardown", attributed that
report to the ROSE t0 timer; the freed object in the report is the
ax25_dev, as it is here.

A connection that is on the list in time is not safe either while it
is still being set up: ax25_kill_by_device() can detach it, clearing
its ax25_dev pointer, between the moment ax25_send_frame() adds it and
the moment it starts the link and queues the frame, which then
dereference NULL.

Make the two exclude each other with RCU. ax25_send_frame() now runs
entirely under rcu_read_lock() and gives up when the device is no
longer marked up. ax25_kill_by_device() clears device_up and calls
synchronize_rcu() before it walks the list: once that returns, every
connection ax25_send_frame() was working on is complete and on the
list, and no new one can appear behind the walk. This adds one RCU
grace period to taking an AX.25 interface down.

Tested on 6.12.94 with KASAN and lockdep, with the modules of this
tree and the rest of this series:

 - with a 100 ms delay inserted between ax25_kill_by_device() and
   ax25_dev_device_down(), a single "ifconfig bpq0 down" during eight
   ROSE call requests left connections on the list and ended in a
   use-after-free in ax25_heartbeat_expiry(); with the series the list
   is empty after the down and there is no report;

 - the syzbot C reproducer, with the interface brought up again in a
   loop, caused 217 KASAN reports and a panic after 41 seconds; with
   the series it ran for 600 seconds without any report;

 - 60 plain "ifconfig bpq0 down" / "up" under 20 ROSE call requests
   per second, and a ROSE call through a three node chain over mkiss,
   behave as before;

 - eight ROSE calls started at the same instant still end up on a
   single AX.25 connection.

Reported-by: syzbot+caa052a0958a9146870d@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=caa052a0958a9146870d
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
Assisted-by: Claude:claude-opus-5-5
(cherry picked from commit 45071a40f7d5db10350dbd177decd3f68fdaaa01)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/ax25/af_ax25.c  | 12 +++++++++++-
 net/ax25/ax25_out.c | 38 ++++++++++++++++++++------------------
 2 files changed, 31 insertions(+), 19 deletions(-)

diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index 0a5cd835d289d..11ac6c83b1442 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -81,7 +81,17 @@ static void ax25_kill_by_device(struct net_device *dev)
 
 	if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL)
 		return;
-	ax25_dev->device_up = false;
+	WRITE_ONCE(ax25_dev->device_up, false);
+
+	/*
+	 * ax25_send_frame() creates connections that hold no reference on
+	 * the ax25_dev: they rely on the walk below to detach them before the
+	 * ax25_dev is freed. It runs under rcu_read_lock() and gives up when
+	 * device_up is clear, so once this returns every connection it was
+	 * setting up is complete and on the list, and no new one can appear
+	 * behind the walk.
+	 */
+	synchronize_rcu();
 
 	spin_lock_bh(&ax25_list_lock);
 again:
diff --git a/net/ax25/ax25_out.c b/net/ax25/ax25_out.c
index eeb2aa1e2186f..f082b69126623 100644
--- a/net/ax25/ax25_out.c
+++ b/net/ax25/ax25_out.c
@@ -34,34 +34,34 @@ ax25_cb *ax25_send_frame(struct sk_buff *skb, int paclen, const ax25_address *sr
 	ax25_dev *ax25_dev;
 	ax25_cb *ax25, *existing;
 
+	/*
+	 * The connection made or used here holds no reference on the
+	 * ax25_dev. ax25_kill_by_device() clears device_up, waits for the RCU
+	 * readers and only then detaches the connections of the device: stay
+	 * under the RCU read lock until the frame is queued, and do not start
+	 * anything on a device that is going down.
+	 */
+	rcu_read_lock();
+	ax25_dev = ax25_dev_ax25dev(dev);
+	if (!ax25_dev || !READ_ONCE(ax25_dev->device_up)) {
+		rcu_read_unlock();
+		return NULL;
+	}
+
 	/*
 	 * Take the default packet length for the device if zero is
 	 * specified.
 	 */
-	if (paclen == 0) {
-		rcu_read_lock();
-		ax25_dev = ax25_dev_ax25dev(dev);
-		if (!ax25_dev) {
-			rcu_read_unlock();
-			return NULL;
-		}
+	if (paclen == 0)
 		paclen = ax25_dev->values[AX25_VALUES_PACLEN];
-		rcu_read_unlock();
-	}
 
 	/*
 	 * Look for an existing connection.
 	 */
 	if ((ax25 = ax25_find_cb(src, dest, digi, dev)) != NULL) {
 		ax25_output(ax25, paclen, skb);
-		return ax25;		/* It already existed */
-	}
-
-	rcu_read_lock();
-	ax25_dev = ax25_dev_ax25dev(dev);
-	if (!ax25_dev) {
 		rcu_read_unlock();
-		return NULL;
+		return ax25;		/* It already existed */
 	}
 
 	if ((ax25 = ax25_create_cb()) == NULL) {
@@ -69,7 +69,6 @@ ax25_cb *ax25_send_frame(struct sk_buff *skb, int paclen, const ax25_address *sr
 		return NULL;
 	}
 	ax25_fillin_cb(ax25, ax25_dev);
-	rcu_read_unlock();
 
 	ax25->source_addr = *src;
 	ax25->dest_addr   = *dest;
@@ -78,6 +77,7 @@ ax25_cb *ax25_send_frame(struct sk_buff *skb, int paclen, const ax25_address *sr
 		ax25->digipeat = kmemdup(digi, sizeof(*digi), GFP_ATOMIC);
 		if (ax25->digipeat == NULL) {
 			ax25_cb_put(ax25);
+			rcu_read_unlock();
 			return NULL;
 		}
 	}
@@ -91,10 +91,11 @@ ax25_cb *ax25_send_frame(struct sk_buff *skb, int paclen, const ax25_address *sr
 	if (existing) {
 		ax25_cb_put(ax25);
 		ax25_output(existing, paclen, skb);
+		rcu_read_unlock();
 		return existing;
 	}
 
-	switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
+	switch (ax25_dev->values[AX25_VALUES_PROTOCOL]) {
 	case AX25_PROTO_STD_SIMPLEX:
 	case AX25_PROTO_STD_DUPLEX:
 		ax25_std_establish_data_link(ax25);
@@ -121,6 +122,7 @@ ax25_cb *ax25_send_frame(struct sk_buff *skb, int paclen, const ax25_address *sr
 	ax25_start_heartbeat(ax25);
 
 	ax25_output(ax25, paclen, skb);
+	rcu_read_unlock();
 
 	return ax25;			/* We had to create it */
 }
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 176/247] ax25: dont accept frames on a device that is going down
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (174 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 175/247] ax25: wait for ax25_send_frame() before detaching the connections of a device Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 177/247] ax25: send a private copy of each I frame Greg Kroah-Hartman
                   ` (78 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Bernard Pidoux <bernard.f6bvp@gmail.com>

ax25_rcv() creates a connection on an incoming SABM, for a listening
socket or for a callsign registered by ROSE or NET/ROM. Like the ones
made by ax25_send_frame(), it holds no reference on the ax25_dev and
relies on ax25_kill_by_device() to detach it before the ax25_dev is
freed. If it is added to ax25_list after ax25_kill_by_device() has
walked the list, it is left pointing to a freed ax25_dev.

ax25_rcv() is called from the packet type handler, under
rcu_read_lock(), and ax25_kill_by_device() now clears device_up and
waits for the RCU readers before its walk. Drop the frame when
device_up is clear: a frame that gets past the test is fully processed
before the walk starts, and none is processed behind it.

The window is much smaller than for ax25_send_frame(): the core already
drops what is received on a device that is no longer running, so only a
frame that was queued before the device was stopped and is processed
late can hit it. I could not exercise it. The change was checked for
regressions only: incoming connections still work in the ROSE tests of
the previous patch, where every AX.25 link is opened by an incoming
SABM on one side.

Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
Assisted-by: Claude:claude-opus-5-5
(cherry picked from commit 748551f72b27325043eafe969311b15ae1eb0c7c)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/ax25/af_ax25.c | 12 ++++++------
 net/ax25/ax25_in.c |  9 +++++++++
 2 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index 11ac6c83b1442..95224600b5a13 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -84,12 +84,12 @@ static void ax25_kill_by_device(struct net_device *dev)
 	WRITE_ONCE(ax25_dev->device_up, false);
 
 	/*
-	 * ax25_send_frame() creates connections that hold no reference on
-	 * the ax25_dev: they rely on the walk below to detach them before the
-	 * ax25_dev is freed. It runs under rcu_read_lock() and gives up when
-	 * device_up is clear, so once this returns every connection it was
-	 * setting up is complete and on the list, and no new one can appear
-	 * behind the walk.
+	 * ax25_send_frame() and ax25_rcv() create connections that hold no
+	 * reference on the ax25_dev: they rely on the walk below to detach
+	 * them before the ax25_dev is freed. Both run under rcu_read_lock()
+	 * and give up when device_up is clear, so once this returns every
+	 * connection they were setting up is complete and on the list, and
+	 * no new one can appear behind the walk.
 	 */
 	synchronize_rcu();
 
diff --git a/net/ax25/ax25_in.c b/net/ax25/ax25_in.c
index 18e15c3c26e46..c81bc8c4563b5 100644
--- a/net/ax25/ax25_in.c
+++ b/net/ax25/ax25_in.c
@@ -216,6 +216,15 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev,
 	if (skb_linearize(skb))
 		goto free;
 
+	/*
+	 * A connection made below on an incoming SABM holds no reference on
+	 * the ax25_dev either. We are called under rcu_read_lock(), which
+	 * ax25_kill_by_device() waits for after it has cleared device_up:
+	 * leave a device that is going down alone.
+	 */
+	if (!READ_ONCE(ax25_dev->device_up))
+		goto free;
+
 	/*
 	 *	Parse the address header.
 	 */
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 177/247] ax25: send a private copy of each I frame
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (175 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 176/247] ax25: dont accept frames on a device that is going down Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 178/247] rose: clear the circuits of a neighbour that restarts the link Greg Kroah-Hartman
                   ` (77 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Bernard Pidoux <bernard.f6bvp@gmail.com>

ax25_kick() keeps every I frame on the ack queue until it is
acknowledged and hands a clone of it to the device. After a REJ or a T1
timeout the frame goes back to the write queue and ax25_kick() clones it
again. A clone shares its data with the original, so ax25_send_iframe()
and ax25_transmit_buffer() write the control field and the address
header of the new clone in the very bytes used by the previous one. If
the previous clone is still waiting in the device queue, its control
field is rewritten there: it leaves with the N(R) current at the time
of the retransmission, not the one it was sent with.

Frames queued behind it, an RR for instance, were built in between with
a lower N(R). The peer then receives an N(R) lower than one it has
already been given. ax25_validate_nr() rejects it and
ax25_std_nr_error_recovery() resets the link with a SABM, in the middle
of a transfer. The layers above pay for it: on a ROSE circuit, the
frames replayed after the reset carry stale sequence numbers and the
circuit is reset as well, with loss of data.

Hand a private copy to the device instead. The frames are small (256
bytes of data by default) and the link is slow, the extra copy is not
measurable.

Found on a test bench: two virtual machines with four CPUs each, a
6.12.94 kernel with KASAN and lockdep, one ROSE circuit over an AX.25
link on a serial line (mkiss), 192 messages each way in bursts of 24,
and three REJ frames injected by one side. Instrumentation showed that
frames reached the driver in the order they were given to
dev_queue_xmit(), that V(R) never went backwards on the sender, and
that the driver nevertheless saw frames whose N(R) was lower than the
one before.

Counting, on the receiver, the frames whose N(R) is lower than the
previous one:

 - this code plus the two pending AX.25 fixes used on the bench (REJ
   guard, requeue on re-establishment): 4 runs, 13 such frames, 4 link
   resets; with this patch: 6 runs, none, no link reset;
 - the same with the transmit serialisation patches for AX.25 and ROSE
   on top: link resets in most runs before; with this patch: 6 runs,
   none, no link reset, no ROSE reset, 192/192 messages both ways in
   every run.

Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
Assisted-by: Claude:claude-opus-5-5
(cherry picked from commit 1b464137f3173fadf81a7a1bf4a9584ebaf72c7b)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/ax25/ax25_out.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/net/ax25/ax25_out.c b/net/ax25/ax25_out.c
index f082b69126623..7c4ebef5ae6c2 100644
--- a/net/ax25/ax25_out.c
+++ b/net/ax25/ax25_out.c
@@ -341,7 +341,16 @@ void ax25_kick(ax25_cb *ax25)
 	ax25->vs = start;
 
 	do {
-		if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
+		/*
+		 * Send a private copy, not a clone. The frame stays on the
+		 * ack queue and is sent again after a REJ or a T1 timeout,
+		 * while the previous copy may still be waiting in the device
+		 * queue. A clone shares its data with the original: building
+		 * the frame again would rewrite the control field, and so
+		 * the N(R), of the copy already queued.
+		 */
+		skbn = skb_copy(skb, GFP_ATOMIC);
+		if (!skbn) {
 			skb_queue_head(&ax25->write_queue, skb);
 			break;
 		}
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 178/247] rose: clear the circuits of a neighbour that restarts the link
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (176 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 177/247] ax25: send a private copy of each I frame Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 179/247] ax25: send unacknowledged I frames again when a link is re-established Greg Kroah-Hartman
                   ` (76 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Bernard Pidoux <bernard.f6bvp@gmail.com>

A Restart Request is the X.25 way to say that every virtual circuit of
a link is gone. rose_link_rx_restart() only marks the neighbour as
restarted and answers with a Restart Confirmation: the sockets and the
through routes that used the link are left as they were.

That is harmless on a link coming up, nothing is established yet. It
is not when the other end restarts its AX.25 and ROSE stack while we
keep the link: the first thing it sends is a SABM, which resets our
AX.25 connection without bringing it down, then a Restart Request. Its
circuits are gone, ours stay in state 3 forever:

 - a frame for a logical channel that the other end does not know is
   dropped silently by rose_route_frame(), so no Clear Request ever
   comes back;
 - no timer watches the acknowledgement of data in state 3, and the
   idle timer is off by default;
 - the through routes stay in /proc/net/rose_routes and the remote
   ends of those calls are never told.

The stale entries are not just a leak. The restarted end allocates its
logical channel numbers afresh, so a new circuit can get the number of
a stale through route on the same link, and whatever still arrives on
the stale half is then relayed into the new circuit.

Seen on a live network: a node that restarts its stack from cron left,
on each of three neighbours, a data circuit with five unacknowledged
frames that never moved again, and five through routes on the node
that relays for the others.

Clear them when a Restart Request arrives on a link that is already
up: send a Clear Request to the other half of each through route and
drop the route, and disconnect the local sockets, as rose_link_failed()
does when the link goes down. The loop of rose_del_route_by_neigh() is
moved to a helper for that, since the caller here already holds
rose_route_list_lock. Nothing is sent to the restarting neighbour: it
has no circuit left, and a Clear Request could hit a call it has just
placed on a reused channel number.

A link that is not up yet is left alone: nothing can be established
over it, and the sockets found there are calls waiting in neigh->queue
for the restart to complete.

Tested with three QEMU guests in a line, A - B - C, on a kernel with
lockdep and KASAN. A calls C through B and B calls C, both circuits
stay open, then C destroys and recreates its AX.25 interface, reloads
its routes and calls B. Before: both circuits are still open a minute
later, B keeps the through route, nobody is told. After: A and B get
the circuit cleared (cause 0x09) within a second of the Restart
Request, B has no through route left, and the new call from C goes
through at the first attempt. Four runs, no lockdep, KASAN or refcount
report.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
Assisted-by: Claude:claude-opus-5-5
(cherry picked from commit 34de1b990c7c690c19594a49ee5b9a74883baf2b)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 include/net/rose.h    |  1 +
 net/rose/rose_link.c  |  8 ++++++++
 net/rose/rose_route.c | 44 +++++++++++++++++++++++++++++++++----------
 3 files changed, 43 insertions(+), 10 deletions(-)

diff --git a/include/net/rose.h b/include/net/rose.h
index 6ce065480a4e6..2820b7e4697e6 100644
--- a/include/net/rose.h
+++ b/include/net/rose.h
@@ -269,6 +269,7 @@ struct rose_neigh *rose_get_neigh(rose_address *, unsigned char *,
 				  unsigned char *, int);
 int rose_rt_ioctl(unsigned int, void __user *);
 void rose_link_failed(ax25_cb *, int);
+void rose_link_restarted(struct rose_neigh *);
 int rose_route_frame(struct sk_buff *, ax25_cb *);
 void rose_rt_free(void);
 
diff --git a/net/rose/rose_link.c b/net/rose/rose_link.c
index 64ae309441a74..76032148a95eb 100644
--- a/net/rose/rose_link.c
+++ b/net/rose/rose_link.c
@@ -142,6 +142,14 @@ void rose_link_rx_restart(struct sk_buff *skb, struct rose_neigh *neigh, unsigne
 
 	switch (frametype) {
 	case ROSE_RESTART_REQUEST:
+		/*
+		 * A Restart Request on a link that is already up means that
+		 * the other end has lost its virtual circuits, clear ours.
+		 * Nothing is established over a link that is not up yet, and
+		 * the calls waiting in neigh->queue must be left alone.
+		 */
+		if (neigh->restarted)
+			rose_link_restarted(neigh);
 		rose_stop_t0timer(neigh);
 		neigh->restarted = 1;
 		neigh->dce_mode  = (skb->data[3] == ROSE_DTE_ORIGINATED);
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c
index 883b204121566..68a4f2385277b 100644
--- a/net/rose/rose_route.c
+++ b/net/rose/rose_route.c
@@ -827,19 +827,15 @@ int rose_rt_ioctl(unsigned int cmd, void __user *arg)
 	return 0;
 }
 
-static void rose_del_route_by_neigh(struct rose_neigh *rose_neigh)
+/*
+ *	Blow away the through routes using this neighbour: the half on the
+ *	neighbour is dropped and the other half is told with a Clear Request.
+ *	The caller holds rose_route_list_lock.
+ */
+static void rose_clear_routes_by_neigh(struct rose_neigh *rose_neigh)
 {
 	struct rose_route *rose_route, *s;
 
-	rose_neigh->restarted = 0;
-
-	rose_stop_t0timer(rose_neigh);
-	rose_start_ftimer(rose_neigh);
-
-	skb_queue_purge(&rose_neigh->queue);
-
-	spin_lock_bh(&rose_route_list_lock);
-
 	rose_route = rose_route_list;
 
 	while (rose_route != NULL) {
@@ -866,9 +862,37 @@ static void rose_del_route_by_neigh(struct rose_neigh *rose_neigh)
 
 		rose_route = rose_route->next;
 	}
+}
+
+static void rose_del_route_by_neigh(struct rose_neigh *rose_neigh)
+{
+	rose_neigh->restarted = 0;
+
+	rose_stop_t0timer(rose_neigh);
+	rose_start_ftimer(rose_neigh);
+
+	skb_queue_purge(&rose_neigh->queue);
+
+	spin_lock_bh(&rose_route_list_lock);
+	rose_clear_routes_by_neigh(rose_neigh);
 	spin_unlock_bh(&rose_route_list_lock);
 }
 
+/*
+ *	The neighbour has restarted a link that was up: it has lost every
+ *	virtual circuit that ran over it. Blow away the through routes and
+ *	the connections using this neighbour, the link itself stays up.
+ *	Called from rose_route_frame() with rose_neigh_list_lock and
+ *	rose_route_list_lock held.
+ */
+void rose_link_restarted(struct rose_neigh *rose_neigh)
+{
+	lockdep_assert_held(&rose_route_list_lock);
+
+	rose_clear_routes_by_neigh(rose_neigh);
+	rose_kill_by_neigh(rose_neigh);
+}
+
 /*
  * 	A level 2 link has timed out, therefore it appears to be a poor link,
  *	then don't use that neighbour until it is reset. Blow away all through
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 179/247] ax25: send unacknowledged I frames again when a link is re-established
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (177 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 178/247] rose: clear the circuits of a neighbour that restarts the link Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 180/247] rose: bring up the link of the preferred route passed over by a connect request Greg Kroah-Hartman
                   ` (75 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Bernard Pidoux <bernard.f6bvp@gmail.com>

When a connection goes back through state 1 from state 3 or 4 (invalid
N(R), FRMR, illegal frame), the UA that re-establishes it resets V(S),
V(A) and V(R) but leaves the I frames that were waiting for their
acknowledgment in the ack queue. From then on every acknowledgment
frees the frame at the head of the queue, an old one, instead of the
one it is for, so the queue keeps that many frames too many for ever:

- they stay charged to the socket that sent them, whose send memory is
  never given back;
- they are sent again by the next go-back-N, long after the event, and
  the peer gets duplicates;
- they were not sent again when the link came back, so the layer above
  lost them.

Seen on a live ROSE node: an AX.25 connection in state 3 with
V(S) == V(A), empty write queue and 18 frames in its ack queue, and the
ROSE sockets using it showing a send queue that never drains.

Requeue those frames when the UA is received, as is already done when
the peer resets the link with a SABM in state 3 or 4. Same change in
the DAMA slave state machine.

Like that existing path, this can send again a frame that the peer had
received just before the reset: AX.25 has no way to know. The layer
above sees a duplicate instead of a silent loss. ROSE drops an exact
duplicate, but resets the circuit when the replayed frame carries an
N(R) that is no longer valid. On the nodes below those resets came
with link re-establishments caused by a late N(R), which "ax25: send a
private copy of each I frame" removes: with both patches the node that
is instrumented saw no re-establishment and no reset in 49 hours,
against five resets in the 47 hours before.

Tested in QEMU (6.12.94 with lockdep and KASAN), two nodes over a
mkiss serial link, one ROSE circuit, 40 messages 150 ms apart, the
link forced through state 1 three times by an injected FRMR. Before:
6 runs of 6 deliver 40/40 and leave one frame in the ack queue, the
ROSE socket keeps 960 bytes of send memory. After: 6 of 6 deliver
40/40 and the send memory goes back to zero. No lockdep, KASAN or
refcount report.

On four production nodes since 3 October 2026, six since 6 October. A
relay node that had 18 to 20 such frames on one link is sampled every
hour: 124 samples and 1301 link states in five days, none with a frame
left in an ack queue.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
Assisted-by: Claude:claude-opus-5-5
(cherry picked from commit 7b22827cb729de19ccba284ebaff3eeee21d4f11)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/ax25/ax25_ds_in.c  | 2 ++
 net/ax25/ax25_std_in.c | 8 ++++++++
 2 files changed, 10 insertions(+)

diff --git a/net/ax25/ax25_ds_in.c b/net/ax25/ax25_ds_in.c
index c62f8fb06189e..b78a577760c6f 100644
--- a/net/ax25/ax25_ds_in.c
+++ b/net/ax25/ax25_ds_in.c
@@ -58,6 +58,8 @@ static int ax25_ds_state1_machine(ax25_cb *ax25, struct sk_buff *skb, int framet
 		ax25->vr      = 0;
 		ax25->state   = AX25_STATE_3;
 		ax25->n2count = 0;
+		/* I frames left unacknowledged by a link reset: send them again */
+		ax25_requeue_frames(ax25);
 		if (ax25->sk != NULL) {
 			bh_lock_sock(ax25->sk);
 			ax25->sk->sk_state = TCP_ESTABLISHED;
diff --git a/net/ax25/ax25_std_in.c b/net/ax25/ax25_std_in.c
index f280683f83fcf..d0269ece4fc58 100644
--- a/net/ax25/ax25_std_in.c
+++ b/net/ax25/ax25_std_in.c
@@ -66,6 +66,14 @@ static int ax25_std_state1_machine(ax25_cb *ax25, struct sk_buff *skb, int frame
 			ax25->vr      = 0;
 			ax25->state   = AX25_STATE_3;
 			ax25->n2count = 0;
+			/*
+			 * The link may have been re-established from state
+			 * 3 or 4 with I frames still waiting for their
+			 * acknowledgment. V(S) and V(A) start again from
+			 * zero: send those frames again, as is done when
+			 * the peer resets the link with a SABM.
+			 */
+			ax25_requeue_frames(ax25);
 			if (ax25->sk != NULL) {
 				bh_lock_sock(ax25->sk);
 				ax25->sk->sk_state = TCP_ESTABLISHED;
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 180/247] rose: bring up the link of the preferred route passed over by a connect request
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (178 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 179/247] ax25: send unacknowledged I frames again when a link is re-established Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 181/247] ax25: dont free an incoming SABM skb left on the listeners queue Greg Kroah-Hartman
                   ` (74 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Bernard Pidoux <bernard.f6bvp@gmail.com>

For a connect request rose_get_neigh() walks the routes that match the
address, from the most specific to the least specific, and takes the
first neighbour whose link is restarted. A neighbour whose link is down
is only used when no matching route at all has a restarted neighbour.

A node that has both an exact route to a neighbouring node and a wide
route through a relay therefore never uses the exact route once its
link is down: the relay is restarted, it is always found first, and
since no frame is ever sent over the direct link nothing brings it up
again. The calls keep going through the relay, which may have no route
other than back to the calling node and then clears them. Seen on a node
whose White Pages daemon calls an adjacent node: every call goes to the
relay and comes back as CLEAR REQUEST "not obtainable", for as long as
the node runs.

Keep sending the call to the restarted neighbour, so that a call never
waits for a link that may not answer, but when a neighbour of a more
specific route, or an earlier neighbour of the same route, was passed
over because its link is down, start the restart procedure on that link.
If the other end answers, the next call finds the link restarted and
uses it. A link that has just failed is left alone for
link_fail_timeout, and nothing is done while a restart is under way.

Frames in transit are handled as before.

Tested in QEMU with a lockdep and KASAN kernel, three nodes A - B - C
where B has an exact route to C over their direct link and a wide route
through A, and the link B - A is restarted while B - C is not. Before,
every call from B to C goes to A and is cleared there, and the direct
link stays down. After, the first call still goes to A, the direct link
is restarted within 20 ms and the following calls go through it. With C
switched off no call waits: they all go to A at once, the restart is
attempted once, and after the AX.25 connection gives up the link is left
alone for link_fail_timeout. A call from A to C in transit through B
gets the same answer before and after. No lockdep, KASAN or refcount
report.

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
(cherry picked from commit cdf5a2eba2bc4f79dabb013a3a935f54aedb85e9)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 include/net/rose.h    |  1 +
 net/rose/rose_link.c  | 14 ++++++++++++++
 net/rose/rose_route.c | 14 ++++++++++++++
 3 files changed, 29 insertions(+)

diff --git a/include/net/rose.h b/include/net/rose.h
index 2820b7e4697e6..2fa0331e36f09 100644
--- a/include/net/rose.h
+++ b/include/net/rose.h
@@ -240,6 +240,7 @@ void rose_link_rx_restart(struct sk_buff *, struct rose_neigh *,
 void rose_transmit_clear_request(struct rose_neigh *, unsigned int,
 				 unsigned char, unsigned char);
 void rose_link_restart(struct rose_neigh *neigh);
+void rose_link_bring_up(struct rose_neigh *neigh);
 void rose_transmit_link(struct sk_buff *, struct rose_neigh *);
 
 /* rose_loopback.c */
diff --git a/net/rose/rose_link.c b/net/rose/rose_link.c
index 76032148a95eb..9cfd4aa174f81 100644
--- a/net/rose/rose_link.c
+++ b/net/rose/rose_link.c
@@ -287,6 +287,20 @@ void rose_link_restart(struct rose_neigh *neigh)
 	rose_start_t0timer(neigh);
 }
 
+/*
+ * Start the restart procedure on a link that is down without waiting for
+ * a frame to send over it. Nothing is done while a restart is under way.
+ */
+void rose_link_bring_up(struct rose_neigh *neigh)
+{
+	if (neigh->loopback || neigh->restarted || rose_t0timer_running(neigh))
+		return;
+
+	rose_transmit_restart_request(neigh);
+	neigh->dce_mode = 0;
+	rose_start_t0timer(neigh);
+}
+
 void rose_transmit_link(struct sk_buff *skb, struct rose_neigh *neigh)
 {
 	unsigned char *dptr;
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c
index 68a4f2385277b..6a1de0055e28b 100644
--- a/net/rose/rose_route.c
+++ b/net/rose/rose_route.c
@@ -741,6 +741,7 @@ struct rose_neigh *rose_get_neigh(rose_address *addr, unsigned char *cause,
 	unsigned char *diagnostic, int route_frame)
 {
 	struct rose_neigh *res = NULL;
+	struct rose_neigh *down = NULL;
 	struct rose_node *node;
 	int failed = 0;
 	int i;
@@ -752,8 +753,21 @@ struct rose_neigh *rose_get_neigh(rose_address *addr, unsigned char *cause,
 				if (node->neighbour[i]->restarted) {
 					res = node->neighbour[i];
 					rose_neigh_hold(node->neighbour[i]);
+					/*
+					 * A neighbour of a more specific route
+					 * was passed over because its link is
+					 * down: this call does not wait for it,
+					 * but have the link brought up for the
+					 * next ones.
+					 */
+					if (down)
+						rose_link_bring_up(down);
 					goto out;
 				}
+				/* The first one is the preferred one. */
+				if (!route_frame && !down &&
+				    !rose_ftimer_running(node->neighbour[i]))
+					down = node->neighbour[i];
 			}
 		}
 	}
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 181/247] ax25: dont free an incoming SABM skb left on the listeners queue
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (179 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 180/247] rose: bring up the link of the preferred route passed over by a connect request Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 182/247] mm/pagewalk: fix stale walk->action escaping walk_pmd_range() Greg Kroah-Hartman
                   ` (73 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Bernard Pidoux, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Bernard Pidoux <bernard.f6bvp@gmail.com>

When a SABM comes in for a listening socket, ax25_rcv() creates the new
socket, puts the skb on the listener's receive queue and only then
allocates the digipeater path. If that allocation fails, the skb is
freed with kfree_skb() while it is still linked on the queue, and the
accept backlog count taken by sk_acceptq_added() is never given back.
The next accept() or the close of the listener then walks a queue that
contains a freed skb.

Allocate the path before the skb is queued, so that the error path only
has to free an skb nobody else knows about and to destroy the new
socket. The later allocation remains for a connection that has no
listening socket.

Only reachable when the atomic allocation fails for a call that comes
through digipeaters. Regression tested in QEMU (6.12.94 with lockdep
and KASAN): 14 incoming connections to a listening socket, each
accepted, served and closed, before and after; no report.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
(cherry picked from commit 2d67e8e9f3d627327114fb946c3a28ef72becb2d)
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/ax25/ax25_in.c | 23 ++++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/net/ax25/ax25_in.c b/net/ax25/ax25_in.c
index c81bc8c4563b5..1bcb5e321467d 100644
--- a/net/ax25/ax25_in.c
+++ b/net/ax25/ax25_in.c
@@ -383,6 +383,24 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev,
 		}
 
 		ax25 = sk_to_ax25(make);
+
+		/*
+		 * Get the digipeater path before the skb goes on the
+		 * listener's queue: once queued it belongs to that queue
+		 * and cannot simply be freed if the allocation fails.
+		 */
+		if (dp.ndigi && !ax25->digipeat) {
+			ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC);
+			if (!ax25->digipeat) {
+				kfree_skb(skb);
+				ax25_destroy_socket(ax25);
+				bh_unlock_sock(sk);
+				sock_put(sk);
+
+				return 0;
+			}
+		}
+
 		skb_set_owner_r(skb, make);
 		skb_queue_head(&sk->sk_receive_queue, skb);
 
@@ -406,14 +424,13 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev,
 	ax25->dest_addr   = src;
 
 	/*
-	 *	Sort out any digipeated paths.
+	 *	Sort out any digipeated paths. A socket made from a listener
+	 *	already has its path allocated, see above.
 	 */
 	if (dp.ndigi && !ax25->digipeat &&
 	    (ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
 		kfree_skb(skb);
 		ax25_destroy_socket(ax25);
-		if (sk)
-			sock_put(sk);
 		return 0;
 	}
 
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 182/247] mm/pagewalk: fix stale walk->action escaping walk_pmd_range()
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (180 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 181/247] ax25: dont free an incoming SABM skb left on the listeners queue Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 183/247] block: avoid potential deadlock on zone revalidation failure Greg Kroah-Hartman
                   ` (72 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Hyunwoo Kim, Lorenzo Stoakes (ARM),
	David Hildenbrand (Arm), Max Boone, Liam R. Howlett, Michal Hocko,
	Mike Rapoport, Suren Baghdasaryan, Vlastimil Babka, Andrew Morton,
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Hyunwoo Kim <imv4bel@gmail.com>

[ Upstream commit aedf2efd18977e0cef7eb963166e2b1fcc0aa321 ]

If ->pmd_entry() sets walk->action = ACTION_AGAIN, the pmd_none() check is
retried.  The PMD entry may be cleared at the point of retry.

In this case, if walk->ops->install_pte is not specified, the code
continues to the next PMD entry in the range without resetting
walk->action to ACTION_SUBTREE.

This leaves walk->action erroneously set to ACTION_AGAIN, which is
incorrect.

This was incorrect but not problematic up until commit 3b89863c3fa4
("mm/pagewalk: fix race between concurrent split and refault") which
updated walk_pud_range() to check for walk->action == ACTION_AGAIN upon
walk_pmd_range()'s return, causing the PUD walk to be retried.

In this case this results in duplicate walk callbacks being invoked,
which is erroneous and will break any caller that is not idempotent
with respect to this (and waste time for those which are).  The result
is an out-of-bounds write, triggered by a local fuzzer:

[    2.272695] ==================================================================
[    2.273471] BUG: KASAN: slab-out-of-bounds in __mincore_unmapped_range+0x14f/0x190
[    2.274302] Write of size 1 at addr ffff888008d9b000 by task poc/106
[    2.274966]
[    2.275154] CPU: 0 UID: 1000 PID: 106 Comm: poc Not tainted 7.2.0-rc6-00429-ga7c7074b58d2 #55 PREEMPT(lazy)
[    2.275159] Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[    2.275164] Call Trace:
[    2.275170]  <TASK>
[    2.275172]  dump_stack_lvl+0x53/0x70
[    2.275200]  print_report+0xd0/0x630
[    2.275210]  ? __pfx__raw_spin_lock_irqsave+0x10/0x10
[    2.275219]  ? irqentry_exit+0xd2/0x670
[    2.275224]  ? irqentry_exit+0xd2/0x670
[    2.275226]  ? __virt_addr_valid+0xef/0x1a0
[    2.275239]  ? __mincore_unmapped_range+0x14f/0x190
[    2.275242]  kasan_report+0xce/0x100
[    2.275245]  ? __mincore_unmapped_range+0x14f/0x190
[    2.275248]  __mincore_unmapped_range+0x14f/0x190
[    2.275252]  mincore_unmapped_range+0x45/0x70
[    2.275254]  walk_pgd_range+0xafc/0xfc0
[    2.275261]  ? __pfx_walk_pgd_range+0x10/0x10
[    2.275264]  ? __update_load_avg_se+0x3d1/0x670
[    2.275275]  __walk_page_range+0xc0/0x310
[    2.275278]  ? __pfx_find_vma+0x10/0x10
[    2.275281]  ? finish_task_switch.isra.0+0x16d/0x4f0
[    2.275290]  walk_page_range_mm_unsafe+0x26f/0x3a0
[    2.275293]  ? __pfx_mtree_load+0x10/0x10
[    2.275298]  ? __pfx_walk_page_range_mm_unsafe+0x10/0x10
[    2.275302]  ? __free_frozen_pages+0x54d/0x7e0
[    2.275308]  __do_sys_mincore+0x132/0x380
[    2.275311]  do_syscall_64+0xf9/0x540
[    2.275316]  entry_SYSCALL_64_after_hwframe+0x77/0x7f
[    2.275322] RIP: 0033:0x422ccd
[    2.275326] Code: b3 66 2e 0f 1f 84 00 00 00 00 00 66 90 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b8 ff ff ff f7 d8 64 89 01 48
[    2.275329] RSP: 002b:00007fffffffec18 EFLAGS: 00000287 ORIG_RAX: 000000000000001b
[    2.275337] RAX: ffffffffffffffda RBX: 0000000000000066 RCX: 0000000000422ccd
[    2.275339] RDX: 00000000004d0940 RSI: 0000000001000000 RDI: 00007ffff4000000
[    2.275340] RBP: 00000000004d0940 R08: 0000000000000100 R09: 0000000000000100
[    2.275342] R10: 0000000000000100 R11: 0000000000000287 R12: 20c49ba5e353f7cf
[    2.275343] R13: 00000000004990d3 R14: 0000000000000000 R15: 0000000000000001
[    2.275346]  </TASK>
[    2.275347]
[    2.296904] The buggy address belongs to the object at ffff888008d9b000
[    2.296904]  which belongs to the cache sigqueue of size 80
[    2.298151] The buggy address is located 0 bytes inside of
[    2.298151]  allocated 80-byte region [ffff888008d9b000, ffff888008d9b050)
[    2.299408]
[    2.299601] The buggy address belongs to the physical page:
[    2.300191] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x8d9b
[    2.301001] flags: 0x100000000000000(node=0|zone=1)
[    2.301535] page_type: f5(slab)
[    2.301884] raw: 0100000000000000 ffff888107e46780 dead000000000122 0000000000000000
[    2.302687] raw: 0000000000000000 0000000800240024 00000000f5000000 0000000000000000
[    2.303489] page dumped because: kasan: bad access detected
[    2.304092]
[    2.304276] Memory state around the buggy address:
[    2.304801]  ffff888008d9af00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[    2.305567]  ffff888008d9af80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[    2.306340] >ffff888008d9b000: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[    2.307115]                    ^
[    2.307474]  ffff888008d9b080: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[    2.308237]  ffff888008d9b100: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[    2.308997] ==================================================================

A specific example of this breaking things is mincore which walks an
internal cursor data structure a byte at a time on assumption that page
table entry callbacks are called only once for each entry.

Fix the problem by resetting walk->action to ACTION_SUBTREE prior to the
none check.

The pattern also exists in walk_pud_range() so fix it there too.

This issue was found through AI-based fuzzing.

Link: https://lore.kernel.org/20260811161949.3879321-2-imv4bel@gmail.com
Fixes: 3b89863c3fa4 ("mm/pagewalk: fix race between concurrent split and refault")
Assisted-by: Claude:claude-opus-5
Signed-off-by: Hyunwoo Kim <imv4bel@gmail.com>
Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
Acked-by: David Hildenbrand (Arm) <david@kernel.org>
Cc: Max Boone <mboone@akamai.com>
Cc: Liam R. Howlett <liam@infradead.org>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Mike Rapoport <rppt@kernel.org>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: Vlastimil Babka <vbabka@kernel.org>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 mm/pagewalk.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/mm/pagewalk.c b/mm/pagewalk.c
index 3d795ad47a897..150e641d03913 100644
--- a/mm/pagewalk.c
+++ b/mm/pagewalk.c
@@ -108,6 +108,7 @@ static int walk_pmd_range(pud_t *pud, unsigned long addr, unsigned long end,
 	pmd = pmd_offset(pud, addr);
 	do {
 again:
+		walk->action = ACTION_SUBTREE;
 		next = pmd_addr_end(addr, end);
 		if (pmd_none(*pmd)) {
 			if (ops->pte_hole)
@@ -117,8 +118,6 @@ static int walk_pmd_range(pud_t *pud, unsigned long addr, unsigned long end,
 			continue;
 		}
 
-		walk->action = ACTION_SUBTREE;
-
 		/*
 		 * This implies that each ->pmd_entry() handler
 		 * needs to know about pmd_trans_huge() pmds
@@ -167,6 +166,7 @@ static int walk_pud_range(p4d_t *p4d, unsigned long addr, unsigned long end,
 	pud = pud_offset(p4d, addr);
 	do {
  again:
+		walk->action = ACTION_SUBTREE;
 		next = pud_addr_end(addr, end);
 		if (pud_none(*pud)) {
 			if (ops->pte_hole)
@@ -176,8 +176,6 @@ static int walk_pud_range(p4d_t *p4d, unsigned long addr, unsigned long end,
 			continue;
 		}
 
-		walk->action = ACTION_SUBTREE;
-
 		if (ops->pud_entry)
 			err = ops->pud_entry(pud, addr, next, walk);
 		if (err)
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 183/247] block: avoid potential deadlock on zone revalidation failure
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (181 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 182/247] mm/pagewalk: fix stale walk->action escaping walk_pmd_range() Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 184/247] Revert "srcu: Use irq_work to start GP in tiny SRCU" Greg Kroah-Hartman
                   ` (71 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, stable, Damien Le Moal,
	Christoph Hellwig, Hannes Reinecke, Jens Axboe, Stanley Jhu,
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Damien Le Moal <dlemoal@kernel.org>

commit 3dd63dba8f9cb6990a40af7ed66ee0159f475819 upstream.

If revalidating the zones of a zoned block device with
blk_revalidate_disk_zones() fails during a SCSI disk rescan, the following
lockdep splat is thrown:

[  347.251859] [  T11230] sda: failed to revalidate zones

[  347.261380] [  T11230] ======================================================
[  347.263882] [  T11230] WARNING: possible circular locking dependency detected
[  347.266353] [  T11230] 7.1.0+ #1194 Not tainted
[  347.268052] [  T11230] ------------------------------------------------------
[  347.270537] [  T11230] tcsh/11230 is trying to acquire lock:
[  347.272555] [  T11230] ffffffff8f91d400 (wq_pool_mutex){+.+.}-{4:4}, at: destroy_workqueue+0x15d/0x8d0
[  347.275914] [  T11230]
                          but task is already holding lock:
[  347.278646] [  T11230] ffff88812fa1bcc0 (&q->q_usage_counter(io)#5){++++}-{0:0}, at: blk_mq_freeze_queue_nomemsave+0x16/0x30
[  347.282503] [  T11230]
                          which lock already depends on the new lock.

[  347.286239] [  T11230]
                          the existing dependency chain (in reverse order) is:
[  347.289408] [  T11230]
                          -> #2 (&q->q_usage_counter(io)#5){++++}-{0:0}:
[  347.292437] [  T11230]        blk_alloc_queue+0x5ca/0x750
[  347.294379] [  T11230]        blk_mq_alloc_queue+0x14c/0x240
[  347.296375] [  T11230]        scsi_alloc_sdev+0x871/0xd10 [scsi_mod]
[  347.298619] [  T11230]        scsi_probe_and_add_lun+0x600/0xc50 [scsi_mod]
[  347.301056] [  T11230]        __scsi_scan_target+0x187/0x3b0 [scsi_mod]
[  347.303385] [  T11230]        scsi_scan_channel+0xf2/0x180 [scsi_mod]
[  347.305651] [  T11230]        scsi_scan_host_selected+0x20b/0x2d0 [scsi_mod]
[  347.308119] [  T11230]        do_scan_async+0x42/0x420 [scsi_mod]
[  347.310276] [  T11230]        async_run_entry_fn+0x94/0x5a0
[  347.312284] [  T11230]        process_one_work+0x8da/0x1690
[  347.314287] [  T11230]        worker_thread+0x5fe/0x1010
[  347.316216] [  T11230]        kthread+0x358/0x450
[  347.317675] [  T11230]        ret_from_fork+0x5b9/0x8e0
[  347.319181] [  T11230]        ret_from_fork_asm+0x11/0x20
[  347.320778] [  T11230]
                          -> #1 (fs_reclaim){+.+.}-{0:0}:
[  347.322890] [  T11230]        fs_reclaim_acquire+0xd5/0x120
[  347.324464] [  T11230]        __kmalloc_cache_node_noprof+0x39/0x620
[  347.326223] [  T11230]        init_rescuer+0x19b/0x560
[  347.327697] [  T11230]        workqueue_init+0x33b/0x6a0
[  347.329224] [  T11230]        kernel_init_freeable+0x2eb/0x600
[  347.330881] [  T11230]        kernel_init+0x1c/0x140
[  347.332334] [  T11230]        ret_from_fork+0x5b9/0x8e0
[  347.333847] [  T11230]        ret_from_fork_asm+0x11/0x20
[  347.335360] [  T11230]
                          -> #0 (wq_pool_mutex){+.+.}-{4:4}:
[  347.337510] [  T11230]        __lock_acquire+0xdea/0x2260
[  347.339030] [  T11230]        lock_acquire+0x187/0x2f0
[  347.340495] [  T11230]        __mutex_lock+0x1ab/0x2600
[  347.341464] [  T11230]        destroy_workqueue+0x15d/0x8d0
[  347.342485] [  T11230]        disk_free_zone_resources+0xd5/0x560
[  347.343577] [  T11230]        blk_revalidate_disk_zones+0x620/0xac7
[  347.344723] [  T11230]        sd_zbc_revalidate_zones+0x1dd/0x790 [sd_mod]
[  347.345938] [  T11230]        sd_revalidate_disk+0xc66/0x8e60 [sd_mod]
[  347.347112] [  T11230]        scsi_rescan_device+0x1f9/0x310 [scsi_mod]
[  347.348318] [  T11230]        store_rescan_field+0x19/0x20 [scsi_mod]
[  347.349507] [  T11230]        kernfs_fop_write_iter+0x3d2/0x5e0
[  347.350565] [  T11230]        vfs_write+0x469/0x1000
[  347.351484] [  T11230]        ksys_write+0x116/0x250
[  347.352403] [  T11230]        do_syscall_64+0xf0/0x6e0
[  347.353361] [  T11230]        entry_SYSCALL_64_after_hwframe+0x4b/0x53
[  347.354533] [  T11230]
                          other info that might help us debug this:

[  347.356432] [  T11230] Chain exists of:
                            wq_pool_mutex --> fs_reclaim --> &q->q_usage_counter(io)#5

[  347.358919] [  T11230]  Possible unsafe locking scenario:

[  347.360307] [  T11230]        CPU0                    CPU1
[  347.361327] [  T11230]        ----                    ----
[  347.362340] [  T11230]   lock(&q->q_usage_counter(io)#5);
[  347.363344] [  T11230]                                lock(fs_reclaim);
[  347.364526] [  T11230]                                lock(&q->q_usage_counter(io)#5);
[  347.365968] [  T11230]   lock(wq_pool_mutex);
[  347.366811] [  T11230]
                           *** DEADLOCK ***

This happens because SCSI disk rescan is executed from a work context
and a failure of blk_revalidate_disk_zones() causes a call to
disk_free_zone_resources() which will free the disk zone write plug
workqueue.

Avoid this by delaying the destruction of the disk zone write plug
workqueue to disk_release(). Do this by introducing the function
disk_release_zone_resources() and using this new function from
disk_release(). This new function destroys the zone write plugs workqueue
and calls disk_free_zone_resources(), thus allowing to remove the call to
destroy_workqueue() from disk_free_zone_resources().
disk_alloc_zone_resources() is modified to not create the disk zone
write plug work queue if it already exists.

Fixes: a8f59e5a5dea ("block: use a per disk workqueue for zone write plugging")
Cc: stable@vger.kernek.org
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Hannes Reinecke <hare@kernel.org>
Link: https://patch.msgid.link/20260701082155.1369996-1-dlemoal@kernel.org
Signed-off-by: Jens Axboe <axboe@kernel.dk>
[ stanleyjhu: 6.12.y has no zone write plug kthread worker and does not
  use WQ_PERCPU, so only the workqueue part applies:
  disk_alloc_zone_resources() reuses an existing workqueue,
  disk_free_zone_resources() drains it instead of destroying it, and
  the new disk_release_zone_resources() destroys it from
  disk_release(). ]
Signed-off-by: Stanley Jhu <stanleyjhu@google.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 block/blk-zoned.c | 37 +++++++++++++++++++++++++++----------
 block/blk.h       |  4 ++--
 block/genhd.c     |  2 +-
 3 files changed, 30 insertions(+), 13 deletions(-)

diff --git a/block/blk-zoned.c b/block/blk-zoned.c
index e3d6e7a18868a..d6f7e487bfe56 100644
--- a/block/blk-zoned.c
+++ b/block/blk-zoned.c
@@ -1408,11 +1408,20 @@ static int disk_alloc_zone_resources(struct gendisk *disk,
 	if (!disk->zone_wplugs_pool)
 		goto free_hash;
 
-	disk->zone_wplugs_wq =
-		alloc_workqueue("%s_zwplugs", WQ_MEM_RECLAIM | WQ_HIGHPRI,
-				pool_size, disk->disk_name);
-	if (!disk->zone_wplugs_wq)
-		goto destroy_pool;
+	/*
+	 * We may already have a zone write plug workqueue as this function may
+	 * be called after disk_free_zone_resources(), which does not destroy
+	 * the workqueue (the zone write plugs workqueue is destroyed at
+	 * disk_release() time).
+	 */
+	if (!disk->zone_wplugs_wq) {
+		disk->zone_wplugs_wq =
+			alloc_workqueue("%s_zwplugs",
+					WQ_MEM_RECLAIM | WQ_HIGHPRI,
+					pool_size, disk->disk_name);
+		if (!disk->zone_wplugs_wq)
+			goto destroy_pool;
+	}
 
 	return 0;
 
@@ -1469,15 +1478,13 @@ static unsigned int disk_set_conv_zones_bitmap(struct gendisk *disk,
 	return nr_conv_zones;
 }
 
-void disk_free_zone_resources(struct gendisk *disk)
+static void disk_free_zone_resources(struct gendisk *disk)
 {
 	if (!disk->zone_wplugs_pool)
 		return;
 
-	if (disk->zone_wplugs_wq) {
-		destroy_workqueue(disk->zone_wplugs_wq);
-		disk->zone_wplugs_wq = NULL;
-	}
+	if (disk->zone_wplugs_wq)
+		drain_workqueue(disk->zone_wplugs_wq);
 
 	disk_destroy_zone_wplugs_hash_table(disk);
 
@@ -1496,6 +1503,16 @@ void disk_free_zone_resources(struct gendisk *disk)
 	disk->nr_zones = 0;
 }
 
+void disk_release_zone_resources(struct gendisk *disk)
+{
+	if (disk->zone_wplugs_wq) {
+		destroy_workqueue(disk->zone_wplugs_wq);
+		disk->zone_wplugs_wq = NULL;
+	}
+
+	disk_free_zone_resources(disk);
+}
+
 static inline bool disk_need_zone_resources(struct gendisk *disk)
 {
 	/*
diff --git a/block/blk.h b/block/blk.h
index b3a7e518d7999..4500ba33dc7af 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -489,7 +489,7 @@ static inline struct bio *blk_queue_bounce(struct bio *bio,
 
 #ifdef CONFIG_BLK_DEV_ZONED
 void disk_init_zone_resources(struct gendisk *disk);
-void disk_free_zone_resources(struct gendisk *disk);
+void disk_release_zone_resources(struct gendisk *disk);
 static inline bool bio_zone_write_plugging(struct bio *bio)
 {
 	return bio_flagged(bio, BIO_ZONE_WRITE_PLUGGING);
@@ -550,7 +550,7 @@ int blkdev_zone_mgmt_ioctl(struct block_device *bdev, blk_mode_t mode,
 static inline void disk_init_zone_resources(struct gendisk *disk)
 {
 }
-static inline void disk_free_zone_resources(struct gendisk *disk)
+static inline void disk_release_zone_resources(struct gendisk *disk)
 {
 }
 static inline bool bio_zone_write_plugging(struct bio *bio)
diff --git a/block/genhd.c b/block/genhd.c
index f4f18ca70aa05..4063ee78c27bd 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -1219,7 +1219,7 @@ static void disk_release(struct device *dev)
 
 	disk_release_events(disk);
 	kfree(disk->random);
-	disk_free_zone_resources(disk);
+	disk_release_zone_resources(disk);
 	xa_destroy(&disk->part_tbl);
 
 	disk->queue->disk = NULL;
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 184/247] Revert "srcu: Use irq_work to start GP in tiny SRCU"
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (182 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 183/247] block: avoid potential deadlock on zone revalidation failure Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 185/247] net_sched: codel: fix stale state for empty flows in fq_codel Greg Kroah-Hartman
                   ` (70 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Guenter Roeck, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

This reverts commit 2127e6b79d9d579ea538a350d1bbe859e39814d5.

Reported-by: Guenter Roeck <linux@roeck-us.net>
Link: https://lore.kernel.org/r/49da816c-8082-46f1-bb12-f0d6187bb06a@roeck-us.net
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 include/linux/srcutiny.h |  4 ----
 kernel/rcu/srcutiny.c    | 19 +------------------
 2 files changed, 1 insertion(+), 22 deletions(-)

diff --git a/include/linux/srcutiny.h b/include/linux/srcutiny.h
index 6f39d3d8ef879..4d96bbdb45f08 100644
--- a/include/linux/srcutiny.h
+++ b/include/linux/srcutiny.h
@@ -11,7 +11,6 @@
 #ifndef _LINUX_SRCU_TINY_H
 #define _LINUX_SRCU_TINY_H
 
-#include <linux/irq_work_types.h>
 #include <linux/swait.h>
 
 struct srcu_struct {
@@ -25,21 +24,18 @@ struct srcu_struct {
 	struct rcu_head *srcu_cb_head;	/* Pending callbacks: Head. */
 	struct rcu_head **srcu_cb_tail;	/* Pending callbacks: Tail. */
 	struct work_struct srcu_work;	/* For driving grace periods. */
-	struct irq_work srcu_irq_work;	/* Defer schedule_work() to irq work. */
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 	struct lockdep_map dep_map;
 #endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
 };
 
 void srcu_drive_gp(struct work_struct *wp);
-void srcu_tiny_irq_work(struct irq_work *irq_work);
 
 #define __SRCU_STRUCT_INIT(name, __ignored, ___ignored)			\
 {									\
 	.srcu_wq = __SWAIT_QUEUE_HEAD_INITIALIZER(name.srcu_wq),	\
 	.srcu_cb_tail = &name.srcu_cb_head,				\
 	.srcu_work = __WORK_INITIALIZER(name.srcu_work, srcu_drive_gp),	\
-	.srcu_irq_work = { .func = srcu_tiny_irq_work },		\
 	__SRCU_DEP_MAP_INIT(name)					\
 }
 
diff --git a/kernel/rcu/srcutiny.c b/kernel/rcu/srcutiny.c
index ddea40b68e5f6..4dcbf8aa80ff7 100644
--- a/kernel/rcu/srcutiny.c
+++ b/kernel/rcu/srcutiny.c
@@ -9,7 +9,6 @@
  */
 
 #include <linux/export.h>
-#include <linux/irq_work.h>
 #include <linux/mutex.h>
 #include <linux/preempt.h>
 #include <linux/rcupdate_wait.h>
@@ -38,7 +37,6 @@ static int init_srcu_struct_fields(struct srcu_struct *ssp)
 	ssp->srcu_idx_max = 0;
 	INIT_WORK(&ssp->srcu_work, srcu_drive_gp);
 	INIT_LIST_HEAD(&ssp->srcu_work.entry);
-	init_irq_work(&ssp->srcu_irq_work, srcu_tiny_irq_work);
 	return 0;
 }
 
@@ -82,7 +80,6 @@ EXPORT_SYMBOL_GPL(init_srcu_struct);
 void cleanup_srcu_struct(struct srcu_struct *ssp)
 {
 	WARN_ON(ssp->srcu_lock_nesting[0] || ssp->srcu_lock_nesting[1]);
-	irq_work_sync(&ssp->srcu_irq_work);
 	flush_work(&ssp->srcu_work);
 	WARN_ON(ssp->srcu_gp_running);
 	WARN_ON(ssp->srcu_gp_waiting);
@@ -171,20 +168,6 @@ void srcu_drive_gp(struct work_struct *wp)
 }
 EXPORT_SYMBOL_GPL(srcu_drive_gp);
 
-/*
- * Use an irq_work to defer schedule_work() to avoid acquiring the workqueue
- * pool->lock while the caller might hold scheduler locks, causing lockdep
- * splats due to workqueue_init() doing a wakeup.
- */
-void srcu_tiny_irq_work(struct irq_work *irq_work)
-{
-	struct srcu_struct *ssp;
-
-	ssp = container_of(irq_work, struct srcu_struct, srcu_irq_work);
-	schedule_work(&ssp->srcu_work);
-}
-EXPORT_SYMBOL_GPL(srcu_tiny_irq_work);
-
 static void srcu_gp_start_if_needed(struct srcu_struct *ssp)
 {
 	unsigned long cookie;
@@ -198,7 +181,7 @@ static void srcu_gp_start_if_needed(struct srcu_struct *ssp)
 	WRITE_ONCE(ssp->srcu_idx_max, cookie);
 	if (!READ_ONCE(ssp->srcu_gp_running)) {
 		if (likely(srcu_init_done))
-			irq_work_queue(&ssp->srcu_irq_work);
+			schedule_work(&ssp->srcu_work);
 		else if (list_empty(&ssp->srcu_work.entry))
 			list_add(&ssp->srcu_work.entry, &srcu_boot_list);
 	}
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 185/247] net_sched: codel: fix stale state for empty flows in fq_codel
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (183 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 184/247] Revert "srcu: Use irq_work to start GP in tiny SRCU" Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 186/247] Bluetooth: L2CAP: refuse __l2cap_chan_add if chan already has conn Greg Kroah-Hartman
                   ` (69 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Jesper Dangaard Brouer,
	Jonas Köppeler, Chris Arges,
	Toke Høiland-Jørgensen, Eric Dumazet, Jakub Kicinski,
	Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Jonas Köppeler <j.koeppeler@tu-berlin.de>

[ Upstream commit 815980fe6dbb01ad4007e8b260a45617f598b76d ]

When codel_dequeue() finds an empty queue, it resets vars->dropping
but does not reset vars->first_above_time.  The reference CoDel
algorithm (Nichols & Jacobson, ACM Queue 2012) resets both:

  dodeque_result codel_queue_t::dodeque(time_t now) {
      ...
      if (r.p == NULL) {
          first_above_time = 0;   // <-- Linux omits this
      }
      ...
  }

Note that codel_should_drop() does reset first_above_time when called
with a NULL skb, but codel_dequeue() returns early before ever calling
codel_should_drop() in the empty-queue case.  The post-drop code paths
do reach codel_should_drop(NULL) and correctly reset the timer, so a
dropped packet breaks the cycle -- but the next delivered packet
re-arms first_above_time and the cycle repeats.

For sparse flows such as ICMP ping (one packet every 200ms-1s), the
first packet arms first_above_time, the flow goes empty, and the
second packet arrives after the interval has elapsed and gets dropped.
The pattern repeats, producing sustained loss on flows that are not
actually congested.

Test: veth pair, fq_codel, BQL disabled, 30000 iptables rules in the
consumer namespace (NAPI-64 cycle ~14ms, well above fq_codel's 5ms
target), ping at 5 pps under UDP flood:

  Before fix:  26% ping packet loss
  After fix:    0% ping packet loss

Fix by resetting first_above_time to zero in the empty-queue path
of codel_dequeue(), matching the reference algorithm.

Fixes: 76e3cc126bb2 ("codel: Controlled Delay AQM")
Fixes: d068ca2ae2e6 ("codel: split into multiple files")
Co-developed-by: Jesper Dangaard Brouer <hawk@kernel.org>
Signed-off-by: Jesper Dangaard Brouer <hawk@kernel.org>
Signed-off-by: Jonas Köppeler <j.koeppeler@tu-berlin.de>
Reported-by: Chris Arges <carges@cloudflare.com>
Tested-by: Jonas Köppeler <j.koeppeler@tu-berlin.de>
Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
Link: https://lore.kernel.org/all/20260318134826.1281205-7-hawk@kernel.org/
Reviewed-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20260323174920.253526-1-hawk@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 include/net/codel_impl.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/net/codel_impl.h b/include/net/codel_impl.h
index 78a27ac730700..b2c359c6dd1b8 100644
--- a/include/net/codel_impl.h
+++ b/include/net/codel_impl.h
@@ -158,6 +158,7 @@ static struct sk_buff *codel_dequeue(void *ctx,
 	bool drop;
 
 	if (!skb) {
+		vars->first_above_time = 0;
 		vars->dropping = false;
 		return skb;
 	}
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 186/247] Bluetooth: L2CAP: refuse __l2cap_chan_add if chan already has conn
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (184 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 185/247] net_sched: codel: fix stale state for empty flows in fq_codel Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 187/247] tracing: Reject incomplete event filter expressions Greg Kroah-Hartman
                   ` (68 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Pauli Virtanen,
	Luiz Augusto von Dentz, Sasha Levin

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Pauli Virtanen <pav@iki.fi>

[ Upstream commit 86b55991d3cd690e73c5ef8d20b75ae4905b357a ]

l2cap_chan may be linked to l2cap_conn at most once. This is assumed in
several places, eg l2cap_chan_del cleanup.

There is a TOCTOU race where the invariant is violated:

    [Task 1]                          [Task 2]
    l2cap_chan_connect                l2cap_sock_bind
      l2cap_chan_lock                   lock_sock
      l2cap_state_change                if (sk->sk_state != BT_OPEN)
        chan->state = BT_CONNECT
        l2cap_sock_state_change_cb      chan->state = BT_BOUND
                                        sk->sk_state = BT_BOUND
          lock_sock <------------------ release_sock
          sk->sk_state = BT_CONNECT

l2cap_sock_connect() does not check sk->sk_state, so since chan->state
is now BT_BOUND, subsequent connect() ends up with second
__l2cap_chan_add.

Explicitly document and check the invariant in __l2cap_chan_add with
WARN_ON_ONCE. The only callsite where it could be hit is
l2cap_chan_connect, so add pre-check there to avoid relying on
chan->state. chan->state read/write is not properly guarded currently so
there can be other TOCTOUC problems.

Add l2cap_lock_chan in l2cap_sock_bind() to guard chan->state write.

Fixes: b66774b48dd9 ("Bluetooth: L2CAP: Fix UAF in channel timeout by holding conn ref")
Assisted-by: deepseek-4-flash # finding the race condition
Signed-off-by: Pauli Virtanen <pav@iki.fi>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/bluetooth/l2cap_core.c | 7 ++++++-
 net/bluetooth/l2cap_sock.c | 2 ++
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 61914f280d6fa..894fcd779bd03 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -625,6 +625,10 @@ void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
 	BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
 	       __le16_to_cpu(chan->psm), chan->dcid);
 
+	/* Caller must ensure l2cap_chan is linked to l2cap_conn only once */
+	if (WARN_ON_ONCE(chan->conn || test_bit(FLAG_DEL, &chan->flags)))
+		return;
+
 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
 
 	chan->conn = l2cap_conn_get(conn);
@@ -7388,7 +7392,8 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
 		}
 	}
 
-	if (cid && __l2cap_get_chan_by_dcid(conn, cid)) {
+	if ((cid && __l2cap_get_chan_by_dcid(conn, cid)) || chan->conn ||
+	    test_bit(FLAG_DEL, &chan->flags)) {
 		hci_conn_drop(hcon);
 		err = -EBUSY;
 		goto chan_unlock;
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index ef3af57e4637f..f08512a57ab58 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -112,6 +112,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
 			return -EINVAL;
 	}
 
+	l2cap_chan_lock(chan);
 	lock_sock(sk);
 
 	if (sk->sk_state != BT_OPEN) {
@@ -177,6 +178,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
 
 done:
 	release_sock(sk);
+	l2cap_chan_unlock(chan);
 	return err;
 }
 
-- 
2.53.0




^ permalink raw reply related	[flat|nested] 259+ messages in thread

* [PATCH 6.12 187/247] tracing: Reject incomplete event filter expressions
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (185 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 186/247] Bluetooth: L2CAP: refuse __l2cap_chan_add if chan already has conn Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 188/247] tracing: Save the event file instead of the compatible histogram Greg Kroah-Hartman
                   ` (67 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Masami Hiramatsu (Google),
	JongHyuk Kim(MalHyuk), Kyle Zeng, Steven Rostedt

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Kyle Zeng <kylebot@openai.com>

commit 1fdc4164e488916402badddbb1f51e9380dabb91 upstream.

A non-empty expression normally finishes in predicate_parse()'s inner
loop, which resolves the pending logical operators before jumping to
finalization. If the input ends after an operator, possibly followed by
unary '!' tokens, the outer loop instead falls through with unresolved
operator state.

For example, "common_pid == 1 || common_pid == 2 &&" leaves
prog[0].target equal to -1. The second pass then reads prog[-1] before
the forward-jump check can reject it. Depending on adjacent slab
contents, it can also copy an out-of-bounds word into a branch target
that passes the forward-only check. A self-targeted perf tracepoint
counting event can reach this path through PERF_EVENT_IOC_SET_FILTER.

Reject the outer-loop fallthrough when a predicate has already been
parsed. This ensures that non-empty expressions only reach finalization
after the inner loop has resolved their operators. Keep the existing
no-filter error for input that has no predicates. Add a regression test
for trailing logical operators and unary negations.

Fixes: 80765597bc587 ("tracing: Rewrite filter logic to be simpler and faster")
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20261023174620.91969-1-kylebot@openai.com
Assisted-by: Codex:gpt-6-astra
Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Tested-by: JongHyuk Kim(MalHyuk) <malhyuk97@gmail.com>
Signed-off-by: Kyle Zeng <kylebot@openai.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 kernel/trace/trace_events_filter.c                                      |    6 ++
 tools/testing/selftests/ftrace/test.d/filter/event-filter-incomplete.tc |   24 ++++++++++
 2 files changed, 30 insertions(+)
 create mode 100644 tools/testing/selftests/ftrace/test.d/filter/event-filter-incomplete.tc

--- a/kernel/trace/trace_events_filter.c
+++ b/kernel/trace/trace_events_filter.c
@@ -595,6 +595,12 @@ predicate_parse(const char *str, int nr_
 			top--;					/* #12 */
 		}
 	}
+	/* Only the inner loop can complete a non-empty expression. */
+	if (N) {
+		ret = -EINVAL;
+		parse_error(pe, FILT_ERR_INVALID_FILTER, ptr - str);
+		goto out_free;
+	}
  out:
 	if (top != op_stack) {
 		/* Too many '(' */
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/filter/event-filter-incomplete.tc
@@ -0,0 +1,24 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+# description: event filter - reject incomplete logical expressions
+# requires: events/sched/sched_switch/filter
+# flags: instance
+
+filter=events/sched/sched_switch/filter
+
+for base in \
+    'common_pid == 1' \
+    'common_pid == 1 || common_pid == 2' \
+    'common_pid == 1 && common_pid == 2' \
+    '!(common_pid == 1 || common_pid == 2)'
+do
+    printf '%s' "$base" > "$filter"
+    for tail in '&&' '||' '&& !' '|| !' '&& !! ' '|| !! '; do
+        if printf '%s' "$base $tail" > "$filter" 2>/dev/null; then
+            echo "Accepted incomplete filter: $base $tail"
+            exit_fail
+        fi
+    done
+done
+
+echo 0 > "$filter"



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 188/247] tracing: Save the event file instead of the compatible histogram
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (186 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 187/247] tracing: Reject incomplete event filter expressions Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 189/247] tracing: Unregister field variable histograms when the command fails Greg Kroah-Hartman
                   ` (66 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Sashiko, Donggeun Yoo, Tom Zanussi,
	Steven Rostedt

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Donggeun Yoo <donggeunyoo.kernel@gmail.com>

commit d5c42664fc094899af9aae5300b27fe8fdb658ef upstream.

create_field_var_hist() creates a histogram on the matched event to
supply a field variable, and records it on the target so it can be torn
down later:

	hist_data = find_compatible_hist(target_hist_data, file);
	...
	/* Save the compatible histogram information */
	var_hist->hist_data = hist_data;

hist_data is not the histogram it creates. It is one that was already
there, whose keys the new one copies. The saved pointer has a single
user, unregister_field_var_hists(), which runs when the target is
removed:

	file = hist_data->field_var_hists[i]->hist_data->event_file;

find_compatible_hist() matches on keys alone, so it can pick one with no
variables of its own. check_var_refs() then returns false and the user
can remove it while the target still points at it:

 BUG: KASAN: slab-use-after-free in event_hist_trigger_free+0x2b2/0x320
 Read of size 8 at addr ffff8880093b90e0 by task init/1

 Freed by task 1:
  kfree+0x154/0x420
  event_hist_trigger_free+0x1d5/0x320
  event_hist_trigger_parse+0x35f3/0x69e0
  trigger_process_regex+0x1a6/0x250

Save the event file instead. It is all the dereference ever wanted, and
it does not go away when the user removes a trigger.

Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-bot@kernel.org>
Link: https://lore.kernel.org/all/20260914110753.221E61F000FF@smtp.kernel.org/
Link: https://patch.msgid.link/20260914234754.3676905-1-donggeunyoo.kernel@gmail.com
Fixes: 02205a6752f2 ("tracing: Add support for 'field variables'")
Signed-off-by: Donggeun Yoo <donggeunyoo.kernel@gmail.com>
Assisted-by: Claude:claude-fable-5
Acked-by: Tom Zanussi <zanussi@kernel.org>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 kernel/trace/trace_events_hist.c |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

--- a/kernel/trace/trace_events_hist.c
+++ b/kernel/trace/trace_events_hist.c
@@ -542,7 +542,7 @@ struct field_var {
 };
 
 struct field_var_hist {
-	struct hist_trigger_data	*hist_data;
+	struct trace_event_file		*file;
 	char				*cmd;
 };
 
@@ -3077,8 +3077,8 @@ create_field_var_hist(struct hist_trigge
 		return ERR_PTR(-ENOMEM);
 	}
 
-	/* Save the compatible histogram information */
-	var_hist->hist_data = hist_data;
+	/* Needed to remove the histogram when the target goes away */
+	var_hist->file = file;
 
 	/* Create the new histogram with our variable */
 	ret = event_hist_trigger_parse(&trigger_hist_cmd, file,
@@ -6299,7 +6299,7 @@ static void unregister_field_var_hists(s
 	int ret;
 
 	for (i = 0; i < hist_data->n_field_var_hists; i++) {
-		file = hist_data->field_var_hists[i]->hist_data->event_file;
+		file = hist_data->field_var_hists[i]->file;
 		cmd = hist_data->field_var_hists[i]->cmd;
 		ret = event_hist_trigger_parse(&trigger_hist_cmd, file,
 					       "!hist", "hist", cmd);



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 189/247] tracing: Unregister field variable histograms when the command fails
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (187 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 188/247] tracing: Save the event file instead of the compatible histogram Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 190/247] tracing: Fix 64-bit and signed histogram fields on 32-bit kernels Greg Kroah-Hartman
                   ` (65 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, sashiko-bot, Donggeun Yoo,
	Steven Rostedt

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Donggeun Yoo <donggeunyoo.kernel@gmail.com>

commit 91c14d6c13096091c56304120aaa26e479130b8b upstream.

An action that names a field on another event needs that field as a
variable, so create_field_var_hist() registers a second hist trigger on
that event to provide it, and records it in
target_hist_data->field_var_hists[].

If a later part of the same command fails, create_actions() returns an
error and event_hist_trigger_parse() jumps to out_free. The write fails
with -EINVAL and sched_switch gets no trigger, but:

  # echo 'hist:keys=pid:ts0=common_timestamp.usecs' >> \
      events/sched/sched_waking/trigger
  # echo 'my_synth u64 lat; int a; int b' >> synthetic_events
  # echo 'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts0:\
      onmatch(sched.sched_waking).my_synth($wakeup_lat,prio,nosuchfld)'\
      >> events/sched/sched_switch/trigger
  # cat events/sched/sched_waking/trigger
  hist:keys=pid:vals=hitcount:ts0=common_timestamp.usecs:sort=hitcount:size=2048:clock=global [active]
  hist:keys=pid:vals=hitcount:synthetic_prio=prio:sort=hitcount:size=2048 [active]

The second histogram is the one created for 'prio'. It is still active and
still counting.

out_free reaches destroy_field_var_hists(), which frees the
field_var_hists[] entries, but never unregister_field_var_hists(), which is
what removes the triggers and runs only from event_hist_trigger_free(). The
entry is freed and the trigger is left with nothing tracking it.

Unregister the field variable histograms in out_free as well, and record
each one as soon as its trigger is registered rather than after the lookup
that follows it, so no exit can leave a registered trigger untracked. The
entry then belongs to field_var_hists[] and is released by
destroy_field_var_hists(), so freeing it on that exit would be a double
free.

Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20260914104036.1768529-1-donggeunyoo.kernel@gmail.com
Fixes: 02205a6752f2 ("tracing: Add support for 'field variables'")
Reported-by: sashiko-bot@kernel.org
Closes: https://lore.kernel.org/all/20260913204302.DB2551F000FF@smtp.kernel.org/
Signed-off-by: Donggeun Yoo <donggeunyoo.kernel@gmail.com>
Assisted-by: Claude:claude-fable-5
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 kernel/trace/trace_events_hist.c |   12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

--- a/kernel/trace/trace_events_hist.c
+++ b/kernel/trace/trace_events_hist.c
@@ -3093,20 +3093,18 @@ create_field_var_hist(struct hist_trigge
 
 	kfree(cmd);
 
+	n = target_hist_data->n_field_var_hists;
+	target_hist_data->field_var_hists[n] = var_hist;
+	target_hist_data->n_field_var_hists++;
+
 	/* If we can't find the variable, something went wrong */
 	event_var = find_synthetic_field_var(target_hist_data, subsys_name,
 					     event_name, field_name);
 	if (IS_ERR_OR_NULL(event_var)) {
-		kfree(var_hist->cmd);
-		kfree(var_hist);
 		hist_err(tr, HIST_ERR_SYNTH_VAR_NOT_FOUND, errpos(field_name));
 		return ERR_PTR(-EINVAL);
 	}
 
-	n = target_hist_data->n_field_var_hists;
-	target_hist_data->field_var_hists[n] = var_hist;
-	target_hist_data->n_field_var_hists++;
-
 	return event_var;
 }
 
@@ -6915,6 +6913,8 @@ static int event_hist_trigger_parse(stru
 
 	trigger_data_free(trigger_data);
 
+	unregister_field_var_hists(hist_data);
+
 	destroy_hist_data(hist_data);
 	goto out;
 }



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 190/247] tracing: Fix 64-bit and signed histogram fields on 32-bit kernels
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (188 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 189/247] tracing: Unregister field variable histograms when the command fails Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 191/247] tracing/histograms: Verify event_call identity when updating synth_event refcount Greg Kroah-Hartman
                   ` (64 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, sashiko-bot, Donggeun Yoo,
	Steven Rostedt

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Donggeun Yoo <donggeunyoo.kernel@gmail.com>

commit 443d23176812803d0fa182b8d05ef066a7b8271f upstream.

DEFINE_HIST_FIELD_FN() reads a trace event field and widens it to the u64
the histogram uses as a key or a value:

	type *addr = (type *)(event + hist_field->field->offset);

	return (u64)(unsigned long)*addr;

unsigned long is 32 bits on a 32-bit kernel, so the intermediate cast
discards the upper half of a 64-bit field, and widens a signed field by
zero extension from 32 bits rather than sign extension from its own
width. Five of the eight instantiations are wrong there: s64, u64, s32,
s16 and s8.

The cast came in with commit 79e577cbce4c ("tracing: Support string type
key properly"), which also added hist_field_dynstring() and
hist_field_pstring(). Those convert a char * to u64 and do warn without
an unsigned long in between on 32-bit. DEFINE_HIST_FIELD_FN() converts an
integer and never a pointer, so it gains nothing from the cast and only
loses information.

Drop the intermediate cast and let the usual arithmetic conversions widen
*addr according to its own type. unsigned long is 64 bits on LP64, so the
two forms are identical there and 64-bit kernels are unaffected.

Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20260917015532.103081-1-donggeunyoo.kernel@gmail.com
Fixes: 79e577cbce4c ("tracing: Support string type key properly")
Reported-by: sashiko-bot@kernel.org
Closes: https://lore.kernel.org/all/20260914054614.82A9B1F000FF@smtp.kernel.org/
Signed-off-by: Donggeun Yoo <donggeunyoo.kernel@gmail.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 kernel/trace/trace_events_hist.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/kernel/trace/trace_events_hist.c
+++ b/kernel/trace/trace_events_hist.c
@@ -460,7 +460,7 @@ static u64 hist_field_unary_minus(struct
 {									\
 	type *addr = (type *)(event + hist_field->field->offset);	\
 									\
-	return (u64)(unsigned long)*addr;				\
+	return (u64)*addr;						\
 }
 
 DEFINE_HIST_FIELD_FN(s64);



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 191/247] tracing/histograms: Verify event_call identity when updating synth_event refcount
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (189 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 190/247] tracing: Fix 64-bit and signed histogram fields on 32-bit kernels Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 192/247] io-wq: order the exit bit against worker creation task work Greg Kroah-Hartman
                   ` (63 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Lee Jones, Steven Rostedt

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Lee Jones <lee@kernel.org>

commit 3403d9bb27ebc3572bd048620746b4414e073bf9 upstream.

In event_hist_trigger_parse() and hist_unreg_all(), the histogram
registration and unregistration paths look up find_synth_event() using
trace_event_name(file->event_call) and adjust se->ref if a match is
found.

Because find_synth_event() only compares the event basename, registering
or removing a histogram on a non-synthetic trace event whose basename
matches a synthetic event erroneously modifies the synthetic event's
reference count.  If a histogram is registered on the non-synthetic
event before the synthetic event is created and removed afterwards,
se->ref is decremented without a matching increment, allowing the
synthetic event to be freed while an active histogram action still holds
a pointer to it.

Introduce find_synth_event_call() to verify that &se->call matches
file->event_call before adjusting se->ref.

Fixes: 4b147936fa50 ("tracing: Add support for 'synthetic' events")
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20261019120730.2342739-1-lee@kernel.org
Signed-off-by: Lee Jones <lee@kernel.org>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 kernel/trace/trace_events_hist.c  |   11 +++--------
 kernel/trace/trace_events_synth.c |   10 ++++++++++
 kernel/trace/trace_synth.h        |    1 +
 3 files changed, 14 insertions(+), 8 deletions(-)

--- a/kernel/trace/trace_events_hist.c
+++ b/kernel/trace/trace_events_hist.c
@@ -6725,7 +6725,6 @@ static void hist_unreg_all(struct trace_
 	struct event_trigger_data *test, *n;
 	struct hist_trigger_data *hist_data;
 	struct synth_event *se;
-	const char *se_name;
 
 	lockdep_assert_held(&event_mutex);
 
@@ -6738,8 +6737,7 @@ static void hist_unreg_all(struct trace_
 			list_del_rcu(&test->list);
 			trace_event_trigger_enable_disable(file, 0);
 
-			se_name = trace_event_name(file->event_call);
-			se = find_synth_event(se_name);
+			se = find_synth_event_call(file->event_call);
 			if (se)
 				se->ref--;
 
@@ -6763,7 +6761,6 @@ static int event_hist_trigger_parse(stru
 	struct hist_trigger_data *hist_data;
 	char *param, *filter, *p, *start;
 	struct synth_event *se;
-	const char *se_name;
 	bool remove;
 	int ret = 0;
 
@@ -6857,8 +6854,7 @@ static int event_hist_trigger_parse(stru
 		}
 
 		event_trigger_unregister(cmd_ops, file, glob+1, trigger_data);
-		se_name = trace_event_name(file->event_call);
-		se = find_synth_event(se_name);
+		se = find_synth_event_call(file->event_call);
 		if (se)
 			se->ref--;
 		ret = 0;
@@ -6893,8 +6889,7 @@ static int event_hist_trigger_parse(stru
 	if (ret)
 		goto out_unreg;
 
-	se_name = trace_event_name(file->event_call);
-	se = find_synth_event(se_name);
+	se = find_synth_event_call(file->event_call);
 	if (se)
 		se->ref++;
  out:
--- a/kernel/trace/trace_events_synth.c
+++ b/kernel/trace/trace_events_synth.c
@@ -857,6 +857,16 @@ struct synth_event *find_synth_event(con
 	return NULL;
 }
 
+struct synth_event *find_synth_event_call(struct trace_event_call *call)
+{
+	struct synth_event *se;
+	const char *name;
+
+	name = trace_event_name(call);
+	se = find_synth_event(name);
+	return se && &se->call == call ? se : NULL;
+}
+
 static struct trace_event_fields synth_event_fields_array[] = {
 	{ .type = TRACE_FUNCTION_TYPE,
 	  .define_fields = synth_event_define_fields },
--- a/kernel/trace/trace_synth.h
+++ b/kernel/trace/trace_synth.h
@@ -37,5 +37,6 @@ struct synth_event {
 };
 
 extern struct synth_event *find_synth_event(const char *name);
+extern struct synth_event *find_synth_event_call(struct trace_event_call *call);
 
 #endif /* __TRACE_SYNTH_H */



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 192/247] io-wq: order the exit bit against worker creation task work
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (190 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 191/247] tracing/histograms: Verify event_call identity when updating synth_event refcount Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 193/247] io_uring/waitid: own the request before clearing ->head Greg Kroah-Hartman
                   ` (62 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Jens Axboe, Oleg Nesterov,
	Christian Brauner (Amutable)

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Christian Brauner <brauner@kernel.org>

Commit 0e5663856b69219ef2f02e04bac9f5c5be19718a upstream.

io_wq_exit_workers() cancels task work for queued worker creation with
task_work_cancel_match(). That has a plain load of task->task_works.

io_queue_worker_create() adds the new entry and tests IO_WQ_BIT_EXIT to
cancel it if the workqueue is already on its way out.

That must be ordered. task_work_add() has a full barrier via cmpxchg().
But io_wq_exit_start() sets the bit with set_bit() which doesn't have
any memory ordering.

So afaict, on weakly ordered architectures the exiting task may load
task_works before the store of the bit is visible. The other side tests
the bit before the store is visible as well. So the entry remains queued
with worker_refs and the exiting task waits on worker_done indefinitely.

If the task still has rings then io_uring_del_tctx_node() provides the
barrier via test_and_set_bit() in io_wq_set_exit_on_idle(). When it
has closed all rings though that barrier is gone.

Add the barrier after the set_bit().

Fixes: 71a85387546e ("io-wq: check for wq exit after adding new worker task_work")
Cc: stable@vger.kernel.org
Reviewed-by: Jens Axboe <axboe@kernel.dk>
Acked-by: Oleg Nesterov <oleg@redhat.com>
Link: https://patch.msgid.link/20260921-work-coredump-fixes-v3-4-8e4adb1619e6@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/io-wq.c |    2 ++
 1 file changed, 2 insertions(+)

--- a/io_uring/io-wq.c
+++ b/io_uring/io-wq.c
@@ -1234,6 +1234,8 @@ static bool io_task_work_match(struct ca
 void io_wq_exit_start(struct io_wq *wq)
 {
 	set_bit(IO_WQ_BIT_EXIT, &wq->state);
+	/* Pairs with task_work_add() in io_queue_worker_create(). */
+	smp_mb__after_atomic();
 }
 
 static void io_wq_cancel_tw_create(struct io_wq *wq)



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 193/247] io_uring/waitid: own the request before clearing ->head
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (191 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 192/247] io-wq: order the exit bit against worker creation task work Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 194/247] io_uring/cmd: dont leave list poison in ->hash_node Greg Kroah-Hartman
                   ` (61 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Josef Bacik, Jens Axboe

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Josef Bacik <josef@toxicpanda.com>

Commit c254eec4364b9f4b4cbdce43be3fb4df5a651a70 upstream.

io_waitid_remove_wq() only takes the wait queue lock if ->head is set.
io_waitid_wait() clears ->head first thing, before it tries to become the
owner of the request by bumping ->refs. If somebody else owns the request
at that point, nothing keeps it from completing the request while the
wake up handler is still going to touch it:

CPU0 (io_waitid_wait)                 CPU1 (io_waitid, holds a ref)
list_del_init(&wait->entry)
smp_store_release(&iw->head, NULL)
                                      __do_wait() finds another child
                                      io_waitid_remove_wq()
                                        // ->head == NULL, no locking
                                      io_waitid_finish(), IOU_COMPLETE
                                      // request freed and reused
atomic_fetch_inc(&iw->refs)

The same goes for __io_waitid_cancel() if it claims the request in that
window. ->refs is part of the per opcode data of the request, so this
increments whatever the next user of the request keeps there. If that
happens to be zero, the handler concludes that it owns the request, and
queues io_waitid_cb() for it. With the window held open by a delay, and
the request reused for a receive that is waiting for data:

  BUG: KASAN: slab-use-after-free in __wake_up_common+0x1ca/0x1f0
   __wake_up_sync_key+0x36/0x50
   sock_def_readable+0xf1/0x420
   unix_stream_sendmsg+0x60b/0x1110
  Allocated by task 87:
   io_arm_apoll+0x1ed/0x940
  Freed by task 87:
   __io_submit_flush_completions+0x118d/0x1a10
   tctx_task_work_run+0x327/0x950

Only clear ->head once the handler owns the request. If it doesn't, the
owner finds ->head set and has to wait for the lock, which is held by the
caller of the handler. Deleting the already deleted entry again is
harmless.

Fixes: ab673c1bcaf2 ("io_uring/waitid: use io_waitid_remove_wq() consistently")
Assisted-by: LLM
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-1-c1556f5d7bf5@toxicpanda.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/waitid.c |   10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

--- a/io_uring/waitid.c
+++ b/io_uring/waitid.c
@@ -291,12 +291,18 @@ static int io_waitid_wait(struct wait_qu
 		return 0;
 
 	list_del_init(&wait->entry);
-	smp_store_release(&iw->head, NULL);
 
-	/* cancel is in progress */
+	/*
+	 * Cancel or issue is in progress. Leave ->head alone, so that whoever
+	 * owns the request has to take the wait queue lock, which we hold,
+	 * before it can complete and free it.
+	 */
 	if (atomic_fetch_inc(&iw->refs) & IO_WAITID_REF_MASK)
 		return 1;
 
+	/* pairs with the smp_load_acquire() in io_waitid_remove_wq() */
+	smp_store_release(&iw->head, NULL);
+
 	req->io_task_work.func = io_waitid_cb;
 	__io_req_task_work_add(req, IOU_F_TWQ_IN_WAKE);
 	return 1;



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 194/247] io_uring/cmd: dont leave list poison in ->hash_node
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (192 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 193/247] io_uring/waitid: own the request before clearing ->head Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 195/247] io_uring/wait: dont spin on a stuck overflow list Greg Kroah-Hartman
                   ` (60 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Josef Bacik, Jens Axboe

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Josef Bacik <josef@toxicpanda.com>

Commit 4c83e39f4d1944d7146fd06094f2c8053238d55c upstream.

io_uring_cmd_del_cancelable() uses hlist_del() to take a command off
->cancelable_uring_cmd, which leaves LIST_POISON1/2 behind in
->hash_node. Requests are recycled through the request cache without
being reinitialised, and not every user of ->hash_node sets it up before
it is used:

If a vectored futex wait is woken while futex_wait_multiple_setup() is
still queueing the futexes, io_futexv_wait() doesn't add the request to
->futex_list, and leaves the completion to the task_work queued by the
wake up. io_futexv_complete() ends in __io_futex_complete(), whose
hlist_del_init() is fine for a request that is unhashed, which is how all
other users of the node leave it. If the request was a cancelable
uring_cmd in its previous life, e.g. a ublk FETCH_REQ, it writes through
LIST_POISON2:

  Oops: general protection fault, probably for non-canonical address
  KASAN: maybe wild-memory-access in range [0xdead000000000120-...]
  RIP: 0010:io_futexv_complete+0x219/0x420
  Call Trace:
   tctx_task_work_run+0x804/0x950
   tctx_task_work+0x71/0xa0
   task_work_run+0x118/0x200

Leave the node unhashed.

Fixes: 93b8cc60c37b ("io_uring: cancelable uring_cmd")
Assisted-by: LLM
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-2-c1556f5d7bf5@toxicpanda.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/uring_cmd.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/io_uring/uring_cmd.c
+++ b/io_uring/uring_cmd.c
@@ -85,7 +85,7 @@ static void io_uring_cmd_del_cancelable(
 
 	cmd->flags &= ~IORING_URING_CMD_CANCELABLE;
 	io_ring_submit_lock(ctx, issue_flags);
-	hlist_del(&req->hash_node);
+	hlist_del_init(&req->hash_node);
 	io_ring_submit_unlock(ctx, issue_flags);
 }
 



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 195/247] io_uring/wait: dont spin on a stuck overflow list
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (193 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 194/247] io_uring/cmd: dont leave list poison in ->hash_node Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 16:59 ` [PATCH 6.12 196/247] io_uring/io-wq: dont lose the signal that ends work Greg Kroah-Hartman
                   ` (59 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Josef Bacik, Jens Axboe,
	Claude Fable 5.1

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Josef Bacik <josef@toxicpanda.com>

Commit 34f5a664c34d3cb62f6bec7f4156754594a7d25b upstream.

As long as IO_CHECK_CQ_OVERFLOW_BIT is set, io_cqring_wait_schedule()
returns right away, before it gets to look at signals or arms the timeout,
for io_cqring_wait() to flush the overflow list. If that doesn't empty the
list, and the CQ ring doesn't hold the number of events the caller wants,
the loop starts over, with the same result. The task spins in the kernel,
and can't be killed.

The assumption is that this can't happen: if CQEs can't be flushed, the
ring is full, and min_events is capped to the size of the ring. But:

- With IORING_SETUP_CQE_MIXED a 32b CQE needs two contiguous entries. It
  is stuck on the list if a single one is free, and then the ring holds
  less than cq_entries events. A single threaded application that asks
  for as many events as the ring has entries never gets out of
  io_uring_enter().

- Whether the ring is full is up to the CQ head, which the application
  can write to. While one thread waits for events on an empty ring,
  another one can move the head back so that the ring looks full and
  have a CQE overflow. The waiter can't be stopped any more, not even by
  SIGKILL.

Only the application can make room in the CQ ring. Return to it if the
list could not be flushed.

[ 6.12: io_cqring_wait() is in io_uring.c ]
Fixes: 3fcf19d592d5 ("io_uring: parse check_cq out of wq waiting")
Assisted-by: LLM
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-3-c1556f5d7bf5@toxicpanda.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/io_uring.c |   13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

--- a/io_uring/io_uring.c
+++ b/io_uring/io_uring.c
@@ -2608,9 +2608,18 @@ static int io_cqring_wait(struct io_ring
 
 		check_cq = READ_ONCE(ctx->check_cq);
 		if (unlikely(check_cq)) {
-			/* let the caller flush overflows, retry */
-			if (check_cq & BIT(IO_CHECK_CQ_OVERFLOW_BIT))
+			if (check_cq & BIT(IO_CHECK_CQ_OVERFLOW_BIT)) {
 				io_cqring_do_overflow_flush(ctx);
+				/*
+				 * No room for what has overflown. It takes the
+				 * application to change that, so return to it.
+				 */
+				if (test_bit(IO_CHECK_CQ_OVERFLOW_BIT,
+					     &ctx->check_cq)) {
+					ret = 0;
+					break;
+				}
+			}
 			if (check_cq & BIT(IO_CHECK_CQ_DROPPED_BIT)) {
 				ret = -EBADR;
 				break;



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 196/247] io_uring/io-wq: dont lose the signal that ends work
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (194 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 195/247] io_uring/wait: dont spin on a stuck overflow list Greg Kroah-Hartman
@ 2026-10-28 16:59 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 197/247] io_uring/io-wq: dont hide a link from cancellations Greg Kroah-Hartman
                   ` (58 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 16:59 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Josef Bacik, Jens Axboe

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Josef Bacik <josef@toxicpanda.com>

Commit 63c103279a95e82280092f2f4232e91e8117a252 upstream.

When a thread exits, only its tracked requests are cancelled. Then its
io-wq is torn down. io_wq_exit_workers() signals every worker, to get it
out of an interruptible sleep, and waits for all of them to exit. Before
they do, they go through the work that is left. Unbounded work is
cancelled. Bounded work is run, as it is expected to end by itself.

Not all of it does. An open has no file yet, so it counts as bounded, and
the open of a FIFO waits for the other end. That is what the signal is for.
But the workers are signalled once, and a worker that hasn't started the
work by then loses the signal:

  io_wq_exit_workers()               io_worker_handle_work()
    io_wq_worker_wake()
      set TIF_NOTIFY_SIGNAL
                                       io_assign_current_work()
                                         io_run_task_work()
                                           clear TIF_NOTIFY_SIGNAL
                                       io_wq_submit_work()
                                         fifo_open()
                                           wait_for_partner()
    wait_for_completion_timeout()

The thread never gets out of do_exit():

  IORING_OP_OPENAT of a FIFO without a writer, IOSQE_ASYNC
  exit of the thread that has submitted it

hangs in more than 9 of 10 attempts (4 CPUs, KVM), until the process is
killed.

Set TIF_NOTIFY_SIGNAL for bounded work that is started with IO_WQ_BIT_EXIT
set. The bit is set before the workers are signalled, and it is tested
after the flag has been cleared, with clear_notify_signal() providing the
barrier. So either the flag stays, or the bit is seen.

Work that is started while the io-wq exits is treated like work that is
being run at that time: it isn't interrupted unless it waits
interruptibly.

Fixes: afcc4015d1bf ("io-wq: provide an io_wq_put_and_exit() helper")
Assisted-by: LLM
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-4-c1556f5d7bf5@toxicpanda.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/io-wq.c |    7 +++++++
 1 file changed, 7 insertions(+)

--- a/io_uring/io-wq.c
+++ b/io_uring/io-wq.c
@@ -598,9 +598,16 @@ static void io_worker_handle_work(struct
 
 			next_hashed = wq_next_work(work);
 
+			/*
+			 * io_wq_exit_workers() signals us once, so that we
+			 * don't sleep for ever. If that was before this work
+			 * became the current one, the signal is gone.
+			 */
 			if (do_kill &&
 			    (atomic_read(&work->flags) & IO_WQ_WORK_UNBOUND))
 				atomic_or(IO_WQ_WORK_CANCEL, &work->flags);
+			else if (do_kill)
+				set_notify_signal(current);
 			wq->do_work(work);
 			io_assign_current_work(worker, NULL);
 



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 197/247] io_uring/io-wq: dont hide a link from cancellations
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (195 preceding siblings ...)
  2026-10-28 16:59 ` [PATCH 6.12 196/247] io_uring/io-wq: dont lose the signal that ends work Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 198/247] io_uring: dont flood a cancelling task with task_work Greg Kroah-Hartman
                   ` (57 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Josef Bacik, Jens Axboe,
	Claude Fable 5.1

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Josef Bacik <josef@toxicpanda.com>

Commit 436d48a2ed13112d2d27085325838e5bce6b4507 upstream.

A task that exits cancels its tracked requests and waits until they are
gone. io_uring_cancel_generic() looks everywhere a request can be, and
goes to sleep if it found nothing to cancel. It is woken up each time
one of the requests of the task is completed by task work or freed.

When io-wq is done with a request that has a link, there is a time in which
the next request of the link can't be found:

  io_worker_handle_work()
    io_assign_current_work(worker, NULL)
    io_wq_free_work(work)
      io_req_find_next()           // takes the link off the request
      io_free_req()                // task work for the task
    io_assign_current_work(worker, linked)
      io_run_task_work()
      cond_resched()
      worker->cur_work = linked

It is not pending, it is not the current work of a worker, and it is not
yet on the list that it is about to be parked on. If the pass that the
exiting task makes because of io_free_req() falls into that time, it finds
nothing and the task goes to sleep. The worker then runs the link, which
IO_WQ_BIT_EXIT doesn't prevent for bounded work. If that parks the request
nothing is completed or freed, and nobody wakes up the task. If it is the
process that exits it can't be killed any more either.

  NOP, IOSQE_ASYNC | IOSQE_IO_LINK
  FUTEX_WAIT, FUTEX2_PRIVATE
  exit of the thread, or of the process, up to 63us later

With four of these per round 5 to 8 of 10,000 rounds hang (4 CPUs, KVM):

  io_uring_cancel_generic
  do_exit

Commit f8b632e89a10 ("io_uring: tighten task exit cancellations") is about
the same gap, and makes the task look again for whatever happens before
io_free_req().

Free the request once the link is the current work of the worker, or
pending. Whoever is woken up by that can find the link, until it is parked
where cancellations look as well. To do so split io_wq_free_work() in two.

[ 6.12: io-wq still calls back through io_wq_data, so a ->put_work callback
  is added next to ->free_work. io_wq_put_work() keeps the link check of
  6.12, without the REQ_F_CQE_SKIP condition that commit 5530a5102e3c adds
  in 7.3 ]
Fixes: 768134d4f481 ("io_uring: don't do flush cancel under inflight_lock")
Assisted-by: LLM
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-5-c1556f5d7bf5@toxicpanda.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/io-wq.c    |   22 ++++++++++++++++++----
 io_uring/io-wq.h    |    4 +++-
 io_uring/io_uring.c |   29 +++++++++++++++++++++--------
 io_uring/io_uring.h |    3 ++-
 io_uring/tctx.c     |    1 +
 5 files changed, 45 insertions(+), 14 deletions(-)

--- a/io_uring/io-wq.c
+++ b/io_uring/io-wq.c
@@ -98,6 +98,7 @@ enum {
 struct io_wq {
 	unsigned long state;
 
+	put_work_fn *put_work;
 	free_work_fn *free_work;
 	io_wq_work_fn *do_work;
 
@@ -593,8 +594,9 @@ static void io_worker_handle_work(struct
 		/* handle a whole dependent link */
 		do {
 			bool do_kill = test_bit(IO_WQ_BIT_EXIT, &wq->state);
-			struct io_wq_work *next_hashed, *linked;
+			struct io_wq_work *next_hashed, *linked, *done = work;
 			unsigned int hash = io_get_work_hash(work);
+			bool last;
 
 			next_hashed = wq_next_work(work);
 
@@ -611,7 +613,7 @@ static void io_worker_handle_work(struct
 			wq->do_work(work);
 			io_assign_current_work(worker, NULL);
 
-			linked = wq->free_work(work);
+			last = wq->put_work(work, &linked);
 			work = next_hashed;
 			if (!work && linked && !io_wq_is_hashed(linked)) {
 				work = linked;
@@ -620,6 +622,13 @@ static void io_worker_handle_work(struct
 			io_assign_current_work(worker, work);
 			if (linked)
 				io_wq_enqueue(wq, linked);
+			/*
+			 * Not before the link is current or pending work again.
+			 * This may be the last time that a task is woken up
+			 * which exits and looks for requests to cancel.
+			 */
+			if (last)
+				wq->free_work(done);
 
 			if (hash != -1U && !next_hashed) {
 				/* serialize hash clear with wake_up() */
@@ -920,9 +929,13 @@ static bool io_wq_worker_wake(struct io_
 static void io_run_cancel(struct io_wq_work *work, struct io_wq *wq)
 {
 	do {
+		struct io_wq_work *linked;
+
 		atomic_or(IO_WQ_WORK_CANCEL, &work->flags);
 		wq->do_work(work);
-		work = wq->free_work(work);
+		if (wq->put_work(work, &linked))
+			wq->free_work(work);
+		work = linked;
 	} while (work);
 }
 
@@ -1174,7 +1187,7 @@ struct io_wq *io_wq_create(unsigned boun
 	int ret, i;
 	struct io_wq *wq;
 
-	if (WARN_ON_ONCE(!data->free_work || !data->do_work))
+	if (WARN_ON_ONCE(!data->put_work || !data->free_work || !data->do_work))
 		return ERR_PTR(-EINVAL);
 	if (WARN_ON_ONCE(!bounded))
 		return ERR_PTR(-EINVAL);
@@ -1185,6 +1198,7 @@ struct io_wq *io_wq_create(unsigned boun
 
 	refcount_inc(&data->hash->refs);
 	wq->hash = data->hash;
+	wq->put_work = data->put_work;
 	wq->free_work = data->free_work;
 	wq->do_work = data->do_work;
 
--- a/io_uring/io-wq.h
+++ b/io_uring/io-wq.h
@@ -21,7 +21,8 @@ enum io_wq_cancel {
 	IO_WQ_CANCEL_NOTFOUND,	/* work not found */
 };
 
-typedef struct io_wq_work *(free_work_fn)(struct io_wq_work *);
+typedef bool (put_work_fn)(struct io_wq_work *, struct io_wq_work **);
+typedef void (free_work_fn)(struct io_wq_work *);
 typedef void (io_wq_work_fn)(struct io_wq_work *);
 
 struct io_wq_hash {
@@ -40,6 +41,7 @@ struct io_wq_data {
 	struct io_wq_hash *hash;
 	struct task_struct *task;
 	io_wq_work_fn *do_work;
+	put_work_fn *put_work;
 	free_work_fn *free_work;
 };
 
--- a/io_uring/io_uring.c
+++ b/io_uring/io_uring.c
@@ -1770,17 +1770,30 @@ int io_poll_issue(struct io_kiocb *req,
 				 IO_URING_F_COMPLETE_DEFER);
 }
 
-struct io_wq_work *io_wq_free_work(struct io_wq_work *work)
+/*
+ * io-wq is done with @work. Returns true if it held the last reference, and
+ * hands out the next request of the link then. The caller has to make sure
+ * that cancellations can find the latter before it calls io_wq_free_work().
+ */
+bool io_wq_put_work(struct io_wq_work *work, struct io_wq_work **linked)
 {
 	struct io_kiocb *req = container_of(work, struct io_kiocb, work);
 	struct io_kiocb *nxt = NULL;
 
-	if (req_ref_put_and_test_atomic(req)) {
-		if (req->flags & IO_REQ_LINK_FLAGS)
-			nxt = io_req_find_next(req);
-		io_free_req(req);
-	}
-	return nxt ? &nxt->work : NULL;
+	*linked = NULL;
+	if (!req_ref_put_and_test_atomic(req))
+		return false;
+
+	if (req->flags & IO_REQ_LINK_FLAGS)
+		nxt = io_req_find_next(req);
+	if (nxt)
+		*linked = &nxt->work;
+	return true;
+}
+
+void io_wq_free_work(struct io_wq_work *work)
+{
+	io_free_req(container_of(work, struct io_kiocb, work));
 }
 
 void io_wq_submit_work(struct io_wq_work *work)
@@ -1791,7 +1804,7 @@ void io_wq_submit_work(struct io_wq_work
 	bool needs_poll = false;
 	int ret = 0, err = -ECANCELED;
 
-	/* one will be dropped by ->io_wq_free_work() after returning to io-wq */
+	/* one will be dropped by ->put_work() after returning to io-wq */
 	if (!(req->flags & REQ_F_REFCOUNT))
 		__io_req_set_refcount(req, 2);
 	else
--- a/io_uring/io_uring.h
+++ b/io_uring/io_uring.h
@@ -101,7 +101,8 @@ int io_submit_sqes(struct io_ring_ctx *c
 int io_do_iopoll(struct io_ring_ctx *ctx, bool force_nonspin);
 void __io_submit_flush_completions(struct io_ring_ctx *ctx);
 
-struct io_wq_work *io_wq_free_work(struct io_wq_work *work);
+bool io_wq_put_work(struct io_wq_work *work, struct io_wq_work **linked);
+void io_wq_free_work(struct io_wq_work *work);
 void io_wq_submit_work(struct io_wq_work *work);
 
 void io_free_req(struct io_kiocb *req);
--- a/io_uring/tctx.c
+++ b/io_uring/tctx.c
@@ -35,6 +35,7 @@ static struct io_wq *io_init_wq_offload(
 
 	data.hash = hash;
 	data.task = task;
+	data.put_work = io_wq_put_work;
 	data.free_work = io_wq_free_work;
 	data.do_work = io_wq_submit_work;
 



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 198/247] io_uring: dont flood a cancelling task with task_work
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (196 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 197/247] io_uring/io-wq: dont hide a link from cancellations Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 199/247] io_uring/io-wq: dont strand work when a worker exits Greg Kroah-Hartman
                   ` (56 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Josef Bacik, Jens Axboe

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Josef Bacik <josef@toxicpanda.com>

Commit 22e643e61b9b6299b42ff7d88bab48bccada8a5d upstream.

io_ring_exit_work() asks each task which has used the ring to remove its
tctx node, by task_work, and repeats that until the list is empty.
io_tctx_exit_cb() doesn't touch the node while the task is in
io_uring_cancel_generic(), which removes all the nodes at its end. So the
work item queues the callback again as soon as it has completed, for
nothing.

That is more than a waste of time. task_work_run() only returns when it
finds the list empty. If the rings are released from inside the
cancellation, because requests of other rings held the last references to
their files, up to 64 work items keep sending callbacks to the one task
which is running them. It never finds the list empty, never gets back to
the cancellation, the nodes stay, and so it goes on: a task with 60 pairs
of rings which poll each other ran 280000 callbacks in 5 seconds, 20
seconds after exit_group(). It ends when all the senders happen to be late
at the same time. Until then the task keeps a CPU and the work items busy.

An exiting task can't be killed meanwhile. execve() cancels the requests in
the same way, so a live task can get stuck there as well, for minutes. If
it takes more than five, the work items run into the
WARN_ON_ONCE(time_after(jiffies, timeout)) of io_ring_exit_work(). No
privilege is needed for any of this.

If the callback has met a task in cancellation, wait a little before it is
sent again. Nobody has to wake the work item up for that: either the node
is gone by then, or it is the turn of the next round.

Fixes: d56d938b4bef ("io_uring: do ctx initiated file note removal")
Assisted-by: LLM
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-6-c1556f5d7bf5@toxicpanda.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/io_uring.c |   12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

--- a/io_uring/io_uring.c
+++ b/io_uring/io_uring.c
@@ -2873,6 +2873,7 @@ struct io_tctx_exit {
 	struct callback_head		task_work;
 	struct completion		completion;
 	struct io_ring_ctx		*ctx;
+	bool				in_cancel;
 };
 
 static __cold void io_tctx_exit_cb(struct callback_head *cb)
@@ -2887,7 +2888,8 @@ static __cold void io_tctx_exit_cb(struc
 	 * tctx can be NULL if the queueing of this task_work raced with
 	 * work cancelation off the exec path.
 	 */
-	if (tctx && !atomic_read(&tctx->in_cancel))
+	work->in_cancel = tctx && atomic_read(&tctx->in_cancel);
+	if (tctx && !work->in_cancel)
 		io_uring_del_tctx_node((unsigned long)work->ctx);
 	complete(&work->completion);
 }
@@ -2981,6 +2983,14 @@ static __cold void io_ring_exit_work(str
 		 * wait is marked as interruptible.
 		 */
 		wait_for_completion_interruptible(&exit.completion);
+		/*
+		 * The task removes the node when it is done with its
+		 * cancellation. Give it the time for that: it doesn't get back
+		 * to it as long as it finds new task_work each time it has run
+		 * the old one, and we may be one of many who send it.
+		 */
+		if (exit.in_cancel)
+			schedule_timeout_idle(HZ / 20);
 		mutex_lock(&ctx->uring_lock);
 	}
 	mutex_unlock(&ctx->uring_lock);



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 199/247] io_uring/io-wq: dont strand work when a worker exits
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (197 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 198/247] io_uring: dont flood a cancelling task with task_work Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 200/247] io_uring/io-wq: dont exit with a creation pending Greg Kroah-Hartman
                   ` (55 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Josef Bacik, Jens Axboe,
	Claude Fable 5.1

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Josef Bacik <josef@toxicpanda.com>

Commit ad41f325be1271b22d99353819c90f0d5e45acc8 upstream.

A worker exits if its idle timeout fired and it isn't the last one, if
its affinity was changed, or if the wq is marked exit-on-idle. It decides
so after it found the work list empty, and until io_worker_exit() is
through it stays on the free list and in ->nr_running:

worker                                io_wq_enqueue()
io_acct_run_queue() == false
                                      queues work
                                      io_acct_activate_free_worker()
                                        wake_up_process(worker)
                                      // found one, nothing to create
acct->nr_workers--
break
io_worker_exit()

Nobody is going to look at the work. If other workers exist, it has to
wait until one of them finishes what it is blocked on or hits its idle
timeout. If not, which is possible for the affinity and the exit-on-idle
case, it sits there until something else is queued. For exit-on-idle it
takes a task that closes its last ring and sets up a new one while the
workers are on their way out.

Make the worker take itself off the free list when it gives up its
->nr_workers slot, then leave ->nr_running, and only then take the final
look at the work list. That look and queueing work are both done under
acct->lock, so either the worker sees the work and stays, or the enqueue
side sees that the worker is gone and wakes or creates another one. If it
wants to stay and finds that its slot has been taken, a worker has been
created in its place, which is going to look at the work list, and it can
leave after all.

[ 6.12: ->nr_workers and the free list are under wq->lock, there is no
  acct->workers_lock ]
Fixes: 38aa434ab933 ("io_uring/io-wq: add exit-on-idle state")
Fixes: 05c5f4ee4da7 ("io-wq: get rid of FIXED worker flag")
Assisted-by: LLM
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-11-c1556f5d7bf5@toxicpanda.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/io-wq.c |   38 +++++++++++++++++++++++++++++++++++++-
 1 file changed, 37 insertions(+), 1 deletion(-)

--- a/io_uring/io-wq.c
+++ b/io_uring/io-wq.c
@@ -647,6 +647,37 @@ static void io_worker_handle_work(struct
 	} while (1);
 }
 
+/*
+ * The worker has decided to exit, and has given up its ->nr_workers slot and
+ * its place on the free list. io_wq_enqueue() may have picked it from that
+ * list, or seen it running, after it last looked at the work list. Leave
+ * ->nr_running as well and check again. Returns false if the worker has to
+ * stay.
+ */
+static bool io_worker_retire(struct io_wq_acct *acct, struct io_worker *worker)
+{
+	struct io_wq *wq = worker->wq;
+
+	/* turns io_wq_dec_running() and the scheduler hooks into no-ops */
+	clear_bit(IO_WORKER_F_UP, &worker->flags);
+	atomic_dec(&acct->nr_running);
+	if (!io_acct_run_queue(acct))
+		return true;
+	raw_spin_unlock(&acct->lock);
+
+	raw_spin_lock(&wq->lock);
+	if (acct->nr_workers >= acct->max_workers) {
+		/* a worker was created in our place, the work is its business */
+		raw_spin_unlock(&wq->lock);
+		return true;
+	}
+	acct->nr_workers++;
+	raw_spin_unlock(&wq->lock);
+	atomic_inc(&acct->nr_running);
+	set_bit(IO_WORKER_F_UP, &worker->flags);
+	return false;
+}
+
 static int io_wq_worker(void *data)
 {
 	struct io_worker *worker = data;
@@ -680,9 +711,14 @@ static int io_wq_worker(void *data)
 		 */
 		if (last_timeout && (exit_mask || acct->nr_workers > 1)) {
 			acct->nr_workers--;
+			if (test_and_clear_bit(IO_WORKER_F_FREE, &worker->flags))
+				hlist_nulls_del_init_rcu(&worker->nulls_node);
 			raw_spin_unlock(&wq->lock);
 			__set_current_state(TASK_RUNNING);
-			break;
+			if (io_worker_retire(acct, worker))
+				break;
+			last_timeout = false;
+			continue;
 		}
 		last_timeout = false;
 		__io_worker_idle(wq, worker);



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 200/247] io_uring/io-wq: dont exit with a creation pending
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (198 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 199/247] io_uring/io-wq: dont strand work when a worker exits Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 201/247] io_uring/io-wq: let cancel find picked up hashed work Greg Kroah-Hartman
                   ` (54 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Josef Bacik, Jens Axboe,
	Claude Fable 5.1

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Josef Bacik <josef@toxicpanda.com>

Commit e231d2e8f80d3649ecd3851b7f2abdfbe606c04b upstream.

A worker that is the last one to go to sleep while work is pending asks
for another worker. io_wq_dec_running() bumps ->nr_running on behalf of
the new worker and queues create_worker_cb() as task_work for the owner
of the io-wq. Until that has run, everybody else takes it that a worker
is running which is going to look after the work list: io_wq_enqueue()
doesn't create one, and other workers that go to sleep don't find
themselves to be the last.

If the worker that made the request exits, io_worker_exit() cancels the
task_work, and io_worker_cancel_cb() drops ->nr_running without a look at
the work list:

worker A                   worker B                 io_wq_enqueue()
blocks, work is pending
  nr_running++
  queues create_worker_cb()
wakes, handles the work
idle timeout, decides to exit
                           picks up work 1
                                                    queues work 2
                                                    B is on the free list
                                                    still: wakes B
                           work 1 blocks
                             nr_running 2 -> 1
io_worker_exit()
  io_worker_cancel_cb()
    nr_running 1 -> 0

Work 2 has to wait for work 1, although there is room for more workers.
It takes an owner that doesn't get around to run its task_work for the
time of the idle timeout, less if the worker exits because its affinity
was changed or the io-wq is marked exit-on-idle.

Let the worker stay around until its request has been dealt with. Only
the worker itself sets ->create_state, so it can't be set behind its
back once it has decided to leave.

[ 6.12: no exit-on-idle state ]
Fixes: 1d5f5ea7cb7d ("io-wq: remove worker to owner tw dependency")
Assisted-by: LLM
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-12-c1556f5d7bf5@toxicpanda.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/io-wq.c |    6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

--- a/io_uring/io-wq.c
+++ b/io_uring/io-wq.c
@@ -708,8 +708,12 @@ static int io_wq_worker(void *data)
 		/*
 		 * Last sleep timed out. Exit if we're not the last worker,
 		 * or if someone modified our affinity.
+		 * Not as long as a request of ours for another worker is
+		 * pending, though. It is accounted as a running worker, which
+		 * others rely on, and io_worker_exit() would cancel it.
 		 */
-		if (last_timeout && (exit_mask || acct->nr_workers > 1)) {
+		if (last_timeout && (exit_mask || acct->nr_workers > 1) &&
+		    !test_bit(0, &worker->create_state)) {
 			acct->nr_workers--;
 			if (test_and_clear_bit(IO_WORKER_F_FREE, &worker->flags))
 				hlist_nulls_del_init_rcu(&worker->nulls_node);



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 201/247] io_uring/io-wq: let cancel find picked up hashed work
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (199 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 200/247] io_uring/io-wq: dont exit with a creation pending Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 202/247] io_uring/poll: dont lose a cancel as io-wq arms poll Greg Kroah-Hartman
                   ` (53 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Josef Bacik, Jens Axboe

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Josef Bacik <josef@toxicpanda.com>

Commit e9efeb4fc97b0879512a3c3b995ed448f2487e12 upstream.

io_get_next_work() takes all the work items that share a hash off the
work list in one go, and the worker runs them one after the other. Only
the one it is working on is visible as ->cur_work. The others are neither
on the list nor current, so io_wq_cancel_cb() can't find them.

IORING_OP_ASYNC_CANCEL and IORING_REGISTER_SYNC_CANCEL return -ENOENT for
a request that has not even been started, e.g. a buffered write queued
behind another write to the same file that is blocked, and the request is
carried out. The cancellation done for a task or ring that goes away gets
there in the end, as it keeps trying, but it has to wait for each item to
become current.

Keep a pointer to the remainder of the chain next to ->cur_work, and have
io_wq_worker_cancel() look at it. The items on it belong to the worker,
which needs ->lock to move on to the next one. Matching work is flagged
with IO_WQ_WORK_CANCEL and fails with -ECANCELED when its turn comes. The
worker isn't signalled for it, that would interrupt the unrelated work it
is busy with. As the request isn't gone yet, it is reported like running
work, with -EALREADY.

Fixes: 86f3cd1b589a ("io-wq: handle hashed writes in chains")
Assisted-by: LLM
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-13-c1556f5d7bf5@toxicpanda.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/io-wq.c |   35 +++++++++++++++++++++++++++++------
 1 file changed, 29 insertions(+), 6 deletions(-)

--- a/io_uring/io-wq.c
+++ b/io_uring/io-wq.c
@@ -54,6 +54,8 @@ struct io_worker {
 	struct io_wq *wq;
 
 	struct io_wq_work *cur_work;
+	/* rest of the hashed chain ->cur_work was taken off the list with */
+	struct io_wq_work *next_work;
 	raw_spinlock_t lock;
 
 	struct completion ref_done;
@@ -535,6 +537,17 @@ static struct io_wq_work *io_get_next_wo
 	return NULL;
 }
 
+static void __io_assign_current_work(struct io_worker *worker,
+				     struct io_wq_work *work)
+{
+	raw_spin_lock(&worker->lock);
+	worker->cur_work = work;
+	/* stays valid while in between two items of a chain */
+	if (work)
+		worker->next_work = wq_next_work(work);
+	raw_spin_unlock(&worker->lock);
+}
+
 static void io_assign_current_work(struct io_worker *worker,
 				   struct io_wq_work *work)
 {
@@ -543,9 +556,7 @@ static void io_assign_current_work(struc
 		cond_resched();
 	}
 
-	raw_spin_lock(&worker->lock);
-	worker->cur_work = work;
-	raw_spin_unlock(&worker->lock);
+	__io_assign_current_work(worker, work);
 }
 
 /*
@@ -576,9 +587,7 @@ static void io_worker_handle_work(struct
 			 * work list, but isn't yet discoverable as the
 			 * current work item for this worker.
 			 */
-			raw_spin_lock(&worker->lock);
-			worker->cur_work = work;
-			raw_spin_unlock(&worker->lock);
+			__io_assign_current_work(worker, work);
 		}
 
 		raw_spin_unlock(&acct->lock);
@@ -1083,6 +1092,7 @@ static bool __io_wq_worker_cancel(struct
 static bool io_wq_worker_cancel(struct io_worker *worker, void *data)
 {
 	struct io_cb_cancel_data *match = data;
+	struct io_wq_work *work;
 
 	/*
 	 * Hold the lock to avoid ->cur_work going out of scope, caller
@@ -1091,6 +1101,19 @@ static bool io_wq_worker_cancel(struct i
 	raw_spin_lock(&worker->lock);
 	if (__io_wq_worker_cancel(worker, match, worker->cur_work))
 		match->nr_running++;
+	/*
+	 * Hashed work is taken off the work list a chain at a time, what the
+	 * worker hasn't started yet can only be found here. It doesn't move on
+	 * without the lock. Just mark the work, it fails once it is its turn.
+	 */
+	for (work = worker->next_work; work; work = wq_next_work(work)) {
+		if (match->nr_running && !match->cancel_all)
+			break;
+		if (match->fn(work, match->data)) {
+			atomic_or(IO_WQ_WORK_CANCEL, &work->flags);
+			match->nr_running++;
+		}
+	}
 	raw_spin_unlock(&worker->lock);
 
 	return match->nr_running && !match->cancel_all;



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 202/247] io_uring/poll: dont lose a cancel as io-wq arms poll
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (200 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 201/247] io_uring/io-wq: let cancel find picked up hashed work Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 203/247] io_uring: dont lose a cancel as io-wq parks a request Greg Kroah-Hartman
                   ` (52 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Josef Bacik, Jens Axboe

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Josef Bacik <josef@toxicpanda.com>

Commit 6d2d4c2530e95ff6ddeb98195d49d99dbca14369 upstream.

A request on a pollable file that was forced to io-wq is issued without
blocking there. If that ends in -EAGAIN, io_wq_submit_work() arms poll
for it and returns. It looks at IO_WQ_WORK_CANCEL once, before it issues
the request.

Somebody who wants to cancel the request in between finds it running:

  io-wq worker                          io_try_cancel()
  io_wq_submit_work()
    IO_WQ_WORK_CANCEL isn't set
    io_issue_sqe() = -EAGAIN
                                        io_async_cancel_one()
                                          sets IO_WQ_WORK_CANCEL
                                          signals the worker
                                          = -EALREADY
                                        io_poll_cancel() = -ENOENT
                                        ...
                                        = -ENOENT
    io_arm_poll_handler() = IO_APOLL_OK
    return

Nobody looks at the flag again, and the signal doesn't matter to a
worker that doesn't sleep. The request is armed as if nothing had
happened:

 - a linked timeout completes with -ENOENT, and the request it was
   meant to limit waits for as long as it takes.
 - IORING_OP_ASYNC_CANCEL returns -EALREADY, and the request stays.
 - IORING_REGISTER_SYNC_CANCEL waits for the request to complete if it
   gets -EALREADY. Since commit 5623eb1ed035 ("io_uring/tctx: add
   separate lock for list of tctx's in ctx") it doesn't sleep but spins,
   so its next attempt finds the armed poll.

The same goes for a multishot poll, recv or accept that is armed from
io-wq.

With a read of an empty pipe, IOSQE_ASYNC, and a linked timeout of 5ms
or a cancel in the same submission, in a guest that is slow enough (TCG,
KASAN), the request is lost in 21 of 24 rounds of 40 or 100 attempts.

While it arms poll from io-wq, __io_arm_poll_handler() owns the request.
Look at the flag once the request is in the hash table. The table is
searched and the request is added with ->uring_lock held, and the flag is
set before the search. So either the search finds the request, or it
came first and the flag is seen. With the request marked as cancelled, the
task work that is queued, right away or because ownership can't be
released, fails it with -ECANCELED.

What the canceller is told doesn't change. In this window a linked timeout
still completes with -ENOENT rather than -ETIME, a cancel request with
-EALREADY, and one with IORING_ASYNC_CANCEL_ALL or _ANY with a count that
doesn't include the request. But the request is cancelled, so what is new
is a request that completes with -ECANCELED after such a result.

This doesn't help in two cases:

 - IORING_ASYNC_CANCEL_ALL and _ANY, if the work is flagged after the
   test added here, while io-wq still has it as the current work of the
   worker. io_cancel_cb() stamps it with the sequence of the cancel, so the
   search of the hash table on behalf of the same cancel takes it for
   done and skips it.
 - requests that are parked elsewhere by io-wq, like IORING_OP_FUTEX_WAIT
   and IORING_OP_WAITID. They have the same problem.

Fixes: 90fa02883f06 ("io_uring: implement async hybrid mode for pollable requests")
Assisted-by: LLM
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-14-c1556f5d7bf5@toxicpanda.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/poll.c |   12 ++++++++++++
 1 file changed, 12 insertions(+)

--- a/io_uring/poll.c
+++ b/io_uring/poll.c
@@ -656,6 +656,18 @@ static int __io_arm_poll_handler(struct
 
 	io_poll_add_hash(req);
 
+	/*
+	 * Whoever tried to cancel the request while io-wq was running it has
+	 * flagged the work item. If it searched the hash table before the
+	 * request got there it found nothing, and it won't come back. Both
+	 * the search and the insertion are done with ->uring_lock held, and
+	 * the flag is set before the search. If the search came first,
+	 * the flag is visible by now.
+	 */
+	if (ipt->owning &&
+	    (atomic_read(&req->work.flags) & IO_WQ_WORK_CANCEL))
+		io_poll_mark_cancelled(req);
+
 	if (mask && (poll->events & EPOLLET) &&
 	    io_poll_can_finish_inline(req, ipt)) {
 		__io_poll_execute(req, mask, 0);



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 203/247] io_uring: dont lose a cancel as io-wq parks a request
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (201 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 202/247] io_uring/poll: dont lose a cancel as io-wq arms poll Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 204/247] io_uring/cancel: dont forget that the work was running Greg Kroah-Hartman
                   ` (51 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Josef Bacik, Jens Axboe,
	Claude Fable 5.1

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Josef Bacik <josef@toxicpanda.com>

Commit 5cb049d2203d7a81a1c1a737c8df4575e71078e3 upstream.

IORING_OP_FUTEX_WAIT, IORING_OP_FUTEX_WAITV and IORING_OP_WAITID don't
block. They put the request on a list of the ring, where a wake up or a
cancellation finds it, and return IOU_ISSUE_SKIP_COMPLETE. They do so as
well if they are run by io-wq, e.g. because of IOSQE_ASYNC.

io_wq_submit_work() looks at IO_WQ_WORK_CANCEL once, before it issues the
request. Somebody who wants to cancel the request after that, and before
it is on the list, finds it running:

  io-wq worker                          io_try_cancel()
  io_wq_submit_work()
    IO_WQ_WORK_CANCEL isn't set
                                        io_async_cancel_one()
                                          sets IO_WQ_WORK_CANCEL
                                          signals the worker
                                          = -EALREADY
                                        ...
                                        io_futex_cancel() = -ENOENT
                                        ...
    io_futex_wait()
      adds the request to ->futex_list
    = IOU_ISSUE_SKIP_COMPLETE

Nobody looks at the flag again. IORING_OP_ASYNC_CANCEL returns -EALREADY
and the request stays.

It is the problem that "io_uring/poll: don't lose a cancel as io-wq arms
poll" deals with for poll.

Look at the flag once the request is on the list, and cancel it if it is
set. The lists are searched and the requests are added with ->uring_lock
held, and the flag is set before the search. So either the search finds
the request, or it came first and the flag is seen.

What the canceller is told doesn't change, see the other patch, also for
IORING_ASYNC_CANCEL_ALL and _ANY.

[ 6.12: __io_futex_cancel() and __io_waitid_cancel() take the ctx as well.
  futex_wait_setup() returns with the hash bucket locked and the futex_q
  not queued yet, so io_futex_wait() queues it before the check, with
  ->uring_lock still held ]
Fixes: 194bb58c6090 ("io_uring: add support for futex wake and wait")
Fixes: 8f350194d5cf ("io_uring: add support for vectored futex waits")
Fixes: f31ecf671ddc ("io_uring: add IORING_OP_WAITID support")
Assisted-by: LLM
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-15-c1556f5d7bf5@toxicpanda.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/futex.c    |    7 +++++--
 io_uring/io_uring.h |   17 +++++++++++++++++
 io_uring/waitid.c   |    2 ++
 3 files changed, 24 insertions(+), 2 deletions(-)

--- a/io_uring/futex.c
+++ b/io_uring/futex.c
@@ -307,6 +307,8 @@ int io_futexv_wait(struct io_kiocb *req,
 		 */
 		__set_current_state(TASK_RUNNING);
 		hlist_add_head(&req->hash_node, &ctx->futex_list);
+		if (io_wq_cancel_seen(req, issue_flags))
+			__io_futex_cancel(ctx, req);
 	} else {
 		iof->futexv_unqueued = 1;
 		if (woken != -1)
@@ -348,9 +350,10 @@ int io_futex_wait(struct io_kiocb *req,
 			       &ifd->q, &hb);
 	if (!ret) {
 		hlist_add_head(&req->hash_node, &ctx->futex_list);
-		io_ring_submit_unlock(ctx, issue_flags);
-
 		futex_queue(&ifd->q, hb, NULL);
+		if (io_wq_cancel_seen(req, issue_flags))
+			__io_futex_cancel(ctx, req);
+		io_ring_submit_unlock(ctx, issue_flags);
 		return IOU_ISSUE_SKIP_COMPLETE;
 	}
 
--- a/io_uring/io_uring.h
+++ b/io_uring/io_uring.h
@@ -251,6 +251,23 @@ static inline void io_ring_submit_lock(s
 	lockdep_assert_held(&ctx->uring_lock);
 }
 
+/*
+ * For a handler that is run by io-wq and parks the request on a list where
+ * cancellations find it, rather than completing it. Whoever tried to cancel
+ * the request before that found it running. It has flagged the work item,
+ * has searched the list in vain, and won't come back. To be called with
+ * ->uring_lock held, which the search needs as well, once the request is on
+ * the list: if the search came first, the flag is visible.
+ */
+static inline bool io_wq_cancel_seen(struct io_kiocb *req,
+				     unsigned int issue_flags)
+{
+	lockdep_assert_held(&req->ctx->uring_lock);
+
+	return (issue_flags & IO_URING_F_IOWQ) &&
+	       (atomic_read(&req->work.flags) & IO_WQ_WORK_CANCEL);
+}
+
 static inline void io_commit_cqring(struct io_ring_ctx *ctx)
 {
 	/* order cqe stores with ring update */
--- a/io_uring/waitid.c
+++ b/io_uring/waitid.c
@@ -375,6 +375,8 @@ int io_waitid(struct io_kiocb *req, unsi
 		 * a waitqueue callback, or if someone cancels it.
 		 */
 		if (!io_waitid_drop_issue_ref(req)) {
+			if (io_wq_cancel_seen(req, issue_flags))
+				__io_waitid_cancel(ctx, req, true);
 			io_ring_submit_unlock(ctx, issue_flags);
 			return IOU_ISSUE_SKIP_COMPLETE;
 		}



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 204/247] io_uring/cancel: dont forget that the work was running
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (202 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 203/247] io_uring: dont lose a cancel as io-wq parks a request Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 205/247] io_uring/cancel: recognize "no timeout" on 32-bit Greg Kroah-Hartman
                   ` (50 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Josef Bacik, Jens Axboe

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Josef Bacik <josef@toxicpanda.com>

Commit 8aa0e5db4845fb5ac11abe40d7b1cac0656c3ee3 upstream.

If the request to be cancelled is being run by io-wq,
io_async_cancel_one() flags the work, signals the worker and returns
-EALREADY. Since commit ccbf726171b7 ("io_uring: perform poll removal even
if async work removal is successful") io_try_cancel() goes on regardless,
as poll may be armed for the request. If it isn't, and nothing else turns
up, the result is the -ENOENT of the last search.

__io_async_cancel() makes up for that. On -ENOENT it tries the io-wq of
every task that uses the ring, and that of the caller is one of them. So
the work is found a second time, and the result is -EALREADY after all.

Unless the worker is done with it by then. If the work is flagged before
io_wq_submit_work() looks at IO_WQ_WORK_CANCEL, all the worker does is to
queue the request to be failed by task work. Then it isn't anywhere to be
found until the task work has run, and

 - IORING_REGISTER_SYNC_CANCEL returns -ENOENT,
 - IORING_OP_ASYNC_CANCEL completes with -ENOENT,

for a request that they have just cancelled, and that completes with
-ECANCELED.

With a read of an empty pipe, IOSQE_ASYNC, and a sync cancel right behind
it, 1 to 3 of 1,000,000 calls return -ENOENT, and 50 to 110 with
IORING_SETUP_DEFER_TASKRUN (4 CPUs, KVM). Nothing is written to the pipe,
and all of these reads end with -ECANCELED.

Remember that the work was found. IORING_OP_ASYNC_CANCEL completes with
-EALREADY, as it does if the worker is a bit slower. For
IORING_REGISTER_SYNC_CANCEL it means to try again, which ends with 0.

The result of a linked timeout, which calls io_try_cancel() by itself,
and the number that is returned for IORING_ASYNC_CANCEL_ALL and _ANY don't
change.

Fixes: ccbf726171b7 ("io_uring: perform poll removal even if async work removal is successful")
Assisted-by: LLM
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-16-c1556f5d7bf5@toxicpanda.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/cancel.c |   13 ++++++++++++-
 io_uring/cancel.h |    2 ++
 2 files changed, 14 insertions(+), 1 deletion(-)

--- a/io_uring/cancel.c
+++ b/io_uring/cancel.c
@@ -115,6 +115,8 @@ int io_try_cancel(struct io_uring_task *
 	 */
 	if (!ret)
 		return 0;
+	if (ret == -EALREADY)
+		cd->running = true;
 
 	ret = io_poll_cancel(ctx, cd, issue_flags);
 	if (ret != -ENOENT)
@@ -171,6 +173,7 @@ static int __io_async_cancel(struct io_c
 	struct io_tctx_node *node;
 	int ret, nr = 0;
 
+	cd->running = false;
 	do {
 		ret = io_try_cancel(tctx, cd, issue_flags);
 		if (ret == -ENOENT)
@@ -192,7 +195,15 @@ static int __io_async_cancel(struct io_c
 		}
 	}
 	io_ring_submit_unlock(ctx, issue_flags);
-	return all ? nr : ret;
+	if (all)
+		return nr;
+	/*
+	 * The worker may be done with the work that was found running, and
+	 * flagged, above. That isn't the same as not having found it.
+	 */
+	if (ret == -ENOENT && cd->running)
+		ret = -EALREADY;
+	return ret;
 }
 
 int io_async_cancel(struct io_kiocb *req, unsigned int issue_flags)
--- a/io_uring/cancel.h
+++ b/io_uring/cancel.h
@@ -11,6 +11,8 @@ struct io_cancel_data {
 	u8 opcode;
 	u32 flags;
 	int seq;
+	/* io_try_cancel() has found it being run by io-wq, and flagged it */
+	bool running;
 };
 
 int io_async_cancel_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 205/247] io_uring/cancel: recognize "no timeout" on 32-bit
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (203 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 204/247] io_uring/cancel: dont forget that the work was running Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 206/247] io_uring/cancel: let CANCEL_ALL find parked requests Greg Kroah-Hartman
                   ` (49 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Josef Bacik, Jens Axboe

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Josef Bacik <josef@toxicpanda.com>

Commit 3774e4d4c8533da2caae95556c4d635c7c4f45b8 upstream.

IORING_REGISTER_SYNC_CANCEL waits without a limit if both fields of
io_uring_sync_cancel_reg::timeout are -1. io_sync_cancel() compares them
with -1UL. They are of type long long. With a long of 32 bits -1UL is
4294967295, which is what it stays when it is converted for the
comparison, and the fields are never equal to it.

So { -1, -1 } is taken for a timeout. ktime_set() takes the nanoseconds as
an unsigned long, so what becomes of it is -1s + 4294967295ns = 3.29s.

If the request is being run by io-wq and can't be interrupted, the call
returns -ETIME after that time, rather than waiting for the request to be
gone. On i386, with a buffered read from a null_blk device that takes 4s
to complete a request, IOSQE_ASYNC, that is what each call does.

Fixes: 78a861b94959 ("io_uring: add sync cancelation API through io_uring_register()")
Assisted-by: LLM
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-17-c1556f5d7bf5@toxicpanda.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/cancel.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/io_uring/cancel.c
+++ b/io_uring/cancel.c
@@ -315,7 +315,7 @@ int io_sync_cancel(struct io_ring_ctx *c
 	if (ret != -EALREADY)
 		goto out;
 
-	if (sc.timeout.tv_sec != -1UL || sc.timeout.tv_nsec != -1UL) {
+	if (sc.timeout.tv_sec != -1 || sc.timeout.tv_nsec != -1) {
 		struct timespec64 ts = {
 			.tv_sec		= sc.timeout.tv_sec,
 			.tv_nsec	= sc.timeout.tv_nsec



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 206/247] io_uring/cancel: let CANCEL_ALL find parked requests
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (204 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 205/247] io_uring/cancel: recognize "no timeout" on 32-bit Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 207/247] io_uring: wake ring pollers for local task_work Greg Kroah-Hartman
                   ` (48 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Josef Bacik, Jens Axboe

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Josef Bacik <josef@toxicpanda.com>

Commit fe6ca13c98b1223f6005f32913ebd32e4df64b77 upstream.

A cancellation with IORING_ASYNC_CANCEL_ALL or _ANY goes on until it finds
nothing more. A request may stay where it was found for a while after it
has been cancelled, so each one that matches is stamped with the sequence
number of the cancellation, and is skipped from then on.

io_cancel_cb() does so for io-wq work as well. There is no need to:
pending work is taken off the list, and the workers are looked at once per
call. And it does harm. A request that is run by io-wq may be parked
while it still is the current work of the worker: poll gets armed for it,
or it is put on ->futex_list or ->waitid_list.

  io-wq worker                       io_try_cancel()
  io_wq_submit_work()
    io_arm_poll_handler()
      io_poll_add_hash()
                                       io_async_cancel_one()
                                         io_cancel_cb()
                                           stamps the request
                                         sets IO_WQ_WORK_CANCEL
                                         = -EALREADY
                                       io_poll_cancel()
                                         skips the request
                                       = -ENOENT
  io_assign_current_work(NULL)

The flag comes too late for the worker to see it, and the search that
would have found the request takes it for done. The cancellation returns,
and the request stays.

With a multishot poll, IOSQE_ASYNC, and IORING_OP_ASYNC_CANCEL with
IORING_ASYNC_CANCEL_ALL up to 63us later, that happens to 4 of 1,000
requests (4 CPUs, KVM).

Take the stamp off again if the work matches. If the request is found
on one of the lists it gets a new one, and io_cancel_cb() doesn't match it
a second time.

__io_async_cancel() tries the io-wq of the caller twice. So far the stamp
has kept it from counting work that is running there the second time.
Skip it instead, so that the number that is returned stays the same.

Fixes: 8e29da69fead ("io_uring: add support for IORING_ASYNC_CANCEL_ALL")
Assisted-by: LLM
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-18-c1556f5d7bf5@toxicpanda.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/cancel.c |   14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

--- a/io_uring/cancel.c
+++ b/io_uring/cancel.c
@@ -70,7 +70,16 @@ static bool io_cancel_cb(struct io_wq_wo
 	struct io_kiocb *req = container_of(work, struct io_kiocb, work);
 	struct io_cancel_data *cd = data;
 
-	return io_cancel_req_match(req, cd);
+	if (!io_cancel_req_match(req, cd))
+		return false;
+	/*
+	 * Pending work is gone once it has matched. Work that is running may
+	 * park the request where the same cancellation looks next. Don't make
+	 * it skip the request as one that it has dealt with.
+	 */
+	if (cd->flags & (IORING_ASYNC_CANCEL_ALL | IORING_ASYNC_CANCEL_ANY))
+		req->cancel_seq_set = false;
+	return true;
 }
 
 static int io_async_cancel_one(struct io_uring_task *tctx,
@@ -187,6 +196,9 @@ static int __io_async_cancel(struct io_c
 	io_ring_submit_lock(ctx, issue_flags);
 	ret = -ENOENT;
 	list_for_each_entry(node, &ctx->tctx_list, ctx_node) {
+		/* has been done above, don't count what is running there */
+		if (all && node->task->io_uring == tctx)
+			continue;
 		ret = io_async_cancel_one(node->task->io_uring, cd);
 		if (ret != -ENOENT) {
 			if (!all)



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 207/247] io_uring: wake ring pollers for local task_work
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (205 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 206/247] io_uring/cancel: let CANCEL_ALL find parked requests Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 208/247] io_uring/wait: look at all CQ waiters on wake up Greg Kroah-Hartman
                   ` (47 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Josef Bacik, Jens Axboe,
	Claude Fable 5.1

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Josef Bacik <josef@toxicpanda.com>

Commit b88902d8745a701d24275d012f0830e3628e2a22 upstream.

With IORING_SETUP_DEFER_TASKRUN completions are queued as local work, and
only become CQEs when the submitter enters the kernel to wait for events.
For an application that finds out via poll() or epoll on the ring fd when
it is time to do that, io_uring_poll() reports EPOLLIN if local work is
pending.

That only helps if the work is there at the time of the call. When
DEFER_TASKRUN was added, io_req_local_work_add() did io_cqring_wake(),
which took care of tasks sleeping in poll() as well. Then polling got a
wait queue of its own, ->poll_wq, and the wake up in
io_req_local_work_add() was replaced by waking the submitter directly.
Since then ->poll_wq is only woken when CQEs are committed, which for
such a ring is done by the very task that is waiting to be told to:

  submitter                           completion
  poll(ring_fd)
    io_uring_poll()  // nothing yet
    schedule()
                                      io_req_local_work_add()
                                        // ->cq_wait_nr: nobody waits
  // sleeps on

Wake ->poll_wq when the first entry is put on the work list. Like for the
eventfd, that must not be done right away if the work is queued from a
wake up handler, as the chain of wake ups could get back to the wait
queue whose lock is held. Use an RCU callback in that case, with a
reference to the ring.

[ 6.12: the code is in io_uring.c, ->poll_activated is a bitfield, and
  there is no IOU_F_TWQ_IN_WAKE to tell a wake up handler apart, so the
  wake up always goes through the RCU callback ]
Fixes: 130bd686d9be ("io_uring: waitqueue-less cq waiting")
Assisted-by: LLM
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-19-c1556f5d7bf5@toxicpanda.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 include/linux/io_uring_types.h |    3 +++
 io_uring/io_uring.c            |   28 ++++++++++++++++++++++++++++
 2 files changed, 31 insertions(+)

--- a/include/linux/io_uring_types.h
+++ b/include/linux/io_uring_types.h
@@ -403,6 +403,9 @@ struct io_ring_ctx {
 	u32				iowq_limits[2];
 
 	struct callback_head		poll_wq_task_work;
+	/* deferred ->poll_wq wake up for local task_work */
+	struct rcu_head			poll_wq_rcu;
+	atomic_t			poll_wq_rcu_pending;
 	struct list_head		defer_list;
 
 #ifdef CONFIG_NET_RX_BUSY_POLL
--- a/io_uring/io_uring.c
+++ b/io_uring/io_uring.c
@@ -1143,6 +1143,31 @@ void tctx_task_work(struct callback_head
 	WARN_ON_ONCE(ret);
 }
 
+static void io_poll_wq_wake_rcu(struct rcu_head *rcu)
+{
+	struct io_ring_ctx *ctx = container_of(rcu, struct io_ring_ctx,
+					       poll_wq_rcu);
+
+	atomic_set(&ctx->poll_wq_rcu_pending, 0);
+	io_poll_wq_wake(ctx);
+	percpu_ref_put(&ctx->refs);
+}
+
+/*
+ * io_uring_poll() reports pending local work as EPOLLIN, as it takes a trip to
+ * the kernel to turn it into CQEs. Let those know who are asleep already.
+ * This may be called from a wake up handler with some wait queue lock held,
+ * and this wake up could lead back to it. Do it from a clean context.
+ */
+static void io_local_work_wake_poll(struct io_ring_ctx *ctx)
+{
+	if (!wq_has_sleeper(&ctx->poll_wq) ||
+	    atomic_xchg(&ctx->poll_wq_rcu_pending, 1))
+		return;
+	percpu_ref_get(&ctx->refs);
+	call_rcu_hurry(&ctx->poll_wq_rcu, io_poll_wq_wake_rcu);
+}
+
 static inline void io_req_local_work_add(struct io_kiocb *req,
 					 struct io_ring_ctx *ctx,
 					 unsigned flags)
@@ -1202,6 +1227,9 @@ static inline void io_req_local_work_add
 			atomic_or(IORING_SQ_TASKRUN, &ctx->rings->sq_flags);
 		if (ctx->has_evfd)
 			io_eventfd_signal(ctx, flags & IOU_F_TWQ_IN_WAKE);
+		/* whoever sets the flag wakes ->poll_wq afterwards */
+		if (ctx->poll_activated)
+			io_local_work_wake_poll(ctx);
 	}
 
 	nr_wait = atomic_read(&ctx->cq_wait_nr);



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 208/247] io_uring/wait: look at all CQ waiters on wake up
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (206 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 207/247] io_uring: wake ring pollers for local task_work Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 209/247] io_uring/poll: drop stale double poll entry on rearm Greg Kroah-Hartman
                   ` (46 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Josef Bacik, Jens Axboe,
	Claude Fable 5.1

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Josef Bacik <josef@toxicpanda.com>

Commit 356f92f2412686f822383b784fa102924407457a upstream.

io_wake_function() returns -1 if the waiter it is called for doesn't have
enough events yet, which makes __wake_up_common() stop walking the wait
queue. That assumes that the waiters behind it can't be satisfied either.
Each waiter has its own target though, computed from the min_complete it
passed in:

  thread A: io_uring_enter(GETEVENTS, min_complete = 10)  // queued first
  thread B: io_uring_enter(GETEVENTS, min_complete = 1)
  one CQE is posted: A isn't woken, and B isn't even considered

B keeps sleeping with the event it asked for sitting in the CQ ring, until
A's demand is met or a timeout or signal ends the wait.

Return 0 to carry on with the next waiter. Only waiters whose condition
is met are woken, like before.

[ 6.12: io_wake_function() is in io_uring.c ]
Fixes: bda521624e75 ("io_uring: make CQ ring wakeups be more efficient")
Assisted-by: LLM
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-20-c1556f5d7bf5@toxicpanda.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/io_uring.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

--- a/io_uring/io_uring.c
+++ b/io_uring/io_uring.c
@@ -2384,7 +2384,8 @@ static int io_wake_function(struct wait_
 	 */
 	if (io_should_wake(iowq) || io_has_work(iowq->ctx))
 		return autoremove_wake_function(curr, mode, wake_flags, key);
-	return -1;
+	/* keep going, a waiter further down may be content with less */
+	return 0;
 }
 
 int io_run_task_work_sig(struct io_ring_ctx *ctx)



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 209/247] io_uring/poll: drop stale double poll entry on rearm
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (207 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 208/247] io_uring/wait: look at all CQ waiters on wake up Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 210/247] io_uring/timeout: dont skip over reached sequences Greg Kroah-Hartman
                   ` (45 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Josef Bacik, Jens Axboe,
	Claude Fable 5.1

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Josef Bacik <josef@toxicpanda.com>

Commit f2dbe87968a3aef74a11c025776d293b80964d3f upstream.

A file that uses two wait queues for poll, e.g. a tty, gets a second
io_poll entry, which IORING_OP_POLL_ADD keeps in ->async_data until the
request is freed. io_poll_add() can run more than once for a request
though: IORING_OP_POLL_REMOVE with one of the update flags disarms and
rearms it, and io_poll_task_func() reissues it if a wake up turns out to
be spurious. The second poll_wait() of the new round then finds
*poll_ptr set, with ->head cleared by the disarm, and __io_queue_proc()
fails what it takes for a third wait queue with -EINVAL.

For an update that means that the poll request is completed with
-ECANCELED, while the update itself reports success. For a spurious wake
up, e.g. tcsetattr() on the polled tty, the poll request fails with
-EINVAL.

Free the old entry and clear the poll flags before arming, which is what
io_arm_apoll() does for internal polling. All entries have been removed
from their wait queues at that point.

[ 6.12: no io_req_async_data_free(), open-coded ]
Fixes: b69de288e913 ("io_uring: allow events and user_data update of running poll requests")
Fixes: 6e5aedb9324a ("io_uring/poll: attempt request issue after racy poll wakeup")
Assisted-by: LLM
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-21-c1556f5d7bf5@toxicpanda.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/poll.c |   12 ++++++++++++
 1 file changed, 12 insertions(+)

--- a/io_uring/poll.c
+++ b/io_uring/poll.c
@@ -996,6 +996,18 @@ int io_poll_add(struct io_kiocb *req, un
 	if (req->ctx->flags & (IORING_SETUP_SQPOLL|IORING_SETUP_SINGLE_ISSUER))
 		req->flags |= REQ_F_HASH_LOCKED;
 
+	/*
+	 * A poll update or a spurious wake up arms the request again. Forget
+	 * the entries of the previous round like io_arm_apoll() does, a stale
+	 * second entry would be taken for a third wait queue.
+	 */
+	if (req_has_async_data(req)) {
+		kfree(req->async_data);
+		req->async_data = NULL;
+		req->flags &= ~REQ_F_ASYNC_DATA;
+	}
+	req->flags &= ~(REQ_F_SINGLE_POLL | REQ_F_DOUBLE_POLL);
+
 	ret = __io_arm_poll_handler(req, poll, &ipt, poll->events, issue_flags);
 	if (ret > 0) {
 		io_req_set_res(req, ipt.result_mask, 0);



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 210/247] io_uring/timeout: dont skip over reached sequences
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (208 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 209/247] io_uring/poll: drop stale double poll entry on rearm Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 211/247] io_uring/timeout: keep repeat count on multishot update Greg Kroah-Hartman
                   ` (44 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Josef Bacik, Jens Axboe

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Josef Bacik <josef@toxicpanda.com>

Commit c6c0b3eba88c3b13ca11ea112404982e86d58f7a upstream.

io_flush_timeouts() copes with the wrap of the CQ sequence by looking at
the distance from ->cq_last_tm_flush. That relies on the target of each
pending timeout being at or ahead of the last flush.

io_timeout() breaks that. It sets ->cq_last_tm_flush to the current
sequence, on the assumption that nothing has been posted since the last
flush. That isn't true. A multishot request posts its CQEs right when it
is issued or retried, but they are committed, and the timeouts flushed,
at the end of the submission or task_work run:

  X: IORING_OP_TIMEOUT, off == 1       target_seq == N + 1
  io_submit_sqes()
    multishot recv, posts two CQEs     sequence == N + 2
    Y: IORING_OP_TIMEOUT, off == 100   ->cq_last_tm_flush = N + 2
  io_flush_timeouts()
    X: events_needed = N + 1 - (N + 2) // 0xffffffff
       events_got = 0                  // not yet

X isn't completed although the completions it was waiting for have
happened, only its timer can end it now. And as the list is sorted and
the walk ends at the first timeout that isn't due, it gets in the way of
the ones behind it. The insertion sort has the same problem, it measures
the distance of the pending targets from the current sequence.

->cq_last_tm_flush only needs to be brought up to date if no timeout is
waiting for a sequence, as io_flush_timeouts() isn't called before the
first one is set up. Otherwise it is current enough. Timeouts with a
sequence come first in the list, so looking at the first entry will do.
Use the last flush as the base for the insertion sort as well.

Fixes: f010505b78a4 ("io_uring: flush timeouts that should already have expired")
Assisted-by: LLM
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-29-c1556f5d7bf5@toxicpanda.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/timeout.c |   21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

--- a/io_uring/timeout.c
+++ b/io_uring/timeout.c
@@ -574,8 +574,9 @@ int io_timeout(struct io_kiocb *req, uns
 	struct io_timeout *timeout = io_kiocb_to_cmd(req, struct io_timeout);
 	struct io_ring_ctx *ctx = req->ctx;
 	struct io_timeout_data *data = req->async_data;
+	struct io_timeout *first;
 	struct list_head *entry;
-	u32 tail, off = timeout->off;
+	u32 tail, base, off = timeout->off;
 
 	spin_lock_irq(&ctx->timeout_lock);
 
@@ -592,11 +593,17 @@ int io_timeout(struct io_kiocb *req, uns
 	tail = data_race(ctx->cached_cq_tail) - atomic_read(&ctx->cq_timeouts);
 	timeout->target_seq = tail + off;
 
-	/* Update the last seq here in case io_flush_timeouts() hasn't.
-	 * This is safe because ->completion_lock is held, and submissions
-	 * and completions are never mixed in the same ->completion_lock section.
+	/*
+	 * Update the last seq here in case io_flush_timeouts() hasn't, it only
+	 * gets called once sequences are in use. Leave it alone if there are
+	 * timeouts waiting for one. CQEs may have been posted since the last
+	 * flush, and a target that has been reached must not fall behind it.
 	 */
-	ctx->cq_last_tm_flush = tail;
+	first = list_first_entry_or_null(&ctx->timeout_list, struct io_timeout,
+					 list);
+	if (!first || io_is_timeout_noseq(cmd_to_io_kiocb(first)))
+		ctx->cq_last_tm_flush = tail;
+	base = ctx->cq_last_tm_flush;
 
 	/*
 	 * Insertion sort, ensuring the first entry in the list is always
@@ -608,8 +615,8 @@ int io_timeout(struct io_kiocb *req, uns
 
 		if (io_is_timeout_noseq(nxt))
 			continue;
-		/* nxt.seq is behind @tail, otherwise would've been completed */
-		if (off >= nextt->target_seq - tail)
+		/* no target is behind the last flush, see io_flush_timeouts() */
+		if (timeout->target_seq - base >= nextt->target_seq - base)
 			break;
 	}
 add:



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 211/247] io_uring/timeout: keep repeat count on multishot update
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (209 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 210/247] io_uring/timeout: dont skip over reached sequences Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 212/247] io_uring/wait: no early -ETIME if min_wait finds work Greg Kroah-Hartman
                   ` (43 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Josef Bacik, Jens Axboe

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Josef Bacik <josef@toxicpanda.com>

Commit 3dc2a32cd356ee382aa4a8c7d844c53b2c0ad83b upstream.

IORING_TIMEOUT_UPDATE clears ->off of the timeout it updates, to turn a
timeout that waits for a number of completions into a pure one. For a
multishot timeout ->off isn't a sequence though, it tells whether the
number of repeats is limited: io_timeout_finish() only looks at
->repeats if ->off is set.

A multishot timeout that was set up to fire N times hence fires forever
once its interval has been updated. Leave ->off alone for those, they are
never treated as sequence timeouts anyway.

Fixes: ea97f6c8558e ("io_uring: add support for multishot timeouts")
Assisted-by: LLM
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-30-c1556f5d7bf5@toxicpanda.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/timeout.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

--- a/io_uring/timeout.c
+++ b/io_uring/timeout.c
@@ -407,8 +407,10 @@ static int io_timeout_update(struct io_r
 	if (IS_ERR(req))
 		return PTR_ERR(req);
 
-	timeout->off = 0; /* noseq */
 	data = req->async_data;
+	/* for a multishot request this isn't a sequence, keep the repeats */
+	if (!(data->flags & IORING_TIMEOUT_MULTISHOT))
+		timeout->off = 0; /* noseq */
 	data->ts = *ts;
 
 	list_add_tail(&timeout->list, &ctx->timeout_list);



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 212/247] io_uring/wait: no early -ETIME if min_wait finds work
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (210 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 211/247] io_uring/timeout: keep repeat count on multishot update Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 213/247] io_uring/napi: make stale entries time out after 60s Greg Kroah-Hartman
                   ` (42 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Josef Bacik, Jens Axboe,
	Claude Fable 5.1

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Josef Bacik <josef@toxicpanda.com>

Commit 83cce67298ab1f4d2e9205a49f56975475cdb154 upstream.

When the min wait time is over and there is work to run, which for
DEFER_TASKRUN includes task_work that was queued lazily and didn't wake
the waiter, io_cqring_min_timer_wakeup() ends the wait via
io_cqring_timer_wakeup(). That flags it as timed out. io_cqring_wait()
runs the work, leaves the loop, and returns 0 if the CQ ring holds
something.

Running task_work doesn't have to result in a CQE, though. A poll wake up
can turn out to be spurious, for instance if somebody else has read the
data by the time the request is retried. The application then gets -ETIME
once the min wait time has passed, no matter how far away the timeout it
asked for is.

Wake the task without declaring a timeout. From now on a single CQE
satisfies the wait, like in the case where the timer is switched over to
the normal timeout. If running the work doesn't post one, the loop in
io_cqring_wait() goes back to sleep with the normal timeout.

[ 6.12: io_cqring_min_timer_wakeup() is in io_uring.c ]
Fixes: 1100c4a2656d ("io_uring: add support for batch wait timeout")
Assisted-by: LLM
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-32-c1556f5d7bf5@toxicpanda.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/io_uring.c |   13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

--- a/io_uring/io_uring.c
+++ b/io_uring/io_uring.c
@@ -2435,9 +2435,16 @@ static enum hrtimer_restart io_cqring_mi
 	if (iowq->timeout == KTIME_MAX ||
 	    ktime_compare(iowq->min_timeout, iowq->timeout) >= 0)
 		goto out_wake;
-	/* work we may need to run, wake function will see if we need to wake */
-	if (io_has_work(ctx))
-		goto out_wake;
+	/*
+	 * Work we need to run. It isn't known if that is going to post a CQE,
+	 * so this isn't a timeout. Carry on with the normal one if it doesn't.
+	 */
+	if (io_has_work(ctx)) {
+		iowq->min_timeout = 0;
+		iowq->cq_tail = iowq->cq_min_tail + 1;
+		wake_up_process(iowq->wq.private);
+		return HRTIMER_NORESTART;
+	}
 	/* got events since we started waiting, min timeout is done */
 	if (iowq->cq_min_tail != READ_ONCE(ctx->rings->cq.tail))
 		goto out_wake;



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 213/247] io_uring/napi: make stale entries time out after 60s
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (211 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 212/247] io_uring/wait: no early -ETIME if min_wait finds work Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 214/247] io_uring/napi: dont busy poll past an expired timeout Greg Kroah-Hartman
                   ` (41 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Josef Bacik, Jens Axboe

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Josef Bacik <josef@toxicpanda.com>

Commit 9c151648780d89e5446e5f89f3fa2e416c3bb911 upstream.

With dynamic tracking a NAPI id that hasn't been seen for a minute is
meant to be dropped from the list the ring busy polls. The timeout is
added to jiffies, but it is defined as 60 * SEC_CONVERSION, and
SEC_CONVERSION isn't the number of jiffies in a second. It is the
internal factor of __timespec64_to_jiffies(), HZ scaled up by
SEC_JIFFIE_SC bits. For HZ=1000 that is 1000 << 22, which puts the
timeout at about eight years. On 32-bit the multiplication overflows.

So entries are never removed, and every id that a socket of the ring
ever had keeps being polled on each wait.

Fixes: 8d0c12a80cde ("io-uring: add napi busy poll support")
Assisted-by: LLM
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-33-c1556f5d7bf5@toxicpanda.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/napi.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/io_uring/napi.c
+++ b/io_uring/napi.c
@@ -6,7 +6,7 @@
 #ifdef CONFIG_NET_RX_BUSY_POLL
 
 /* Timeout for cleanout of stale entries. */
-#define NAPI_TIMEOUT		(60 * SEC_CONVERSION)
+#define NAPI_TIMEOUT		(60 * HZ)
 
 struct io_napi_entry {
 	unsigned int		napi_id;



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 214/247] io_uring/napi: dont busy poll past an expired timeout
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (212 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 213/247] io_uring/napi: make stale entries time out after 60s Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 215/247] io_uring/kbuf: handle index wrap in last buffer check Greg Kroah-Hartman
                   ` (40 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Josef Bacik, Jens Axboe

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Josef Bacik <josef@toxicpanda.com>

Commit 21ed976c12f6b77d7ea028a4fe9a08e69a56179f upstream.

__io_napi_busy_loop() caps the busy poll time to what is left until the
timeout of the wait. The difference is negative if the timeout has passed
already, which is what an application gets if it uses
IORING_ENTER_ABS_TIMER with a time that isn't in the future any more. The
min_t(u64, ...) turns that into a huge value, so the cap has no effect
and the wait, which should return right away, spins for the full busy
poll time first.

Fixes: d5cce407e4f5 ("io_uring/napi: postpone napi timeout adjustment")
Assisted-by: LLM
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-34-c1556f5d7bf5@toxicpanda.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/napi.c |    2 ++
 1 file changed, 2 insertions(+)

--- a/io_uring/napi.c
+++ b/io_uring/napi.c
@@ -288,6 +288,8 @@ void __io_napi_busy_loop(struct io_ring_
 	if (iowq->timeout != KTIME_MAX) {
 		ktime_t dt = ktime_sub(iowq->timeout, io_get_time(ctx));
 
+		/* an absolute timeout may have passed already */
+		dt = max_t(ktime_t, dt, 0);
 		iowq->napi_busy_poll_dt = min_t(u64, iowq->napi_busy_poll_dt, dt);
 	}
 



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 215/247] io_uring/kbuf: handle index wrap in last buffer check
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (213 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 214/247] io_uring/napi: dont busy poll past an expired timeout Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 216/247] io_uring/sqpoll: let the thread sleep on disabled rings Greg Kroah-Hartman
                   ` (39 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Josef Bacik, Jens Axboe

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Josef Bacik <josef@toxicpanda.com>

Commit 6e773b5161506a4d0e739eb3aa4667d28f20219c upstream.

io_ring_buffer_select() flags the request with REQ_F_BL_EMPTY if it takes
the last buffer of the ring. Head and tail are 16-bit counters, but
"head + 1" is computed as an int. If head is 65535 and tail has wrapped
to 0, that compares 65536 to 0 and the flag isn't set.

A bundle receive relies on the flag to tell that there is no point in
trying to get more data. Without it, it goes for another round, finds no
buffer, and the request, which has received data, is marked as failed on
account of the -ENOBUFS. That severs a link, and ends a multishot.

Fixes: c3f9109dbc9e ("io_uring/kbuf: flag request if buffer pool is empty after buffer pick")
Assisted-by: LLM
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-36-c1556f5d7bf5@toxicpanda.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/kbuf.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/io_uring/kbuf.c
+++ b/io_uring/kbuf.c
@@ -181,7 +181,7 @@ static struct io_br_sel io_ring_buffer_s
 	if (unlikely(tail == head))
 		return sel;
 
-	if (head + 1 == tail)
+	if ((__u16)(head + 1) == tail)
 		req->flags |= REQ_F_BL_EMPTY;
 
 	buf = io_ring_head_to_buf(br, head, bl->mask);



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 216/247] io_uring/sqpoll: let the thread sleep on disabled rings
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (214 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 215/247] io_uring/kbuf: handle index wrap in last buffer check Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 217/247] io_uring: dont pass restart error codes to userspace Greg Kroah-Hartman
                   ` (38 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Josef Bacik, Jens Axboe

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Josef Bacik <josef@toxicpanda.com>

Commit d492dcbb3b81c1c2d0aabef41fa1307093f3a556 upstream.

__io_sq_thread() doesn't submit anything as long as the ring has
IORING_SETUP_R_DISABLED set. The check that keeps the SQPOLL thread from
going to sleep while the SQ ring holds entries doesn't know about that.
If an application fills in SQEs first and enables the ring later, the
thread finds that there is work each time it is about to sleep, goes
around, doesn't submit it, and so on. It uses up a CPU until the ring
gets enabled.

Entries in the SQ ring of a disabled ring are no reason to stay awake.
io_register_enable_rings() clears the flag and then wakes the thread, and
the flag is looked at after prepare_to_wait(), so the thread can't miss
that.

Fixes: 0298ef969a11 ("io_uring: clean R_DISABLED startup mess")
Assisted-by: LLM
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-37-c1556f5d7bf5@toxicpanda.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/sqpoll.c |    7 +++++++
 1 file changed, 7 insertions(+)

--- a/io_uring/sqpoll.c
+++ b/io_uring/sqpoll.c
@@ -387,6 +387,13 @@ static int io_sq_thread(void *data)
 				 */
 				smp_mb__after_atomic();
 
+				/*
+				 * Nothing gets submitted before the ring is
+				 * enabled, which comes with a wake up.
+				 */
+				if (READ_ONCE(ctx->flags) & IORING_SETUP_R_DISABLED)
+					continue;
+
 				if (io_sqring_entries(ctx)) {
 					needs_sched = false;
 					break;



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 217/247] io_uring: dont pass restart error codes to userspace
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (215 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 216/247] io_uring/sqpoll: let the thread sleep on disabled rings Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 218/247] io_uring/net: dont retry recv on uncommitted buffers Greg Kroah-Hartman
                   ` (37 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Josef Bacik, Jens Axboe

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Josef Bacik <josef@toxicpanda.com>

Commit e1a64bc64897f4c2fe460922c345f2ed8f889b5f upstream.

-ERESTARTSYS and friends are instructions for the system call exit code,
which either restarts the call or turns them into -EINTR. They are not
supposed to be seen by applications. A request isn't a system call,
nobody looks at what it returns before that is put into a CQE.

The read/write and the networking opcodes convert these codes to -EINTR
by hand. The others don't. An io-wq worker that is blocked in the open of
a FIFO, a tty or some other device, or in a splice from an empty pipe,
and that gets interrupted because the request is cancelled, completes it
with -512:

  IORING_OP_OPENAT, IOSQE_ASYNC       // FIFO without a writer
  IORING_OP_ASYNC_CANCEL              // -EALREADY, worker is signalled
  CQE of the open: res == -512

There are more candidates, like whatever a file system or driver returns
from ->flush(), ->fsync(), ->fallocate() or ->uring_cmd(), or breaking a
lease or delegation.

Take care of it in io_issue_sqe(), which all of them go through. The
helper is moved from rw.c as is. The cost is a compare and a branch that
is not taken per request.

Fixes: 15b71abe7b52 ("io_uring: add support for IORING_OP_OPENAT")
Assisted-by: LLM
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-39-c1556f5d7bf5@toxicpanda.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/io_uring.c |    5 +++++
 io_uring/io_uring.h |   18 ++++++++++++++++++
 io_uring/rw.c       |   18 ------------------
 3 files changed, 23 insertions(+), 18 deletions(-)

--- a/io_uring/io_uring.c
+++ b/io_uring/io_uring.c
@@ -1773,6 +1773,9 @@ static int io_issue_sqe(struct io_kiocb
 	}
 
 	if (ret == IOU_OK) {
+		/* not all handlers take care of the internal restart codes */
+		if (unlikely(req->cqe.res <= -ERESTARTSYS))
+			req->cqe.res = io_fixup_restart_res(req->cqe.res);
 		if (issue_flags & IO_URING_F_COMPLETE_DEFER)
 			io_req_complete_defer(req);
 		else
@@ -1788,6 +1791,8 @@ static int io_issue_sqe(struct io_kiocb
 		if ((req->ctx->flags & IORING_SETUP_IOPOLL) && def->iopoll_queue)
 			io_iopoll_req_issued(req, issue_flags);
 	}
+	if (unlikely(ret <= -ERESTARTSYS))
+		ret = io_fixup_restart_res(ret);
 	return ret;
 }
 
--- a/io_uring/io_uring.h
+++ b/io_uring/io_uring.h
@@ -203,6 +203,24 @@ static __always_inline bool io_fill_cqe_
 	return true;
 }
 
+static inline ssize_t io_fixup_restart_res(ssize_t ret)
+{
+	switch (ret) {
+	case -ERESTARTSYS:
+	case -ERESTARTNOINTR:
+	case -ERESTARTNOHAND:
+	case -ERESTART_RESTARTBLOCK:
+		/*
+		 * We can't just restart the syscall, since previously
+		 * submitted sqes may already be in progress. Just fail
+		 * this IO with EINTR.
+		 */
+		return -EINTR;
+	default:
+		return ret;
+	}
+}
+
 static inline void req_set_fail(struct io_kiocb *req)
 {
 	req->flags |= REQ_F_FAIL;
--- a/io_uring/rw.c
+++ b/io_uring/rw.c
@@ -560,24 +560,6 @@ static void io_complete_rw_iopoll(struct
 	smp_store_release(&req->iopoll_completed, 1);
 }
 
-static inline ssize_t io_fixup_restart_res(ssize_t ret)
-{
-	switch (ret) {
-	case -ERESTARTSYS:
-	case -ERESTARTNOINTR:
-	case -ERESTARTNOHAND:
-	case -ERESTART_RESTARTBLOCK:
-		/*
-		 * We can't just restart the syscall, since previously
-		 * submitted sqes may already be in progress. Just fail
-		 * this IO with EINTR.
-		 */
-		return -EINTR;
-	default:
-		return ret;
-	}
-}
-
 static inline void io_rw_done(struct kiocb *kiocb, ssize_t ret)
 {
 	/* IO was queued async, completion will happen later */



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 218/247] io_uring/net: dont retry recv on uncommitted buffers
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (216 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 217/247] io_uring: dont pass restart error codes to userspace Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 219/247] io_uring/timeout: no ABS update of multishot timeouts Greg Kroah-Hartman
                   ` (36 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Josef Bacik, Jens Axboe

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Josef Bacik <josef@toxicpanda.com>

Commit 8444de681a179e41a4eb92d5bbe770a0677074a6 upstream.

Commit 41b70df5b38b ("io_uring/net: commit partial buffers on retry")
commits ring provided buffers when a receive is going to be retried after
a partial transfer, so that another request using the same buffer group
can't be handed the memory the first one keeps receiving into. It commits
the number of bytes received so far. That does the job for a single
buffer which is consumed as a whole, but the request hangs on to all it
has mapped:

- For a buffer ring with IOU_PBUF_RING_INC only these bytes are consumed.
  The rest of the buffer stays at the head of the ring.
- For a bundle only the buffers which hold these bytes are consumed, the
  others that were peeked stay in the ring.

In both cases the next receive with that buffer group gets memory that
the retried request is still going to write to, and whoever comes last
overwrites the data of the other. What the retry fills isn't committed at
all, as the buffer list isn't known any more at that point. So the kernel
hands it out again later on, while the CQE tells the application that it
was used, and for an incremental buffer that it is done with.

The remainder can't be committed in advance: if the request ends up
receiving less, there is no way to tell the application that more was
consumed than the CQE accounts for. Complete the request with what it has
got instead of retrying it. MSG_WAITALL is no longer honoured for
receives into incremental buffers or multi buffer bundles, they can
return a short count, with the request marked as failed like for other
short MSG_WAITALL transfers.

Fixes: 41b70df5b38b ("io_uring/net: commit partial buffers on retry")
Assisted-by: LLM
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-40-c1556f5d7bf5@toxicpanda.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/net.c |   24 ++++++++++++++++++++++--
 1 file changed, 22 insertions(+), 2 deletions(-)

--- a/io_uring/net.c
+++ b/io_uring/net.c
@@ -500,6 +500,24 @@ static int io_bundle_nbufs(struct io_asy
 	return nbufs;
 }
 
+/*
+ * A receive that is retried after a partial transfer keeps writing to what it
+ * has mapped. io_net_kbuf_recyle() only commits what was filled so far, which
+ * takes a buffer out of circulation if it's a single one that is consumed as a
+ * whole. The tail of an incrementally consumed buffer, or the yet unused
+ * buffers of a bundle, would be up for grabs. They can't be committed in
+ * advance either, the CQE has no way to tell if they end up not being used.
+ */
+static bool io_net_kbuf_can_retry(struct io_kiocb *req,
+				  struct io_buffer_list *bl,
+				  struct io_async_msghdr *kmsg)
+{
+	/* not ring provided, or committed at selection time */
+	if (!(req->flags & REQ_F_BUFFERS_COMMIT))
+		return true;
+	return !(bl->flags & IOBL_INC) && iter_is_ubuf(&kmsg->msg.msg_iter);
+}
+
 static int io_net_kbuf_recyle(struct io_kiocb *req, struct io_buffer_list *bl,
 			      struct io_async_msghdr *kmsg, int len)
 {
@@ -1086,7 +1104,8 @@ retry_multishot:
 				return IOU_ISSUE_SKIP_COMPLETE;
 			return -EAGAIN;
 		}
-		if (ret > 0 && io_net_retry(sock, flags)) {
+		if (ret > 0 && io_net_retry(sock, flags) &&
+		    io_net_kbuf_can_retry(req, sel.buf_list, kmsg)) {
 			sr->done_io += ret;
 			return io_net_kbuf_recyle(req, sel.buf_list, kmsg, ret);
 		}
@@ -1233,7 +1252,8 @@ retry_multishot:
 				return IOU_ISSUE_SKIP_COMPLETE;
 			return -EAGAIN;
 		}
-		if (ret > 0 && io_net_retry(sock, flags)) {
+		if (ret > 0 && io_net_retry(sock, flags) &&
+		    io_net_kbuf_can_retry(req, sel.buf_list, kmsg)) {
 			sr->len -= ret;
 			sr->buf += ret;
 			sr->done_io += ret;



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 219/247] io_uring/timeout: no ABS update of multishot timeouts
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (217 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 218/247] io_uring/net: dont retry recv on uncommitted buffers Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 220/247] io_uring/timeout: dont end a linked timeout with 1 Greg Kroah-Hartman
                   ` (35 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Josef Bacik, Jens Axboe

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Josef Bacik <josef@toxicpanda.com>

Commit b088ae34d4da730dc647261b893a6eb622fe5e1f upstream.

IORING_TIMEOUT_MULTISHOT can't be combined with IORING_TIMEOUT_ABS, prep
rejects that, as the request is armed again with the same value each time
it fires. IORING_TIMEOUT_UPDATE doesn't check and takes an absolute time
for a multishot timeout. The first expiry is as asked for, but
io_timeout_complete() then arms the timer with ->mode of the original
request, i.e. it uses the absolute time as the interval. With
CLOCK_MONOTONIC the next expiry is an uptime away, with CLOCK_REALTIME
more than fifty years.

Fail such an update with -EINVAL, and do so before the timeout is
touched.

Fixes: ea97f6c8558e ("io_uring: add support for multishot timeouts")
Assisted-by: LLM
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-41-c1556f5d7bf5@toxicpanda.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/timeout.c |   38 ++++++++++++++++++++++++++------------
 1 file changed, 26 insertions(+), 12 deletions(-)

--- a/io_uring/timeout.c
+++ b/io_uring/timeout.c
@@ -254,22 +254,29 @@ static enum hrtimer_restart io_timeout_f
 	return HRTIMER_NORESTART;
 }
 
-static struct io_kiocb *io_timeout_extract(struct io_ring_ctx *ctx,
-					   struct io_cancel_data *cd)
+static struct io_kiocb *io_timeout_find(struct io_ring_ctx *ctx,
+					struct io_cancel_data *cd)
 	__must_hold(&ctx->timeout_lock)
 {
 	struct io_timeout *timeout;
-	struct io_timeout_data *io;
-	struct io_kiocb *req = NULL;
 
 	list_for_each_entry(timeout, &ctx->timeout_list, list) {
-		struct io_kiocb *tmp = cmd_to_io_kiocb(timeout);
+		struct io_kiocb *req = cmd_to_io_kiocb(timeout);
 
-		if (io_cancel_req_match(tmp, cd)) {
-			req = tmp;
-			break;
-		}
+		if (io_cancel_req_match(req, cd))
+			return req;
 	}
+	return NULL;
+}
+
+static struct io_kiocb *io_timeout_extract(struct io_ring_ctx *ctx,
+					   struct io_cancel_data *cd)
+	__must_hold(&ctx->timeout_lock)
+{
+	struct io_kiocb *req = io_timeout_find(ctx, cd);
+	struct io_timeout *timeout;
+	struct io_timeout_data *io;
+
 	if (!req)
 		return ERR_PTR(-ENOENT);
 
@@ -400,14 +407,21 @@ static int io_timeout_update(struct io_r
 	__must_hold(&ctx->timeout_lock)
 {
 	struct io_cancel_data cd = { .ctx = ctx, .data = user_data, };
-	struct io_kiocb *req = io_timeout_extract(ctx, &cd);
+	struct io_kiocb *req = io_timeout_find(ctx, &cd);
 	struct io_timeout *timeout = io_kiocb_to_cmd(req, struct io_timeout);
 	struct io_timeout_data *data;
 
-	if (IS_ERR(req))
-		return PTR_ERR(req);
+	if (!req)
+		return -ENOENT;
 
 	data = req->async_data;
+	/* multishot requests only make sense with rel values */
+	if ((data->flags & IORING_TIMEOUT_MULTISHOT) && mode == HRTIMER_MODE_ABS)
+		return -EINVAL;
+
+	req = io_timeout_extract(ctx, &cd);
+	if (IS_ERR(req))
+		return PTR_ERR(req);
 	/* for a multishot request this isn't a sequence, keep the repeats */
 	if (!(data->flags & IORING_TIMEOUT_MULTISHOT))
 		timeout->off = 0; /* noseq */



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 220/247] io_uring/timeout: dont end a linked timeout with 1
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (218 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 219/247] io_uring/timeout: no ABS update of multishot timeouts Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 221/247] io_uring: look up the file before queueing to io-wq Greg Kroah-Hartman
                   ` (34 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Josef Bacik, Jens Axboe

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Josef Bacik <josef@toxicpanda.com>

Commit c74193430febdd120e35936dda3e5aeec3a54405 upstream.

A linked timeout that fires cancels the request it is linked to, and
completes with -ETIME if that worked out:

	ret = io_try_cancel(req->tctx, &cd, 0);
	...
	io_req_set_res(req, ret ?: -ETIME, 0);

io_try_cancel() returns 0 or an error, except for requests that are parked
on ->futex_list or ->waitid_list. io_futex_cancel() and io_waitid_cancel()
return the number of requests that they have cancelled, and
io_try_cancel() hands it on.

So the linked timeout of an IORING_OP_FUTEX_WAIT, IORING_OP_FUTEX_WAITV or
IORING_OP_WAITID that it has cancelled completes with 1, each time.

The waitid test of liburing checks for that 1, and has to be changed to
expect -ETIME, which is what the linked timeout of any other request
completes with.

Fixes: f31ecf671ddc ("io_uring: add IORING_OP_WAITID support")
Fixes: 194bb58c6090 ("io_uring: add support for futex wake and wait")
Assisted-by: LLM
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-42-c1556f5d7bf5@toxicpanda.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/timeout.c |    3 +++
 1 file changed, 3 insertions(+)

--- a/io_uring/timeout.c
+++ b/io_uring/timeout.c
@@ -317,6 +317,9 @@ static void io_req_task_link_timeout(str
 			};
 
 			ret = io_try_cancel(req->task->io_uring, &cd, 0);
+			/* a number of requests for futex and waitid */
+			if (ret > 0)
+				ret = 0;
 		}
 		io_req_set_res(req, ret ?: -ETIME, 0);
 		io_req_task_complete(req, ts);



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 221/247] io_uring: look up the file before queueing to io-wq
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (219 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 220/247] io_uring/timeout: dont end a linked timeout with 1 Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 222/247] io_uring/poll: avoid retry wakeup loss when dropping ownership Greg Kroah-Hartman
                   ` (33 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Josef Bacik, Jens Axboe

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Josef Bacik <josef@toxicpanda.com>

Commit 98bc044d5a5374f8d3605fe55a8e2df6d6fc3f82 upstream.

io_prep_async_work() decides by the file of a request what kind of work
it is for io-wq. I/O on regular files and block devices is bounded work,
limited to min(SQ entries, 4 * CPUs) workers, for anything else that may
block indefinitely the limit is RLIMIT_NPROC. Writes to a regular file
are hashed by the inode, so that they are run one after the other instead
of having a bunch of workers fight for the inode lock.

Since the file is only assigned when a request is issued, a request that
is queued without an attempt to issue it, REQ_F_FORCE_ASYNC, doesn't have
one at that point. io_prep_async_work() takes that for "not a regular
file or block device":

- Reads and writes end up as unbound work. 32 reads with IOSQE_ASYNC from
  a slow block device on a ring with 4 SQ entries get 32 workers, not 4.
- Writes aren't hashed. Four buffered writes to one file get four
  workers, three of which do nothing but wait for the lock.

The late assignment is for the benefit of links, where a request may use
a fixed file that one of its predecessors installs. By the time a request
gets to io_queue_iowq() these are done, it is as good as issued. Assign
the file there.

io_assign_file() moves up and is forced inline. With a third caller the
compiler may stop inlining it, and every request that is issued would
pay for a call.

IORING_OP_SPLICE is left as it is, unbound and not hashed. The file of
the request is where it writes to, which says nothing about how long it
takes: a splice from an empty pipe or a socket into a regular file waits
for its input. As bounded work, four of these on a ring with 4 SQ entries
keep all other bounded work of the task from running, and as hashed work
one of them blocks all writes to that file.

REQ_F_FORCE_ASYNC is not only set for IOSQE_ASYNC. What changes, and
brings back what was the case before the file assignment was deferred:

- Requests with IOSQE_ASYNC or IOSQE_IO_DRAIN, and all requests that are
  submitted while a drain is active: reads and writes on regular files
  and block devices count against the limit for bounded workers, including
  the one set with IORING_REGISTER_IOWQ_MAX_WORKERS, so fewer of them run
  at the same time.
- Of these, writes to one regular file are run one at a time, unless they
  are O_DIRECT and the filesystem has FOP_DIO_PARALLEL_WRITE.
- IORING_OP_FALLOCATE and IORING_OP_FTRUNCATE, which always go to io-wq,
  are run one at a time per file, and in turn with these writes.
- The descriptor or the fixed file slot is looked up when the request is
  queued, not when a worker gets around to it, so closing or replacing it
  in between no longer has an effect on the request.

Fixes: 6bf9c47a3989 ("io_uring: defer file assignment")
Assisted-by: LLM
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-43-c1556f5d7bf5@toxicpanda.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/io_uring.c |   43 +++++++++++++++++++++++++++++--------------
 1 file changed, 29 insertions(+), 14 deletions(-)

--- a/io_uring/io_uring.c
+++ b/io_uring/io_uring.c
@@ -481,17 +481,46 @@ static void io_prep_async_link(struct io
 	}
 }
 
+/* Called for every request that is issued: keep it inline */
+static __always_inline bool io_assign_file(struct io_kiocb *req,
+					   const struct io_issue_def *def,
+					   unsigned int issue_flags)
+{
+	if (req->file || !def->needs_file)
+		return true;
+
+	if (req->flags & REQ_F_FIXED_FILE)
+		req->file = io_file_get_fixed(req, req->cqe.fd, issue_flags);
+	else
+		req->file = io_file_get_normal(req, req->cqe.fd);
+
+	return !!req->file;
+}
+
 static void io_queue_iowq(struct io_kiocb *req)
 {
 	struct io_uring_task *tctx = req->task->io_uring;
 
 	BUG_ON(!tctx);
+	lockdep_assert_held(&req->ctx->uring_lock);
 
 	if ((current->flags & PF_KTHREAD) || !tctx->io_wq) {
 		io_req_task_queue_fail(req, -ECANCELED);
 		return;
 	}
 
+	/*
+	 * The file is looked up as late as possible, as it may be the result
+	 * of an earlier request of the link. This one is up now, and what kind
+	 * of work it is depends on the file. If that fails, leave the error
+	 * handling to the worker.
+	 *
+	 * Not for a splice: whatever it writes to, it may wait for its input
+	 * for ever. It has to remain unbound work that isn't hashed.
+	 */
+	if (req->opcode != IORING_OP_SPLICE)
+		io_assign_file(req, &io_issue_defs[req->opcode], 0);
+
 	/* init ->work of the whole link before punting */
 	io_prep_async_link(req);
 
@@ -1724,20 +1753,6 @@ queue:
 	spin_unlock(&ctx->completion_lock);
 }
 
-static bool io_assign_file(struct io_kiocb *req, const struct io_issue_def *def,
-			   unsigned int issue_flags)
-{
-	if (req->file || !def->needs_file)
-		return true;
-
-	if (req->flags & REQ_F_FIXED_FILE)
-		req->file = io_file_get_fixed(req, req->cqe.fd, issue_flags);
-	else
-		req->file = io_file_get_normal(req, req->cqe.fd);
-
-	return !!req->file;
-}
-
 #define REQ_ISSUE_SLOW_FLAGS	(REQ_F_CREDS | REQ_F_ARM_LTIMEOUT)
 
 static int io_issue_sqe(struct io_kiocb *req, unsigned int issue_flags)



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 222/247] io_uring/poll: avoid retry wakeup loss when dropping ownership
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (220 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 221/247] io_uring: look up the file before queueing to io-wq Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 223/247] io_uring/timeout: dont put a sequence target behind the last flush Greg Kroah-Hartman
                   ` (32 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Juanlu Herrero, Anand Natarajan,
	Jens Axboe

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Juanlu Herrero <juanlu@fastmail.com>

Commit 937d38dcacd675dc0572d6c9b6743960df3128ed upstream.

If a wakeup sets IO_POLL_RETRY_FLAG between the owning task consuming
the existing instance of IO_POLL_RETRY_FLAG and the loop check
of io_poll_check_events(), then we stall on processing the request
until an unrelated wakeup comes along.

Using atomic_cmpxchg instead of atomic_sub_return to guarantee both the
count v and poll_refs are 0 and no wake-ups are missed.

Cc: stable@vger.kernel.org
Fixes: a26a35e9019f ("io_uring: make poll refs more robust")
Signed-off-by: Juanlu Herrero <juanlu@fastmail.com>
Assisted-by: LLM
Suggested-by: Anand Natarajan <anand@meta.com>
Link: https://patch.msgid.link/20261013-pu-cmpxchg-v1-1-4ddc10fd8a03@fastmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/poll.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

--- a/io_uring/poll.c
+++ b/io_uring/poll.c
@@ -350,7 +350,8 @@ static int io_poll_check_events(struct i
 		 * Release all references, retry if someone tried to restart
 		 * task_work while we were executing it.
 		 */
-	} while (atomic_sub_return(v, &req->poll_refs) & IO_POLL_REF_MASK);
+		v &= IO_POLL_REF_MASK;
+	} while (atomic_cmpxchg(&req->poll_refs, v, 0) != v);
 
 	io_napi_add(req);
 	return IOU_POLL_NO_ACTION;



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 223/247] io_uring/timeout: dont put a sequence target behind the last flush
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (221 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 222/247] io_uring/poll: avoid retry wakeup loss when dropping ownership Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 224/247] io_uring/timeout: dont flush with the sequence " Greg Kroah-Hartman
                   ` (31 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Jens Axboe

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Jens Axboe <axboe@kernel.dk>

Commit fdfce905a58edea053ee7b68b5bd4348dd1b36e0 upstream.

io_timeout_fn() and io_kill_timeout() bump ->cq_timeouts when a timeout
fires, but its CQE is only posted later from task_work. Until then the
sequence io_timeout() computes is one below the last flush per fired
timeout. Now that ->cq_last_tm_flush is kept while sequence timeouts are
pending, a timeout armed in that window with a small offset gets a target
behind the base. Its distance from the base wraps, and it's never
completed by events, only by its timer. With DEFER_TASKRUN that window
is as wide as the application makes it, as submission runs before the
local task_work.

Nothing but those in flight CQEs separates the two, so use the last
flush as the base for the target when the sequence is behind it.

Fixes: c6c0b3eba88c ("io_uring/timeout: don't skip over reached sequences")
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/timeout.c |   10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

--- a/io_uring/timeout.c
+++ b/io_uring/timeout.c
@@ -610,7 +610,6 @@ int io_timeout(struct io_kiocb *req, uns
 	}
 
 	tail = data_race(ctx->cached_cq_tail) - atomic_read(&ctx->cq_timeouts);
-	timeout->target_seq = tail + off;
 
 	/*
 	 * Update the last seq here in case io_flush_timeouts() hasn't, it only
@@ -625,6 +624,15 @@ int io_timeout(struct io_kiocb *req, uns
 	base = ctx->cq_last_tm_flush;
 
 	/*
+	 * A fired timeout bumps ->cq_timeouts before its CQE is posted, which
+	 * leaves the sequence behind the last flush until it is. Nothing else
+	 * separates the two then, so count from the flush.
+	 */
+	if ((s32)(tail - base) < 0)
+		tail = base;
+	timeout->target_seq = tail + off;
+
+	/*
 	 * Insertion sort, ensuring the first entry in the list is always
 	 * the one we need first.
 	 */



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 224/247] io_uring/timeout: dont flush with the sequence behind the last flush
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (222 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 223/247] io_uring/timeout: dont put a sequence target behind the last flush Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 225/247] io_uring/timeout: dont lose a cancel as io-wq arms a timeout Greg Kroah-Hartman
                   ` (30 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Jens Axboe

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Jens Axboe <axboe@kernel.dk>

Commit 85f85d573ffa7772e1ad4504d0cec5113a5c5cf1 upstream.

io_flush_timeouts() measures the events since the last flush as the
distance of the current sequence from ->cq_last_tm_flush. A fired
timeout bumps ->cq_timeouts before its CQE is posted, so until it is
the sequence can be behind the last flush, and the distance wraps:

  last flush: seq 100, cq_last_tm_flush = 100
  Y: IORING_OP_TIMEOUT, off 50, target_seq 150
  pure timeout A fires, cq_timeouts = 1
  task_work posts A's CQE, cached_cq_tail = 101
  pure timeout B fires before the flush, cq_timeouts = 2
  io_flush_timeouts(): seq = 99, events_got = 0xffffffff

Y, and every sequence timeout behind it, is ended with -ETIME although
no event happened. Two timeouts expiring close together is all it takes,
a completion with IOSQE_CQE_SKIP_SUCCESS after a single one does it too.

Nothing but those in flight CQEs separates the two, so count from the
last flush when the sequence is behind it, as io_timeout() does.

Fixes: f010505b78a4 ("io_uring: flush timeouts that should already have expired")
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/timeout.c |    8 ++++++++
 1 file changed, 8 insertions(+)

--- a/io_uring/timeout.c
+++ b/io_uring/timeout.c
@@ -113,6 +113,14 @@ __cold void io_flush_timeouts(struct io_
 	spin_lock_irq(&ctx->timeout_lock);
 	seq = ctx->cached_cq_tail - atomic_read(&ctx->cq_timeouts);
 
+	/*
+	 * A fired timeout bumps ->cq_timeouts before its CQE is posted, which
+	 * leaves the sequence behind the last flush until it is. No event has
+	 * happened then, see io_timeout().
+	 */
+	if ((s32)(seq - ctx->cq_last_tm_flush) < 0)
+		seq = ctx->cq_last_tm_flush;
+
 	list_for_each_entry_safe(timeout, tmp, &ctx->timeout_list, list) {
 		struct io_kiocb *req = cmd_to_io_kiocb(timeout);
 		u32 events_needed, events_got;



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 225/247] io_uring/timeout: dont lose a cancel as io-wq arms a timeout
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (223 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 224/247] io_uring/timeout: dont flush with the sequence " Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 226/247] io_uring/poll: dont loop on HUP with multiple references Greg Kroah-Hartman
                   ` (29 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Jens Axboe, Claude Fable 5.1

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Jens Axboe <axboe@kernel.dk>

Commit 89f193dc3ef462059387e9691bf6af4b1808379a upstream.

An IORING_OP_TIMEOUT run by io-wq, because of IOSQE_ASYNC, has the same
problem as poll, futex and waitid. io_wq_submit_work() looks at
IO_WQ_WORK_CANCEL once, before it issues the request. A cancel in between
flags the work, gets -EALREADY, and searches ->timeout_list in vain,
while the worker then adds the request and starts the timer:

  io-wq worker                          io_try_cancel()
  io_wq_submit_work()
    IO_WQ_WORK_CANCEL isn't set
                                        io_async_cancel_one()
                                          sets IO_WQ_WORK_CANCEL
                                          = -EALREADY
                                        io_timeout_cancel() = -ENOENT
    io_timeout()
      adds the request to ->timeout_list
      hrtimer_start()
    = IOU_ISSUE_SKIP_COMPLETE

Nobody looks at the flag again, and the timeout runs its course. At ring
exit, io_uring_try_cancel_requests() cancels io-wq work and then kills
the timeouts the same way, so an exiting task can get stuck for the full
duration of such a timeout.

Look at the flag under ->timeout_lock, which the search takes as well,
and fail the request if it is set. If the search came first, the flag is
visible. If it comes later, it finds the request on the list.

[ 6.12: ->timeout_lock is a spinlock here ]
Fixes: ce35a47a3a02 ("io_uring: add IOSQE_ASYNC")
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/io_uring.h |   14 ++++++++++----
 io_uring/timeout.c  |    7 +++++++
 2 files changed, 17 insertions(+), 4 deletions(-)

--- a/io_uring/io_uring.h
+++ b/io_uring/io_uring.h
@@ -274,16 +274,22 @@ static inline void io_ring_submit_lock(s
  * cancellations find it, rather than completing it. Whoever tried to cancel
  * the request before that found it running. It has flagged the work item,
  * has searched the list in vain, and won't come back. To be called with
- * ->uring_lock held, which the search needs as well, once the request is on
- * the list: if the search came first, the flag is visible.
+ * the lock the search takes held: if the search came first, the flag is
+ * visible. For most lists that is ->uring_lock, timeouts use ->timeout_lock.
  */
+static inline bool __io_wq_cancel_seen(struct io_kiocb *req,
+				       unsigned int issue_flags)
+{
+	return (issue_flags & IO_URING_F_IOWQ) &&
+	       (atomic_read(&req->work.flags) & IO_WQ_WORK_CANCEL);
+}
+
 static inline bool io_wq_cancel_seen(struct io_kiocb *req,
 				     unsigned int issue_flags)
 {
 	lockdep_assert_held(&req->ctx->uring_lock);
 
-	return (issue_flags & IO_URING_F_IOWQ) &&
-	       (atomic_read(&req->work.flags) & IO_WQ_WORK_CANCEL);
+	return __io_wq_cancel_seen(req, issue_flags);
 }
 
 static inline void io_commit_cqring(struct io_ring_ctx *ctx)
--- a/io_uring/timeout.c
+++ b/io_uring/timeout.c
@@ -607,6 +607,13 @@ int io_timeout(struct io_kiocb *req, uns
 
 	spin_lock_irq(&ctx->timeout_lock);
 
+	/* the list is searched under ->timeout_lock, see io_wq_cancel_seen() */
+	if (__io_wq_cancel_seen(req, issue_flags)) {
+		spin_unlock_irq(&ctx->timeout_lock);
+		io_req_task_queue_fail(req, -ECANCELED);
+		return IOU_ISSUE_SKIP_COMPLETE;
+	}
+
 	/*
 	 * sqe->off holds how many events that need to occur for this
 	 * timeout event to be satisfied. If it isn't set, then this is



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 226/247] io_uring/poll: dont loop on HUP with multiple references
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (224 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 225/247] io_uring/timeout: dont lose a cancel as io-wq arms a timeout Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 227/247] io_uring/net: keep recv buffer select length within MAX_RW_COUNT Greg Kroah-Hartman
                   ` (28 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Jens Axboe, Claude Fable 5.1

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Jens Axboe <axboe@kernel.dk>

Commit cf1d5c9d335e2c673811da641531da82cb01393a upstream.

io_poll_check_events() drops down to one reference when a multishot
request sees HUP with more than one, so that the loop goes around once
more. It did so by subtracting one less than it had. With the cmpxchg
that only takes the local count down: the exchange fails, the next pass
reads the unchanged count, and goes through the same motions again. The
loop then only ends once io_poll_issue() stops the request.

Drop the extra references from the counter instead, and loop once more
without trying the exchange. The next pass sees one reference, like it
did before, and ends unless a wake up came in.

Fixes: 937d38dcacd6 ("io_uring/poll: avoid retry wakeup loss when dropping ownership")
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/poll.c |   16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

--- a/io_uring/poll.c
+++ b/io_uring/poll.c
@@ -264,12 +264,14 @@ static inline void io_poll_execute(struc
  */
 static int io_poll_check_events(struct io_kiocb *req, struct io_tw_state *ts)
 {
+	bool again;
 	int v;
 
 	if (unlikely(io_should_terminate_tw(req->ctx)))
 		return -ECANCELED;
 
 	do {
+		again = false;
 		v = atomic_read(&req->poll_refs);
 
 		if (unlikely(v != 1)) {
@@ -331,9 +333,15 @@ static int io_poll_check_events(struct i
 		} else {
 			int ret;
 
-			/* multiple refs and HUP, ensure we loop once more */
-			if ((req->cqe.res & (POLLHUP | POLLRDHUP)) && v != 1)
-				v--;
+			/*
+			 * Multiple refs and HUP, ensure we loop once more. Drop
+			 * down to one ref now, so the next pass ends unless a
+			 * wake up came in.
+			 */
+			if ((req->cqe.res & (POLLHUP | POLLRDHUP)) && v != 1) {
+				atomic_sub(v - 1, &req->poll_refs);
+				again = true;
+			}
 			ret = io_poll_issue(req, ts);
 			if (ret == IOU_STOP_MULTISHOT)
 				return IOU_POLL_REMOVE_POLL_USE_RES;
@@ -351,7 +359,7 @@ static int io_poll_check_events(struct i
 		 * task_work while we were executing it.
 		 */
 		v &= IO_POLL_REF_MASK;
-	} while (atomic_cmpxchg(&req->poll_refs, v, 0) != v);
+	} while (again || atomic_cmpxchg(&req->poll_refs, v, 0) != v);
 
 	io_napi_add(req);
 	return IOU_POLL_NO_ACTION;



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 227/247] io_uring/net: keep recv buffer select length within MAX_RW_COUNT
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (225 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 226/247] io_uring/poll: dont loop on HUP with multiple references Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 228/247] io_uring/wait: wake real-time waiters from hard interrupt context Greg Kroah-Hartman
                   ` (27 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Tamaki Yanagawa, Jens Axboe

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Tamaki Yanagawa <ty@000ty.net>

Commit 96262cfab554cf11412de7a6247f0e82c94e130f upstream.

Since commit dcbd1c054848 ("io_uring/net: let io_recv_buf_select return
the length of the buffer region"), io_recv_buf_select() returns the
selected length as an int. For a non-bundle recv with sqe->len == 0 the
length comes from the ring provided buffer, which can be up to 4G, so a
buffer of 2G or more makes io_recv() fail the request with a bogus
negative result (e.g. -2147483648) instead of receiving into it. Clamp
the length to MAX_RW_COUNT, which import_ubuf() limits the transfer to
anyway.

Fixes: dcbd1c054848 ("io_uring/net: let io_recv_buf_select return the length of the buffer region")
Cc: stable@vger.kernel.org
Signed-off-by: Tamaki Yanagawa <ty@000ty.net>
Assisted-by: Claude:claude-opus-5-5
Link: https://patch.msgid.link/20261018042227.1105-1-ty@000ty.net
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/net.c |    2 ++
 1 file changed, 2 insertions(+)

--- a/io_uring/net.c
+++ b/io_uring/net.c
@@ -1188,6 +1188,8 @@ static int io_recv_buf_select(struct io_
 		*sel = io_buffer_select(req, &len, issue_flags);
 		if (!sel->addr)
 			return -ENOBUFS;
+		/* ring provided buffers can be up to 4G, keep len an int */
+		len = min_t(size_t, len, MAX_RW_COUNT);
 		sr->buf = sel->addr;
 		sr->len = len;
 map_ubuf:



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 228/247] io_uring/wait: wake real-time waiters from hard interrupt context
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (226 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 227/247] io_uring/net: keep recv buffer select length within MAX_RW_COUNT Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 229/247] io_uring/waitid: prevent cancel reference wrap Greg Kroah-Hartman
                   ` (26 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Austin Schuh, Jens Axboe

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Austin Schuh <austin.linux@gmail.com>

Commit 5b01d5955ac206e38097f777eff6ab2a8b948c41 upstream.

Since commit cebf123c634a ("io_uring: implement our own schedule timeout
handling"), a CQ wait with a timeout sleeps on io_uring's own hrtimer
instead of an hrtimer sleeper.  On PREEMPT_RT, an hrtimer that isn't
marked for hard interrupt expiry expires in the per-CPU ktimers thread,
which runs at SCHED_FIFO 1.  A real-time task waiting in io_uring_enter()
is therefore not woken at its deadline while any other real-time task is
runnable on its CPU: the wakeup waits until every one of them has blocked.

hrtimer sleepers, which schedule_hrtimeout_range_clock() used to give
io_uring, don't have this problem: __hrtimer_setup_sleeper() marks the
timer hard when the sleeping task is in a real-time or deadline class.
Both of io_uring's callbacks are fine in hard interrupt context:
io_cqring_timer_wakeup() sets a flag and calls wake_up_process(), and
io_cqring_min_timer_wakeup() only reads ring state, under RCU, before
doing the same or re-arming the timer.  Apply the sleeper rule to them.

Measured on a Jetson Orin Nano running 6.18.39-rt with this change
backported: a SCHED_FIFO 40 task waits in io_uring_enter() for 40,000
deadlines 500us apart, while a SCHED_FIFO 20 task runs bursts of up to
1ms on the same CPU.  Before, 6,647 wakeups were more than 100us late,
the latest by 1,040us, and 2,758 deadlines passed without a wakeup at
all.  After, none were more than 100us late and the latest was 18us.

This mirrors epoll: epoll_pwait2() waits on an hrtimer sleeper, so its
timeout is already hard for real-time tasks, and on the same setup it
was never more than 17us late.

[ 6.12: the wait code is still in io_uring.c, hrtimer_init_on_stack() API ]
Fixes: cebf123c634a ("io_uring: implement our own schedule timeout handling")
Cc: stable@vger.kernel.org
Assisted-by: LLM
Signed-off-by: Austin Schuh <austin.linux@gmail.com>
Link: https://patch.msgid.link/20261017171726.601443-1-austin.linux@gmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/io_uring.c |   14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

--- a/io_uring/io_uring.c
+++ b/io_uring/io_uring.c
@@ -48,6 +48,7 @@
 #include <linux/uio.h>
 #include <linux/bits.h>
 
+#include <linux/sched/rt.h>
 #include <linux/sched/signal.h>
 #include <linux/fs.h>
 #include <linux/file.h>
@@ -2495,12 +2496,21 @@ out_wake:
 	return io_cqring_timer_wakeup(timer);
 }
 
+/* Same policy as for hrtimer sleepers, see __hrtimer_setup_sleeper(). */
+static enum hrtimer_mode io_cqring_timer_mode(void)
+{
+	if (IS_ENABLED(CONFIG_PREEMPT_RT) && rt_or_dl_task_policy(current))
+		return HRTIMER_MODE_ABS_HARD;
+	return HRTIMER_MODE_ABS;
+}
+
 static int io_cqring_schedule_timeout(struct io_wait_queue *iowq,
 				      clockid_t clock_id, ktime_t start_time)
 {
+	enum hrtimer_mode mode = io_cqring_timer_mode();
 	ktime_t timeout;
 
-	hrtimer_init_on_stack(&iowq->t, clock_id, HRTIMER_MODE_ABS);
+	hrtimer_init_on_stack(&iowq->t, clock_id, mode);
 	if (iowq->min_timeout) {
 		timeout = ktime_add_ns(iowq->min_timeout, start_time);
 		iowq->t.function = io_cqring_min_timer_wakeup;
@@ -2510,7 +2520,7 @@ static int io_cqring_schedule_timeout(st
 	}
 
 	hrtimer_set_expires_range_ns(&iowq->t, timeout, 0);
-	hrtimer_start_expires(&iowq->t, HRTIMER_MODE_ABS);
+	hrtimer_start_expires(&iowq->t, mode);
 
 	if (!READ_ONCE(iowq->hit_timeout))
 		schedule();



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 229/247] io_uring/waitid: prevent cancel reference wrap
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (227 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 228/247] io_uring/wait: wake real-time waiters from hard interrupt context Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 230/247] keys: Avoid the owner account dereference in named keyring lookup Greg Kroah-Hartman
                   ` (25 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Junyeong Lee, Jens Axboe

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Junyeong Lee <jylee5498@gmail.com>

Commit 98787d3fa4e99564d2b2bc21255b21f670c450d0 upstream.

io_waitid packs the cancellation state into bit 31 of ->refs and uses
bits 30:0 as a 31-bit reference counter:

  #define IO_WAITID_CANCEL_FLAG BIT(31)
  #define IO_WAITID_REF_MASK    GENMASK(30, 0)

__io_waitid_cancel() marks a request canceled, then increments the low
bits of ->refs to claim completion ownership. When another path owns the
request, the increment remains even though cancellation returns false.
The request remains discoverable by cancellation, so repeated failed
attempts can wrap the 31-bit reference field to zero. A later
cancellation can claim ownership and complete the request a second time.

Use atomic_fetch_or() when setting the cancel flag and inspect the old
flag value. The first cancel attempt continues to the existing ownership
increment, preserving its wake and issuer handoff semantics. Later
attempts see the cancel flag and return without incrementing the
reference field.

This makes repeated failed cancellation attempts idempotent while
leaving the first-cancel state transitions unchanged.

Fixes: f31ecf671ddc ("io_uring: add IORING_OP_WAITID support")
Cc: stable@vger.kernel.org
Assisted-by: LLM
Signed-off-by: Junyeong Lee <jylee5498@gmail.com>
Link: https://patch.msgid.link/20261019152100.63565-1-jylee5498@gmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 io_uring/waitid.c |    7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

--- a/io_uring/waitid.c
+++ b/io_uring/waitid.c
@@ -161,9 +161,12 @@ static bool __io_waitid_cancel(struct io
 
 	/*
 	 * Mark us canceled regardless of ownership. This will prevent a
-	 * potential retry from a spurious wakeup.
+	 * potential retry from a spurious wakeup. Only the first cancel
+	 * attempt should take a reference for the ownership handoff.
 	 */
-	atomic_or(IO_WAITID_CANCEL_FLAG, &iw->refs);
+	if (atomic_fetch_or(IO_WAITID_CANCEL_FLAG, &iw->refs) &
+	    IO_WAITID_CANCEL_FLAG)
+		return false;
 
 	/* claim ownership */
 	if (atomic_fetch_inc(&iw->refs) & IO_WAITID_REF_MASK)



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 230/247] keys: Avoid the owner account dereference in named keyring lookup
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (228 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 229/247] io_uring/waitid: prevent cancel reference wrap Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 231/247] keys: Check the authorization payload in process keyring searches Greg Kroah-Hartman
                   ` (24 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Cen Zhang, Jarkko Sakkinen

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Cen Zhang <zzzccc427@gmail.com>

commit 51409aaa01f8602552c336009fd22b226b0cdf1d upstream.

Named keyring lookup must keep the storage containing the owner UID
alive through the namespace mapping check.  find_keyring_by_name()
reads keyring->user->uid under keyring_name_lock, but that lock protects
the keyring's name entry and allocation, not its separate key_user.

A named session-keyring join can overlap a privileged KEYCTL_CHOWN on
another CPU.  If the keyring holds the last reference to its old dynamic
key_user and the ownership transfer succeeds, the following ordering is
possible:

    Named join                         Chown
    find_keyring_by_name()              keyctl_chown_key()
      read_lock(keyring_name_lock)       down_write(key->sem)
      load old keyring->user
                                         replace key->user and key->uid
                                         up_write(key->sem)
                                         key_put(key)
                                         key_user_put(old user): free
      read old user->uid
      read_unlock(keyring_name_lock)

Chown neither takes keyring_name_lock nor key_session_mutex, so it can
free the old account between the pointer load and the UID read.  The
lookup then reads freed memory even though the keyring itself is alive.

Use keyring->uid for the mapping check.  key_alloc() initializes this
inline owner UID and keyctl_chown_key() updates it on chown.
The existing name lock keeps its containing keyring allocated throughout
the check, so lookup no longer depends on the account's lifetime.  This
also matches the owner UID used by the permission check.

KASAN report as below:

    BUG: KASAN: slab-use-after-free in find_keyring_by_name+0x577/0x5d0
    Read of size 4 at addr ffff8881128ae2ec by task keycase/500

Cc: stable@vger.kernel.org
Fixes: 2ea190d0a006 ("keys: skip keys from another user namespace")
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
Link: https://lore.kernel.org/r/pm-key-management-objects-candidate-0002-v3-2baa8cad2bb554364e10@gmail.com
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 security/keys/keyring.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -1158,7 +1158,7 @@ struct key *find_keyring_by_name(const c
 	 * grants Search permission and that hasn't been revoked
 	 */
 	list_for_each_entry(keyring, &ns->keyring_name_list, name_link) {
-		if (!kuid_has_mapping(ns, keyring->user->uid))
+		if (!kuid_has_mapping(ns, keyring->uid))
 			continue;
 
 		if (test_bit(KEY_FLAG_REVOKED, &keyring->flags))



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 231/247] keys: Check the authorization payload in process keyring searches
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (229 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 230/247] keys: Avoid the owner account dereference in named keyring lookup Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 232/247] keys: Protect the type name while describing a key Greg Kroah-Hartman
                   ` (23 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Cen Zhang, Jarkko Sakkinen

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Cen Zhang <zzzccc427@gmail.com>

commit 0a0ec45bf577a9b4d4960567f20d3877ef480de9 upstream.

An authorization payload and its saved credentials must remain valid
while search_process_keyrings_rcu() searches the requestor's keyrings.
The function validates the authorization key, then separately loads
payload.data[0] and unconditionally reads rka->cred. Validation does
not prevent request_key_auth_revoke() from clearing the payload.

A request-key helper can assume authority and fork a descendant that
inherits the authorization key. If the descendant misses in its own
keyrings, it falls back to the saved requestor credentials. Successful
target instantiation invalidates the authorization key without clearing
the payload. After the helper exits, UMH_WAIT_PROC returns to the
requester, which calls complete_request_key() and revokes that key.

With the descendant paused after validation, the paths can interleave
as follows:

  1. The descendant enters search_process_keyrings_rcu() under RCU and
     key_validate() succeeds.
  2. The helper instantiates the target, invalidates the authorization
     key, and exits.
  3. The requester resumes from UMH_WAIT_PROC, calls
     complete_request_key(), and revokes the authorization key.
     request_key_auth_revoke() sets its payload pointer to NULL.
  4. The descendant loads NULL and dereferences rka->cred.

This NULL dereference can oops the kernel. RCU delays payload disposal
but does not prevent the pointer from being cleared.

Load the payload with dereference_key_rcu() and require a non-NULL
result before validating the authorization key and searching its saved
credentials. A non-NULL payload and its credentials remain alive for
the caller's RCU read-side section; a cleared payload skips the fallback
search and follows the existing error selection.

KASAN report as below:

    Oops: general protection fault, probably for non-canonical address 0xdffffc0000000005: 0000 [#1] SMP KASAN NOPTI
    KASAN: null-ptr-deref in range [0x0000000000000028-0x000000000000002f]
    RIP: 0010:search_process_keyrings_rcu+0x32b/0x790

Cc: stable@vger.kernel.org
Fixes: e59428f721ee ("keys: Move the RCU locks outwards from the keyring search functions")
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
Link: https://lore.kernel.org/r/pm-key-management-objects-candidate-0004-v3-598361863b76bc25d58d@gmail.com
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 security/keys/process_keys.c |    5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -556,9 +556,8 @@ key_ref_t search_process_keyrings_rcu(st
 	    ) {
 		const struct cred *cred = ctx->cred;
 
-		if (key_validate(cred->request_key_auth) == 0) {
-			rka = ctx->cred->request_key_auth->payload.data[0];
-
+		rka = dereference_key_rcu(cred->request_key_auth);
+		if (rka && key_validate(cred->request_key_auth) == 0) {
 			//// was search_process_keyrings() [ie. recursive]
 			ctx->cred = rka->cred;
 			key_ref = search_cred_keyrings_rcu(ctx);



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 232/247] keys: Protect the type name while describing a key
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (230 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 231/247] keys: Check the authorization payload in process keyring searches Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 233/247] keys: make keyring indexes independent of kernel addresses Greg Kroah-Hartman
                   ` (22 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Cen Zhang, Jarkko Sakkinen

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Cen Zhang <zzzccc427@gmail.com>

commit fced7238b7e80cf8aa688d5af976e4aa6e33c329 upstream.

keyctl_describe_key() must keep the key type's name alive until
kasprintf() has consumed it. The retained key reference keeps the key
and its description alive, but does not pin the module providing its
type. The name is passed to kasprintf() without holding key->sem.

kvasprintf() uses the saved name pointer in two formatting passes, with
a GFP_KERNEL allocation between them. With AF_RXRPC=m, a task that
passes View permission before type retirement can overlap a privileged
module unload in this order:

1. KEYCTL_DESCRIBE looks up the key, saves key->type->name in the
   kasprintf() arguments and completes the first formatting pass.
2. While the formatter is delayed before its second pass,
   af_rxrpc_exit() calls unregister_key_type(), which removes the type
   from the registry and waits for key_gc_keytype().
3. The collector takes key->sem for writing, retypes the retained key
   to key_type_dead and completes retirement. Unregistration and module
   exit return, allowing free_module() to release the type and name.
4. The formatter resumes its second pass and reads the saved name from
   released module storage, which can fault in string().

Hold key->sem for reading across kasprintf(). The collector then cannot
retype the key or complete retirement until both formatting passes have
finished. If retirement wins the lock first, formatting uses the core
key_type_dead name instead. Release the semaphore immediately after
kasprintf(), including on allocation failure, before copying to
userspace.

Oops report as below:

    BUG: unable to handle page fault for address: fffffbfff8054794
    #PF: supervisor read access in kernel mode
    #PF: error_code(0x0000) - not-present page
    RIP: 0010:string+0x23f/0x470
    Call Trace:
     vsnprintf+0x330/0x1110

Cc: stable@vger.kernel.org
Fixes: aa9d4437893f ("KEYS: Fix the size of the key description passed to/from userspace")
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
Link: https://lore.kernel.org/r/pm-key-management-objects-candidate-0009-v4-6b537c5732fd957c33fa@gmail.com
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 security/keys/keyctl.c |    2 ++
 1 file changed, 2 insertions(+)

--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -677,12 +677,14 @@ okay:
 
 	/* calculate how much information we're going to return */
 	ret = -ENOMEM;
+	down_read(&key->sem);
 	infobuf = kasprintf(GFP_KERNEL,
 			    "%s;%d;%d;%08x;",
 			    key->type->name,
 			    from_kuid_munged(current_user_ns(), key->uid),
 			    from_kgid_munged(current_user_ns(), key->gid),
 			    key->perm);
+	up_read(&key->sem);
 	if (!infobuf)
 		goto error2;
 	infolen = strlen(infobuf);



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 233/247] keys: make keyring indexes independent of kernel addresses
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (231 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 232/247] keys: Protect the type name while describing a key Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 234/247] keys: Protect the read method check against type removal Greg Kroah-Hartman
                   ` (21 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Kyle Zeng, Jarkko Sakkinen

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Kyle Zeng <kylebot@openai.com>

commit de891c73c1cf41ac8de12c07fa2c84d6a912ad0c upstream.

KEYCTL_READ returns the serial numbers in a keyring in associative-array
traversal order.  The first word of the index is a public, deterministic
hash of the type pointer, domain pointer and description.  An unprivileged
user can therefore insert keys with known descriptions, predict their
order for each possible KASLR slide, and recover the kernel image address.
On an x86-64 build with 16 MiB alignment, 45 user keys suffice to
distinguish the candidate slides.

Remove the addresses from the whole index, not just its first hash word.
Assign each key type and domain a nonzero 64-bit ID and hash those IDs and
the description with a once-initialized SipHash key.  Use the full IDs in
the later index chunks as well.  Truncating or hashing the IDs there would
lose the guarantee that distinct type/domain/description tuples have a
differing index bit.

Allocate IDs lazily since private key types need not be registered.  Cache
them in the index key so tree walks and copies of an existing index do not
need to dereference a type descriptor that may have been unregistered.
Keep the 32-bit chunk layout and diff_objects() bit offsets consistent,
and retain the separate root slot for keyrings used by recursive search.
The key comparison, permissions and userspace data format are unchanged;
only the address-dependent in-memory ordering is replaced.

Cc: stable@vger.kernel.org
Fixes: b2a4df200d57 ("KEYS: Expand the capacity of a keyring")
Assisted-by: Codex:gpt-6-astra
Signed-off-by: Kyle Zeng <kylebot@openai.com>
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
Link: https://lore.kernel.org/r/20261013231251.56170-1-kylebot@openai.com
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 include/linux/key-type.h |    1 
 include/linux/key.h      |    5 +
 security/keys/keyring.c  |  150 +++++++++++++++++++++++++----------------------
 3 files changed, 86 insertions(+), 70 deletions(-)

--- a/include/linux/key-type.h
+++ b/include/linux/key-type.h
@@ -158,6 +158,7 @@ struct key_type {
 				     const void *in, const void *in2);
 
 	/* internal fields */
+	atomic64_t		index_id;	/* Opaque keyring index ID */
 	struct list_head	link;		/* link in types list */
 	struct lock_class_key	lock_class;	/* key->sem lock class */
 } __randomize_layout;
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -107,6 +107,7 @@ struct keyring_name;
 
 struct key_tag {
 	struct rcu_head		rcu;
+	atomic64_t		index_id;	/* Opaque keyring index ID */
 	refcount_t		usage;
 	bool			removed;	/* T when subject removed */
 };
@@ -129,6 +130,8 @@ struct keyring_index_key {
 	struct key_type		*type;
 	struct key_tag		*domain_tag;	/* Domain of operation */
 	const char		*description;
+	u64			type_id;	/* Cached index IDs */
+	u64			domain_id;
 };
 
 union key_payload {
@@ -251,6 +254,8 @@ struct key {
 			struct key_type	*type;		/* type of key */
 			struct key_tag	*domain_tag;	/* Domain of operation */
 			char		*description;
+			u64		type_id;
+			u64		domain_id;
 		};
 	};
 
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -14,6 +14,9 @@
 #include <linux/err.h>
 #include <linux/user_namespace.h>
 #include <linux/nsproxy.h>
+#include <linux/once.h>
+#include <linux/random.h>
+#include <linux/siphash.h>
 #include <keys/keyring-type.h>
 #include <keys/user-type.h>
 #include <linux/assoc_array_priv.h>
@@ -147,49 +150,46 @@ static int keyring_instantiate(struct ke
 }
 
 /*
- * Multiply 64-bits by 32-bits to 96-bits and fold back to 64-bit.  Ideally we'd
- * fold the carry back too, but that requires inline asm.
+ * Give key types and domains address-independent identities.  Zero means that
+ * an ID has not yet been allocated.  As with inode sequence numbers used by
+ * futexes, this relies on the 64-bit counter not wrapping in a machine's
+ * lifetime.
  */
-static u64 mult_64x32_and_fold(u64 x, u32 y)
+static u64 key_index_id(atomic64_t *id)
 {
-	u64 hi = (u64)(u32)(x >> 32) * y;
-	u64 lo = (u64)(u32)(x) * y;
-	return lo + ((u64)(u32)hi << 32) + (u32)(hi >> 32);
+	static atomic64_t next_id;
+	u64 old, new;
+
+	old = atomic64_read(id);
+	if (likely(old))
+		return old;
+
+	do {
+		new = atomic64_inc_return(&next_id);
+	} while (WARN_ON_ONCE(!new));
+
+	old = 0;
+	if (!atomic64_try_cmpxchg_relaxed(id, &old, new))
+		return old;
+	return new;
 }
 
 /*
- * Hash a key type and description.
+ * Hash a key type, domain and description.  KEYCTL_READ exposes the tree's
+ * traversal order, so no part of the index may contain kernel addresses.
  */
 static void hash_key_type_and_desc(struct keyring_index_key *index_key)
 {
 	const unsigned level_shift = ASSOC_ARRAY_LEVEL_STEP;
 	const unsigned long fan_mask = ASSOC_ARRAY_FAN_MASK;
-	const char *description = index_key->description;
-	unsigned long hash, type;
-	u32 piece;
+	static siphash_key_t hash_key __read_mostly;
+	unsigned long hash;
 	u64 acc;
-	int n, desc_len = index_key->desc_len;
 
-	type = (unsigned long)index_key->type;
-	acc = mult_64x32_and_fold(type, desc_len + 13);
-	acc = mult_64x32_and_fold(acc, 9207);
-	piece = (unsigned long)index_key->domain_tag;
-	acc = mult_64x32_and_fold(acc, piece);
-	acc = mult_64x32_and_fold(acc, 9207);
-
-	for (;;) {
-		n = desc_len;
-		if (n <= 0)
-			break;
-		if (n > 4)
-			n = 4;
-		piece = 0;
-		memcpy(&piece, description, n);
-		description += n;
-		desc_len -= n;
-		acc = mult_64x32_and_fold(acc, piece);
-		acc = mult_64x32_and_fold(acc, 9207);
-	}
+	get_random_once(&hash_key, sizeof(hash_key));
+	acc = siphash(index_key->description, index_key->desc_len, &hash_key);
+	acc = siphash_3u64(index_key->type_id, index_key->domain_id, acc,
+			   &hash_key);
 
 	/* Fold the hash down to 32 bits if need be. */
 	hash = acc;
@@ -209,7 +209,7 @@ static void hash_key_type_and_desc(struc
 
 /*
  * Finalise an index key to include a part of the description actually in the
- * index key, to set the domain tag and to calculate the hash.
+ * index key, to set the domain tag and index IDs, and to calculate the hash.
  */
 void key_set_index_key(struct keyring_index_key *index_key)
 {
@@ -225,6 +225,14 @@ void key_set_index_key(struct keyring_in
 			index_key->domain_tag = &default_domain_tag;
 	}
 
+	/* Preserve the IDs when copying an existing key's index.  In
+	 * particular, its type may already have been unregistered.
+	 */
+	if (!index_key->type_id)
+		index_key->type_id = key_index_id(&index_key->type->index_id);
+	if (!index_key->domain_id)
+		index_key->domain_id = key_index_id(&index_key->domain_tag->index_id);
+
 	hash_key_type_and_desc(index_key);
 }
 
@@ -263,15 +271,19 @@ void key_remove_domain(struct key_tag *d
 /*
  * Build the next index key chunk.
  *
+ * The hash and inline description are followed by the 64-bit type and domain
+ * IDs, low word first, and then by the rest of the description.
  * We return it one word-sized chunk at a time.
  */
 static unsigned long keyring_get_key_chunk(const void *data, int level)
 {
+	const unsigned int id_chunks = sizeof(u64) / sizeof(unsigned long);
 	const struct keyring_index_key *index_key = data;
+	int desc_len = index_key->desc_len;
 	unsigned long chunk = 0;
-	const u8 *d;
-	int desc_len = index_key->desc_len, n = sizeof(chunk);
+	int n = sizeof(chunk);
 	unsigned int offset;
+	const u8 *d;
 
 	level /= ASSOC_ARRAY_KEY_CHUNK_SIZE;
 	switch (level) {
@@ -279,27 +291,30 @@ static unsigned long keyring_get_key_chu
 		return index_key->hash;
 	case 1:
 		return index_key->x;
-	case 2:
-		return (unsigned long)index_key->type;
-	case 3:
-		return (unsigned long)index_key->domain_tag;
-	default:
-		level -= 4;
-		offset = sizeof(index_key->desc) + level * sizeof(long);
-		if (desc_len <= offset)
-			return 0;
-
-		d = index_key->description + offset;
-		desc_len -= offset;
-		if (desc_len > n)
-			desc_len = n;
-		d += desc_len;
-		do {
-			chunk <<= 8;
-			chunk |= *--d;
-		} while (--desc_len > 0);
-		return chunk;
 	}
+
+	level -= 2;
+	if (level < id_chunks)
+		return index_key->type_id >> (level * ASSOC_ARRAY_KEY_CHUNK_SIZE);
+	level -= id_chunks;
+	if (level < id_chunks)
+		return index_key->domain_id >> (level * ASSOC_ARRAY_KEY_CHUNK_SIZE);
+	level -= id_chunks;
+
+	offset = sizeof(index_key->desc) + level * sizeof(long);
+	if (desc_len <= offset)
+		return 0;
+
+	d = index_key->description + offset;
+	desc_len -= offset;
+	if (desc_len > n)
+		desc_len = n;
+	d += desc_len;
+	do {
+		chunk <<= 8;
+		chunk |= *--d;
+	} while (--desc_len > 0);
+	return chunk;
 }
 
 static unsigned long keyring_get_object_key_chunk(const void *object, int level)
@@ -331,6 +346,7 @@ static int keyring_diff_objects(const vo
 	const struct keyring_index_key *b = data;
 	unsigned long seg_a, seg_b;
 	int level, i;
+	u64 diff;
 
 	level = 0;
 	seg_a = a->hash;
@@ -339,28 +355,22 @@ static int keyring_diff_objects(const vo
 		goto differ;
 	level += ASSOC_ARRAY_KEY_CHUNK_SIZE / 8;
 
-	/* The number of bits contributed by the hash is controlled by a
-	 * constant in the assoc_array headers.  Everything else thereafter we
-	 * can deal with as being machine word-size dependent.
-	 */
+	/* The inline description contributes one machine-word-sized chunk. */
 	seg_a = a->x;
 	seg_b = b->x;
 	if ((seg_a ^ seg_b) != 0)
 		goto differ;
 	level += sizeof(unsigned long);
 
-	/* The next bit may not work on big endian */
-	seg_a = (unsigned long)a->type;
-	seg_b = (unsigned long)b->type;
-	if ((seg_a ^ seg_b) != 0)
-		goto differ;
-	level += sizeof(unsigned long);
-
-	seg_a = (unsigned long)a->domain_tag;
-	seg_b = (unsigned long)b->domain_tag;
-	if ((seg_a ^ seg_b) != 0)
-		goto differ;
-	level += sizeof(unsigned long);
+	diff = a->type_id ^ b->type_id;
+	if (diff)
+		return level * 8 + __ffs64(diff);
+	level += sizeof(u64);
+
+	diff = a->domain_id ^ b->domain_id;
+	if (diff)
+		return level * 8 + __ffs64(diff);
+	level += sizeof(u64);
 
 	i = sizeof(a->desc);
 	if (a->desc_len <= i)



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 234/247] keys: Protect the read method check against type removal
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (232 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 233/247] keys: make keyring indexes independent of kernel addresses Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 235/247] KEYS: Fix key_reject_and_link() race with keyring restriction Greg Kroah-Hartman
                   ` (20 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Jarkko Sakkinen, Cen Zhang,
	David Howells

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Cen Zhang <zzzccc427@gmail.com>

commit 925c84e3cc21caf09de92d9bcafab0147790debf upstream.

keyctl_read_key() checks key->type->read without holding key->sem.
A reference keeps the key alive, but does not pin the module containing
its type. A surviving RxRPC key can therefore be read while AF_RXRPC
is being unloaded:

  KEYCTL_READ task                    Module unload and key GC
  ----------------                   ------------------------
  lookup_user_key()
  permission / possession checks
  load key->type
                                     af_rxrpc_exit()
                                       unregister_key_type()
                                         GC: down_write(key->sem)
                                         GC: retype to key_type_dead
                                         GC: up_write(key->sem)
                                       unregister_key_type() returns
                                     free_module()
  read saved type's read member

The final access can read freed module storage. The read invocation in
__keyctl_read_key() is already protected by key->sem, but the earlier
method check is outside that critical section.

Move the method check into __keyctl_read_key(), after key_validate() and
under its existing read hold on key->sem. The check and invocation then
use the same protected type for length queries and every read retry.
The GC cannot retype the key until the semaphore is released, and type
unregistration waits for that GC pass before the module can be freed.

Return -EOPNOTSUPP when validation succeeds and the type has no read
method. A temporary buffer may now be allocated before this result;
allocation and copying to userspace remain outside the semaphore.

Assisted-by: LLM
Cc: stable@vger.kernel.org # v5.10+
Fixes: d3ec10aa9581 ("KEYS: Don't write out to userspace while holding key semaphore")
Suggested-by: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
Reviewed-by: David Howells <dhowells@redhat.com>
Link: https://lore.kernel.org/r/pm-key-management-objects-candidate-0010-v7-fc85721ff5cfb9e33ac6@gmail.com
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 security/keys/keyctl.c |   13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -808,8 +808,12 @@ static long __keyctl_read_key(struct key
 
 	down_read(&key->sem);
 	ret = key_validate(key);
-	if (ret == 0)
-		ret = key->type->read(key, buffer, buflen);
+	if (ret == 0) {
+		if (key->type->read)
+			ret = key->type->read(key, buffer, buflen);
+		else
+			ret = -EOPNOTSUPP;
+	}
 	up_read(&key->sem);
 	return ret;
 }
@@ -863,11 +867,6 @@ long keyctl_read_key(key_serial_t keyid,
 
 	/* the key is probably readable - now try to read it */
 can_read_key:
-	if (!key->type->read) {
-		ret = -EOPNOTSUPP;
-		goto key_put_out;
-	}
-
 	if (!buffer || !buflen) {
 		/* Get the key length from the read method */
 		ret = __keyctl_read_key(key, NULL, 0);



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 235/247] KEYS: Fix key_reject_and_link() race with keyring restriction
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (233 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 234/247] keys: Protect the read method check against type removal Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 236/247] KEYS: trusted: Fix blob allocation size in tpm2_key_decode() Greg Kroah-Hartman
                   ` (19 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Jarkko Sakkinen, Adrian Martinez

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Adrian Martinez <adrimg3196@gmail.com>

commit 0b157166e612b70f98a332b6c7be7eac6f8e9593 upstream.

The restrict_link check in key_reject_and_link() is done before taking
the keyring semaphore, racing with a concurrent keyring_restrict()
that installs the restriction while holding the semaphore in write
mode.

Move the check to after __key_link_lock(), so it is done under the
semaphore, matching the pattern used in __key_create_or_update().

Cc: stable@vger.kernel.org
Fixes: 5ac7eace2d00 ("KEYS: Add a facility to restrict new links into a keyring")
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Adrian Martinez <adrimg3196@gmail.com>
Link: https://lore.kernel.org/r/CACO1+RT+m==BY+ZPkE+fo536D0qu3wog4xE1dfuXQ56g+=Qv=A@mail.gmail.com
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 security/keys/key.c |   13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -587,11 +587,18 @@ int key_reject_and_link(struct key *key,
 	ret = -EBUSY;
 
 	if (keyring) {
-		if (keyring->restrict_link)
-			return -EPERM;
-
 		link_ret = __key_link_lock(keyring, &key->index_key);
 		if (link_ret == 0) {
+			/*
+			 * Check the restriction under the keyring semaphore.
+			 * keyring_restrict() installs it while holding the
+			 * semaphore, so testing it beforehand races with a
+			 * concurrent restriction install.
+			 */
+			if (keyring->restrict_link) {
+				__key_link_end(keyring, &key->index_key, edit);
+				return -EPERM;
+			}
 			link_ret = __key_link_begin(keyring, &key->index_key, &edit);
 			if (link_ret < 0)
 				__key_link_end(keyring, &key->index_key, edit);



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 236/247] KEYS: trusted: Fix blob allocation size in tpm2_key_decode()
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (234 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 235/247] KEYS: Fix key_reject_and_link() race with keyring restriction Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 237/247] keys/trusted_keys: return immediately after TPM unseal failure Greg Kroah-Hartman
                   ` (18 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Stefano Garzarella, Jarkko Sakkinen

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Stefano Garzarella <sgarzare@redhat.com>

commit 11077cbcc2695f71c944a84a5f08c6672ab759f1 upstream.

tpm2_key_decode() allocates 4 bytes more than needed. The ASN.1
callbacks tpm2_key_priv() and tpm2_key_pub() provide the lengths
of TPM2B_PRIVATE and TPM2B_PUBLIC, so ctx.priv_len and ctx.pub_len
already account for the 2-byte `size` field each of those structures
starts with.

I noticed this while reviewing commit 114f00d738f1 ("KEYS: trusted:
Fix tpm2_load_cmd() boundary check"), which correctly reports
ctx.priv_len + ctx.pub_len as the decoded blob size [1].

Let's allocate exactly that amount, matching the data copied into
the blob.

[1] https://lore.kernel.org/linux-integrity/apfoKo-BdwaLXtkT@sgarzare-redhat/

Cc: stable@vger.kernel.org # v5.13+
Fixes: f2219745250f ("security: keys: trusted: use ASN.1 TPM2 key format for the blobs")
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
Link: https://lore.kernel.org/r/20260923173506.41519-1-sgarzare@redhat.com
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 security/keys/trusted-keys/trusted_tpm2.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/security/keys/trusted-keys/trusted_tpm2.c
+++ b/security/keys/trusted-keys/trusted_tpm2.c
@@ -124,7 +124,7 @@ static int tpm2_key_decode(struct truste
 	if (ctx.priv_len + ctx.pub_len > MAX_BLOB_SIZE)
 		return -EINVAL;
 
-	blob = kmalloc(ctx.priv_len + ctx.pub_len + 4, GFP_KERNEL);
+	blob = kmalloc(ctx.priv_len + ctx.pub_len, GFP_KERNEL);
 	if (!blob)
 		return -ENOMEM;
 



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 237/247] keys/trusted_keys: return immediately after TPM unseal failure
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (235 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 236/247] KEYS: trusted: Fix blob allocation size in tpm2_key_decode() Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 238/247] asymmetric_keys: reject trust keys without IDs Greg Kroah-Hartman
                   ` (17 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Srish Srinivasan, Jarkko Sakkinen

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Srish Srinivasan <ssrish@linux.ibm.com>

commit f92d0ccb05bf9089072cb067dda0dffd5394c4ef upstream.

trusted_tpm_unseal() proceeds to pcrlock() when the TPM unseal operation
fails. If pcrlock() succeeds, its return value overwrites the unseal error,
causing key instantiation to succeed.

Return immediately when unseal fails to preserve the original error.

Cc: stable@vger.kernel.org # v5.15+
Fixes: 5d0682be3189 ("KEYS: trusted: Add generic trusted keys framework")
Signed-off-by: Srish Srinivasan <ssrish@linux.ibm.com>
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
Link: https://lore.kernel.org/r/20260912062950.279104-2-ssrish@linux.ibm.com
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 security/keys/trusted-keys/trusted_tpm1.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

--- a/security/keys/trusted-keys/trusted_tpm1.c
+++ b/security/keys/trusted-keys/trusted_tpm1.c
@@ -970,8 +970,10 @@ static int trusted_tpm_unseal(struct tru
 		ret = tpm2_unseal_trusted(chip, p, options);
 	else
 		ret = key_unseal(p, options);
-	if (ret < 0)
+	if (ret < 0) {
 		pr_info("key_unseal failed (%d)\n", ret);
+		goto out;
+	}
 
 	if (options->pcrlock) {
 		ret = pcrlock(options->pcrlock);



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 238/247] asymmetric_keys: reject trust keys without IDs
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (236 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 237/247] keys/trusted_keys: return immediately after TPM unseal failure Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 239/247] ftrace: Initialize modname and offset in print_rec() Greg Kroah-Hartman
                   ` (16 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, Xiang Mei, Weiming Shi, Herbert Xu

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Weiming Shi <bestswngs@gmail.com>

commit 9695df3b1db4ac4534274d38ee16e3b9b0bf910e upstream.

The PKCS#8 parser deliberately leaves the asym_key_ids payload slot
empty. key_or_keyring_common() unconditionally dereferences that slot
when a PKCS#8 key is supplied to a key_or_keyring restriction. Both the
plain and :chain forms reach this branch, allowing an unprivileged caller
to trigger a NULL pointer dereference through KEYCTL_RESTRICT_KEYRING
followed by add_key().

 Oops: general protection fault, probably for non-canonical address 0xdffffc0000000000
 KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007]
 RIP: 0010:key_or_keyring_common (crypto/asymmetric_keys/restrict.c:205 crypto/asymmetric_keys/restrict.c:279)
 Call Trace:
  <TASK>
  __key_create_or_update (security/keys/key.c:884)
  key_create_or_update (security/keys/key.c:1021)
  __do_sys_add_key (security/keys/keyctl.c:134)
  do_syscall_64 (arch/x86/entry/common.c:52 arch/x86/entry/common.c:83)
  entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:130)
  </TASK>
 Kernel panic - not syncing: Fatal exception

Reject an asymmetric restriction key without key IDs. A PKCS#8 private
key cannot identify the signer of a candidate certificate and is not a
valid trust anchor.

Fixes: 3c58b2362ba8 ("KEYS: Implement PKCS#8 RSA Private Key parser [ver #2]")
Cc: stable@vger.kernel.org
Reported-by: Xiang Mei <xmei5@asu.edu>
Link: https://lore.kernel.org/r/20260429181629.110802-2-bestswngs@gmail.com
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Weiming Shi <bestswngs@gmail.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 crypto/asymmetric_keys/restrict.c |    8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

--- a/crypto/asymmetric_keys/restrict.c
+++ b/crypto/asymmetric_keys/restrict.c
@@ -240,10 +240,14 @@ static int key_or_keyring_common(struct
 			if (IS_ERR(key))
 				key = NULL;
 		} else if (trusted->type == &key_type_asymmetric) {
+			const struct asymmetric_key_ids *kids;
 			const struct asymmetric_key_id **signer_ids;
 
-			signer_ids = (const struct asymmetric_key_id **)
-				asymmetric_key_ids(trusted)->id;
+			kids = asymmetric_key_ids(trusted);
+			if (!kids)
+				return -ENOKEY;
+
+			signer_ids = (const struct asymmetric_key_id **)kids->id;
 
 			/*
 			 * The auth_ids come from the candidate key (the



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 239/247] ftrace: Initialize modname and offset in print_rec()
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (237 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 238/247] asymmetric_keys: reject trust keys without IDs Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 240/247] coredump: hold RCU while releasing parked threads Greg Kroah-Hartman
                   ` (15 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Gavin Inglis, Aaron Ahmed,
	Steven Rostedt

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Aaron Ahmed <aarnahmd@amazon.com>

commit e1f339ff3b83857b93baf8b88186275a413d445e upstream.

print_rec() leaves 'modname' and 'offset' uninitialized and
kallsyms_lookup() only sets them on success. When the lookup fails like
when a module is being loaded or unloaded, 'modname' holds a garbage
value, passes the 'if (modname)' check, and is dereferenced by
seq_printf().

  Oops: general protection fault
  RIP: 0010:string+0x48/0xe0
  Call Trace:
   vsnprintf+0x1f5/0x650
   seq_printf+0x8e/0xb0
   print_rec+0x6c/0xc0
   t_show+0x4c/0x440
   seq_read_iter+0x119/0x480

This can be triggered by reading available_filter_functions while a
module is being loaded or unloaded.

Initialize both variables so a failed lookup skips the module name.

Cc: stable@vger.kernel.org
Fixes: b39181f7c690 ("ftrace: Add FTRACE_MCOUNT_MAX_OFFSET to avoid adding weak function")
Link: https://patch.msgid.link/20261016230403.4916-1-aarnahmd@amazon.com
Tested-by: Gavin Inglis <giinglis@amazon.com>
Signed-off-by: Aaron Ahmed <aarnahmd@amazon.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 kernel/trace/ftrace.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -4316,9 +4316,9 @@ subsys_initcall(ftrace_check_for_weak_fu
 
 static int print_rec(struct seq_file *m, unsigned long ip)
 {
-	unsigned long offset;
+	unsigned long offset = 0;
 	char str[KSYM_SYMBOL_LEN];
-	char *modname;
+	char *modname = NULL;
 	const char *ret;
 
 	ret = kallsyms_lookup(ip, NULL, &offset, &modname, str);



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 240/247] coredump: hold RCU while releasing parked threads
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (238 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 239/247] ftrace: Initialize modname and offset in print_rec() Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 241/247] signal: only SIGKILL and the freezers interrupt a coredumping task Greg Kroah-Hartman
                   ` (14 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Oleg Nesterov,
	Christian Brauner (Amutable)

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Christian Brauner <brauner@kernel.org>

commit 61d58591aa0188bf2463e263962256316ff8b576 upstream.

coredump_finish() releases the parked threads by clearing ->task in
their core_thread entry and calling wake_up_process() on each of them.
It does that without holding a reference on the task and without being
inside rcu.

But calling wake_up_process(task) without rcu here isn't safe. A parked
thread doesn't need that wakeup to leave. A spurious wakeup or a
preemption after the store is enough for the task to go away.

So if the coredump client is preempted between the store and
wake_up_process() the thread can exit and be freed in the meantime and
try_to_wake_up() takes pi_lock in freed memory.

Hold rcu across the loop.

Fixes: a94e2d408eae ("coredump: kill mm->core_done")
Cc: stable@vger.kernel.org
Acked-by: Oleg Nesterov <oleg@redhat.com>
Link: https://patch.msgid.link/20260921-work-coredump-fixes-v3-1-8e4adb1619e6@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 fs/coredump.c |    3 +++
 1 file changed, 3 insertions(+)

--- a/fs/coredump.c
+++ b/fs/coredump.c
@@ -474,6 +474,8 @@ static void coredump_finish(bool core_du
 	current->signal->core_state = NULL;
 	spin_unlock_irq(&current->sighand->siglock);
 
+	/* A released thread may exit and be freed before it is woken. */
+	guard(rcu)();
 	while ((curr = next) != NULL) {
 		next = curr->next;
 		task = curr->task;
@@ -482,6 +484,7 @@ static void coredump_finish(bool core_du
 		 * ->task == NULL before we read ->next.
 		 */
 		smp_mb();
+		/* Any wakeup now lets the thread exit, rcu keeps it alive. */
 		curr->task = NULL;
 		wake_up_process(task);
 	}



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 241/247] signal: only SIGKILL and the freezers interrupt a coredumping task
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (239 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 240/247] coredump: hold RCU while releasing parked threads Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 242/247] signal: dont retarget shared signals in a dying thread group Greg Kroah-Hartman
                   ` (13 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Oleg Nesterov,
	Christian Brauner (Amutable)

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Christian Brauner <brauner@kernel.org>

commit 563d606b93d7a1d23512832fc252d32c68860d87 upstream.

For quite a while now coredump has allowed either SIGKILL or freezing to
interrupt an ongoing coredump. Since we seem to like it complicated
"freezing" can mean a lot of things:

(1) Power Management induced freezing
(2) cgroup v1 freezer controller induced freezing
(3) cgroup v2 freezer controller induced freezing

So (1) and (2) are handled by checking freezing() but (3) isn't.
(3) uses cgroup_freeze_task() which sets JOBCTL_TRAP_FREEZE and calls
signal_wake_up() on every task in the cgroup. The trap isn't handled by
the coredump code.

Which means the current logic is inconsistent. Power and cgroup v1
freeze and abort the coredump. With cgroup v2 it depends on where the
core goes. A dump to a file completes and the cgroup v2 freeze has to
wait for it to finish. When dumping to a pipe or socket the dump is
interrupted at the next write because of trap's TIF_SIGPENDING. Which is
it? Let's be consistent and align (1)-(3): freezing interrupts an
ongoing coredump and doesn't make it wait until the dump is done.

All three freezers go through signal_wake_up() and so set
TIF_SIGPENDING on the dumper. And once zap_threads() has set core_state
that flag can't mean anything else anymore. prepare_signal() drops every
signal but SIGKILL for the group, the dying threads don't retarget
shared signals to the dumper, and zap_process() cleared the pending job
control traps. So the flag is the thing to check. Let dump_interrupted()
test task_sigpending() and nothing else. That is also what the pipe and
socket writes already fail on. TIF_NOTIFY_SIGNAL is left out on
purpose, task work must not cut a dump short.

A seized tracee that gets PTRACE_INTERRUPT during the dump is cut short
the same way. It already was for pipes and sockets.

The one freeze that check can miss is one requested before the dump
started. zap_threads() clears TIF_SIGPENDING and the cgroup v2 freezer
only wakes a task once while its JOBCTL_TRAP_FREEZE isn't part of
JOBCTL_PENDING_MASK and survives zap_process(). So refuse to start the
dump when freezing() is true or the trap is pending. The task then exits
without dumping, which is what happens today when the freeze interrupts
the dump at the first write.

Fixes: 403bad72b67d ("coredump: only SIGKILL should interrupt the coredumping task")
Fixes: 76f969e8948d ("cgroup: cgroup v2 freezer")
Cc: stable@vger.kernel.org
Suggested-by: Oleg Nesterov <oleg@redhat.com>
Link: https://lore.kernel.org/r/arJ6zZuI59BJnXpl@redhat.com
Link: https://patch.msgid.link/20260921-work-coredump-fixes-v3-2-8e4adb1619e6@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 fs/coredump.c |   13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

--- a/fs/coredump.c
+++ b/fs/coredump.c
@@ -420,7 +420,9 @@ static int zap_threads(struct task_struc
 	int nr = -EAGAIN;
 
 	spin_lock_irq(&tsk->sighand->siglock);
-	if (!(signal->flags & SIGNAL_GROUP_EXIT) && !signal->group_exec_task) {
+	/* A freeze requested before the dump would be lost with TIF_SIGPENDING. */
+	if (!(signal->flags & SIGNAL_GROUP_EXIT) && !signal->group_exec_task &&
+	    !freezing(tsk) && !(tsk->jobctl & JOBCTL_TRAP_FREEZE)) {
 		/* Allow SIGKILL, see prepare_signal() */
 		signal->core_state = core_state;
 		nr = zap_process(signal, exit_code);
@@ -492,13 +494,8 @@ static void coredump_finish(bool core_du
 
 static bool dump_interrupted(void)
 {
-	/*
-	 * SIGKILL or freezing() interrupt the coredumping. Perhaps we
-	 * can do try_to_freeze() and check __fatal_signal_pending(),
-	 * but then we need to teach dump_write() to restart and clear
-	 * TIF_SIGPENDING.
-	 */
-	return fatal_signal_pending(current) || freezing(current);
+	/* Only SIGKILL and the freezers set it after zap_threads(). */
+	return task_sigpending(current);
 }
 
 static void wait_for_dump_helpers(struct file *file)



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 242/247] signal: dont retarget shared signals in a dying thread group
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (240 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 241/247] signal: only SIGKILL and the freezers interrupt a coredumping task Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 243/247] ptrace: refuse to change the signal mask of a user worker Greg Kroah-Hartman
                   ` (12 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Oleg Nesterov,
	Christian Brauner (Amutable)

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Christian Brauner <brauner@kernel.org>

commit c0e659511d4f49087da095a95799edb5b775a705 upstream.

If the calling thread has blocked a signal then
retarget_shared_pending() slingshots a shared pending signal to a
sibling thread. Today it only skips PF_EXITING threads but not a
coredumping thread.

But if SIGNAL_GROUP_EXIT is set no thread in the thread-group can
dequeue such signals anymore as get_signal() sends SIGKILL to every
thread and prepare_signal() drops any other signal.

exit_signals() also returns early on SIGNAL_GROUP_EXIT. But neither
sigprocmask() nor the mask restore in sigtimedwait() do.

Say a thread sleeps in sigtimedwait() and a sibling thread crashes. The
sleeping thread gets woken by the zap call. It restores its mask on the
way out and retargets a signal that was queued for the coredumping
process. That means TIF_SIGPENDING is set on the coredumping task which
zap_threads() had cleared. So a blocking write sees TIF_SIGPENDING and
truncates the dump.

Stop retargeting signals when SIGNAL_GROUP_EXIT is set and avoid
needlessly truncating coredumps.

Fixes: e6fa16ab9c1e ("signal: sigprocmask() should do retarget_shared_pending()")
Cc: stable@vger.kernel.org
Acked-by: Oleg Nesterov <oleg@redhat.com>
Link: https://patch.msgid.link/20260921-work-coredump-fixes-v3-5-8e4adb1619e6@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 kernel/signal.c |    4 ++++
 1 file changed, 4 insertions(+)

--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -2999,6 +2999,10 @@ static void retarget_shared_pending(stru
 	sigset_t retarget;
 	struct task_struct *t;
 
+	/* Nobody dequeues them in a dying group, see get_signal(). */
+	if (tsk->signal->flags & SIGNAL_GROUP_EXIT)
+		return;
+
 	sigandsets(&retarget, &tsk->signal->shared_pending.signal, which);
 	if (sigisemptyset(&retarget))
 		return;



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 243/247] ptrace: refuse to change the signal mask of a user worker
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (241 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 242/247] signal: dont retarget shared signals in a dying thread group Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 244/247] fork: release the files of a failed fork after sched_cancel_fork() Greg Kroah-Hartman
                   ` (11 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Oleg Nesterov,
	Christian Brauner (Amutable)

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Christian Brauner <brauner@kernel.org>

commit cabc249e6560bee7bdfee9fbcb7ce4e951dcfd41 upstream.

A user worker is created with every signal other than SIGKILL and
SIGSTOP blocked. It never runs user code and that mask is what keeps
get_signal() from dequeuing anything else for it. complete_signal()
never picks a thread that blocks the signal, tkill() queues on the
worker but nothing dequeues it. ptrace_signal() requeues an injected
signal that the tracee blocks.

PTRACE_SETSIGMASK is the only way to change that mask from the outside.
A tracer that clears it makes the worker eligible for every signal.
Whatever the worker then dequeues it can only act on by leaving.

Refuse PTRACE_SETSIGMASK for a user worker with -EPERM, the way
ptrace_attach() refuses a kernel thread. A worker is guaranteed to only
ever dequeue SIGKILL or SIGSTOP and an injected signal stays pending on
it, which is what already happens when the mask isn't touched.

Taking the request and quietly leaving the mask alone was the other
option, the way set_current_blocked() keeps SIGKILL and SIGSTOP
unblocked whatever userspace asks for. But then a tracer gets success
back with nothing changed and no way to tell that apart from a mask that
took effect.

Fixes: e8b33b8cfafc ("Revert "kernel: treat PF_IO_WORKER like PF_KTHREAD for ptrace/signals"")
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20260921-work-coredump-fixes-v3-9-8e4adb1619e6@kernel.org
Acked-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 kernel/ptrace.c |    6 ++++++
 1 file changed, 6 insertions(+)

--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -1086,6 +1086,12 @@ int ptrace_request(struct task_struct *c
 	case PTRACE_SETSIGMASK: {
 		sigset_t new_set;
 
+		/* A user worker only ever takes SIGKILL and SIGSTOP. */
+		if (child->flags & PF_USER_WORKER) {
+			ret = -EPERM;
+			break;
+		}
+
 		if (addr != sizeof(sigset_t)) {
 			ret = -EINVAL;
 			break;



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 244/247] fork: release the files of a failed fork after sched_cancel_fork()
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (242 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 243/247] ptrace: refuse to change the signal mask of a user worker Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 245/247] pid_namespace: prevent TIF_NOTIFY_SIGNAL from interrupting the reaper Greg Kroah-Hartman
                   ` (10 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Chris Mason,
	Christian Brauner (Amutable)

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Christian Brauner <brauner@kernel.org>

commit 296a98c1fa50778c3b31eebed1a3f903f9684349 upstream.

Reorder copy_process() cleanup so sched_fork() taking scx_fork_rwsem
scx_pre_fork() is safe and isn't held around exiting files. Right now, a
fork that fails while another thread closed the bpf link fd will
deadlock against its own read side. It also blocks every fork on the
system:

    copy_process()                  holds scx_fork_rwsem for read
      exit_files()
        close_files()
          filp_close_sync()
            bpf_scx_unreg()
              kthread_flush_work()  waits for the disable work
                scx_root_disable()
                  percpu_down_write(&scx_fork_rwsem)

Simply release the child's files after sched_cancel_fork() dropped the
lock. The task starts out as a copy of its parent so p->files points to
the parent's table until copy_files() replaces it. exit_files() must not
run for a fork that failed before that. Clear p->files up front so
exit_files() is a no-op for those and make copy_files() set it
explicitly for CLONE_FILES.

Reported-by: Chris Mason <mason@kernel.org>
Link: https://patch.msgid.link/20260921-work-coredump-fixes-v3-7-8e4adb1619e6@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 kernel/fork.c |    9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1814,6 +1814,7 @@ static int copy_files(unsigned long clon
 
 	if (clone_flags & CLONE_FILES) {
 		atomic_inc(&oldf->count);
+		tsk->files = oldf;
 		return 0;
 	}
 
@@ -2305,6 +2306,8 @@ __latent_entropy struct task_struct *cop
 	INIT_LIST_HEAD(&p->sibling);
 	rcu_copy_process(p);
 	p->vfork_done = NULL;
+	/* Set by copy_files(), exit_files() on the error path skips NULL. */
+	p->files = NULL;
 	spin_lock_init(&p->alloc_lock);
 
 	init_sigpending(&p->pending);
@@ -2402,7 +2405,7 @@ __latent_entropy struct task_struct *cop
 		goto bad_fork_cleanup_semundo;
 	retval = copy_fs(clone_flags, p);
 	if (retval)
-		goto bad_fork_cleanup_files;
+		goto bad_fork_cleanup_semundo;
 	retval = copy_sighand(clone_flags, p);
 	if (retval)
 		goto bad_fork_cleanup_fs;
@@ -2681,8 +2684,6 @@ bad_fork_cleanup_sighand:
 	__cleanup_sighand(p->sighand);
 bad_fork_cleanup_fs:
 	exit_fs(p); /* blocking */
-bad_fork_cleanup_files:
-	exit_files(p); /* blocking */
 bad_fork_cleanup_semundo:
 	exit_sem(p);
 bad_fork_cleanup_security:
@@ -2693,6 +2694,8 @@ bad_fork_cleanup_perf:
 	perf_event_free_task(p);
 bad_fork_sched_cancel_fork:
 	sched_cancel_fork(p);
+	/* ->release() of a file may need scx_fork_rwsem for write. */
+	exit_files(p); /* blocking */
 bad_fork_cleanup_policy:
 	lockdep_free_task(p);
 #ifdef CONFIG_NUMA



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 245/247] pid_namespace: prevent TIF_NOTIFY_SIGNAL from interrupting the reaper
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (243 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 244/247] fork: release the files of a failed fork after sched_cancel_fork() Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 246/247] signal: allow taks to temporarily block TIF_NOTIFY_SIGNAL Greg Kroah-Hartman
                   ` (9 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Oleg Nesterov,
	Christian Brauner (Amutable)

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Christian Brauner <brauner@kernel.org>

commit 5c0985dd3c32fc2bbd0e8beaf13cf52cd97376a2 upstream.

Since commit 7fea700e04bd ("zap_pid_ns_processes: clear
TIF_NOTIFY_SIGNAL along with TIF_SIGPENDING") zap_pid_ns_processes()
clears TIF_NOTIFY_SIGNAL before every kernel_wait4() call. Otherwise
kernel_wait4() doesn't sleep and returns -ERESTARTSYS if
signal_pending() is true and the reaper busy-waits.

But clearing TIF_NOTIFY_SIGNAL doesn't fix it. It can get raised again.
For example, klp_send_signals() sets it raw against any task that hasn't
transitioned yet. And it keeps sending it until the livepatch finishes.

The sleep loop waiting for pid_allocated to drop has the same problem
and it doesn't even clear anything. So a schedule() in
TASK_INTERRUPTIBLE returns immediately.

Use a no_notify_signal guard. signal_pending() will ignore
TIF_NOTIFY_SIGNAL and the pid namespace reaper sleeps until a child
exits or free_pid() wakes it.

Link: https://patch.msgid.link/20260824-work-tif_notify_signal-v2-5-6609e42b3157@kernel.org
Fixes: 7fea700e04bd ("zap_pid_ns_processes: clear TIF_NOTIFY_SIGNAL along with TIF_SIGPENDING")
Reviewed-by: Oleg Nesterov <oleg@redhat.com>
Cc: stable@vger.kernel.org
Suggested-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 kernel/pid_namespace.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

--- a/kernel/pid_namespace.c
+++ b/kernel/pid_namespace.c
@@ -216,9 +216,10 @@ void zap_pid_ns_processes(struct pid_nam
 	 * kernel_wait4() will also block until our children traced from the
 	 * parent namespace are detached and become EXIT_DEAD.
 	 */
+	/* Task work must not busy-loop the reaper, see signal_pending(). */
+	guard(no_notify_signal)();
 	do {
 		clear_thread_flag(TIF_SIGPENDING);
-		clear_thread_flag(TIF_NOTIFY_SIGNAL);
 		rc = kernel_wait4(-1, NULL, __WALL, NULL);
 	} while (rc != -ECHILD);
 



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 246/247] signal: allow taks to temporarily block TIF_NOTIFY_SIGNAL
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (244 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 245/247] pid_namespace: prevent TIF_NOTIFY_SIGNAL from interrupting the reaper Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 17:00 ` [PATCH 6.12 247/247] fanotify: Fix crash in fanotify_init(2) Greg Kroah-Hartman
                   ` (8 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable
  Cc: Greg Kroah-Hartman, patches, Oleg Nesterov,
	Christian Brauner (Amutable)

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Christian Brauner <brauner@kernel.org>

commit 22b7f491be8f93ff72de0a3fe02b8ee9e64d3f21 upstream.

TIF_NOTIFY_SIGNAL is used to kick a task in uninterruptible sleep to
return to userspace and run task work and then go back to sleep. This
mechanism works well but breaks e.g., coredumps. dump_interrupted() only
allows fatal signals to interrupt a coredump and the whole regular write
path going to actual filesystems is impervious to TIF_NOTIFY_SIGNAL as
well.

Add PF_NO_NOTIFY_SIGNAL and helpers to raise and restore it. This is the
same approach as memalloc_nofs_save(). signal_pending() will not report
a fake pending signal via TIF_NOTIFY_SIGNAL if inside a
PF_NO_NOTIFY_SIGNAL section.

No functional changes.

Link: https://patch.msgid.link/20260824-work-tif_notify_signal-v2-1-6609e42b3157@kernel.org
Reviewed-by: Oleg Nesterov <oleg@redhat.com>
Cc: stable@vger.kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 include/linux/sched.h        |    2 +-
 include/linux/sched/signal.h |   27 +++++++++++++++++++++++++--
 2 files changed, 26 insertions(+), 3 deletions(-)

--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1712,7 +1712,7 @@ extern struct pid __rcu *cad_pid;
 						 * I am cleaning dirty pages from some other bdi. */
 #define PF_KTHREAD		0x00200000	/* I am a kernel thread */
 #define PF_RANDOMIZE		0x00400000	/* Randomize virtual address space */
-#define PF__HOLE__00800000	0x00800000
+#define PF_NO_NOTIFY_SIGNAL	0x00800000	/* see no_notify_signal_save() */
 #define PF__HOLE__01000000	0x01000000
 #define PF__HOLE__02000000	0x02000000
 #define PF_NO_SETAFFINITY	0x04000000	/* Userland is not allowed to meddle with cpus_mask */
--- a/include/linux/sched/signal.h
+++ b/include/linux/sched/signal.h
@@ -2,6 +2,7 @@
 #ifndef _LINUX_SCHED_SIGNAL_H
 #define _LINUX_SCHED_SIGNAL_H
 
+#include <linux/cleanup.h>
 #include <linux/rculist.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
@@ -380,14 +381,36 @@ static inline int task_sigpending(struct
 	return unlikely(test_tsk_thread_flag(p,TIF_SIGPENDING));
 }
 
+/* Prevent TIF_NOTIFY_SIGNAL from interrupting this task. */
+static inline unsigned int no_notify_signal_save(void)
+{
+	unsigned int flags = current->flags;
+
+	current->flags |= PF_NO_NOTIFY_SIGNAL;
+	return flags;
+}
+
+/* Restore the previous PF_NO_NOTIFY_SIGNAL state. */
+static inline void no_notify_signal_restore(unsigned int flags)
+{
+	current_restore_flags(flags, PF_NO_NOTIFY_SIGNAL);
+}
+
+DEFINE_LOCK_GUARD_0(no_notify_signal,
+		    _T->flags = no_notify_signal_save(),
+		    no_notify_signal_restore(_T->flags),
+		    unsigned int flags)
+
 static inline int signal_pending(struct task_struct *p)
 {
 	/*
 	 * TIF_NOTIFY_SIGNAL isn't really a signal, but it requires the same
 	 * behavior in terms of ensuring that we break out of wait loops
-	 * so that notify signal callbacks can be processed.
+	 * so that notify signal callbacks can be processed. Not for a task
+	 * that asked not to be interrupted by it, see no_notify_signal_save().
 	 */
-	if (unlikely(test_tsk_thread_flag(p, TIF_NOTIFY_SIGNAL)))
+	if (unlikely(test_tsk_thread_flag(p, TIF_NOTIFY_SIGNAL)) &&
+	    likely(!(READ_ONCE(p->flags) & PF_NO_NOTIFY_SIGNAL)))
 		return 1;
 	return task_sigpending(p);
 }



^ permalink raw reply	[flat|nested] 259+ messages in thread

* [PATCH 6.12 247/247] fanotify: Fix crash in fanotify_init(2)
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (245 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 246/247] signal: allow taks to temporarily block TIF_NOTIFY_SIGNAL Greg Kroah-Hartman
@ 2026-10-28 17:00 ` Greg Kroah-Hartman
  2026-10-28 19:39 ` [PATCH 6.12 000/247] 6.12.115-rc1 review Brett A C Sheffield
                   ` (7 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-28 17:00 UTC (permalink / raw)
  To: stable; +Cc: Greg Kroah-Hartman, patches, syzbot+6a3aa63412255587b21b,
	Jan Kara

6.12-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Jan Kara <jack@suse.cz>

commit 0c0214df28f0dba8de084cb4dedc0c459dfbc083 upstream.

The rrror handling in fanotify_init(2) is buggy and overwrites 'fd'
before calling put_unused_fd() leading to possible access beyond the end
of fd bitmap. Fix it.

Reported-by: syzbot+6a3aa63412255587b21b@syzkaller.appspotmail.com
Fixes: ebe559609d78 ("fs: get rid of __FMODE_NONOTIFY kludge")
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 fs/notify/fanotify/fanotify_user.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -1552,8 +1552,8 @@ SYSCALL_DEFINE2(fanotify_init, unsigned
 	file = anon_inode_getfile_fmode("[fanotify]", &fanotify_fops, group,
 					f_flags, FMODE_NONOTIFY);
 	if (IS_ERR(file)) {
-		fd = PTR_ERR(file);
 		put_unused_fd(fd);
+		fd = PTR_ERR(file);
 		goto out_destroy_group;
 	}
 	fd_install(fd, file);



^ permalink raw reply	[flat|nested] 259+ messages in thread

* Re: [PATCH 6.12 122/247] fs: get rid of __FMODE_NONOTIFY kludge
  2026-10-28 16:58 ` [PATCH 6.12 122/247] fs: get rid of __FMODE_NONOTIFY kludge Greg Kroah-Hartman
@ 2026-10-28 17:56   ` Amir Goldstein
  2026-10-29  2:53     ` Sasha Levin
  0 siblings, 1 reply; 259+ messages in thread
From: Amir Goldstein @ 2026-10-28 17:56 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: stable, patches, Al Viro, Jan Kara, Guenter Roeck, Edvard Conrad

On Wed, Oct 28, 2026 at 7:15 PM Greg Kroah-Hartman
<gregkh@linuxfoundation.org> wrote:
>
> 6.12-stable review patch.  If anyone has any objections, please let me know.

Objection.

This causes a (potential) deadlock regression:

https://lore.kernel.org/linux-unionfs/P4sl5iz--F-9@tuta.io/

Working on a fix, but no reason to backport a commit, which is essentially
code cleanup that causes a regression.

Not sure if this already hit other LTS kernels.

Thanks,
Amir.

^ permalink raw reply	[flat|nested] 259+ messages in thread

* Re: [PATCH 6.12 000/247] 6.12.115-rc1 review
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (246 preceding siblings ...)
  2026-10-28 17:00 ` [PATCH 6.12 247/247] fanotify: Fix crash in fanotify_init(2) Greg Kroah-Hartman
@ 2026-10-28 19:39 ` Brett A C Sheffield
  2026-10-28 23:30 ` Florian Fainelli
                   ` (6 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Brett A C Sheffield @ 2026-10-28 19:39 UTC (permalink / raw)
  To: gregkh
  Cc: stable, patches, linux-kernel, torvalds, akpm, linux, shuah,
	patches, lkft-triage, pavel, jonathanh, f.fainelli,
	sudipm.mukherjee, rwarsow, conor, hargar, broonie, achill, sr,
	Brett A C Sheffield

# Librecast Test Results

044/044 [ OK ] liblcrq
010/010 [ OK ] libmld
120/120 [ OK ] liblibrecast

CPU/kernel: Linux auntie 6.12.115-rc1-gadc8e434cf08 #1 SMP PREEMPT_DYNAMIC Wed Oct 28 17:52:53 -00 2026 x86_64 AMD Ryzen 9 9950X 16-Core Processor AuthenticAMD GNU/Linux

Tested-by: Brett A C Sheffield <bacs@librecast.net>

^ permalink raw reply	[flat|nested] 259+ messages in thread

* Re: [PATCH 6.12 000/247] 6.12.115-rc1 review
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (247 preceding siblings ...)
  2026-10-28 19:39 ` [PATCH 6.12 000/247] 6.12.115-rc1 review Brett A C Sheffield
@ 2026-10-28 23:30 ` Florian Fainelli
  2026-10-29  2:15 ` Peter Schneider
                   ` (5 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Florian Fainelli @ 2026-10-28 23:30 UTC (permalink / raw)
  To: Greg Kroah-Hartman, stable
  Cc: patches, linux-kernel, torvalds, akpm, linux, shuah, patches,
	lkft-triage, pavel, jonathanh, sudipm.mukherjee, rwarsow, conor,
	hargar, broonie, achill, sr

On 10/28/26 09:56, Greg Kroah-Hartman wrote:
> This is the start of the stable review cycle for the 6.12.115 release.
> There are 247 patches in this series, all will be posted as a response
> to this one.  If anyone has any issues with these being applied, please
> let me know.
> 
> Responses should be made by Fri, 30 Oct 2026 16:59:22 +0000.
> Anything received after that time might be too late.
> 
> The whole patch series can be found in one patch at:
> 	https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.12.115-rc1.gz
> or in the git tree and branch at:
> 	git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-6.12.y
> and the diffstat can be found below.
> 
> thanks,
> 
> greg k-h

On ARCH_BRCMSTB using 32-bit and 64-bit ARM kernels, build tested on 
BMIPS_GENERIC:

Tested-by: Florian Fainelli <florian.fainelli@broadcom.com>
-- 
Florian

^ permalink raw reply	[flat|nested] 259+ messages in thread

* Re: [PATCH 6.12 000/247] 6.12.115-rc1 review
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (248 preceding siblings ...)
  2026-10-28 23:30 ` Florian Fainelli
@ 2026-10-29  2:15 ` Peter Schneider
  2026-10-29  9:20 ` Dominique Martinet
                   ` (4 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Peter Schneider @ 2026-10-29  2:15 UTC (permalink / raw)
  To: Greg Kroah-Hartman, stable
  Cc: patches, linux-kernel, torvalds, akpm, linux, shuah, patches,
	lkft-triage, pavel, jonathanh, f.fainelli, sudipm.mukherjee,
	rwarsow, conor, hargar, broonie, achill, sr

Am 28.10.2026 um 17:56 schrieb Greg Kroah-Hartman:
> This is the start of the stable review cycle for the 6.12.115 release.
> There are 247 patches in this series, all will be posted as a response
> to this one.  If anyone has any issues with these being applied, please
> let me know.

Builds, boots and works on my 2-socket Ivy Bridge Xeon E5-2697v2 server. No dmesg oddities or regressions found.

Tested-by: Peter Schneider <pschneider1968@googlemail.com>


Beste Grüße,
Peter Schneider

-- 
Climb the mountain not to plant your flag, but to embrace the challenge,
enjoy the air and behold the view. Climb it so you can see the world,
not so the world can see you.                    -- David McCullough Jr.

OpenPGP:  0xA3828BD796CCE11A8CADE8866E3A92C92C3FF244
Download: https://www.peters-netzplatz.de/download/pschneider1968_pub.asc
https://keys.mailvelope.com/pks/lookup?op=get&search=pschneider1968@googlemail.com
https://keys.mailvelope.com/pks/lookup?op=get&search=pschneider1968@gmail.com

^ permalink raw reply	[flat|nested] 259+ messages in thread

* Re: [PATCH 6.12 122/247] fs: get rid of __FMODE_NONOTIFY kludge
  2026-10-28 17:56   ` Amir Goldstein
@ 2026-10-29  2:53     ` Sasha Levin
  0 siblings, 0 replies; 259+ messages in thread
From: Sasha Levin @ 2026-10-29  2:53 UTC (permalink / raw)
  To: Amir Goldstein
  Cc: Sasha Levin, Greg Kroah-Hartman, stable, patches, Al Viro,
	Jan Kara, Guenter Roeck, Edvard Conrad

On Wed, Oct 28, 2026 at 7:56 PM Amir Goldstein wrote:
> Objection.
>
> This causes a (potential) deadlock regression:
>
> https://lore.kernel.org/linux-unionfs/P4sl5iz--F-9@tuta.io/

Dropped from the 6.12 queue, together with its follow-up "fanotify: Fix
crash in fanotify_init(2)", which does not apply without it.

For context, it had been queued only to fix the sparc 6.12.y build
(fcntl_init() BUILD_BUG_ON) that came from the 6.12 backport of
"fsnotify: opt-in for permission events at file open time". We will
revisit it together with Edvard's fix once that is in mainline.

> Not sure if this already hit other LTS kernels.

6.18.y, 7.2.y and 7.3.y already carry it via mainline (v6.14), so they
will need the upstream fix. 6.6.y and older do not have it.

-- 
Thanks,
Sasha

^ permalink raw reply	[flat|nested] 259+ messages in thread

* Re: [PATCH 6.12 000/247] 6.12.115-rc1 review
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (249 preceding siblings ...)
  2026-10-29  2:15 ` Peter Schneider
@ 2026-10-29  9:20 ` Dominique Martinet
  2026-10-29 10:05 ` Pavel Machek
                   ` (3 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Dominique Martinet @ 2026-10-29  9:20 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: stable, patches, linux-kernel, torvalds, akpm, linux, shuah,
	patches, lkft-triage, pavel, jonathanh, f.fainelli,
	sudipm.mukherjee, rwarsow, conor, hargar, broonie, achill, sr

Greg Kroah-Hartman wrote on Wed, Oct 28, 2026 at 05:56:43PM +0100:
> This is the start of the stable review cycle for the 6.12.115 release.
> There are 247 patches in this series, all will be posted as a response
> to this one.  If anyone has any issues with these being applied, please
> let me know.
> 
> Responses should be made by Fri, 30 Oct 2026 16:59:22 +0000.
> Anything received after that time might be too late.
> 
> The whole patch series can be found in one patch at:
> 	https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.12.115-rc1.gz
> or in the git tree and branch at:
> 	git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-6.12.y
> and the diffstat can be found below.

Tested adc8e434cf08 ("Linux 6.12.115-rc1") on:
- arm i.MX6ULL (Armadillo 640)
- arm64 i.MX8MP (Armadillo G4)
- arm64 i.MX8ULP (Armadillo IoT A9E)

No obvious regression in dmesg or basic tests:
Tested-by: Dominique Martinet <dominique.martinet@atmark-techno.com>
-- 
Dominique Martinett

^ permalink raw reply	[flat|nested] 259+ messages in thread

* Re: [PATCH 6.12 000/247] 6.12.115-rc1 review
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (250 preceding siblings ...)
  2026-10-29  9:20 ` Dominique Martinet
@ 2026-10-29 10:05 ` Pavel Machek
  2026-10-29 10:24 ` Pavel Machek
                   ` (2 subsequent siblings)
  254 siblings, 0 replies; 259+ messages in thread
From: Pavel Machek @ 2026-10-29 10:05 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: stable, patches, linux-kernel, torvalds, akpm, linux, shuah,
	patches, lkft-triage, pavel, jonathanh, f.fainelli,
	sudipm.mukherjee, rwarsow, conor, hargar, broonie, achill, sr

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

Hi!

> This is the start of the stable review cycle for the 6.12.115 release.
> There are 247 patches in this series, all will be posted as a response
> to this one.  If anyone has any issues with these being applied, please
> let me know.

CIP testing did not find any problems here:

https://gitlab.com/cip-project/cip-testing/linux-stable-rc-ci/-/tree/linux-6.12.y

Tested-by: Pavel Machek (CIP) <pavel@nabladev.com>

Best regards,
                                                                Pavel

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

^ permalink raw reply	[flat|nested] 259+ messages in thread

* Re: [PATCH 6.12 000/247] 6.12.115-rc1 review
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (251 preceding siblings ...)
  2026-10-29 10:05 ` Pavel Machek
@ 2026-10-29 10:24 ` Pavel Machek
  2026-10-29 12:30   ` Greg Kroah-Hartman
  2026-10-29 13:40 ` Miguel Ojeda
  2026-10-29 14:28 ` Ron Economos
  254 siblings, 1 reply; 259+ messages in thread
From: Pavel Machek @ 2026-10-29 10:24 UTC (permalink / raw)
  To: Greg Kroah-Hartman, bernard.f6bvp
  Cc: stable, patches, linux-kernel, torvalds, akpm, linux, shuah,
	patches, lkft-triage, pavel, jonathanh, f.fainelli,
	sudipm.mukherjee, rwarsow, conor, hargar, broonie, achill, sr

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

Hi!

> This is the start of the stable review cycle for the 6.12.115 release.
> There are 247 patches in this series, all will be posted as a response
> to this one.  If anyone has any issues with these being applied, please
> let me know.

What is up with these?

They don't have usual "Commit upstream XXX" markings. They do have
commit ids in the sign-off area (which is a logical place), except
that those hashes don't exist in mainline.

Best regards,
								Pavel

    Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
    
    (cherry picked from commit 741a4863ad570889c75f7a8e404567d8f3e46335)
    Signed-off-by: Sasha Levin <sashal@kernel.org>



> Bernard Pidoux <bernard.f6bvp@gmail.com>
>     rose: purge rose_neigh->queue on final teardown
> 
> Bernard Pidoux <bernard.f6bvp@gmail.com>
>     ax25: bound REJ-driven fast retransmits with the existing N2 counter
> 
> Bernard Pidoux <bernard.f6bvp@gmail.com>
>     rose: hold a reference on incoming sockets queued for accept()
> 
> Bernard Pidoux <bernard.f6bvp@gmail.com>
>     rose: don't warn on stray CALL_ACCEPTED/CLEAR_CONFIRMATION in state 3
> 
> Bernard Pidoux <bernard.f6bvp@gmail.com>
>     rose: use timer_shutdown_sync() for t0timer teardown
> 
> Bernard Pidoux <bernard.f6bvp@gmail.com>
>     rose: guard rose_transmit_link() against a NULL neighbour
> 
> Bernard Pidoux <bernard.f6bvp@gmail.com>
>     rose: keep the route needed for routing loop detection
> 
> Bernard Pidoux <bernard.f6bvp@gmail.com>
>     rose: don't free fd-owned sockets when reaping in the heartbeat
> 
> Bernard Pidoux <bernard.f6bvp@gmail.com>
>     rose: clear neighbour pointer in rose_kill_by_device()
> 
> Bernard Pidoux <bernard.f6bvp@gmail.com>
>     rose: release netdev ref and destroy orphaned incoming sockets
> 
> Bernard Pidoux <bernard.f6bvp@gmail.com>
>     rose: disconnect orphaned STATE_2 sockets when device is gone
> 
> Bernard Pidoux <bernard.f6bvp@gmail.com>
>     rose: set SOCK_DESTROY in rose_kill_by_device() for prompt cleanup
> 
> 
> -------------
> 
> Diffstat:
> 
>  Makefile                                           |   4 +-
>  arch/nios2/include/asm/checksum.h                  |   2 +-
>  arch/s390/mm/fault.c                               |  11 +-
>  arch/s390/pci/pci_sysfs.c                          |   3 +
>  arch/x86/hyperv/hv_init.c                          |   3 +-
>  arch/x86/kernel/kvm.c                              |  32 +-
>  arch/x86/kvm/mmu/mmu.c                             |   4 +-
>  arch/x86/kvm/vmx/nested.c                          |   4 +-
>  block/blk-zoned.c                                  |  37 +-
>  block/blk.h                                        |   4 +-
>  block/bsg-lib.c                                    |  13 +-
>  block/genhd.c                                      |   2 +-
>  crypto/asymmetric_keys/restrict.c                  |   8 +-
>  drivers/base/regmap/internal.h                     |   1 +
>  drivers/base/regmap/regcache-maple.c               |   9 +-
>  drivers/base/regmap/regcache.c                     |  18 +-
>  drivers/gpio/gpio-mxc.c                            |  69 ++--
>  drivers/gpio/gpiolib.c                             |   9 +-
>  drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c             |   6 +
>  drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c        |  23 +-
>  drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c             |  25 +-
>  drivers/gpu/drm/amd/amdgpu/vce_v3_0.c              |   2 +-
>  drivers/gpu/drm/drm_exec.c                         |  77 +++--
>  drivers/gpu/drm/i915/display/intel_dmc.c           |  21 +-
>  drivers/gpu/drm/vc4/vc4_hdmi.c                     |  20 +-
>  drivers/gpu/drm/xe/xe_exec.c                       |   7 +-
>  drivers/gpu/drm/xe/xe_vm.c                         |  31 +-
>  drivers/gpu/drm/xe/xe_vm.h                         |   2 +
>  drivers/hv/channel_mgmt.c                          |  12 +-
>  drivers/hv/connection.c                            |   1 -
>  drivers/hv/vmbus_drv.c                             |   1 -
>  drivers/i2c/busses/i2c-qcom-cci.c                  |   4 +-
>  drivers/i2c/busses/i2c-viai2c-wmt.c                |  22 +-
>  drivers/md/dm-cache-target.c                       |  59 ++--
>  drivers/md/dm-crypt.c                              |   3 +-
>  drivers/md/dm-ebs-target.c                         |   3 +-
>  drivers/md/dm-integrity.c                          |   6 +-
>  drivers/net/ethernet/broadcom/genet/bcmgenet.c     |  10 +
>  drivers/net/wireless/intersil/p54/fwio.c           |  42 ++-
>  drivers/pci/pci.c                                  |  15 +-
>  drivers/pinctrl/pinctrl-amd.c                      |   9 +
>  drivers/pinctrl/qcom/pinctrl-ipq5018.c             |  10 +-
>  drivers/power/supply/ds2780_battery.c              |   2 +-
>  drivers/power/supply/generic-adc-battery.c         |   9 +-
>  drivers/s390/net/ctcm_mpc.c                        |   3 +-
>  drivers/scsi/libiscsi.c                            |  14 +-
>  drivers/scsi/libsas/sas_expander.c                 |  14 +-
>  drivers/scsi/mpi3mr/mpi3mr_app.c                   |   2 +-
>  drivers/scsi/scsi_transport_fc.c                   |   6 +-
>  drivers/scsi/scsi_transport_iscsi.c                |   2 +-
>  drivers/scsi/scsi_transport_sas.c                  |   6 +-
>  drivers/scsi/st.c                                  |  18 +-
>  drivers/scsi/xen-scsifront.c                       |   1 +
>  drivers/soc/tegra/fuse/tegra-apbmisc.c             |   2 +-
>  drivers/spi/spi-tegra114.c                         |   7 +
>  drivers/target/iscsi/iscsi_target_configfs.c       |  26 +-
>  drivers/ufs/core/ufs_bsg.c                         |   2 +-
>  fs/afs/internal.h                                  |   2 +
>  fs/afs/super.c                                     |   2 +-
>  fs/autofs/waitq.c                                  |  25 +-
>  fs/coredump.c                                      |  16 +-
>  fs/ext4/ext4.h                                     |   2 +
>  fs/ext4/extents_status.c                           |   7 +-
>  fs/ext4/extents_status.h                           |   1 +
>  fs/ext4/super.c                                    |  13 +-
>  fs/fat/dir.c                                       |  44 ++-
>  fs/fcntl.c                                         |   4 +-
>  fs/namei.c                                         |   3 +-
>  fs/notify/fanotify/fanotify_user.c                 |  25 +-
>  fs/notify/mark.c                                   |  11 +
>  fs/ntfs3/ntfs_fs.h                                 |   1 +
>  fs/ntfs3/super.c                                   |  29 +-
>  fs/ocfs2/dlm/dlmcommon.h                           |   2 +
>  fs/ocfs2/dlm/dlmdebug.c                            |   5 +-
>  fs/ocfs2/dlm/dlmrecovery.c                         |   2 +-
>  fs/open.c                                          |  23 +-
>  fs/pipe.c                                          |   6 +-
>  fs/smb/client/cifssmb.c                            |  13 +-
>  fs/smb/client/connect.c                            |  21 +-
>  fs/smb/client/smb2ops.c                            |   7 +-
>  fs/smb/server/smb2pdu.c                            |   5 +
>  fs/tracefs/event_inode.c                           |  16 +-
>  fs/unicode/utf8-core.c                             |  21 +-
>  fs/xfs/libxfs/xfs_sb.c                             |  17 +-
>  fs/xfs/xfs_fsmap.c                                 |   2 +-
>  fs/xfs/xfs_ioctl.c                                 |   2 +-
>  fs/xfs/xfs_iops.c                                  |   2 +-
>  include/drm/drm_exec.h                             |  15 +-
>  include/linux/bsg-lib.h                            |   3 +-
>  include/linux/cgroup-defs.h                        |   5 +-
>  include/linux/fs.h                                 |   6 +-
>  include/linux/fsnotify_backend.h                   |   1 +
>  include/linux/futex.h                              |  14 +-
>  include/linux/huge_mm.h                            |   2 +-
>  include/linux/io_uring_types.h                     |   3 +
>  include/linux/ipv6.h                               |  22 ++
>  include/linux/key-type.h                           |   1 +
>  include/linux/key.h                                |   5 +
>  include/linux/maple_tree.h                         |   4 +
>  include/linux/mm_types.h                           |   3 +
>  include/linux/power_supply.h                       |   6 +-
>  include/linux/sched.h                              |   2 +-
>  include/linux/sched/signal.h                       |  27 +-
>  include/linux/sched/user.h                         |   8 +-
>  include/linux/srcutiny.h                           |   4 -
>  include/linux/unicode.h                            |   1 +
>  include/net/af_vsock.h                             |   3 +
>  include/net/ax25.h                                 |   6 +
>  include/net/codel_impl.h                           |   1 +
>  include/net/ipv6.h                                 |   2 -
>  include/net/netfilter/nf_tables_ipv6.h             |   4 +-
>  include/net/netrom.h                               |  18 +-
>  include/net/rose.h                                 |  45 ++-
>  include/uapi/asm-generic/fcntl.h                   |   1 -
>  io_uring/cancel.c                                  |  29 +-
>  io_uring/cancel.h                                  |   2 +
>  io_uring/futex.c                                   |   7 +-
>  io_uring/io-wq.c                                   | 110 +++++-
>  io_uring/io-wq.h                                   |   4 +-
>  io_uring/io_uring.c                                | 167 +++++++--
>  io_uring/io_uring.h                                |  44 ++-
>  io_uring/kbuf.c                                    |   2 +-
>  io_uring/napi.c                                    |   4 +-
>  io_uring/net.c                                     |  26 +-
>  io_uring/poll.c                                    |  41 ++-
>  io_uring/rw.c                                      |  18 -
>  io_uring/sqpoll.c                                  |   7 +
>  io_uring/tctx.c                                    |   1 +
>  io_uring/timeout.c                                 |  91 +++--
>  io_uring/uring_cmd.c                               |   2 +-
>  io_uring/waitid.c                                  |  19 +-
>  kernel/cgroup/cgroup.c                             |   6 +-
>  kernel/events/core.c                               |  33 +-
>  kernel/exit.c                                      |   2 +-
>  kernel/fork.c                                      |  12 +-
>  kernel/futex/core.c                                |  47 +--
>  kernel/pid_namespace.c                             |   5 +-
>  kernel/printk/printk.c                             |   2 +-
>  kernel/ptrace.c                                    |   6 +
>  kernel/rcu/srcutiny.c                              |  19 +-
>  kernel/sched/ext.c                                 |  18 +-
>  kernel/signal.c                                    |   4 +
>  kernel/trace/ftrace.c                              |   4 +-
>  kernel/trace/ring_buffer.c                         |  13 +-
>  kernel/trace/trace.c                               |  13 +-
>  kernel/trace/trace_events_filter.c                 |  15 +-
>  kernel/trace/trace_events_hist.c                   |  52 +--
>  kernel/trace/trace_events_synth.c                  |  10 +
>  kernel/trace/trace_probe.c                         |   3 +-
>  kernel/trace/trace_synth.h                         |   1 +
>  kernel/watch_queue.c                               |  16 +-
>  kernel/workqueue.c                                 |  24 +-
>  mm/filemap.c                                       |   9 -
>  mm/huge_memory.c                                   |  81 +++--
>  mm/internal.h                                      |   6 +
>  mm/khugepaged.c                                    |   3 +
>  mm/pagewalk.c                                      |   6 +-
>  net/ax25/af_ax25.c                                 |  81 ++++-
>  net/ax25/ax25_ds_in.c                              |   2 +
>  net/ax25/ax25_in.c                                 |  55 ++-
>  net/ax25/ax25_out.c                                | 121 +++++--
>  net/ax25/ax25_std_in.c                             |  44 +++
>  net/ax25/ax25_subr.c                               |  44 ++-
>  net/bluetooth/l2cap_core.c                         |   7 +-
>  net/bluetooth/l2cap_sock.c                         |   2 +
>  net/bridge/br_multicast.c                          |  13 +-
>  net/bridge/br_netfilter_ipv6.c                     |   2 +-
>  net/bridge/netfilter/nf_conntrack_bridge.c         |   4 +-
>  net/core/page_pool.c                               |   3 +-
>  net/ipv4/fib_semantics.c                           |   2 +-
>  net/ipv4/tcp.c                                     |  18 +-
>  net/ipv4/tcp_cong.c                                |   4 +-
>  net/ipv4/tcp_dctcp.c                               |   4 +-
>  net/ipv4/tcp_minisocks.c                           |   2 +-
>  net/ipv4/tcp_output.c                              |   2 +-
>  net/ipv4/udp.c                                     |  11 +-
>  net/ipv6/calipso.c                                 |   6 +-
>  net/ipv6/ip6_input.c                               |   2 +-
>  net/ipv6/ip6_offload.c                             |   7 +-
>  net/ipv6/output_core.c                             |   7 +-
>  net/iucv/af_iucv.c                                 |  42 ++-
>  net/mac802154/ieee802154_i.h                       |   7 +-
>  net/mac802154/main.c                               |   1 +
>  net/mac802154/scan.c                               |  51 ++-
>  net/mptcp/protocol.c                               |  14 +-
>  net/netfilter/ipvs/ip_vs_xmit.c                    |   2 +-
>  net/netfilter/nf_conntrack_ovs.c                   |   2 +-
>  net/netfilter/nf_log_syslog.c                      |   2 +-
>  net/netfilter/nft_byteorder.c                      |  51 ++-
>  net/netlink/af_netlink.c                           |  10 +-
>  net/netrom/af_netrom.c                             |  33 +-
>  net/netrom/nr_in.c                                 |  26 ++
>  net/netrom/nr_route.c                              | 383 +++++++++++----------
>  net/rds/rdma_transport.c                           |  38 +-
>  net/rose/af_rose.c                                 |  73 +++-
>  net/rose/rose_in.c                                 |  44 ++-
>  net/rose/rose_link.c                               |  47 +++
>  net/rose/rose_loopback.c                           |   2 +-
>  net/rose/rose_out.c                                |   1 +
>  net/rose/rose_route.c                              | 200 +++++++++--
>  net/rose/rose_timer.c                              |  87 ++++-
>  net/sched/act_api.c                                |  11 +-
>  net/sched/cls_flower.c                             |   5 +
>  net/sched/sch_cake.c                               |   2 +-
>  net/sctp/inqueue.c                                 |   6 +-
>  net/sctp/socket.c                                  |  33 +-
>  net/socket.c                                       |  54 ++-
>  net/tipc/node.c                                    |   2 +
>  net/vmw_vsock/af_vsock.c                           |  49 ++-
>  net/vmw_vsock/virtio_transport_common.c            |   9 +-
>  samples/pidfd/Makefile                             |   2 +-
>  security/keys/key.c                                |  13 +-
>  security/keys/keyctl.c                             |  15 +-
>  security/keys/keyring.c                            | 150 ++++----
>  security/keys/process_keys.c                       |   5 +-
>  security/keys/trusted-keys/trusted_tpm1.c          |   4 +-
>  security/keys/trusted-keys/trusted_tpm2.c          |   2 +-
>  sound/soc/codecs/cs42l52.c                         |   2 +-
>  sound/soc/codecs/cs42l56.c                         |   2 +-
>  sound/soc/codecs/max98371.c                        |   2 +-
>  sound/soc/codecs/nau8822.c                         |   4 +-
>  sound/soc/codecs/pcm3168a.c                        |   2 +-
>  sound/soc/codecs/wm8978.c                          |   4 +-
>  sound/soc/intel/avs/pcm.c                          |   2 +-
>  sound/soc/sof/ipc4-topology.c                      |  16 +-
>  sound/soc/stm/stm32_spdifrx.c                      |   2 +-
>  tools/gpio/Makefile                                |   6 +
>  tools/power/x86/turbostat/turbostat.c              |  11 +-
>  .../test.d/filter/event-filter-incomplete.tc       |  24 ++
>  229 files changed, 3065 insertions(+), 1216 deletions(-)
> 
> 

-- 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

^ permalink raw reply	[flat|nested] 259+ messages in thread

* Re: [PATCH 6.12 000/247] 6.12.115-rc1 review
  2026-10-29 10:24 ` Pavel Machek
@ 2026-10-29 12:30   ` Greg Kroah-Hartman
  0 siblings, 0 replies; 259+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-29 12:30 UTC (permalink / raw)
  To: Pavel Machek
  Cc: bernard.f6bvp, stable, patches, linux-kernel, torvalds, akpm,
	linux, shuah, patches, lkft-triage, jonathanh, f.fainelli,
	sudipm.mukherjee, rwarsow, conor, hargar, broonie, achill, sr

On Thu, Oct 29, 2026 at 11:24:29AM +0100, Pavel Machek wrote:
> Hi!
> 
> > This is the start of the stable review cycle for the 6.12.115 release.
> > There are 247 patches in this series, all will be posted as a response
> > to this one.  If anyone has any issues with these being applied, please
> > let me know.
> 
> What is up with these?
> 
> They don't have usual "Commit upstream XXX" markings. They do have
> commit ids in the sign-off area (which is a logical place), except
> that those hashes don't exist in mainline.
> 
> Best regards,
> 								Pavel
> 
>     Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
>     
>     (cherry picked from commit 741a4863ad570889c75f7a8e404567d8f3e46335)
>     Signed-off-by: Sasha Levin <sashal@kernel.org>

These are coming from the out-of-tree rose repo as this code has been
dropped from the newer kernel versions.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 259+ messages in thread

* Re: [PATCH 6.12 000/247] 6.12.115-rc1 review
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (252 preceding siblings ...)
  2026-10-29 10:24 ` Pavel Machek
@ 2026-10-29 13:40 ` Miguel Ojeda
  2026-10-29 14:28 ` Ron Economos
  254 siblings, 0 replies; 259+ messages in thread
From: Miguel Ojeda @ 2026-10-29 13:40 UTC (permalink / raw)
  To: gregkh
  Cc: achill, akpm, broonie, conor, f.fainelli, hargar, jonathanh,
	linux-kernel, linux, lkft-triage, patches, patches, pavel,
	rwarsow, shuah, sr, stable, sudipm.mukherjee, torvalds,
	Miguel Ojeda

On Wed, 28 Oct 2026 17:56:43 +0100 Greg Kroah-Hartman <gregkh@linuxfoundation.org> wrote:
>
> This is the start of the stable review cycle for the 6.12.115 release.
> There are 247 patches in this series, all will be posted as a response
> to this one.  If anyone has any issues with these being applied, please
> let me know.
> 
> Responses should be made by Fri, 30 Oct 2026 16:59:22 +0000.
> Anything received after that time might be too late.

Boot-tested under QEMU for Rust x86_64, arm64 and riscv64; built-tested
for loongarch64:

Tested-by: Miguel Ojeda <ojeda@kernel.org>

Thanks!

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 259+ messages in thread

* Re: [PATCH 6.12 000/247] 6.12.115-rc1 review
  2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
                   ` (253 preceding siblings ...)
  2026-10-29 13:40 ` Miguel Ojeda
@ 2026-10-29 14:28 ` Ron Economos
  254 siblings, 0 replies; 259+ messages in thread
From: Ron Economos @ 2026-10-29 14:28 UTC (permalink / raw)
  To: Greg Kroah-Hartman, stable
  Cc: patches, linux-kernel, torvalds, akpm, linux, shuah, patches,
	lkft-triage, pavel, jonathanh, f.fainelli, sudipm.mukherjee,
	rwarsow, conor, hargar, broonie, achill, sr

On 10/28/26 09:56, Greg Kroah-Hartman wrote:
> This is the start of the stable review cycle for the 6.12.115 release.
> There are 247 patches in this series, all will be posted as a response
> to this one.  If anyone has any issues with these being applied, please
> let me know.
>
> Responses should be made by Fri, 30 Oct 2026 16:59:22 +0000.
> Anything received after that time might be too late.
>
> The whole patch series can be found in one patch at:
> 	https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.12.115-rc1.gz
> or in the git tree and branch at:
> 	git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-6.12.y
> and the diffstat can be found below.
>
> thanks,
>
> greg k-h

Built and booted successfully on RISC-V RV64 (HiFive Unmatched).

Tested-by: Ron Economos <re@w6rz.net>


^ permalink raw reply	[flat|nested] 259+ messages in thread

end of thread, other threads:[~2026-10-29 14:28 UTC | newest]

Thread overview: 259+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-28 16:56 [PATCH 6.12 000/247] 6.12.115-rc1 review Greg Kroah-Hartman
2026-10-28 16:56 ` [PATCH 6.12 001/247] rose: set SOCK_DESTROY in rose_kill_by_device() for prompt cleanup Greg Kroah-Hartman
2026-10-28 16:56 ` [PATCH 6.12 002/247] rose: disconnect orphaned STATE_2 sockets when device is gone Greg Kroah-Hartman
2026-10-28 16:56 ` [PATCH 6.12 003/247] rose: release netdev ref and destroy orphaned incoming sockets Greg Kroah-Hartman
2026-10-28 16:56 ` [PATCH 6.12 004/247] rose: clear neighbour pointer in rose_kill_by_device() Greg Kroah-Hartman
2026-10-28 16:56 ` [PATCH 6.12 005/247] rose: dont free fd-owned sockets when reaping in the heartbeat Greg Kroah-Hartman
2026-10-28 16:56 ` [PATCH 6.12 006/247] rose: keep the route needed for routing loop detection Greg Kroah-Hartman
2026-10-28 16:56 ` [PATCH 6.12 007/247] rose: guard rose_transmit_link() against a NULL neighbour Greg Kroah-Hartman
2026-10-28 16:56 ` [PATCH 6.12 008/247] rose: use timer_shutdown_sync() for t0timer teardown Greg Kroah-Hartman
2026-10-28 16:56 ` [PATCH 6.12 009/247] rose: dont warn on stray CALL_ACCEPTED/CLEAR_CONFIRMATION in state 3 Greg Kroah-Hartman
2026-10-28 16:56 ` [PATCH 6.12 010/247] rose: hold a reference on incoming sockets queued for accept() Greg Kroah-Hartman
2026-10-28 16:56 ` [PATCH 6.12 011/247] ax25: bound REJ-driven fast retransmits with the existing N2 counter Greg Kroah-Hartman
2026-10-28 16:56 ` [PATCH 6.12 012/247] rose: purge rose_neigh->queue on final teardown Greg Kroah-Hartman
2026-10-28 16:56 ` [PATCH 6.12 013/247] mptcp: move the OoO check back into __mptcp_try_fallback() Greg Kroah-Hartman
2026-10-28 16:56 ` [PATCH 6.12 014/247] fat: stop reading directory entries past the end-of-directory marker Greg Kroah-Hartman
2026-10-28 16:56 ` [PATCH 6.12 015/247] soc/tegra: fuse: Add missing newline to APBMISC error message Greg Kroah-Hartman
2026-10-28 16:56 ` [PATCH 6.12 016/247] power: supply: Fix maintenance charge table kernel-doc Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 017/247] power: supply: ds2780: Fix ds2780_get_capacity() returning raw value Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 018/247] Drivers: hv: Avoid infinite retry loop in init_vp_index() Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 019/247] x86/hyperv: Avoid using per-cpu output page in hv_apicid_to_vp_index() Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 020/247] Drivers: hv: Dont reset VMBus connection state on error/exit paths Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 021/247] pinctrl: qcom: ipq5018: add missing pwm3 function on gpio13 Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 022/247] tools/power turbostat: Fix fd_perf leak on reset Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 023/247] tools/power turbostat: Fix add_counter issue if > 24 counters Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 024/247] power: supply: generic-adc-battery: Fix temperature IIO channel conversion Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 025/247] pinctrl: qcom: ipq5018: replace gcc_plltest with pwm2 on gpio12 Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 026/247] drm/vc4: hdmi: Move packet RAM enable to PM runtime Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 027/247] vsock: treat TCP_CLOSING as once-established Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 028/247] net/rds: dont let the rdma_cm destroy an id RDS still owns on route failure Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 029/247] ASoC: Intel: avs: Reset the stream unless it is already prepared Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 030/247] ASoC: stm32: spdifrx: fix synchronization state check Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 031/247] ASoC: cs42l56: Put the Limiter Cushion control on the limiter register Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 032/247] ASoC: cs42l52: Fix the NG Type Switch bit Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 033/247] ASoC: pcm3168a: Fix the DAC zero flag polarity bit Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 034/247] ASoC: max98371: Fix the Speaker DHT Min Volume bits Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 035/247] ASoC: wm8978: Fix the 128x oversampling switch bits Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 036/247] ASoC: nau8822: " Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 037/247] regcache: Add ->populate() callback to separate from ->init() Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 038/247] regcache: Do not overwrite error code when finalizing cache after error Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 039/247] regmap: Drop map lock during cache init and exit Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 040/247] netlink: reset skb headers before unicast and multicast filtering Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 041/247] spi: tegra114: assert CS GPIO for every transfer in a message Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 042/247] nios2: fix __wsum type degradation in csum_fold() Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 043/247] scsi: st: Save the visited block for the partition the drive is in Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 044/247] scsi: target: iscsi: Fix race in discovery auth updates Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 045/247] ocfs2/dlm: Protect the recovery list during debugfs reads Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 046/247] samples: pidfd: fix userprogs typo Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 047/247] pipe: preserve existing fasync readers on writer setup failure Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 048/247] tracing: probes: error if BTF is required but unavailable Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 049/247] scsi: libsas: Fix SMP IO deadlock during HA resume Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 050/247] netlink: avoid hashing the network namespace pointer Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 051/247] net: bcmgenet: unshare the skb before writing the control block Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 052/247] net/ipv6: Introduce payload_len helpers Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 053/247] calipso: keep BIG TCP payload_len in calipso_skbuff_setattr() Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 054/247] gpiolib: fix memory leak in gpiod_set_array_value_complex() on error paths Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 055/247] gpio: mxc: use lock guards for the generic GPIO chip lock Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 056/247] gpio: mxc: fix both_edges bit operations Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 057/247] gpio: mxc: use BIT() macro Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 058/247] gpio: mxc: fix wakeup_pads bit operations Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 059/247] perf: Fix perf_pmu_migrate_context() leaving events behind Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 060/247] printk: Postpone kthread startup Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 061/247] PCI: Dont treat ~0 as ready in pci_dev_wait() with RRS SV Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 062/247] afs: free the super info after a grace period Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 063/247] autofs: ignore notification errors from a replaced pipe Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 064/247] unicode: free the map after a grace period Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 065/247] x86/kvm: Dont consume async #PF flags on a kernel #PF in NMI context Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 066/247] KVM: nVMX: Reset MMU back to the root MMU if loading L2 state fails for !VM-Entry Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 067/247] fsnotify: prevent mark additions during connector teardown Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 068/247] pid_namespace: make zap_pid_ns_processes() freezable Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 069/247] eventfs: Free the eventfs_inode after an rcu grace period too Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 070/247] namei: test for a negative dentry the way traverse_mounts() does Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 071/247] net/sched: fix use-after-free in __tcf_action_put() Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 072/247] net: rds: fix uninitialized trans dereference in CM event handler Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 073/247] pinctrl: amd: Clear S4 wake bits when firmware has _AEI Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 074/247] sctp: revalidate output stream after association connect wait Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 075/247] tools: gpio: fix building from the top level with O= Greg Kroah-Hartman
2026-10-28 16:57 ` [PATCH 6.12 076/247] tracing/histograms: Reject non-stacktrace fields for synthetic stacktrace fields Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 077/247] i2c: qcom-cci: Fix HALT_ACK reset request being dropped Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 078/247] perf: Update cgroup time when rotating multiplexed events Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 079/247] ring-buffer: Do not show buffer_meta for CPUs without a buffer Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 080/247] ring-buffer: Fix the sub-buffer array base in rb_meta_subbuf_idx() Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 081/247] ring-buffer: Fix false warning in ring_buffer_map_get_reader() Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 082/247] scsi: bsg: Pass reply_len to bsg_setup_queue() to fit UFS ARPMB replies Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 083/247] scsi: xen/scsifront: Check for a NULL shadow entry on a backend response Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 084/247] scsi: libiscsi: Reject a negative task index from parse_pdu_itt Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 085/247] scsi: libiscsi: Validate the ITT reflected in a Reject PDU Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 086/247] scsi: libiscsi: Validate the task named by a management response Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 087/247] drm/amdgpu/sdma3: Work around POLL_REGMEM / FENCE hang Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 088/247] drm/amdgpu: dont drop the runtime PM reference twice in amdgpu_gpr Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 089/247] drm/exec: dont immediately add prelocked obj to array of locked objs Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 090/247] tracing: Fix the shift out of bounds in the log2 histogram modifier Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 091/247] tracing: Take trace_types_lock when dropping the buffer_meta reference Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 092/247] tracing: Check operator stack capacity before pushing Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 093/247] tracing: Do not initialize tracefs work if tracing is disabled Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 094/247] tracing: Fix hist trigger timestamps for buffered events Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 095/247] wifi: p54: validate firmware record lengths Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 096/247] tcp: fix use-after-free in do_tcp_getsockopt(TCP_CONGESTION) Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 097/247] tcp: fix use-after-free in do_tcp_getsockopt(TCP_CC_INFO) Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 098/247] cgroup: fix spurious SIGKILL of CLONE_INTO_CGROUP children Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 099/247] dm cache: fix demotion stats in passthrough mode Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 100/247] dm cache: fix issue with background work locking Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 101/247] dm-crypt: fix a tiny race condition in crypt_dec_pending Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 102/247] dm-ebs: fix incorrect device offset check in ebs_ctr() Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 103/247] dm-integrity: fix infinite loop on discard with large tag size Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 104/247] dm-integrity: require stable writes for internal hash modes Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 105/247] mac802154: fix data race and NULL deref on local->assoc_dev Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 106/247] net/iucv: fix the recvmsg window update Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 107/247] xfs: fix capability check in xfs Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 108/247] workqueue: Use raise_softirq() to trigger softirq in irq_work handler Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 109/247] tipc: protect node reset trace dump with node lock Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 110/247] sctp: validate chunk length in the inqueue parser Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 111/247] page_pool: keep frag_offset aligned for odd-sized requests Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 112/247] s390/ctcm: Prevent XID null dereference Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 113/247] s390/pci: Fix leak of uninitialized kernel data in SCLP report Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 114/247] ipv4: avoid divide by zero in fib_rebalance Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 115/247] drm/amdgpu: Fix VCE 3 ring align_mask Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 116/247] mm, madvise: fix potential workingset node list_lru leaks Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 117/247] mm/huge_memory: initialise workingset state before folio split Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 118/247] Revert "s390/mm: Add missing secure storage access fixups for donated memory" Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 119/247] netfilter: nft_byteorder: remove multi-register support Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 120/247] mm/huge_memory: bypass THP tuneables for huge pfnmap mappings Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 121/247] KVM: x86/mmu: Preserve nested TDP shadow page tables if they are used as roots Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 122/247] fs: get rid of __FMODE_NONOTIFY kludge Greg Kroah-Hartman
2026-10-28 17:56   ` Amir Goldstein
2026-10-29  2:53     ` Sasha Levin
2026-10-28 16:58 ` [PATCH 6.12 123/247] net: bridge: mcast: dont truncate the port group walk on teardown Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 124/247] ksmbd: fill in FileSysIdentifier in FS_POSIX_INFORMATION Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 125/247] ksmbd: initialize FileSystemControlFlags in FS_CONTROL_INFORMATION Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 126/247] ksmbd: zero the FS_OBJECT_ID_INFORMATION buffer before filling it in Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 127/247] net/sched: cls_flower: validate mask pointer after nla_next() Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 128/247] smb: client: fix heap overflow in cifs_do_set_acl() Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 129/247] smb: client: fix multiuser mount with krb5 Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 130/247] scsi: st: Fix use-after-free race between st_remove() and st_open() Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 131/247] perf: Track the perf mlock gift separately Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 132/247] eventfs: fix SRCU read lock leak in eventfs_iterate() Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 133/247] net: call getsockopt_iter if available Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 134/247] kernel/watch_queue: Use pipe_buf() to retrieve the pipe buffer Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 135/247] watch_queue: Fix note pool publication race in watch_queue_set_size() Greg Kroah-Hartman
2026-10-28 16:58 ` [PATCH 6.12 136/247] ntfs3: free the sbi after a grace period Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 137/247] ext4: " Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 138/247] ASoC: SOF: ipc4-topology: Fix shift-out-of-bounds for aggregated ALH capture Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 139/247] drm/xe: Bump LRU for external objects on exec and rebind Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 140/247] tracing: Keep the predicate limit separate from program capacity Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 141/247] io_uring/cancel: dont spin on local work the task cant run Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 142/247] virtio: set skb owner of virtio_transport_reset_no_sock() reply Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 143/247] vsock/virtio: validate packet source for connected sockets Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 144/247] ipv4: udp: Create exceptions before socket matching Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 145/247] workqueue: release pwq pools by pool type Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 146/247] workqueue: Fix unbound pool lifetime for pending pwqs Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 147/247] i2c: viai2c-wmt: Replace dev_err() with dev_err_probe() in probe function Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 148/247] i2c: viai2c-wmt: Fix clock leak in wmt_i2c_probe() Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 149/247] futex: Fix mm reuse handling for FUT_OFF_MMSHARED Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 150/247] drm/i915/dmc: Harden DMC firmware payload parsing Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 151/247] tracing: Fix ignored return value of resize_buffer_duplicate_size() Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 152/247] drm/amdgpu: free the userptr ranges when a CS fails after parser_bos Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 153/247] sched_ext: Fix stall when a task enqueued with SCX_ENQ_LAST lands back on its CPUs local DSQ Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 154/247] cifs: add revalidation on FSCTL failure in smb2_duplicate_extents() Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 155/247] xfs: dont hold buffer locks across sync transaction commit in xfs_sync_sb_buf Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 156/247] rose: clear stale N(R)/N(S) before (re)transmitting a data frame Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 157/247] netrom: linearize and validate lengths in nr_rx_frame() Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 158/247] netrom: require full NET/ROM headers in nr_route_frame() Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 159/247] net: netrom: validate source address in nr_find_socket() Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 160/247] netrom: bound fragment reassembly in nr_queue_rx_frame() Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 161/247] ax25: fix OOB read after address header strip in ax25_rcv() Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 162/247] ax25: check frame length in ax25_decode() and ax25_rx_iframe() Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 163/247] net: ax25: fix integer overflow in ax25_rx_fragment() Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 164/247] netrom: use a single lock for the node and neighbour lists Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 165/247] netrom: look up and update routes in one critical section Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 166/247] netrom: fix reference count leak in nr_rt_device_down Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 167/247] netrom: clear nr_neigh->ax25 under the routing lock in nr_link_failed() Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 168/247] netrom: fix nr_node leak when nr_del_node() removes the last route Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 169/247] rose: clear through routes when a neighbour is removed from the tables Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 170/247] rose: restart the link of a neighbour created over a live AX.25 connection Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 171/247] ax25: serialise the transmission of I frames on a connection Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 172/247] rose: process received frames and send with the socket locked Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 173/247] ax25: dont create two connections for the same link in ax25_send_frame() Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 174/247] ax25: read the connections ax25_dev only once when walking ax25_list Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 175/247] ax25: wait for ax25_send_frame() before detaching the connections of a device Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 176/247] ax25: dont accept frames on a device that is going down Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 177/247] ax25: send a private copy of each I frame Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 178/247] rose: clear the circuits of a neighbour that restarts the link Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 179/247] ax25: send unacknowledged I frames again when a link is re-established Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 180/247] rose: bring up the link of the preferred route passed over by a connect request Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 181/247] ax25: dont free an incoming SABM skb left on the listeners queue Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 182/247] mm/pagewalk: fix stale walk->action escaping walk_pmd_range() Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 183/247] block: avoid potential deadlock on zone revalidation failure Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 184/247] Revert "srcu: Use irq_work to start GP in tiny SRCU" Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 185/247] net_sched: codel: fix stale state for empty flows in fq_codel Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 186/247] Bluetooth: L2CAP: refuse __l2cap_chan_add if chan already has conn Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 187/247] tracing: Reject incomplete event filter expressions Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 188/247] tracing: Save the event file instead of the compatible histogram Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 189/247] tracing: Unregister field variable histograms when the command fails Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 190/247] tracing: Fix 64-bit and signed histogram fields on 32-bit kernels Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 191/247] tracing/histograms: Verify event_call identity when updating synth_event refcount Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 192/247] io-wq: order the exit bit against worker creation task work Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 193/247] io_uring/waitid: own the request before clearing ->head Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 194/247] io_uring/cmd: dont leave list poison in ->hash_node Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 195/247] io_uring/wait: dont spin on a stuck overflow list Greg Kroah-Hartman
2026-10-28 16:59 ` [PATCH 6.12 196/247] io_uring/io-wq: dont lose the signal that ends work Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 197/247] io_uring/io-wq: dont hide a link from cancellations Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 198/247] io_uring: dont flood a cancelling task with task_work Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 199/247] io_uring/io-wq: dont strand work when a worker exits Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 200/247] io_uring/io-wq: dont exit with a creation pending Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 201/247] io_uring/io-wq: let cancel find picked up hashed work Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 202/247] io_uring/poll: dont lose a cancel as io-wq arms poll Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 203/247] io_uring: dont lose a cancel as io-wq parks a request Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 204/247] io_uring/cancel: dont forget that the work was running Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 205/247] io_uring/cancel: recognize "no timeout" on 32-bit Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 206/247] io_uring/cancel: let CANCEL_ALL find parked requests Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 207/247] io_uring: wake ring pollers for local task_work Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 208/247] io_uring/wait: look at all CQ waiters on wake up Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 209/247] io_uring/poll: drop stale double poll entry on rearm Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 210/247] io_uring/timeout: dont skip over reached sequences Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 211/247] io_uring/timeout: keep repeat count on multishot update Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 212/247] io_uring/wait: no early -ETIME if min_wait finds work Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 213/247] io_uring/napi: make stale entries time out after 60s Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 214/247] io_uring/napi: dont busy poll past an expired timeout Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 215/247] io_uring/kbuf: handle index wrap in last buffer check Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 216/247] io_uring/sqpoll: let the thread sleep on disabled rings Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 217/247] io_uring: dont pass restart error codes to userspace Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 218/247] io_uring/net: dont retry recv on uncommitted buffers Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 219/247] io_uring/timeout: no ABS update of multishot timeouts Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 220/247] io_uring/timeout: dont end a linked timeout with 1 Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 221/247] io_uring: look up the file before queueing to io-wq Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 222/247] io_uring/poll: avoid retry wakeup loss when dropping ownership Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 223/247] io_uring/timeout: dont put a sequence target behind the last flush Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 224/247] io_uring/timeout: dont flush with the sequence " Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 225/247] io_uring/timeout: dont lose a cancel as io-wq arms a timeout Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 226/247] io_uring/poll: dont loop on HUP with multiple references Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 227/247] io_uring/net: keep recv buffer select length within MAX_RW_COUNT Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 228/247] io_uring/wait: wake real-time waiters from hard interrupt context Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 229/247] io_uring/waitid: prevent cancel reference wrap Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 230/247] keys: Avoid the owner account dereference in named keyring lookup Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 231/247] keys: Check the authorization payload in process keyring searches Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 232/247] keys: Protect the type name while describing a key Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 233/247] keys: make keyring indexes independent of kernel addresses Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 234/247] keys: Protect the read method check against type removal Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 235/247] KEYS: Fix key_reject_and_link() race with keyring restriction Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 236/247] KEYS: trusted: Fix blob allocation size in tpm2_key_decode() Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 237/247] keys/trusted_keys: return immediately after TPM unseal failure Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 238/247] asymmetric_keys: reject trust keys without IDs Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 239/247] ftrace: Initialize modname and offset in print_rec() Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 240/247] coredump: hold RCU while releasing parked threads Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 241/247] signal: only SIGKILL and the freezers interrupt a coredumping task Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 242/247] signal: dont retarget shared signals in a dying thread group Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 243/247] ptrace: refuse to change the signal mask of a user worker Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 244/247] fork: release the files of a failed fork after sched_cancel_fork() Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 245/247] pid_namespace: prevent TIF_NOTIFY_SIGNAL from interrupting the reaper Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 246/247] signal: allow taks to temporarily block TIF_NOTIFY_SIGNAL Greg Kroah-Hartman
2026-10-28 17:00 ` [PATCH 6.12 247/247] fanotify: Fix crash in fanotify_init(2) Greg Kroah-Hartman
2026-10-28 19:39 ` [PATCH 6.12 000/247] 6.12.115-rc1 review Brett A C Sheffield
2026-10-28 23:30 ` Florian Fainelli
2026-10-29  2:15 ` Peter Schneider
2026-10-29  9:20 ` Dominique Martinet
2026-10-29 10:05 ` Pavel Machek
2026-10-29 10:24 ` Pavel Machek
2026-10-29 12:30   ` Greg Kroah-Hartman
2026-10-29 13:40 ` Miguel Ojeda
2026-10-29 14:28 ` Ron Economos

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