Changelog in Linux kernel 7.2.14

 
asymmetric_keys: reject trust keys without IDs [+ + +]
Author: Weiming Shi <bestswngs@gmail.com>
Date:   Sun Sep 6 19:01:53 2026 +0800

    asymmetric_keys: reject trust keys without IDs
    
    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>

 
Bluetooth: L2CAP: refuse __l2cap_chan_add if chan already has conn [+ + +]
Author: Pauli Virtanen <pav@iki.fi>
Date:   Wed Sep 2 00:04:36 2026 +0300

    Bluetooth: L2CAP: refuse __l2cap_chan_add if chan already has conn
    
    [ 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>

 
coredump: hold RCU while releasing parked threads [+ + +]
Author: Christian Brauner <brauner@kernel.org>
Date:   Mon Sep 21 15:44:50 2026 +0200

    coredump: hold RCU while releasing parked threads
    
    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>

coredump: prevent TIF_NOTIFY_SIGNAL from interrupting coredumps [+ + +]
Author: Christian Brauner <brauner@kernel.org>
Date:   Mon Aug 24 14:08:17 2026 +0200

    coredump: prevent TIF_NOTIFY_SIGNAL from interrupting coredumps
    
    commit a58d647acfdc62561f3570d114025b3bf38ae41b 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 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.
    
    However, both the usermodehelper pipe and the coredump socket will bail
    early on TIF_NOTIFY_SIGNAL. This affects the following codepaths:
    
    - coredump_sock_recv() -> unix_stream_read_generic()
      The request/ack handshake is abandoned before any coredump data is
      sent.
    
    - anon_pipe_write() returning -ERESTARTSYS
      Once the pipe is full this truncates the coredump.
    
    - unix_stream_sendmsg() returning -ERESTARTSYS
      Once the send buffer is full this truncates the coredump.
    
    - coredump_sock_wait() -> __kernel_read()
      This reports a failure that didn't happen.
    
    - wait_for_dump_helpers() -> wait_event_interruptible()
      This stops waiting for the coredump helpers.
    
    Such truncation is entirely invisible to userspace and all uapi bits
    still indicate that a successful coredump happened. A crashing process
    with a bunch of file backed mappings and io_uring thrown in loses most
    of the coredump data. If the NT_FILE note goes past PAGE_SIZE mappings
    it's gonzo.
    
    TIF_NOTIFY_SIGNAL is sent by io_uring for the common case. And it uses
    poll without sleeping so a completion callback runs task_work_add() from
    interrupt context against the task that submitted the request. This is
    the task that is running the coredump. Since that task hasn't set
    work_exited (it hasn't exited yet after all) TIF_NOTIFY_SIGNAL keeps
    reappearing.
    
    A coredumping task doesn't return to userspace. The task work is run at
    exit. So interrupting it doesn't buy anything and just loses the
    coredump which is quite valuable.
    
    Note that this isn't specific to io_uring. There's also
    klp_send_signals(), bpf_task_work_schedule_signal(), landlock's tsync
    and then  technically, kthread_stop() and the printk kunit test set the
    bit raw.
    
    Link: https://patch.msgid.link/20260824-work-tif_notify_signal-v2-2-6609e42b3157@kernel.org
    Fixes: 12db8b690010 ("entry: Add support for TIF_NOTIFY_SIGNAL")
    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>

 
exit: hang up the tty before closing the files [+ + +]
Author: Christian Brauner <brauner@kernel.org>
Date:   Mon Sep 21 15:44:57 2026 +0200

    exit: hang up the tty before closing the files
    
    commit ad016f0131ebfec250a3360ea75d35128b3f4aa8 upstream.
    
    do_exit() closes the task's files in exit_files() and hangs up the
    controlling tty of a session leader in disassociate_ctty(1) after
    that. Since commit d99d38540bf0 ("fs: make close_files() synchronous")
    the final __fput() of every file runs inside exit_files(). So when the
    session leader holds the last open of its tty the tty is released
    before disassociate_ctty() runs. tty_release() clears signal->tty for
    the whole session in session_clear_tty() once the count drops to zero
    and sends no signal doing so. disassociate_ctty(1) then finds neither a
    tty nor a tty_old_pgrp and does nothing. The foreground process group
    loses its SIGHUP:
    
        do_exit()
          exit_files()
            close_files()
              tty_release()             tty->count == 0
                session_clear_tty()     signal->tty = NULL, no signal
          disassociate_ctty(1)
            get_current_tty()           NULL
            signal->tty_old_pgrp        NULL, nothing sent
    
    That only affects real ttys. For a pty the master's open keeps the
    slave's count above zero. And it only affects a foreground job that
    holds no descriptor to the tty anymore while its session leader exits.
    Everything else is unchanged. The DTR drop on the last close happens in
    tty_port_shutdown() regardless, stopped jobs get their SIGHUP from
    kill_orphaned_pgrp() and signal->tty is cleared either way.
    
    Before that commit the final __fput() ran from exit_task_work() which
    comes after disassociate_ctty(). That order isn't old. Until v3.14
    exit_task_work() came right after exit_files() and before v3.6 fput()
    was synchronous, so the tty was always released first. Commit
    c39df5fa37b0 ("exit: call disassociate_ctty() before
    exit_task_namespaces()") moved disassociate_ctty() up to fix a pppd
    crash and in front of exit_task_work() as a side effect. The hangup in
    this case has worked since then and that's eleven years of userspace
    being able to rely on it.
    
    Hang the tty up before closing the files. This is the ordinary hangup
    with the file still open: __tty_hangup() swaps in hung_up_tty_fops and
    tty_release() runs from the close afterwards as it does when a modem
    drops the line. disassociate_ctty() stays in front of
    exit_task_namespaces() which the pppd fix needs.
    
    Reported-by: Chris Mason <mason@kernel.org>
    Link: https://patch.msgid.link/20260921-work-coredump-fixes-v3-8-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>

 
fork: release the files of a failed fork after sched_cancel_fork() [+ + +]
Author: Christian Brauner <brauner@kernel.org>
Date:   Mon Sep 21 15:44:56 2026 +0200

    fork: release the files of a failed fork after sched_cancel_fork()
    
    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>

 
ftrace: Initialize modname and offset in print_rec() [+ + +]
Author: Aaron Ahmed <aarnahmd@amazon.com>
Date:   Fri Oct 16 23:04:03 2026 +0000

    ftrace: Initialize modname and offset in print_rec()
    
    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>

 
io-wq: order the exit bit against worker creation task work [+ + +]
Author: Christian Brauner <brauner@kernel.org>
Date:   Mon Sep 21 15:44:53 2026 +0200

    io-wq: order the exit bit against worker creation task work
    
    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/cancel: don't forget that the work was running [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:30:40 2026 +0000

    io_uring/cancel: don't forget that the work was running
    
    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: let CANCEL_ALL find parked requests [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:30:42 2026 +0000

    io_uring/cancel: let CANCEL_ALL find parked requests
    
    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: rearm local work wake up before sleep [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:30:32 2026 +0000

    io_uring/cancel: rearm local work wake up before sleep
    
    Commit 76a82c666abf155ad52d5f41043eac77dd3e41d8 upstream.
    
    io_uring_try_cancel_requests() sets ->cq_wait_nr to 1 so that the next
    io_req_local_work_add() wakes the cancelling task. The add that takes the
    count to zero is the only one that wakes, later ones see a count <= 0 and
    return. io_uring_cancel_generic() however only becomes
    TASK_INTERRUPTIBLE much later, so the one wake up can be spent on a
    running task. That is fine as long as the entry of that add is still
    queued, as the io_local_work_pending() check then skips the sleep. It is
    not if the add was delayed after queueing its entry:
    
    CPU0 (submitter in exec or exit)      CPU1 (io_req_local_work_add)
                                          mpscq_push(req A)
    io_uring_try_cancel_requests()
      io_run_local_work()  // runs req A
    io_uring_try_cancel_requests()
      atomic_set(&ctx->cq_wait_nr, 1)
                                          atomic_read(&ctx->cq_wait_nr) == 1
                                          count taken, wake_up_state()
                                            // task is running, no-op
    prepare_to_wait(TASK_INTERRUPTIBLE)
    io_local_work_pending() == false
    schedule()
                                          mpscq_push(req B)
                                          cq_wait_nr <= 0, return
    
    Only the sleeping task can run req B, so it is stuck in execve() until a
    signal happens to wake it. An exiting task doesn't even get that.
    
    Arm the count again once the task state is set and before the work list
    is checked, for the rings whose local work this task is the one to run.
    
    [ 7.2: the loop still has the WARN_ON_ONCE() that commit fddcf4c5321b replaced in
      7.3; the new check makes it unreachable, so it is dropped ]
    Fixes: d46ab2c98aba ("io_uring: switch local task_work to a mpscq")
    Assisted-by: LLM
    Signed-off-by: Josef Bacik <josef@toxicpanda.com>
    Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-8-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/cancel: recognize "no timeout" on 32-bit [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:30:41 2026 +0000

    io_uring/cancel: recognize "no timeout" on 32-bit
    
    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/cmd: don't leave list poison in ->hash_node [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:30:26 2026 +0000

    io_uring/cmd: don't leave list poison in ->hash_node
    
    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/fdinfo: fix CQE dump of CQE32 rings [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:30:52 2026 +0000

    io_uring/fdinfo: fix CQE dump of CQE32 rings
    
    Commit e4507a62c247081fffe299622c04c6f7c3d98e92 upstream.
    
    Since the CQ ring dump was changed to deal with IORING_SETUP_CQE_MIXED, a
    32b CQE is taken to occupy two entries of the ring. That is how it works
    for mixed rings. With IORING_SETUP_CQE32 each entry has twice the size:
    head and tail count 32b CQEs, and entry n is found at cqes[n << 1].
    
    For such rings the dump reads cqes[n], and skips every other entry. It
    shows half of the pending CQEs at best, and what it shows is taken from
    the wrong place unless the head happens to be at the start of the ring.
    The extra data of the last entry isn't shown at all, as the check that
    keeps the dump of a mixed ring from reading beyond the array is applied to
    these rings as well.
    
    [ 7.2: without the last-slot check, which 7.2 does not have ]
    Fixes: 82ceb7fcc5ff ("io_uring/fdinfo: handle mixed sized CQEs")
    Assisted-by: LLM
    Signed-off-by: Josef Bacik <josef@toxicpanda.com>
    Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-28-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: allocate private hash before waiting [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:30:46 2026 +0000

    io_uring/futex: allocate private hash before waiting
    
    Commit 3eff68bce25584cded3fb6ec033ff9a1c9913d04 upstream.
    
    The futex code relies on there being no private futex waiters by the time
    the first private hash of a mm is installed: __futex_pivot_hash() moves
    the waiters from the previous private hash to the new one, but it does not
    look for them in the global hash which is used as long as there is no
    private hash. That is why every clone(CLONE_VM) allocates it up front: a
    task which is alone in its mm cannot block in futex_wait() and create a
    thread or invoke prctl(PR_FUTEX_HASH) at the same time.
    
    IORING_OP_FUTEX_WAIT and IORING_OP_FUTEX_WAITV do not block the submitter
    though:
    
      io_uring_enter()
        io_futex_wait()
          futex_wait_setup()        // no private hash: queued in the global hash
      pthread_create()
        futex_hash_allocate_default()
          __futex_pivot_hash()      // first private hash, nothing is moved
                                    futex(FUTEX_WAKE_PRIVATE)
                                      futex_hash()  // private hash: no waiter
    
    The wakeup is lost and the request only completes when it is cancelled.
    prctl(PR_FUTEX_HASH, PR_FUTEX_HASH_SET_SLOTS, n) instead of
    pthread_create() has the same effect.
    
    Allocate the default private hash when a wait request on a private futex
    is prepared, which happens in the context of the submitter. This is a RCU
    protected pointer check once the hash exists. A failure to allocate it
    fails the request with -ENOMEM.
    
    Fixes: 80367ad01d93 ("futex: Add basic infrastructure for local task local hash")
    Assisted-by: LLM
    Signed-off-by: Josef Bacik <josef@toxicpanda.com>
    Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-22-c1556f5d7bf5@toxicpanda.com
    Signed-off-by: Jens Axboe <axboe@kernel.dk>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

 
io_uring/io-wq: don't exit with a creation pending [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:30:36 2026 +0000

    io_uring/io-wq: don't exit with a creation pending
    
    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.
    
    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>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

io_uring/io-wq: don't go to sleep on pending work [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:30:34 2026 +0000

    io_uring/io-wq: don't go to sleep on pending work
    
    Commit f19c38feb96802ee53a99649d740d2bf630bcce7 upstream.
    
    io_wq_enqueue() wakes a worker off the free list. If there is none it
    creates one, unless ->nr_running says that a worker is running. That
    relies on whoever takes ->nr_running to zero to check for pending work,
    which io_wq_dec_running() no longer does for a worker without
    ->cur_work, on the grounds that an idle worker is either woken right
    away or someone else has created a worker. Neither has to be the case:
    
    worker A (idle)          worker B (idle)          io_wq_enqueue()
                             woken for work 1
    woken (e.g. timeout)     takes work 1
    work list is empty
                                                      queues work 2
                                                      B is first on the free
                                                      list: wake_up_process(B)
                             leaves the free list
                             work 1 blocks
                               nr_running 2 -> 1
    schedule_timeout()
      nr_running 1 -> 0
      ->cur_work == NULL
    
    Work 2 isn't looked at until work 1 is done or A's idle timeout fires,
    five seconds later. ->cur_work is also NULL while a worker blocks on
    ->uring_lock in io_wq_put_work(), with the same result if it was the
    only one running.
    
    Let the idle worker leave ->nr_running by itself before it takes its last
    look at the work list. Both that and queueing work are done under
    acct->lock, so either the worker sees the work, or the enqueue side sees
    that it can't count on this worker. This doesn't bring back the request
    for a new worker which the check was meant to avoid, and as idle workers
    don't get to io_wq_dec_running() any more, the check can go.
    
    Fixes: 8343cae362e1 ("io_uring/io-wq: ignore non-busy worker going to sleep")
    Assisted-by: LLM
    Signed-off-by: Josef Bacik <josef@toxicpanda.com>
    Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-10-c1556f5d7bf5@toxicpanda.com
    Signed-off-by: Jens Axboe <axboe@kernel.dk>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

io_uring/io-wq: don't hide a link from cancellations [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:30:29 2026 +0000

    io_uring/io-wq: don't hide a link from cancellations
    
    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.
    
    [ 7.2: io_wq_put_work() keeps the link check of 7.2, 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: don't lose the signal that ends work [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:30:28 2026 +0000

    io_uring/io-wq: don't lose the signal that ends work
    
    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: don't strand work when a worker exits [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:30:35 2026 +0000

    io_uring/io-wq: don't strand work when a worker exits
    
    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.
    
    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>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

io_uring/io-wq: let cancel find picked up hashed work [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:30:37 2026 +0000

    io_uring/io-wq: let cancel find picked up hashed work
    
    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/kbuf: handle index wrap in last buffer check [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:31:00 2026 +0000

    io_uring/kbuf: handle index wrap in last buffer check
    
    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/mpscq: disable preemption while pushing [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:30:33 2026 +0000

    io_uring/mpscq: disable preemption while pushing
    
    Commit 68a95c3968895cd198f42baadb23e635fecc5a66 upstream.
    
    A push makes the node the new tail, and then links it to its predecessor.
    In between the queue isn't empty, but mpscq_pop() can't get at the node.
    The consumers deal with that by trying again, with a cond_resched() in
    the loop to give a preempted producer the chance to finish.
    
    cond_resched() doesn't do that if the consumer has a higher priority than
    the producer and both have to use the same CPU:
    
      producer (SCHED_OTHER)              consumer (SCHED_FIFO), same CPU
      io_req_local_work_add()
        mpscq_push()
          prev = xchg(&q->tail, node)
      <preempted>                         io_cqring_wait()
                                            __io_run_local_work()
                                          again:
                                              cond_resched()  // nothing to do
                                              mpscq_pop()     // NULL
                                              // work pending, no events yet
                                              goto again
    
    The producer can be any task that is able to queue task_work for the
    ring: an io-wq worker, or somebody who sends a message with
    IORING_OP_MSG_RING. The consumer spins, holding ->uring_lock, until the
    scheduler takes pity on the fair class, which takes about a second with
    the default settings of the fair server, and forever without it. The
    loops in tctx_task_work_run() and io_cancel_local_task_work() have the
    same problem.
    
    Don't allow preemption between the two steps. That bounds the time the
    window is open on the CPU of the producer by what interrupts take, and a
    consumer that waits for that is on another CPU. The cost is a
    preempt_disable()/preempt_enable() pair per push.
    
    Fixes: 50cb44bd0d5f ("io_uring/mpscq: add lockless multi-producer, single-consumer FIFO queue")
    Assisted-by: LLM
    Signed-off-by: Josef Bacik <josef@toxicpanda.com>
    Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-9-c1556f5d7bf5@toxicpanda.com
    Signed-off-by: Jens Axboe <axboe@kernel.dk>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

 
io_uring/napi: don't busy poll past an expired timeout [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:30:58 2026 +0000

    io_uring/napi: don't busy poll past an expired timeout
    
    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: make stale entries time out after 60s [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:30:57 2026 +0000

    io_uring/napi: make stale entries time out after 60s
    
    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/net: don't retry recv on uncommitted buffers [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:31:04 2026 +0000

    io_uring/net: don't retry recv on uncommitted buffers
    
    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: keep recv buffer select length within MAX_RW_COUNT [+ + +]
Author: Tamaki Yanagawa <ty@000ty.net>
Date:   Sun Oct 18 04:22:32 2026 +0000

    io_uring/net: keep recv buffer select length within MAX_RW_COUNT
    
    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/openclose: keep the lock in io_pipe_fixed() [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:31:02 2026 +0000

    io_uring/openclose: keep the lock in io_pipe_fixed()
    
    Commit a3d7ee11289f657aa9af826d8f0844221292a27a upstream.
    
    io_pipe_fixed() installs both ends of the pipe in the fixed file table,
    drops ->uring_lock, and copies the slot numbers to the application. If
    that faults, it takes the lock again and removes whatever is in these
    slots.
    
    If the request is run by io-wq the lock really is dropped in between, and
    the slots are visible to everybody else. By the time the error path gets
    to them, they may have been closed and reused, by IORING_OP_CLOSE and a
    direct open or accept, or by IORING_REGISTER_FILES_UPDATE. Then a file is
    removed from the table that has nothing to do with the failed request.
    
    Do the copy with the lock held. Faulting in user memory under
    ->uring_lock is fine, the registration paths do it all the time.
    
    Fixes: 53db8a71ecb4 ("io_uring: add support for IORING_OP_PIPE")
    Assisted-by: LLM
    Signed-off-by: Josef Bacik <josef@toxicpanda.com>
    Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-38-c1556f5d7bf5@toxicpanda.com
    Signed-off-by: Jens Axboe <axboe@kernel.dk>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

 
io_uring/poll: avoid retry wakeup loss when dropping ownership [+ + +]
Author: Juanlu Herrero <juanlu@fastmail.com>
Date:   Tue Oct 13 15:37:20 2026 -0700

    io_uring/poll: avoid retry wakeup loss when dropping ownership
    
    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: don't loop on HUP with multiple references [+ + +]
Author: Jens Axboe <axboe@kernel.dk>
Date:   Fri Oct 16 09:15:13 2026 -0600

    io_uring/poll: don't loop on HUP with multiple references
    
    Commit 67bb1ad9a517bedf1e1599fe5448620b9f38bf2a 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: don't lose a cancel as io-wq arms poll [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:30:38 2026 +0000

    io_uring/poll: don't lose a cancel as io-wq arms poll
    
    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: drop stale double poll entry on rearm [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:30:45 2026 +0000

    io_uring/poll: drop stale double poll entry on rearm
    
    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.
    
    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>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

 
io_uring/register: don't wrap 32b CQEs when resizing [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:30:49 2026 +0000

    io_uring/register: don't wrap 32b CQEs when resizing
    
    Commit 0edf1930b8ed3c398d3cbdbafd8f72dbd1a3d9e4 upstream.
    
    On an IORING_SETUP_CQE_MIXED ring, a 32b CQE uses two contiguous CQ
    entries and is never allowed to wrap the end of the ring. When posting,
    io_cqe_cache_refill() inserts a dummy IORING_CQE_F_SKIP entry if only
    one entry is left before the ring wraps, and the application relies on
    that to read a 32b CQE as one contiguous 32 byte slot.
    
    io_register_resize_rings() copies pending CQEs to the new ring one 16b
    entry at a time, placing entry i at i & (new_entries - 1). When the CQ
    ring is shrunk, a pending 32b CQE that was contiguous in the old ring
    can land with its first half on the last entry of the new ring and its
    second half on entry 0. For example, with 8 old entries, 4 new entries
    and a 32b CQE at index 3, the halves end up at entries 3 and 0. The
    application then reads the extra data of that CQE from past the end of
    the CQ array, and the CQE content it sees is wrong.
    
    This was found by code inspection and has not been reproduced.
    
    Fix by failing the resize with -EOVERFLOW if a pending 32b CQE would
    wrap the new ring, the same way the resize fails when the pending CQEs
    don't fit.
    
    Fixes: e26dca67fde1 ("io_uring: add support for IORING_SETUP_CQE_MIXED")
    Assisted-by: LLM
    Signed-off-by: Josef Bacik <josef@toxicpanda.com>
    Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-25-c1556f5d7bf5@toxicpanda.com
    Signed-off-by: Jens Axboe <axboe@kernel.dk>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

io_uring/register: handle index wrap when resizing [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:30:50 2026 +0000

    io_uring/register: handle index wrap when resizing
    
    Commit e8dee8d5498c710a22a84076d8ecb661627032b4 upstream.
    
    The ring heads and tails are free running 32-bit counters.
    io_register_resize_rings() takes that into account when it checks whether
    the pending entries fit into the new rings, but then copies them with
    
            for (i = old_head; i < tail; i++)
    
    If the tail has wrapped and the head hasn't, that copies nothing. The new
    rings get the old head and tail, so the application finds whatever is in
    the freshly allocated memory, zeroes, in place of the CQEs it hasn't
    reaped yet, or the kernel in place of the SQEs that have not been
    submitted yet. A ring that completes a million requests per second gets
    there after little more than an hour.
    
    Loop until the tail is reached, the number of iterations has been bounded
    by the size of the new ring at that point.
    
    Fixes: 79cfe9e59c2a ("io_uring/register: add IORING_REGISTER_RESIZE_RINGS")
    Assisted-by: LLM
    Signed-off-by: Josef Bacik <josef@toxicpanda.com>
    Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-26-c1556f5d7bf5@toxicpanda.com
    Signed-off-by: Jens Axboe <axboe@kernel.dk>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

io_uring/register: keep 128b SQEs intact on resize [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:30:51 2026 +0000

    io_uring/register: keep 128b SQEs intact on resize
    
    Commit 0feb5bcd2d4261d656729892aef4d643461ea5ac upstream.
    
    On a ring with IORING_SETUP_SQE_MIXED a 128b SQE takes two entries that
    have to be contiguous in memory, io_init_req() fails it with -EINVAL if
    it starts on the last entry of the SQ ring. The entry a pending SQE ends
    up in after IORING_REGISTER_RESIZE_RINGS depends on the size of the new
    ring, and nothing takes care of that. With four entries instead of eight,
    a 128b SQE which was fine in entries 3 and 4 is split up between entry 3
    and entry 0. The resize succeeds, and the request fails later on.
    
    If the ring has an SQ array, the second half is also taken from the
    wrong place unless the array happens to map the following index to the
    following entry. The submission side doesn't look at the array for the
    second half.
    
    Do what is done for 32b CQEs on IORING_SETUP_CQE_MIXED rings: fail the
    resize with -EOVERFLOW if a 128b SQE would wrap. And copy the second half
    from where it is.
    
    Fixes: 1cba30bf9fdd ("io_uring: add support for IORING_SETUP_SQE_MIXED")
    Assisted-by: LLM
    Signed-off-by: Josef Bacik <josef@toxicpanda.com>
    Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-27-c1556f5d7bf5@toxicpanda.com
    Signed-off-by: Jens Axboe <axboe@kernel.dk>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

 
io_uring/sqpoll: let the thread sleep on disabled rings [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:31:01 2026 +0000

    io_uring/sqpoll: let the thread sleep on disabled rings
    
    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/timeout: don't end a linked timeout with 1 [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:31:06 2026 +0000

    io_uring/timeout: don't end a linked timeout with 1
    
    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: don't flush with the sequence behind the last flush [+ + +]
Author: Jens Axboe <axboe@kernel.dk>
Date:   Thu Oct 15 14:25:00 2026 -0600

    io_uring/timeout: don't flush with the sequence behind the last flush
    
    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: don't lose a cancel as io-wq arms a timeout [+ + +]
Author: Jens Axboe <axboe@kernel.dk>
Date:   Thu Oct 15 16:38:45 2026 -0600

    io_uring/timeout: don't lose a cancel as io-wq arms a timeout
    
    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.
    
    Fixes: ce35a47a3a02 ("io_uring: add IOSQE_ASYNC")
    Signed-off-by: Jens Axboe <axboe@kernel.dk>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

io_uring/timeout: don't put a sequence target behind the last flush [+ + +]
Author: Jens Axboe <axboe@kernel.dk>
Date:   Thu Oct 15 14:18:22 2026 -0600

    io_uring/timeout: don't put a sequence target behind the last flush
    
    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: don't skip over reached sequences [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:30:53 2026 +0000

    io_uring/timeout: don't skip over reached sequences
    
    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: keep repeat count on multishot update [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:30:54 2026 +0000

    io_uring/timeout: keep repeat count on multishot update
    
    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: no ABS update of multishot timeouts [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:31:05 2026 +0000

    io_uring/timeout: no ABS update of multishot timeouts
    
    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: use the right clock for ABS updates [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:30:55 2026 +0000

    io_uring/timeout: use the right clock for ABS updates
    
    Commit dad82eb1805d76c555224e4030319e3844642b64 upstream.
    
    io_parse_user_time() converts an absolute time from the time namespace of
    the caller to the host's view, for the clock given by the flags. The
    flags of IORING_TIMEOUT_UPDATE and IORING_LINK_TIMEOUT_UPDATE can't name
    a clock, the updated timer keeps running on the clock the timeout was
    set up with. So the time is always converted as if it was
    CLOCK_MONOTONIC.
    
    In a time namespace with a monotonic offset, that moves the new expiry of
    a CLOCK_REALTIME timeout by that offset, although the clock isn't
    affected by time namespaces at all, and the one of a CLOCK_BOOTTIME
    timeout by the difference between the two offsets.
    
    Do the conversion when the timeout has been looked up and its clock is
    known. The update is run by the submitter, its SQPOLL thread or one of
    its io-wq workers, all of which share the time namespace.
    
    Fixes: 9cc6bac1bebf ("io_uring/timeout: honour caller's time namespace for IORING_TIMEOUT_ABS")
    Assisted-by: LLM
    Signed-off-by: Josef Bacik <josef@toxicpanda.com>
    Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-31-c1556f5d7bf5@toxicpanda.com
    Signed-off-by: Jens Axboe <axboe@kernel.dk>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

 
io_uring/wait: don't spin on a stuck overflow list [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:30:27 2026 +0000

    io_uring/wait: don't spin on a stuck overflow list
    
    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.
    
    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>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

io_uring/wait: look at all CQ waiters on wake up [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:30:44 2026 +0000

    io_uring/wait: look at all CQ waiters on wake up
    
    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.
    
    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>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

io_uring/wait: no early -ETIME if min_wait finds work [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:30:56 2026 +0000

    io_uring/wait: no early -ETIME if min_wait finds work
    
    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.
    
    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>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

io_uring/wait: wake real-time waiters from hard interrupt context [+ + +]
Author: Austin Schuh <austin.linux@gmail.com>
Date:   Sat Oct 17 10:17:26 2026 -0700

    io_uring/wait: wake real-time waiters from hard interrupt context
    
    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.
    
    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/waitid: own the request before clearing ->head [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:30:25 2026 +0000

    io_uring/waitid: own the request before clearing ->head
    
    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: prevent cancel reference wrap [+ + +]
Author: Junyeong Lee <jylee5498@gmail.com>
Date:   Tue Oct 20 00:21:00 2026 +0900

    io_uring/waitid: prevent cancel reference wrap
    
    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/zcrx: fix buffer offsets in areas above 4GB [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:30:59 2026 +0000

    io_uring/zcrx: fix buffer offsets in areas above 4GB
    
    Commit ab4536bf2e5617b04f2d9396f06393c7bbfb071d upstream.
    
    io_zcrx_queue_cqe() computes the offset of the buffer in its area from
    net_iov_idx(), which is an unsigned int, so the shift is done in 32 bits
    and only the result is widened to the u64 that goes into the CQE. An area
    can be up to 1TB in size. For every niov beyond the first 4GB the CQE
    points the application at a buffer 4GB, or a multiple of that, below the
    one which has the data. It reads the wrong data, and then returns a
    buffer it doesn't own via the refill queue while the real one is never
    given back.
    
    Fixes: 11ed914bbf94 ("io_uring/zcrx: add io_recvzc request")
    Assisted-by: LLM
    Signed-off-by: Josef Bacik <josef@toxicpanda.com>
    Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-35-c1556f5d7bf5@toxicpanda.com
    Signed-off-by: Jens Axboe <axboe@kernel.dk>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

 
io_uring: don't flood a cancelling task with task_work [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:30:30 2026 +0000

    io_uring: don't flood a cancelling task with task_work
    
    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: don't lose a cancel as io-wq parks a request [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:30:39 2026 +0000

    io_uring: don't lose a cancel as io-wq parks a request
    
    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.
    
    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>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

io_uring: don't lose the DEFER_TASKRUN wake up [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:30:31 2026 +0000

    io_uring: don't lose the DEFER_TASKRUN wake up
    
    Commit 8257f6ec45ee07c6ed933c59d8982b03cc7bc1ca upstream.
    
    Since local task_work moved to the mpscq, ->cq_wait_nr is a credit: the
    add that counts it down to zero, or exchanges it for IO_CQ_WAKE_INIT,
    issues the only wake up of the wait cycle, and every later add returns
    early as the count is <= 0.
    
    An add looks at the count after it has queued its entry, so an add that
    gets delayed in between can take the credit of a later cycle. That was
    assumed to cause an early wake up at worst, but the waiter publishes the
    count before it changes its task state:
    
    CPU0 (submitter, io_cqring_wait)      CPU1 (io_req_local_work_add)
                                          mpscq_push(req A)
    io_run_local_work()  // runs req A
    atomic_set(&ctx->cq_wait_nr, 1)
                                          atomic_read(&ctx->cq_wait_nr) == 1
                                          atomic_xchg(.., IO_CQ_WAKE_INIT)
                                          wake_up_state(.., TASK_INTERRUPTIBLE)
                                            // still TASK_RUNNING, no-op
    set_current_state(TASK_INTERRUPTIBLE)
    io_local_work_pending() == false
    schedule()
                                          mpscq_push(req B)
                                          cq_wait_nr <= 0, return
    
    The task now sleeps with req B queued, until a signal or a timeout ends
    the wait.
    
    Set the task state first and only then make the count visible, so that
    whoever takes the credit finds a task it can wake. The full barrier that
    orders the count against the check of the work list is kept. Do the same
    for the wait of the BPF driven loop, which copied the sequence.
    
    Fixes: d46ab2c98aba ("io_uring: switch local task_work to a mpscq")
    Assisted-by: LLM
    Signed-off-by: Josef Bacik <josef@toxicpanda.com>
    Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-7-c1556f5d7bf5@toxicpanda.com
    Signed-off-by: Jens Axboe <axboe@kernel.dk>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

io_uring: don't pass restart error codes to userspace [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:31:03 2026 +0000

    io_uring: don't pass restart error codes to userspace
    
    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: don't split 128b SQEs at the SQPOLL cap [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:30:48 2026 +0000

    io_uring: don't split 128b SQEs at the SQPOLL cap
    
    Commit 79956bb39b4d372eb146955ea159ecb6fba37f5b upstream.
    
    If an SQPOLL thread serves more than one ring, __io_sq_thread() submits
    no more than IORING_SQPOLL_CAP_ENTRIES_VALUE entries per ring and round,
    for fairness. On a ring with IORING_SETUP_SQE_MIXED the cap may fall
    between the two entries of a 128b SQE. io_init_req() finds that just one
    entry is left of what it was asked to submit and fails the request with
    -EINVAL, although the second entry is sitting in the SQ ring.
    
    In the next round the second entry is taken for an SQE of its own, so on
    top of the failed request the application gets whatever its payload
    amounts to when it is read as an SQE.
    
    The application has done nothing wrong, and it can't know where the cap
    is going to be applied. For SQPOLL, let the request have its second entry
    if the SQ ring holds it, in excess of the number of entries that were to
    be submitted.
    
    Fixes: 1cba30bf9fdd ("io_uring: add support for IORING_SETUP_SQE_MIXED")
    Assisted-by: LLM
    Signed-off-by: Josef Bacik <josef@toxicpanda.com>
    Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-24-c1556f5d7bf5@toxicpanda.com
    Signed-off-by: Jens Axboe <axboe@kernel.dk>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

io_uring: drop the CQE cache if a refill fails [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:30:47 2026 +0000

    io_uring: drop the CQE cache if a refill fails
    
    Commit 78f9c9cffef02a290b6e97672aaa9c75df0d21da upstream.
    
    ->cqe_cached and ->cqe_sentinel delimit the CQ entries which can be
    handed out without looking at the ring. io_get_cqe_overflow() only calls
    io_cqe_cache_refill() if that range is too small. Without
    IORING_SETUP_CQE_MIXED too small means empty. With it, a 32b CQE needs
    two entries, and one may be left. If the refill then fails, the entry
    stays in the cache, and the next 16b CQE gets it without any checks.
    
    That CQE overtakes the 32b one, which went to the overflow list. The test
    for IO_CHECK_CQ_OVERFLOW_BIT, which is there to prevent that, is part of
    the refill:
    
      CQ ring with 4 entries, head == 0
      16b CQE, 32b CQE       tail == 3, one entry cached
      32b CQE                no room, the CQE overflows
      16b CQE                written to entry 3, ahead of the 32b CQE
    
    Forget about the rest of the cache when it is refilled.
    
    Fixes: e26dca67fde1 ("io_uring: add support for IORING_SETUP_CQE_MIXED")
    Reported-by: Leonid Ovchinnikov <teiny.work@gmail.com>
    Closes: https://lore.kernel.org/io-uring/CAECZYD5OMD9vMTzjteFMMP40Dn+SWKj9SFj=43U6uO3XMnxJbw@mail.gmail.com/
    Assisted-by: LLM
    Signed-off-by: Josef Bacik <josef@toxicpanda.com>
    Link: https://patch.msgid.link/20261015-b4-io-uring-fixes-v1-23-c1556f5d7bf5@toxicpanda.com
    Signed-off-by: Jens Axboe <axboe@kernel.dk>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

io_uring: end the drain when the drain request completes [+ + +]
Author: Jens Axboe <axboe@kernel.dk>
Date:   Mon Oct 19 13:30:51 2026 -0600

    io_uring: end the drain when the drain request completes
    
    Commit ecb6817b769fd7d71af2c9f446188649020b2e53 upstream.
    
    Since requests are drained based on allocated requests, the drain stays
    active after the drain request has posted its CQE, until it is freed and
    a new request finds the defer list empty. A drain request run by io-wq
    is freed only after the worker drops its reference, so a request
    submitted after the drain completed can still be deferred behind it,
    and get issued much later than the application expects.
    
    A drain request dispatched from the defer list runs alone. Track it,
    and end the drain when its CQE is flushed and nothing else is deferred.
    Have io-wq complete drain requests through task_work, so that this
    happens under ->uring_lock before the CQE is visible. Linked drain
    requests keep waiting until the link is freed.
    
    Reported-by: Wei Gao <wegao@suse.com>
    Link: https://lore.kernel.org/io-uring/20261018070154.16944-1-wegao@suse.com/
    Fixes: 8fb7aee05591 ("io_uring: drain based on allocates reqs")
    Cc: stable@vger.kernel.org
    Tested-by: Wei Gao <wegao@suse.com>
    Signed-off-by: Jens Axboe <axboe@kernel.dk>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

io_uring: keep the drain active when a deferred drain request is started [+ + +]
Author: Jens Axboe <axboe@kernel.dk>
Date:   Tue Oct 27 12:02:04 2026 -0600

    io_uring: keep the drain active when a deferred drain request is started
    
    Commit 2295613cd3713beffc8665e956135a5d48dfc208 upstream.
    
    ecb6817b769f ends the drain when the dispatched drain request has posted
    its CQE and nothing else is deferred. But the deferred list is processed
    in between, and if the request it starts is itself a drain request, the
    drain is over before that one has even run. A request submitted after
    that point then runs ahead of it:
    
      1. P0 in flight, D1 and D2 (both IOSQE_IO_DRAIN) deferred behind it
      2. P0 completes, D1 is started
      3. D1 completes, drain_done is set, D2 is started, the list is empty
      4. IO_RING_F_DRAIN_ACTIVE is cleared with D2 still in flight
    
    Anything submitted now bypasses the drain. The same happens with D2 as
    the head of a link, as those aren't tracked in ->drain_req at all.
    
    Have io_queue_deferred() report whether it started a drain request, and
    don't end the drain if it did. Starting non-drain requests and ending it
    is still fine, they were only waiting on the drain request that just
    completed.
    
    Fixes: ecb6817b769f ("io_uring: end the drain when the drain request completes")
    Reported-by: Karl Mehltretter <kmehltretter@gmail.com>
    Link: https://lore.kernel.org/io-uring/20261027043323.98916-1-kmehltretter@gmail.com/
    Cc: stable@vger.kernel.org
    Signed-off-by: Jens Axboe <axboe@kernel.dk>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

io_uring: look up the file before queueing to io-wq [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:31:07 2026 +0000

    io_uring: look up the file before queueing to io-wq
    
    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: wake ring pollers for local task_work [+ + +]
Author: Josef Bacik <josef@toxicpanda.com>
Date:   Thu Oct 15 19:30:43 2026 +0000

    io_uring: wake ring pollers for local task_work
    
    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.
    
    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>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

 
keys/trusted_keys: return immediately after TPM unseal failure [+ + +]
Author: Srish Srinivasan <ssrish@linux.ibm.com>
Date:   Sat Sep 12 11:59:49 2026 +0530

    keys/trusted_keys: return immediately after TPM unseal failure
    
    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>

 
keys: Avoid the owner account dereference in named keyring lookup [+ + +]
Author: Cen Zhang <zzzccc427@gmail.com>
Date:   Fri Oct 9 13:11:59 2026 +0800

    keys: Avoid the owner account dereference in named keyring lookup
    
    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>

keys: Check the authorization payload in process keyring searches [+ + +]
Author: Cen Zhang <zzzccc427@gmail.com>
Date:   Fri Oct 9 13:52:16 2026 +0800

    keys: Check the authorization payload in process keyring searches
    
    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>

 
KEYS: Fix key_reject_and_link() race with keyring restriction [+ + +]
Author: Adrian Martinez <adrimg3196@gmail.com>
Date:   Sat Oct 10 23:40:00 2026 +0300

    KEYS: Fix key_reject_and_link() race with keyring restriction
    
    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>

 
keys: make keyring indexes independent of kernel addresses [+ + +]
Author: Kyle Zeng <kylebot@openai.com>
Date:   Tue Oct 13 16:12:51 2026 -0700

    keys: make keyring indexes independent of kernel addresses
    
    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>

keys: Protect the read method check against type removal [+ + +]
Author: Cen Zhang <zzzccc427@gmail.com>
Date:   Mon Oct 19 22:57:21 2026 +0800

    keys: Protect the read method check against type removal
    
    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>

keys: Protect the type name while describing a key [+ + +]
Author: Cen Zhang <zzzccc427@gmail.com>
Date:   Fri Oct 9 13:11:03 2026 +0800

    keys: Protect the type name while describing a key
    
    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>

 
KEYS: trusted: Fix blob allocation size in tpm2_key_decode() [+ + +]
Author: Stefano Garzarella <sgarzare@redhat.com>
Date:   Wed Sep 23 19:35:06 2026 +0200

    KEYS: trusted: Fix blob allocation size in tpm2_key_decode()
    
    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>

 
Linux: Linux 7.2.14 [+ + +]
Author: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Date:   Fri Oct 30 13:08:34 2026 +0100

    Linux 7.2.14
    
    Link: https://lore.kernel.org/r/20261028165942.107695352@linuxfoundation.org
    Tested-by: Brett A C Sheffield <bacs@librecast.net>
    Tested-by: Peter Schneider <pschneider1968@googlemail.com>
    Tested-by: Salvatore Bonaccorso <carnil@debian.org>
    Tested-by: Pavel Machek (CIP) <pavel@nabladev.com>
    Tested-by: Miguel Ojeda <ojeda@kernel.org>
    Tested-by: Ron Economos <re@w6rz.net>
    Tested-by: SJ Park <sj@kernel.org>
    Tested-by: Shuah Khan <skhan@linuxfoundation.org>
    Tested-by: Barry K. Nathan <barryn@pobox.com>
    Tested-by: Florian Fainelli <florian.fainelli@broadcom.com>
    Tested-by: Sean Lyon <sean@seanlyon.dev>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

 
mm/damon/core: error damos_commit_quota_goal() for zero target_value [+ + +]
Author: SJ Park <sj@kernel.org>
Date:   Mon Oct 26 06:36:43 2026 -0700

    mm/damon/core: error damos_commit_quota_goal() for zero target_value
    
    [ Upstream commit 610c4438fb66e06d9e693c0ad3b2c1be54c0d61f ]
    
    Patch series "mm/damon: move zero damos quota target_value handling to the
    core layer".
    
    Having zero DAMOS quota target value can cause division by zero.  DAMON
    API callers are checking the target value parameters to avoid that.  It is
    easy to make mistakes in some of the multiple API callers.  Move that to
    the core layer.
    
    Patch 1 adds the corner case handling into the core layer DAMON parameters
    validation logic.  Patches 2 and 3 remove no more needed DAMON API callers
    side handling of the corner case in DAMON_LRU_SORT and DMON_SAMPLIE_MTIER,
    respectively.
    
    This patch (of 3):
    
    If a DAMOS scheme has a damos_quota_goal of zero target_value,
    damos_quota_goal() could trigger division-by-zero error.  Hence each DAMON
    API callers should do the zero target_value validation.  It is easy to
    make mistakes.  Actually such bugs in DAMON_LRU_SORT and
    DAMON_SAMPLE_MTIER were found and fixed [1].
    
    It is better to handle the corner case only once in the core layer,
    instead of multiple places in all DAMON API callers.  One straightforward
    option is using an alternative denominator for the corner case in the
    damos_quota_goal().  However, the zero target_value is meaningless.  In
    this case, the quota goal is always evaluated as achieved or
    over-achieved.  The quota will only keep being reduced.
    
    Simply avoid using zero target_value by adding a check in the core layer
    DAMOS quota goal parameters validation/commit path,
    damos_commit_quota_goal().  Update it to return an error in the case.
    Also update its caller to propagate the error.
    
    Notes for stable kernel porting.  The upstream commit doesn't have
    Fixes: and therefore not ported to stable kernels.  It turned out it
    fixes commit 8b549a4fd3c5 ("mm/damon/sysfs-schemes: commit damos quota
    goals user input to DAMOS") which was merged into v6.8.  The user impact
    is a race condition that can result in divide-by-zero.  Hence backport.
    Reproducing the issue requires sysfs write permission, certain DAMON ABI
    usages that are supposed to be uncommon, and a rare race timing, though.
    The issue was discovered [2] by Sashiko as a part [3] of its bug report.
    
    Also, the upstream commit on this stable kernel can fix the issue for
    parameters commit paths but DAMON start path.  That's because DAMON
    start path does not invoke damon_commit_quota_goals().  To fix the path
    with minimum change, add a new small validation of quota goal target
    value before damon_start() call.
    
    [2] https://sashiko.dev/#/bug/linux-7f814c9a-986f-4103-a55a-ef9537dcf62b
    [3] https://lore.kernel.org/20261021005234.94107-1-sj@kernel.org
    
    Link: https://lore.kernel.org/20260903010722.94244-1-sj@kernel.org
    Link: https://lore.kernel.org/20260903010722.94244-2-sj@kernel.org
    Link: https://lore.kernel.org/20260803134034.15217-1-sj@kernel.org [1]
    Signed-off-by: SJ Park <sj@kernel.org>
    Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
    Signed-off-by: SJ Park <sj@kernel.org>
    Signed-off-by: Sasha Levin <sashal@kernel.org>

 
ntfs: fix race between fallocate and mmap reads [+ + +]
Author: Hongling Zeng <zenghongling@kylinos.cn>
Date:   Mon Oct 26 10:55:32 2026 +0900

    ntfs: fix race between fallocate and mmap reads
    
    [ Upstream commit 67aded1da114dc44808315f249bd9e7e440f799d ]
    
    The fallocate implementation only takes invalidate_lock for punch hole,
    collapse range, and insert range operations. For standard allocation modes
    (mode == 0, FALLOC_FL_KEEP_SIZE), the lock is not held.
    
    During ntfs_attr_fallocate(), new clusters are mapped to the runlist via
    ntfs_attr_map_cluster() before being zeroed by ntfs_dio_zero_range(). This
    creates a window where concurrent mmap page faults can read uninitialized
    disk data.
    
    Since mmap uses filemap_fault() which takes invalidate_lock in shared mode,
    it can fault in pages during this window and expose old disk contents to
    userspace. This is an information leak and data integrity issue.
    
    Fix by taking invalidate_lock for all fallocate operations, not just for
    punch/collapse/insert modes. This prevents concurrent page faults from
    accessing unzeroed clusters during the allocation window.
    
    Fixes: 495e90fa3348 ("ntfs: update attrib operations")
    Cc: stable@vger.kernel.org
    Reviewed-by: Baolin Liu <liubaolin@kylinos.cn>
    Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com>
    Signed-off-by: Hongling Zeng <zenghongling@kylinos.cn>
    Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
    Stable-dep-of: 0fecc393f206 ("ntfs: take invalidate_lock in ntfs_filemap_page_mkwrite")
    Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>

ntfs: take invalidate_lock in ntfs_filemap_page_mkwrite() [+ + +]
Author: Hongling Zeng <zenghongling@kylinos.cn>
Date:   Mon Oct 26 10:55:33 2026 +0900

    ntfs: take invalidate_lock in ntfs_filemap_page_mkwrite()
    
    [ Upstream commit 0fecc393f2060e6bc25138df32cb923ec7071c6b ]
    
    ntfs_filemap_page_mkwrite() calls iomap_page_mkwrite() without holding
    mapping->invalidate_lock, so a concurrent truncate or fallocate can be in
    the middle of invalidating pagecache and rewriting the runlist while the write
    fault maps blocks and dirties the folio. This races with ntfs_attr_fallocate(),
    which merges clusters into the in-memory runlist, drops the runlist lock, and
    only afterwards zeroes the newly allocated clusters on disk; and with the
    punch-hole/insert/collapse paths that free clusters after truncating the cache.
    
    Per Documentation/filesystems/locking.rst, ->page_mkwrite() must ensure there
    are no truncate/invalidate races, "usually mapping->invalidate_lock is suitable
    for proper serialization". xfs takes its mmaplock (= the invalidate_lock
    rwsem) shared in exactly this path.
    
    Take invalidate_lock shared around iomap_page_mkwrite(). The read-only fault
    path is already covered because filemap_fault() itself grabs invalidate_lock
    shared on instantiation/read paths; only page_mkwrite was bypassing it in this
    driver.
    
    Fixes: 9c87959601e8 ("ntfs: update file operations")
    Cc: stable@vger.kernel.org
    Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com>
    Reviewed-by: Baolin Liu <liubaolin@kylinos.cn>
    Signed-off-by: Hongling Zeng <zenghongling@kylinos.cn>
    Co-developed-by: Namjae Jeon <linkinjeon@kernel.org>
    Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
    Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>

 
pid_namespace: prevent TIF_NOTIFY_SIGNAL from interrupting the reaper [+ + +]
Author: Christian Brauner <brauner@kernel.org>
Date:   Mon Aug 24 14:08:20 2026 +0200

    pid_namespace: prevent TIF_NOTIFY_SIGNAL from interrupting the reaper
    
    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>

 
ptrace: refuse to change the signal mask of a user worker [+ + +]
Author: Christian Brauner <brauner@kernel.org>
Date:   Mon Sep 21 15:44:58 2026 +0200

    ptrace: refuse to change the signal mask of a user worker
    
    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>

 
sched/fair: Avoid overflow in place_entity() [+ + +]
Author: Hui Su <sh_def@163.com>
Date:   Mon Oct 26 11:41:09 2026 +0100

    sched/fair: Avoid overflow in place_entity()
    
    [ Upstream commit 2f93bcb3f9aaf6ceee1aec0a97d4fe386d48e781 ]
    
    place_entity() inflates an entity's virtual lag with
    
        lag * (load + weight) / load
    
    Commit 4823725d9d1d ("sched/fair: Increase weight bits for avg_vruntime")
    replaced the scaled-down weights used in this calculation with
    avg_vruntime_weight(), removing the arithmetic headroom provided by
    scale_load_down().
    
    The multiplication can overflow s64 before the division even when the
    final quotient is representable. A task's hierarchical effective weight
    can be as small as 2 after avg_vruntime_weight() scaling under group
    scheduling, while entity_lag() bounds |vlag| by
    
        calc_delta_fair(cfs_rq_max_slice(cfs_rq) + TICK_NSEC, se)
    
    For example, with HZ=1000, NICE_0_LOAD=1048576, and the minimum scaled
    hierarchical weight scale_load(2)=2048, this bound is 891289600. With 114
    maximum-weight entities, the runqueue load is 10361604096. The
    intermediate product is:
    
        891289600 * (10361604096 + 2)
            = 9235189971864780800
            > S64_MAX
    
    The signed overflow corrupts the entity's placement.
    
    Rewrite
    
        lag * (load + weight) / load
    
    as
    
        lag + lag * weight / load
    
    The two expressions are equivalent, but the latter avoids multiplying the
    virtual lag by the total runqueue weight. entity_lag() bounds vlag against
    the entity's effective weight, so the remaining lag * weight product stays
    bounded. rescale_entity() preserves this scale across h_load changes and
    already relies on the same product when rescaling vlag.
    
    Keep the original zero-load warning semantics by multiplying lag by weight
    after replacing the divisor with one.
    
    Fixes: 4823725d9d1d ("sched/fair: Increase weight bits for avg_vruntime")
    Signed-off-by: Hui Su <sh_def@163.com>
    Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
    Link: https://patch.msgid.link/20260928124754.1692077-1-sh_def@163.com
    [ Backport to v7.2 which doesn't have flat hierarchy ]
    Signed-off-by: Vincent Guittot <vincent.guittot@linaro.org>
    Cc: stable@vger.kernel.org
    Signed-off-by: Sasha Levin <sashal@kernel.org>

 
sched_ext: Wait for SCX_OPSS_DISPATCHING before moving tasks off DSQs [+ + +]
Author: Kuba Piecuch <jpiecuch@google.com>
Date:   Sat Oct 24 17:25:13 2026 +0800

    sched_ext: Wait for SCX_OPSS_DISPATCHING before moving tasks off DSQs
    
    [ Upstream commit 2935062be77113c1c4565ca9d0c72180449aafee ]
    
    A task can be found on a non-local DSQ while the CPU which dispatched it
    is still running ops.dequeue() and hasn't cleared SCX_OPSS_DISPATCHING.
    The DSQ consume and move paths don't wait for the dispatch to finish and
    can operate on the task concurrently with the dispatcher.
    
    Call scx_wait_dispatching() in scx_move_local_task_to_local_dsq(),
    unlink_dsq_and_switch_rq_lock() and move_task_between_dsqs() before they
    operate on the task. In scx_move_local_task_to_local_dsq(), wait before
    scx_resolve_local_dsq() as it may update p->scx.flags.
    
    Fixes: ebf1ccff79c4 ("sched_ext: Fix ops.dequeue() semantics")
    Fixes: cb86607ada73 ("sched_ext: Don't run ops.dequeue() with a DSQ lock held")
    Cc: stable@vger.kernel.org # v7.1+
    Reviewed-by: Andrea Righi <arighi@nvidia.com>
    Assisted-by: Claude:claude-opus-5.5
    Signed-off-by: Kuba Piecuch <jpiecuch@google.com>
    Signed-off-by: Tejun Heo <tj@kernel.org>
    [ Inlined scx_wait_dispatching(), which 7.2.y doesn't have, into
      move_local_task_to_local_dsq(), unlink_dsq_and_lock_src_rq() and
      move_task_between_dsqs(), as was done for the reenqueue paths in
      7.2.y. 7.2.y has no scx_resolve_local_dsq(), so
      move_local_task_to_local_dsq() waits before linking the task. ]
    Signed-off-by: Cheng-Yang Chou <yphbchou0911@gmail.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
 
signal: allow taks to temporarily block TIF_NOTIFY_SIGNAL [+ + +]
Author: Christian Brauner <brauner@kernel.org>
Date:   Mon Aug 24 14:08:16 2026 +0200

    signal: allow taks to temporarily block TIF_NOTIFY_SIGNAL
    
    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>

signal: don't retarget shared signals in a dying thread group [+ + +]
Author: Christian Brauner <brauner@kernel.org>
Date:   Mon Sep 21 15:44:54 2026 +0200

    signal: don't retarget shared signals in a dying thread group
    
    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>

signal: only SIGKILL and the freezers interrupt a coredumping task [+ + +]
Author: Christian Brauner <brauner@kernel.org>
Date:   Tue Sep 22 15:26:16 2026 +0200

    signal: only SIGKILL and the freezers interrupt a coredumping task
    
    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>

 
tools/dma: fix building with O= [+ + +]
Author: Sasha Levin <sashal@kernel.org>
Date:   Sun Oct 11 18:33:31 2026 -0400

    tools/dma: fix building with O=
    
    commit 9441e7eca18c8004d1afe57b2f9b27717549562a upstream.
    
    With O= set, "all" depends on $(OUTPUT)dma_map_benchmark, but the only
    rule builds dma_map_benchmark in the source directory, and built-in
    rules are disabled:
    
      make: *** No rule to make target '<O>/dma_map_benchmark', needed by 'all'.  Stop.
    
    Build $(OUTPUT)dma_map_benchmark.
    
    Fixes: f74ee32963f1b ("tools/dma: move dma_map_benchmark from selftests to tools/dma")
    Cc: stable@vger.kernel.org
    Assisted-by: LLM
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    Acked-by: Qinxin Xia <xiaqinxin@huawei.com>
    Link: https://lore.kernel.org/r/20261011223358.2327625-3-sashal@kernel.org
    Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

 
tracing/histograms: Verify event_call identity when updating synth_event refcount [+ + +]
Author: Lee Jones <lee@kernel.org>
Date:   Mon Oct 19 12:07:29 2026 +0000

    tracing/histograms: Verify event_call identity when updating synth_event refcount
    
    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>

 
tracing/syscalls: Use copy_from_user for the faultable syscall buffer [+ + +]
Author: Haoran Wang <haoranwangsec@gmail.com>
Date:   Fri Oct 16 11:33:13 2026 +0800

    tracing/syscalls: Use copy_from_user for the faultable syscall buffer
    
    commit 097fd0050089df17b032f2b852b9b65e548e342a upstream.
    
    syscall_copy_user_array() copies the buffer argument of faultable
    syscalls (write, pwrite64, ...) with __copy_from_user(), which skips
    access_ok(). Use copy_from_user() instead so a non-user address is
    rejected and the entry is recorded as faulted.
    
    It could be a security concern for machines that trust perf a bit too
    much.
    
    Cc: stable@vger.kernel.org
    Fixes: baa031b7bd2ce ("tracing: Allow syscall trace events to read more than one user parameter")
    Link: https://patch.msgid.link/6ad19afd.a938ce27.16851e.3440@mx.google.com
    Signed-off-by: Haoran Wang <haoranwangsec@gmail.com>
    Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

 
tracing: Fix 64-bit and signed histogram fields on 32-bit kernels [+ + +]
Author: Donggeun Yoo <donggeunyoo.kernel@gmail.com>
Date:   Thu Sep 17 10:55:32 2026 +0900

    tracing: Fix 64-bit and signed histogram fields on 32-bit kernels
    
    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>

tracing: Hold trace_types_lock when resetting last boot data from readers [+ + +]
Author: David Carlier <devnexen@gmail.com>
Date:   Fri Oct 16 07:16:35 2026 +0100

    tracing: Hold trace_types_lock when resetting last boot data from readers
    
    commit 5a6bd62f09147b49b31fd19d4eba122cb5f941a1 upstream.
    
    update_last_data_if_empty() is called from tracing_open() with O_TRUNC,
    tracing_read_pipe() and tracing_buffers_read() without trace_types_lock.
    Two readers can both pass the LAST_BOOT test and free module_delta
    twice, and a module notifier can update module_delta while it is being
    freed.
    
    Take trace_types_lock in those paths and keep the callers that already
    hold it on an unlocked variant.
    
    Cc: stable@vger.kernel.org
    Fixes: 32dc0042528d ("tracing: Reset last-boot buffers when reading out all cpu buffers")
    Link: https://patch.msgid.link/20261016061638.214847-2-devnexen@gmail.com
    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>

tracing: Hold trace_types_lock when updating modules in persistent instances [+ + +]
Author: David Carlier <devnexen@gmail.com>
Date:   Fri Oct 16 07:16:34 2026 +0100

    tracing: Hold trace_types_lock when updating modules in persistent instances
    
    commit 66877a312ae3c2c3d849e82e882f642ffd4ec3e2 upstream.
    
    trace_module_record() walks ftrace_trace_arrays from the module notifier
    without trace_types_lock. A concurrent rmdir of an instance removes it
    from the list and frees it under that lock, so a module load or unload
    can walk into a freed trace_array.
    
    Cc: stable@vger.kernel.org
    Fixes: 5f3719f697c3 ("tracing: Update modules to persistent instances when loaded")
    Link: https://patch.msgid.link/20261016061638.214847-1-devnexen@gmail.com
    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>

tracing: Reject incomplete event filter expressions [+ + +]
Author: Kyle Zeng <kylebot@openai.com>
Date:   Fri Oct 23 10:46:20 2026 -0700

    tracing: Reject incomplete event filter expressions
    
    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>

tracing: Save the event file instead of the compatible histogram [+ + +]
Author: Donggeun Yoo <donggeunyoo.kernel@gmail.com>
Date:   Tue Sep 15 08:47:54 2026 +0900

    tracing: Save the event file instead of the compatible histogram
    
    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>

tracing: Unregister field variable histograms when the command fails [+ + +]
Author: Donggeun Yoo <donggeunyoo.kernel@gmail.com>
Date:   Mon Sep 14 19:40:36 2026 +0900

    tracing: Unregister field variable histograms when the command fails
    
    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>