Re: [PATCH] sched/mmcid: Don't assume CID is CPU owned on mode switch

From: Takashi Iwai

Date: Wed Feb 11 2026 - 05:38:02 EST


On Tue, 10 Feb 2026 17:20:51 +0100,
Thomas Gleixner wrote:
>
> Shinichiro reported a KASAN UAF, which is actually an out of bounds access
> in the MMCID management code.
>
> CPU0 CPU1
> T1 runs in userspace
> T0: fork(T4) -> Switch to per CPU CID mode
> fixup() set MM_CID_TRANSIT on T1/CPU1
> T4 exit()
> T3 exit()
> T2 exit()
> T1 exit() switch to per task mode
> ---> Out of bounds access.
>
> As T1 has not scheduled after T0 set the TRANSIT bit, it exits with the
> TRANSIT bit set. sched_mm_cid_remove_user() clears the TRANSIT bit in
> the task and drops the CID, but it does not touch the per CPU storage.
> That's functionally correct because a CID is only owned by the CPU when
> the ONCPU bit is set, which is mutually exclusive with the TRANSIT flag.
>
> Now sched_mm_cid_exit() assumes that the CID is CPU owned because the
> prior mode was per CPU. It invokes mm_drop_cid_on_cpu() which clears the
> not set ONCPU bit and then invokes clear_bit() with an insanely large
> bit number because TRANSIT is set (bit 29).
>
> Prevent that by actually validating that the CID is CPU owned in
> mm_drop_cid_on_cpu().
>
> Fixes: 007d84287c74 ("sched/mmcid: Drop per CPU CID immediately when switching to per task mode")
> Reported-by: Shinichiro Kawasaki <shinichiro.kawasaki@xxxxxxx>
> Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxx>
> Tested-by: Shinichiro Kawasaki <shinichiro.kawasaki@xxxxxxx>
> Cc: stable@xxxxxxxxxxxxxxx
> Closes: https://lore.kernel.org/aYsZrixn9b6s_2zL@shinmob

FWIW, I actually hit this bug yesterday on my laptop with 6.19 kernel,
so it's not only theoretical.

---- 8< ----
Feb 10 12:35:20 valkyrie kernel: BUG: unable to handle page fault for address: ffff8ec348b322d0
Feb 10 12:35:20 valkyrie kernel: #PF: supervisor write access in kernel mode
Feb 10 12:35:20 valkyrie kernel: #PF: error_code(0x0003) - permissions violation
Feb 10 12:35:20 valkyrie kernel: PGD 345801067 P4D 345801067 PUD 107790063 PMD 146391063 PTE 8000000148b32121
Feb 10 12:35:20 valkyrie kernel: Oops: Oops: 0003 [#1] SMP NOPTI
Feb 10 12:35:20 valkyrie kernel: CPU: 5 UID: 1000 PID: 17173 Comm: git Tainted: G E 6.19.0-test+ #679 PREEMPT(voluntary) 18755027502f5b378a0509f6d0a6ba52d8674d8b
Feb 10 12:35:20 valkyrie kernel: Tainted: [E]=UNSIGNED_MODULE
Feb 10 12:35:20 valkyrie kernel: Hardware name: LENOVO 21M2S03K00/21M2S03K00, BIOS R2NET42W (1.16 ) 10/10/2025
Feb 10 12:35:20 valkyrie kernel: RIP: 0010:sched_mm_cid_exit+0xdf/0x1f0
Feb 10 12:35:20 valkyrie kernel: Code: 48 03 05 8c e9 48 02 8b 08 81 e1 ff ff ff bf 89 08 8b 05 34 74 b7 01 83 c0 3f c1 e8 03 25 f8 ff ff 1f 48 8d 84 43 c0 06 00 00 <f0> 48 0f b3 08 48 81 fe ff ef ff ff 77 08 48 89 d7 e8 4b a7 cc 00
Feb 10 12:35:20 valkyrie kernel: RSP: 0018:ffffd4358bea3c08 EFLAGS: 00010002
Feb 10 12:35:20 valkyrie kernel: RAX: ffff8ec344b322d0 RBX: ffff8ec344b31c00 RCX: 0000000020000008
Feb 10 12:35:20 valkyrie kernel: RDX: ffff8ec344b31d10 RSI: ffff8ec344b31d0f RDI: 0000000000000007
Feb 10 12:35:20 valkyrie kernel: RBP: 0000000000000000 R08: 0000000000000010 R09: 0000000000000001
Feb 10 12:35:20 valkyrie kernel: R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000
Feb 10 12:35:20 valkyrie kernel: R13: ffff8ec370e76300 R14: ffff8ec30c100000 R15: 0000000000000000
Feb 10 12:35:20 valkyrie kernel: FS: 00007f7e95e956c0(0000) GS:ffff8ed292088000(0000) knlGS:0000000000000000
Feb 10 12:35:20 valkyrie kernel: CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
Feb 10 12:35:20 valkyrie kernel: CR2: ffff8ec348b322d0 CR3: 0000000108f7b000 CR4: 0000000000f50ef0
Feb 10 12:35:20 valkyrie kernel: PKRU: 55555554
Feb 10 12:35:20 valkyrie kernel: Call Trace:
Feb 10 12:35:20 valkyrie kernel: <TASK>
Feb 10 12:35:20 valkyrie kernel: do_exit+0xad/0xa70
Feb 10 12:35:20 valkyrie kernel: __x64_sys_exit+0x1b/0x20
Feb 10 12:35:20 valkyrie kernel: x64_sys_call+0x1502/0x1510
Feb 10 12:35:20 valkyrie kernel: do_syscall_64+0x81/0x650
Feb 10 12:35:20 valkyrie kernel: ? do_syscall_64+0x81/0x650
Feb 10 12:35:20 valkyrie kernel: ? __do_sys_newfstatat+0x32/0x60
Feb 10 12:35:20 valkyrie kernel: ? do_syscall_64+0x81/0x650
Feb 10 12:35:20 valkyrie kernel: ? do_syscall_64+0x81/0x650
Feb 10 12:35:20 valkyrie kernel: ? do_syscall_64+0x81/0x650
Feb 10 12:35:20 valkyrie kernel: ? do_syscall_64+0x81/0x650
Feb 10 12:35:20 valkyrie kernel: ? do_syscall_64+0x81/0x650
Feb 10 12:35:20 valkyrie kernel: ? do_syscall_64+0x81/0x650
Feb 10 12:35:20 valkyrie kernel: ? __irq_exit_rcu+0x3d/0xe0
Feb 10 12:35:20 valkyrie kernel: entry_SYSCALL_64_after_hwframe+0x76/0x7e
Feb 10 12:35:20 valkyrie kernel: RIP: 0033:0x7f7ea21de556
Feb 10 12:35:20 valkyrie kernel: Code: 8b 44 24 08 31 c9 48 89 88 20 06 00 00 31 c0 87 03 83 e8 01 7f 16 ba 3c 00 00 00 66 0f 1f 84 00 00 00 00 00 31 ff 89 d0 0f 05 <eb> f8 48 89 df e8 be cd ff ff 83 ed 01 0f 85 aa fd ff ff eb d7 48
Feb 10 12:35:20 valkyrie kernel: RSP: 002b:00007f7e95e94ee0 EFLAGS: 00000246 ORIG_RAX: 000000000000003c
Feb 10 12:35:20 valkyrie kernel: RAX: ffffffffffffffda RBX: 00007f7e95e95cdc RCX: 00007f7ea21de556
Feb 10 12:35:20 valkyrie kernel: RDX: 000000000000003c RSI: 0000000000800000 RDI: 0000000000000000
Feb 10 12:35:20 valkyrie kernel: RBP: 00007f7e95695000 R08: 00000000000000ca R09: 0000000000000007
Feb 10 12:35:20 valkyrie kernel: R10: 0000000000000008 R11: 0000000000000246 R12: 0000000000801000
Feb 10 12:35:20 valkyrie kernel: R13: 0000000000000000 R14: 00007ffcf5038cc0 R15: 00007f7e95695000
Feb 10 12:35:20 valkyrie kernel: </TASK>
Feb 10 12:35:20 valkyrie kernel: Modules linked in: tun(E) ccm(E) michael_mic(E) rfcomm(E) snd_seq_dummy(E) snd_hrtimer(E) snd_seq(E) snd_seq_device(E) nft_fib_inet(E) nft_fib_ipv4(E) nft_fib_ipv6(E) nft_fib(E) nft_reject_inet(E) nf_reject_ipv4(E) nf_reject_ipv6(E) nft_reject(E) nft_ct(E) af_packet(E) nft_chain_nat(E) nf_nat(E) nf_conntrack(E) nf_defrag_ipv6(E) nf_defrag_ipv4(E) cmac(E) algif_hash(E) algif_skcipher(E) af_alg(E) ip_set(E) bnep(E) binfmt_misc(E) nls_iso8859_1(E) nls_cp437(E) vfat(E) fat(E) qrtr_mhi(E) snd_acp_legacy_mach(E) snd_acp_mach(E) snd_soc_nau8821(E) snd_acp3x_rn(E) snd_acp70(E) snd_acp_i2s(E) snd_acp_pdm(E) snd_soc_dmic(E) snd_acp_pcm(E) snd_sof_amd_acp70(E) snd_sof_amd_acp63(E) snd_sof_amd_vangogh(E) snd_sof_amd_rembrandt(E) snd_sof_amd_renoir(E) snd_sof_amd_acp(E) snd_sof_pci(E) snd_sof_xtensa_dsp(E) snd_ctl_led(E) snd_sof(E) snd_hda_codec_alc269(E) snd_sof_utils(E) snd_hda_scodec_component(E) snd_pci_ps(E) snd_hda_codec_realtek_lib(E) snd_soc_acpi_amd_match
(E) snd_soc_acpi_amd_sdca_quirks(E)
Feb 10 12:35:20 valkyrie kernel: snd_hda_codec_generic(E) snd_soc_sdca(E) snd_hda_codec_atihdmi(E) snd_hda_codec_hdmi(E) qrtr(E) snd_soc_core(E) intel_rapl_msr(E) amd_atl(E) snd_hda_intel(E) snd_compress(E) intel_rapl_common(E) btusb(E) snd_rpl_pci_acp6x(E) btrtl(E) ath12k(E) snd_hda_codec(E) snd_acp_pci(E) btintel(E) snd_intel_dspcfg(E) btbcm(E) uvcvideo(E) snd_amd_acpi_mach(E) mhi(E) snd_hda_core(E) btmtk(E) videobuf2_vmalloc(E) snd_acp_legacy_common(E) kvm_amd(E) videobuf2_memops(E) qmi_helpers(E) snd_pci_acp6x(E) spd5118(E) bluetooth(E) snd_hwdep(E) uvc(E) kvm(E) snd_pci_acp5x(E) videobuf2_v4l2(E) mac80211(E) amd_pmf(E) think_lmi(E) snd_pcm(E) thinkpad_acpi(E) videodev(E) snd_rn_pci_acp3x(E) irqbypass(E) amdtee(E) libarc4(E) snd_acp_config(E) sparse_keymap(E) snd_timer(E) snd_soc_acpi(E) i2c_piix4(E) videobuf2_common(E) platform_profile(E) pcspkr(E) mc(E) wmi_bmof(E) firmware_attributes_class(E) snd(E) tiny_power_button(E) cfg80211(E) snd_pci_acp3x(E) soundcore(E) k10temp(E) i2c
_smbus(E) thermal(E) battery(E) rfkill(E) ac(E)
Feb 10 12:35:20 valkyrie kernel: amd_sfh(E) fan(E) button(E) tee(E) joydev(E) amd_pmc(E) loop(E) fuse(E) dm_mod(E) efi_pstore(E) dmi_sysfs(E) ip_tables(E) x_tables(E) ext4(E) mbcache(E) jbd2(E) amdgpu(E) amdxcp(E) ucsi_acpi(E) i2c_algo_bit(E) drm_ttm_helper(E) typec_ucsi(E) ttm(E) roles(E) drm_exec(E) drm_panel_backlight_quirks(E) typec(E) drm_suballoc_helper(E) xhci_pci(E) nvme(E) drm_buddy(E) drm_display_helper(E) nvme_core(E) cec(E) hid_multitouch(E) nvme_keyring(E) xhci_hcd(E) video(E) rc_core(E) amdxdna(E) hid_generic(E) nvme_auth(E) ghash_clmulni_intel(E) sp5100_tco(E) gpu_sched(E) usbcore(E) ccp(E) crc16(E) hkdf(E) thunderbolt(E) wmi(E) i2c_hid_acpi(E) i2c_hid(E) serio_raw(E) br_netfilter(E) bridge(E) stp(E) llc(E) nf_tables(E) msr(E) nfnetlink(E) efivarfs(E) aesni_intel(E)
Feb 10 12:35:20 valkyrie kernel: CR2: ffff8ec348b322d0
Feb 10 12:35:20 valkyrie kernel: ---[ end trace 0000000000000000 ]---
Feb 10 12:35:20 valkyrie kernel: RIP: 0010:sched_mm_cid_exit+0xdf/0x1f0
Feb 10 12:35:20 valkyrie kernel: Code: 48 03 05 8c e9 48 02 8b 08 81 e1 ff ff ff bf 89 08 8b 05 34 74 b7 01 83 c0 3f c1 e8 03 25 f8 ff ff 1f 48 8d 84 43 c0 06 00 00 <f0> 48 0f b3 08 48 81 fe ff ef ff ff 77 08 48 89 d7 e8 4b a7 cc 00
Feb 10 12:35:20 valkyrie kernel: RSP: 0018:ffffd4358bea3c08 EFLAGS: 00010002
Feb 10 12:35:20 valkyrie kernel: RAX: ffff8ec344b322d0 RBX: ffff8ec344b31c00 RCX: 0000000020000008
Feb 10 12:35:20 valkyrie kernel: RDX: ffff8ec344b31d10 RSI: ffff8ec344b31d0f RDI: 0000000000000007
Feb 10 12:35:20 valkyrie kernel: RBP: 0000000000000000 R08: 0000000000000010 R09: 0000000000000001
Feb 10 12:35:20 valkyrie kernel: R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000
Feb 10 12:35:20 valkyrie kernel: R13: ffff8ec370e76300 R14: ffff8ec30c100000 R15: 0000000000000000
Feb 10 12:35:20 valkyrie kernel: FS: 00007f7e95e956c0(0000) GS:ffff8ed292088000(0000) knlGS:0000000000000000
Feb 10 12:35:20 valkyrie kernel: CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
Feb 10 12:35:20 valkyrie kernel: CR2: ffff8ec348b322d0 CR3: 0000000108f7b000 CR4: 0000000000f50ef0
Feb 10 12:35:20 valkyrie kernel: PKRU: 55555554
Feb 10 12:35:20 valkyrie kernel: note: git[17173] exited with irqs disabled
Feb 10 12:35:20 valkyrie kernel: note: git[17173] exited with preempt_count 1
---- 8< ----

The stack decode showed the very same code path.

% scripts/faddr2line vmlinux 'sched_mm_cid_exit+0xdf'
sched_mm_cid_exit+0xdf/0x1f0:
arch_clear_bit at arch/x86/include/asm/bitops.h:79
(inlined by) clear_bit at include/asm-generic/bitops/instrumented-atomic.h:42
(inlined by) mm_drop_cid at kernel/sched/sched.h:3746
(inlined by) mm_drop_cid_on_cpu at kernel/sched/sched.h:3762
(inlined by) sched_mm_cid_exit at kernel/sched/core.c:10737

This happened only once, and can't be reproduced since then, though.
I must have been a very bad lock yesterday.


Takashi