6.18.24-rc1 review
Subsystems (6)
Greg Kroah-Hartman
maintainerPATCH 165/198 KVM: selftests: Remove duplicate LAUNCH_UPDATE_VMSA call in SEV-ES migrate test
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Christopherson <[email protected]>
commit 25a642b6abc98bbbabbf2baef9fc498bbea6aee6 upstream.
Drop the explicit KVM_SEV_LAUNCH_UPDATE_VMSA call when creating an SEV-ES VM in the SEV migration test, as sev_vm_create() automatically updates the VMSA pages for SEV-ES guests. The only reason the duplicate call doesn't cause visible problems is because the test doesn't actually try to run the vCPUs. That will change when KVM adds a check to prevent userspace from re-launching a VMSA (which corrupts the VMSA page due to KVM writing encrypted private memory).
--- tools/testing/selftests/kvm/x86/sev_migrate_tests.c | 2 -- 1 file changed, 2 deletions(-)
tools/testing/selftests/kvm/x86/sev_migrate_tests.c +0 -2
@@ -36,8 +36,6 @@ static struct kvm_vm *sev_vm_create(boolsev_vm_launch (vm, es ?SEV_POLICY_ES :0 ); -if (es) -vm_sev_ioctl (vm,KVM_SEV_LAUNCH_UPDATE_VMSA ,NULL );return vm; }
Greg Kroah-Hartman
maintainerPATCH 166/198 KVM: SEV: Reject attempts to sync VMSA of an already-launched/encrypted vCPU
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Christopherson <[email protected]>
commit 9b9f7962e3e879d12da2bf47e02a24ec51690e3d upstream.
Reject synchronizing vCPU state to its associated VMSA if the vCPU has already been launched, i.e. if the VMSA has already been encrypted. On a host with SNP enabled, accessing guest-private memory generates an RMP #PF and panics the host.
BUG: unable to handle page fault for address: ff1276cbfdf36000 #PF: supervisor write access in kernel mode #PF: error_code(0x80000003) - RMP violation PGD 5a31801067 P4D 5a31802067 PUD 40ccfb5063 PMD 40e5954063 PTE 80000040fdf36163 SEV-SNP: PFN 0x40fdf36, RMP entry: [0x6010fffffffff001 - 0x000000000000001f] Oops: Oops: 0003 [#1] SMP NOPTI CPU: 33 UID: 0 PID: 996180 Comm: qemu-system-x86 Tainted: G OE Tainted: [O]=OOT_MODULE, [E]=UNSIGNED_MODULE Hardware name: Dell Inc. PowerEdge R7625/0H1TJT, BIOS 1.5.8 07/21/2023 RIP: 0010:sev_es_sync_vmsa+0x54/0x4c0 [kvm_amd] Call Trace: <TASK> snp_launch_update_vmsa+0x19d/0x290 [kvm_amd] snp_launch_finish+0xb6/0x380 [kvm_amd] sev_mem_enc_ioctl+0x14e/0x720 [kvm_amd] kvm_arch_vm_ioctl+0x837/0xcf0 [kvm] kvm_vm_ioctl+0x3fd/0xcc0 [kvm] __x64_sys_ioctl+0xa3/0x100 x64_sys_call+0xfe0/0x2350 do_syscall_64+0x81/0x10f0 entry_SYSCALL_64_after_hwframe+0x76/0x7e RIP: 0033:0x7ffff673287d </TASK>
Note, the KVM flaw has been present since commit ad73109ae7ec ("KVM: SVM:
Provide support to launch and run an SEV-ES guest"), but has only been actively dangerous for the host since SNP support was added. With SEV-ES, KVM would "just" clobber guest state, which is totally fine from a host kernel perspective since userspace can clobber guest state any time before sev_launch_update_vmsa().
--- arch/x86/kvm/svm/sev.c | 3 +++ 1 file changed, 3 insertions(+)
arch/x86/kvm/svm/sev.c +3 -0
@@ -871,6 +871,9 @@ static int sev_es_sync_vmsa(struct vcpu_u8 *d;int i; +if (vcpu->arch.guest_state_protected) +return -EINVAL ; +/* Check some debug related fields before encrypting the VMSA */ if (svm->vcpu.guest_debug || (svm->vmcb->save.dr7 & ~DR7_FIXED_1 ))return -EINVAL ;
Greg Kroah-Hartman
maintainerPATCH 167/198 KVM: SEV: Protect *all* of sev_mem_enc_register_region() with kvm->lock
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Christopherson <[email protected]>
commit b6408b6cec5df76a165575777800ef2aba12b109 upstream.
Take and hold kvm->lock for before checking sev_guest() in sev_mem_enc_register_region(), as sev_guest() isn't stable unless kvm->lock is held (or KVM can guarantee KVM_SEV_INIT{2} has completed and can't rollack state). If KVM_SEV_INIT{2} fails, KVM can end up trying to add to a not-yet-initialized sev->regions_list, e.g. triggering a #GP
Oops: general protection fault, probably for non-canonical address 0xdffffc0000000000: 0000 [#1] SMP KASAN NOPTI KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007] CPU: 110 UID: 0 PID: 72717 Comm: syz.15.11462 Tainted: G U W O 6.16.0-smp-DEV #1 NONE Tainted: [U]=USER, [W]=WARN, [O]=OOT_MODULE Hardware name: Google, Inc. Arcadia_IT_80/Arcadia_IT_80, BIOS 12.52.0-0 10/28/2024 RIP: 0010:sev_mem_enc_register_region+0x3f0/0x4f0 ../include/linux/list.h:83 Code: <41> 80 3c 04 00 74 08 4c 89 ff e8 f1 c7 a2 00 49 39 ed 0f 84 c6 00 RSP: 0018:ffff88838647fbb8 EFLAGS: 00010256 RAX: dffffc0000000000 RBX: 1ffff92015cf1e0b RCX: dffffc0000000000 RDX: 0000000000000000 RSI: 0000000000001000 RDI: ffff888367870000 RBP: ffffc900ae78f050 R08: ffffea000d9e0007 R09: 1ffffd4001b3c000 R10: dffffc0000000000 R11: fffff94001b3c001 R12: 0000000000000000 R13: ffff8982ab0bde00 R14: ffffc900ae78f058 R15: 0000000000000000 FS: 00007f34e9dc66c0(0000) GS:ffff89ee64d33000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007fe180adef98 CR3: 000000047210e000 CR4: 0000000000350ef0 Call Trace: <TASK> kvm_arch_vm_ioctl+0xa72/0x1240 ../arch/x86/kvm/x86.c:7371 kvm_vm_ioctl+0x649/0x990 ../virt/kvm/kvm_main.c:5363 __se_sys_ioctl+0x101/0x170 ../fs/ioctl.c:51 do_syscall_x64 ../arch/x86/entry/syscall_64.c:63 [inline] do_syscall_64+0x6f/0x1f0 ../arch/x86/entry/syscall_64.c:94 entry_SYSCALL_64_after_hwframe+0x76/0x7e RIP: 0033:0x7f34e9f7e9a9 Code: <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 a8 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007f34e9dc6038 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 RAX: ffffffffffffffda RBX: 00007f34ea1a6080 RCX: 00007f34e9f7e9a9 RDX: 0000200000000280 RSI: 000000008010aebb RDI: 0000000000000007 RBP: 00007f34ea000d69 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 R13: 0000000000000000 R14: 00007f34ea1a6080 R15: 00007ffce77197a8 </TASK>
with a syzlang reproducer that looks like:
syz_kvm_add_vcpu$x86(0x0, &(0x7f0000000040)={0x0, &(0x7f0000000180)=ANY=[], 0x70}) (async) syz_kvm_add_vcpu$x86(0x0, &(0x7f0000000080)={0x0, &(0x7f0000000180)=ANY=[@ANYBLOB="..."], 0x4f}) (async)
r0 = openat$kvm(0xffffffffffffff9c, &(0x7f0000000200), 0x0, 0x0)
r1 = ioctl$KVM_CREATE_VM(r0, 0xae01, 0x0)
r2 = openat$kvm(0xffffffffffffff9c, &(0x7f0000000240), 0x0, 0x0)
r3 = ioctl$KVM_CREATE_VM(r2, 0xae01, 0x0)
ioctl$KVM_SET_CLOCK(r3, 0xc008aeba, &(0x7f0000000040)={0x1, 0x8, 0x0, 0x5625e9b0}) (async) ioctl$KVM_SET_PIT2(r3, 0x8010aebb, &(0x7f0000000280)={[...], 0x5}) (async)
ioctl$KVM_SET_PIT2(r1, 0x4070aea0, 0x0) (async)
r4 = ioctl$KVM_CREATE_VM(0xffffffffffffffff, 0xae01, 0x0)
openat$kvm(0xffffffffffffff9c, 0x0, 0x0, 0x0) (async)
ioctl$KVM_SET_USER_MEMORY_REGION(r4, 0x4020ae46, &(0x7f0000000400)={0x0, 0x0, 0x0, 0x2000, &(0x7f0000001000/0x2000)=nil}) (async) r5 = ioctl$KVM_CREATE_VCPU(r4, 0xae41, 0x2)
close(r0) (async)
openat$kvm(0xffffffffffffff9c, &(0x7f0000000000), 0x8000, 0x0) (async)
ioctl$KVM_SET_GUEST_DEBUG(r5, 0x4048ae9b, &(0x7f0000000300)={0x4376ea830d46549b, 0x0, [0x46, 0x0, 0x0, 0x0, 0x0, 0x1000]}) (async) ioctl$KVM_RUN(r5, 0xae80, 0x0)
Opportunistically use guard() to avoid having to define a new error label and goto usage.
--- arch/x86/kvm/svm/sev.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
arch/x86/kvm/svm/sev.c +2 -4
@@ -2687,6 +2687,8 @@ int sev_mem_enc_register_region(struct kstruct enc_region *region;int ret =0 ; +guard (mutex)(&kvm->lock); +if (!sev_guest (kvm))return -ENOTTY ;
@@ -2701,12 +2703,10 @@ int sev_mem_enc_register_region(struct kif (!region)return -ENOMEM ; -mutex_lock (&kvm->lock); region->pages =sev_pin_memory (kvm, range->addr, range->size, ®ion->npages,FOLL_WRITE |FOLL_LONGTERM );if (IS_ERR (region->pages)) { ret =PTR_ERR (region->pages); -mutex_unlock (&kvm->lock); goto e_free; }
@@ -2724,8 +2724,6 @@ int sev_mem_enc_register_region(struct k region->size = range->size;list_add_tail (®ion->list, &sev->regions_list); -mutex_unlock (&kvm->lock); -return ret; e_free:
Greg Kroah-Hartman
maintainerPATCH 168/198 KVM: SEV: Disallow LAUNCH_FINISH if vCPUs are actively being created
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Christopherson <[email protected]>
commit 624bf3440d7214b62c22d698a0a294323f331d5d upstream.
Reject LAUNCH_FINISH for SEV-ES and SNP VMs if KVM is actively creating one or more vCPUs, as KVM needs to process and encrypt each vCPU's VMSA. Letting userspace create vCPUs while LAUNCH_FINISH is in-progress is "fine", at least in the current code base, as kvm_for_each_vcpu() operates on online_vcpus, LAUNCH_FINISH (all SEV+ sub-ioctls) holds kvm->mutex, and fully onlining a vCPU in kvm_vm_ioctl_create_vcpu() is done under kvm->mutex. I.e. there's no difference between an in-progress vCPU and a vCPU that is created entirely after LAUNCH_FINISH.
However, given that concurrent LAUNCH_FINISH and vCPU creation can't possibly work (for any reasonable definition of "work"), since userspace can't guarantee whether a particular vCPU will be encrypted or not, disallow the combination as a hardening measure, to reduce the probability of introducing bugs in the future, and to avoid having to reason about the safety of future changes related to LAUNCH_FINISH.
--- arch/x86/kvm/svm/sev.c | 10 ++++++++-- include/linux/kvm_host.h | 7 +++++++ 2 files changed, 15 insertions(+), 2 deletions(-)
arch/x86/kvm/svm/sev.c +8 -2
@@ -1019,6 +1019,9 @@ static int sev_launch_update_vmsa(structif (!sev_es_guest (kvm))return -ENOTTY ; +if (kvm_is_vcpu_creation_in_progress (kvm)) +return -EBUSY ; +kvm_for_each_vcpu (i, vcpu, kvm) { ret =mutex_lock_killable (&vcpu->mutex);if (ret)
@@ -2039,8 +2042,8 @@ static int sev_check_source_vcpus(structstruct kvm_vcpu *src_vcpu;unsigned long i; -if (src->created_vcpus !=atomic_read (&src->online_vcpus) || - dst->created_vcpus !=atomic_read (&dst->online_vcpus)) +if (kvm_is_vcpu_creation_in_progress (src) || +kvm_is_vcpu_creation_in_progress (dst))return -EBUSY ;if (!sev_es_guest (src))
@@ -2446,6 +2449,9 @@ static int snp_launch_update_vmsa(structunsigned long i;int ret; +if (kvm_is_vcpu_creation_in_progress (kvm)) +return -EBUSY ; + data.gctx_paddr =__psp_pa (sev->snp_context); data.page_type =SNP_PAGE_TYPE_VMSA ;
include/linux/kvm_host.h +7 -0
@@ -1030,6 +1030,13 @@ static inline struct kvm_vcpu *kvm_get_vreturn NULL ; } +static inline bool kvm_is_vcpu_creation_in_progress (struct kvm *kvm) +{ +lockdep_assert_held (&kvm->lock); + +return kvm->created_vcpus !=atomic_read (&kvm->online_vcpus); +} +void kvm_destroy_vcpus (struct kvm *kvm);int kvm_trylock_all_vcpus (struct kvm *kvm);
Greg Kroah-Hartman
maintainerPATCH 169/198 KVM: SEV: Lock all vCPUs when synchronzing VMSAs for SNP launch finish
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Christopherson <[email protected]>
commit cb923ee6a80f4e604e6242a4702b59251e61a380 upstream.
Lock all vCPUs when synchronizing and encrypting VMSAs for SNP guests, as allowing userspace to manipulate and/or run a vCPU while its state is being synchronized would at best corrupt vCPU state, and at worst crash the host kernel.
Opportunistically assert that vcpu->mutex is held when synchronizing its VMSA (the SEV-ES path already locks vCPUs).
--- arch/x86/kvm/svm/sev.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
arch/x86/kvm/svm/sev.c +12 -4
@@ -871,6 +871,8 @@ static int sev_es_sync_vmsa(struct vcpu_u8 *d;int i; +lockdep_assert_held (&vcpu->mutex); +if (vcpu->arch.guest_state_protected)return -EINVAL ;
@@ -2452,6 +2454,10 @@ static int snp_launch_update_vmsa(structif (kvm_is_vcpu_creation_in_progress (kvm))return -EBUSY ; + ret =kvm_lock_all_vcpus (kvm); +if (ret) +return ret; + data.gctx_paddr =__psp_pa (sev->snp_context); data.page_type =SNP_PAGE_TYPE_VMSA ;
@@ -2461,12 +2467,12 @@ static int snp_launch_update_vmsa(struct ret =sev_es_sync_vmsa (svm);if (ret) -return ret; + goto out;/* Transition the VMSA page to a firmware state. */ ret =rmp_make_private (pfn,INITIAL_VMSA_GPA ,PG_LEVEL_4K , sev->asid, true);if (ret) -return ret; + goto out;/* Issue the SNP command to encrypt the VMSA */ data.address =__sme_pa (svm->sev_es.vmsa);
@@ -2475,7 +2481,7 @@ static int snp_launch_update_vmsa(structif (ret) {snp_page_reclaim (kvm, pfn); -return ret; + goto out; } svm->vcpu.arch.guest_state_protected = true;
@@ -2489,7 +2495,9 @@ static int snp_launch_update_vmsa(structsvm_enable_lbrv (vcpu); } -return 0 ; +out: +kvm_unlock_all_vcpus (kvm); +return ret; }static int snp_launch_finish (struct kvm *kvm,struct kvm_sev_cmd *argp)
Greg Kroah-Hartman
maintainerPATCH 170/198 KVM: SEV: Drop WARN on large size for KVM_MEMORY_ENCRYPT_REG_REGION
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Christopherson <[email protected]>
commit 8acffeef5ef720c35e513e322ab08e32683f32f2 upstream.
Drop the WARN in sev_pin_memory() on npages overflowing an int, as the WARN is comically trivially to trigger from userspace, e.g. by doing:
struct kvm_enc_region range = {
.addr = 0,
.size = -1ul,
};
__vm_ioctl(vm, KVM_MEMORY_ENCRYPT_REG_REGION, &range);Note, the checks in sev_mem_enc_register_region() that presumably exist to verify the incoming address+size are completely worthless, as both "addr" and "size" are u64s and SEV is 64-bit only, i.e. they _can't_ be greater than ULONG_MAX. That wart will be cleaned up in the near future.
if (range->addr > ULONG_MAX || range->size > ULONG_MAX) return -EINVAL;
Opportunistically add a comment to explain why the code calculates the number of pages the "hard" way, e.g. instead of just shifting @ulen.
--- arch/x86/kvm/svm/sev.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
arch/x86/kvm/svm/sev.c +7 -4
@@ -679,10 +679,16 @@ static struct page **sev_pin_memory(struif (ulen ==0 || uaddr + ulen < uaddr)return ERR_PTR (-EINVAL ); -/* Calculate number of pages. */ +/* +* Calculate the number of pages that need to be pinned to cover the +* entire range. Note! This isn't simply ulen >> PAGE_SHIFT, as KVM +* doesn't require the incoming address+size to be page aligned! +*/ first = (uaddr &PAGE_MASK ) >>PAGE_SHIFT ; last = ((uaddr + ulen -1 ) &PAGE_MASK ) >>PAGE_SHIFT ; npages = (last - first +1 ); +if (npages >INT_MAX ) +return ERR_PTR (-EINVAL ); locked = sev->pages_locked + npages; lock_limit =rlimit (RLIMIT_MEMLOCK ) >>PAGE_SHIFT ;
@@ -691,9 +697,6 @@ static struct page **sev_pin_memory(strureturn ERR_PTR (-ENOMEM ); } -if (WARN_ON_ONCE (npages >INT_MAX )) -return ERR_PTR (-EINVAL ); -/* Avoid using vmalloc for smaller buffers. */ size = npages *sizeof (struct page *);if (size >PAGE_SIZE )
Greg Kroah-Hartman
maintainerPATCH 171/198 selftests/bpf: Test refinement of single-value tnum
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paul Chaignon <[email protected]>
commit e6ad477d1bf8829973cddd9accbafa9d1a6cd15a upstream.
This patch introduces selftests to cover the new bounds refinement logic introduced in the previous patch. Without the previous patch, the first two tests fail because of the invariant violation they trigger. The last test fails because the R10 access is not detected as dead code. In addition, all three tests fail because of R0 having a non-constant value in the verifier logs.
In addition, the last two cases are covering the negative cases: when we shouldn't refine the bounds because the u64 and tnum overlap in at least two values.
[shung-hsi.yu: test for backported upstream commit efc11a667878 ("bpf: Improve bounds when tnum has a single possible value")]
--- tools/testing/selftests/bpf/progs/verifier_bounds.c | 137 ++++++++++++++++++++ 1 file changed, 137 insertions(+)
tools/testing/selftests/bpf/progs/verifier_bounds.c +137 -0
@@ -1709,4 +1709,141 @@ __naked void jeq_disagreeing_tnums(void : __clobber_all); } +/* This test covers the bounds deduction when the u64 range and the tnum +* overlap only at umax. After instruction 3, the ranges look as follows: +* +* 0 umin=0xe01 umax=0xf00 U64_MAX +* | [xxxxxxxxxxxxxx] | +* |----------------------------|------------------------------| +* | x x | tnum values +* +* The verifier can therefore deduce that the R0=0xf0=240. +*/ +SEC("socket") +__description("bounds refinement with single-value tnum on umax") +__msg("3: (15) if r0 == 0xe0 {{.*}} R0=240") +__success __log_level(2) +__flag (BPF_F_TEST_REG_INVARIANTS) +__naked void bounds_refinement_tnum_umax(void *ctx) +{ + asmvolatile (" \ +call %[bpf_get_prandom_u32]; \ +r0 |= 0xe0; \ +r0 &= 0xf0; \ +if r0 == 0xe0 goto +2; \ +if r0 == 0xf0 goto +1; \ +r10 = 0; \ +exit; \ +" : + : __imm(bpf_get_prandom_u32) + : __clobber_all); +} + +/* This test covers the bounds deduction when the u64 range and the tnum +* overlap only at umin. After instruction 3, the ranges look as follows: +* +* 0 umin=0xe00 umax=0xeff U64_MAX +* | [xxxxxxxxxxxxxx] | +* |----------------------------|------------------------------| +* | x x | tnum values +* +* The verifier can therefore deduce that the R0=0xe0=224. +*/ +SEC("socket") +__description("bounds refinement with single-value tnum on umin") +__msg("3: (15) if r0 == 0xf0 {{.*}} R0=224") +__success __log_level(2) +__flag (BPF_F_TEST_REG_INVARIANTS) +__naked void bounds_refinement_tnum_umin(void *ctx) +{ + asmvolatile (" \ +call %[bpf_get_prandom_u32]; \ +r0 |= 0xe0; \ +r0 &= 0xf0; \ +if r0 == 0xf0 goto +2; \ +if r0 == 0xe0 goto +1; \ +r10 = 0; \ +exit; \ +" : + : __imm(bpf_get_prandom_u32) + : __clobber_all); +} + +/* This test covers the bounds deduction when the only possible tnum value is +* in the middle of the u64 range. After instruction 3, the ranges look as +* follows: +* +* 0 umin=0x7cf umax=0x7df U64_MAX +* | [xxxxxxxxxxxx] | +* |----------------------------|------------------------------| +* | x x x x x | tnum values +* | +--- 0x7e0 +* +--- 0x7d0 +* +* Since the lower four bits are zero, the tnum and the u64 range only overlap +* in R0=0x7d0=2000. Instruction 5 is therefore dead code. +*/ +SEC("socket") +__description("bounds refinement with single-value tnum in middle of range") +__msg("3: (a5) if r0 < 0x7cf {{.*}} R0=2000") +__success __log_level(2) +__naked void bounds_refinement_tnum_middle(void *ctx) +{ + asmvolatile (" \ +call %[bpf_get_prandom_u32]; \ +if r0 & 0x0f goto +4; \ +if r0 > 0x7df goto +3; \ +if r0 < 0x7cf goto +2; \ +if r0 == 0x7d0 goto +1; \ +r10 = 0; \ +exit; \ +" : + : __imm(bpf_get_prandom_u32) + : __clobber_all); +} + +/* This test cover the negative case for the tnum/u64 overlap. Since +* they contain the same two values (i.e., {0, 1}), we can't deduce +* anything more. +*/ +SEC("socket") +__description("bounds refinement: several overlaps between tnum and u64") +__msg("2: (25) if r0 > 0x1 {{.*}} R0=scalar(smin=smin32=0,smax=umax=smax32=umax32=1,var_off=(0x0; 0x1))") +__failure __log_level(2) +__naked void bounds_refinement_several_overlaps(void *ctx) +{ + asm volatile(" \ + call %[bpf_get_prandom_u32]; \ + if r0 < 0 goto +3; \ + if r0 > 1 goto +2; \ + if r0 == 1 goto +1; \ + r10 = 0; \ + exit; \ +" : + : __imm(bpf_get_prandom_u32) + : __clobber_all); +} + +/* This test cover the negative case for the tnum/u64 overlap. Since +* they overlap in the two values contained by the u64 range (i.e., +* {0xf, 0x10}), we can't deduce anything more. +*/ +SEC("socket") +__description("bounds refinement: multiple overlaps between tnum and u64") +__msg("2: (25) if r0 > 0x10 {{.*}} R0=scalar(smin=umin=smin32=umin32=15,smax=umax=smax32=umax32=16,var_off=(0x0; 0x1f))") +__failure __log_level(2) +__naked void bounds_refinement_multiple_overlaps(void *ctx) +{ + asm volatile(" \ + call %[bpf_get_prandom_u32]; \ + if r0 < 0xf goto +3; \ + if r0 > 0x10 goto +2; \ + if r0 == 0x10 goto +1; \ + r10 = 0; \ + exit; \ +" : + : __imm(bpf_get_prandom_u32) + : __clobber_all); +} + char _license[] SEC("license") = "GPL";
Greg Kroah-Hartman
maintainerPATCH 172/198 KVM: Remove subtle "struct kvm_stats_desc" pseudo-overlay
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Christopherson <[email protected]>
[ Upstream commit da142f3d373a6ddaca0119615a8db2175ddc4121 ]
Remove KVM's internal pseudo-overlay of kvm_stats_desc, which subtly aliases the flexible name[] in the uAPI definition with a fixed-size array of the same name. The unusual embedded structure results in compiler warnings due to -Wflex-array-member-not-at-end, and also necessitates an extra level of dereferencing in KVM. To avoid the "overlay", define the uAPI structure to have a fixed-size name when building for the kernel.
Opportunistically clean up the indentation for the stats macros, and replace spaces with tabs.
No functional change intended.
Stable-dep-of: 2619da73bb2f ("KVM: x86: Use __DECLARE_FLEX_ARRAY() for UAPI structures with VLAs")
--- arch/arm64/kvm/guest.c | 4 +- arch/loongarch/kvm/vcpu.c | 2 - arch/loongarch/kvm/vm.c | 2 - arch/mips/kvm/mips.c | 4 +- arch/powerpc/kvm/book3s.c | 4 +- arch/powerpc/kvm/booke.c | 4 +- arch/riscv/kvm/vcpu.c | 2 - arch/riscv/kvm/vm.c | 2 - arch/s390/kvm/kvm-s390.c | 4 +- arch/x86/kvm/x86.c | 4 +- include/linux/kvm_host.h | 83 +++++++++++++++++++--------------------------- include/uapi/linux/kvm.h | 8 ++++ virt/kvm/binary_stats.c | 2 - virt/kvm/kvm_main.c | 20 +++++------ 14 files changed, 70 insertions(+), 75 deletions(-)
arch/arm64/kvm/guest.c +2 -2
@@ -29,7 +29,7 @@#include "trace.h" -const struct _kvm_stats_desc kvm_vm_stats_desc[] = { +const struct kvm_stats_desc kvm_vm_stats_desc[] = {KVM_GENERIC_VM_STATS () };
@@ -42,7 +42,7 @@ const struct kvm_stats_header kvm_vm_sta sizeof(kvm_vm_stats_desc), }; -const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = { +const struct kvm_stats_desc kvm_vcpu_stats_desc[] = {KVM_GENERIC_VCPU_STATS (),STATS_DESC_COUNTER (VCPU , hvc_exit_stat),STATS_DESC_COUNTER (VCPU , wfe_exit_stat),
arch/loongarch/kvm/vcpu.c +1 -1
@@ -13,7 +13,7 @@#define CREATE_TRACE_POINTS #include "trace.h" -const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = { +const struct kvm_stats_desc kvm_vcpu_stats_desc[] = {KVM_GENERIC_VCPU_STATS (),STATS_DESC_COUNTER (VCPU , int_exits),STATS_DESC_COUNTER (VCPU , idle_exits),
arch/loongarch/kvm/vm.c +1 -1
@@ -9,7 +9,7 @@#include <asm/kvm_eiointc.h> #include <asm/kvm_pch_pic.h> -const struct _kvm_stats_desc kvm_vm_stats_desc[] = { +const struct kvm_stats_desc kvm_vm_stats_desc[] = {KVM_GENERIC_VM_STATS (),STATS_DESC_ICOUNTER (VM , pages),STATS_DESC_ICOUNTER (VM , hugepages),
arch/mips/kvm/mips.c +2 -2
@@ -38,7 +38,7 @@#define VECTORSPACING 0x100/* for EI/VI mode */ #endif -const struct _kvm_stats_desc kvm_vm_stats_desc[] = { +const struct kvm_stats_desc kvm_vm_stats_desc[] = {KVM_GENERIC_VM_STATS () };
@@ -51,7 +51,7 @@ const struct kvm_stats_header kvm_vm_sta sizeof(kvm_vm_stats_desc), }; -const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = { +const struct kvm_stats_desc kvm_vcpu_stats_desc[] = {KVM_GENERIC_VCPU_STATS (),STATS_DESC_COUNTER (VCPU , wait_exits),STATS_DESC_COUNTER (VCPU , cache_exits),
arch/powerpc/kvm/book3s.c +2 -2
@@ -38,7 +38,7 @@/* #define EXIT_DEBUG */ -const struct _kvm_stats_desc kvm_vm_stats_desc[] = { +const struct kvm_stats_desc kvm_vm_stats_desc[] = {KVM_GENERIC_VM_STATS (),STATS_DESC_ICOUNTER (VM , num_2M_pages),STATS_DESC_ICOUNTER (VM , num_1G_pages)
@@ -53,7 +53,7 @@ const struct kvm_stats_header kvm_vm_sta sizeof(kvm_vm_stats_desc), }; -const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = { +const struct kvm_stats_desc kvm_vcpu_stats_desc[] = {KVM_GENERIC_VCPU_STATS (),STATS_DESC_COUNTER (VCPU , sum_exits),STATS_DESC_COUNTER (VCPU , mmio_exits),
arch/powerpc/kvm/booke.c +2 -2
@@ -36,7 +36,7 @@unsigned long kvmppc_booke_handlers; -const struct _kvm_stats_desc kvm_vm_stats_desc[] = { +const struct kvm_stats_desc kvm_vm_stats_desc[] = {KVM_GENERIC_VM_STATS (),STATS_DESC_ICOUNTER (VM , num_2M_pages),STATS_DESC_ICOUNTER (VM , num_1G_pages)
@@ -51,7 +51,7 @@ const struct kvm_stats_header kvm_vm_sta sizeof(kvm_vm_stats_desc), }; -const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = { +const struct kvm_stats_desc kvm_vcpu_stats_desc[] = {KVM_GENERIC_VCPU_STATS (),STATS_DESC_COUNTER (VCPU , sum_exits),STATS_DESC_COUNTER (VCPU , mmio_exits),
arch/riscv/kvm/vcpu.c +1 -1
@@ -24,7 +24,7 @@#define CREATE_TRACE_POINTS #include "trace.h" -const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = { +const struct kvm_stats_desc kvm_vcpu_stats_desc[] = {KVM_GENERIC_VCPU_STATS (),STATS_DESC_COUNTER (VCPU , ecall_exit_stat),STATS_DESC_COUNTER (VCPU , wfi_exit_stat),
arch/riscv/kvm/vm.c +1 -1
@@ -13,7 +13,7 @@#include <linux/kvm_host.h> #include <asm/kvm_mmu.h> -const struct _kvm_stats_desc kvm_vm_stats_desc[] = { +const struct kvm_stats_desc kvm_vm_stats_desc[] = {KVM_GENERIC_VM_STATS () }; static_assert(ARRAY_SIZE(kvm_vm_stats_desc) ==
arch/s390/kvm/kvm-s390.c +2 -2
@@ -64,7 +64,7 @@#define VCPU_IRQS_MAX_BUF (sizeof(struct kvm_s390_irq) * \ (KVM_MAX_VCPUS + LOCAL_IRQS)) -const struct _kvm_stats_desc kvm_vm_stats_desc[] = { +const struct kvm_stats_desc kvm_vm_stats_desc[] = {KVM_GENERIC_VM_STATS (),STATS_DESC_COUNTER (VM , inject_io),STATS_DESC_COUNTER (VM , inject_float_mchk),
@@ -90,7 +90,7 @@ const struct kvm_stats_header kvm_vm_sta sizeof(kvm_vm_stats_desc), }; -const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = { +const struct kvm_stats_desc kvm_vcpu_stats_desc[] = {KVM_GENERIC_VCPU_STATS (),STATS_DESC_COUNTER (VCPU , exit_userspace),STATS_DESC_COUNTER (VCPU , exit_null),
arch/x86/kvm/x86.c +2 -2
@@ -242,7 +242,7 @@ EXPORT_SYMBOL_FOR_KVM_INTERNAL(enable_ipbool __read_mostly enable_device_posted_irqs = true;EXPORT_SYMBOL_FOR_KVM_INTERNAL (enable_device_posted_irqs); -const struct _kvm_stats_desc kvm_vm_stats_desc[] = { +const struct kvm_stats_desc kvm_vm_stats_desc[] = {KVM_GENERIC_VM_STATS (),STATS_DESC_COUNTER (VM , mmu_shadow_zapped),STATS_DESC_COUNTER (VM , mmu_pte_write),
@@ -268,7 +268,7 @@ const struct kvm_stats_header kvm_vm_sta sizeof(kvm_vm_stats_desc), }; -const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = { +const struct kvm_stats_desc kvm_vcpu_stats_desc[] = {KVM_GENERIC_VCPU_STATS (),STATS_DESC_COUNTER (VCPU , pf_taken),STATS_DESC_COUNTER (VCPU , pf_fixed),
include/linux/kvm_host.h +35 -48
107 lines not on this page · raw message
include/uapi/linux/kvm.h +8 -0
@@ -14,6 +14,10 @@#include <linux/ioctl.h> #include <asm/kvm.h> +#ifdef __KERNEL__ +#include <linux/kvm_types.h> +#endif +#define KVM_API_VERSION 12/*
@@ -1568,7 +1572,11 @@ struct kvm_stats_desc {__u16 size;__u32 offset;__u32 bucket_size; +#ifdef __KERNEL__ +char name[KVM_STATS_NAME_SIZE ]; +#else char name[]; +#endif };#define KVM_GET_STATS_FD _IO(KVMIO, 0xce)
virt/kvm/binary_stats.c +1 -1
@@ -50,7 +50,7 @@* Return: the number of bytes that has been successfully read */ ssize_t kvm_stats_read (char *id,const struct kvm_stats_header *header, -const struct _kvm_stats_desc *desc, +const struct kvm_stats_desc *desc,void *stats,size_t size_stats,char __user *user_buffer,size_t size,loff_t *offset) {
virt/kvm/kvm_main.c +10 -10
@@ -982,9 +982,9 @@ static void kvm_free_memslots(struct kvmkvm_free_memslot (kvm, memslot); } -static umode_t kvm_stats_debugfs_mode (const struct _kvm_stats_desc *pdesc) +static umode_t kvm_stats_debugfs_mode (const struct kvm_stats_desc *desc) { -switch (pdesc->desc.flags &KVM_STATS_TYPE_MASK ) { +switch (desc->flags &KVM_STATS_TYPE_MASK ) {case KVM_STATS_TYPE_INSTANT :return 0444 ;case KVM_STATS_TYPE_CUMULATIVE :
@@ -1019,7 +1019,7 @@ static int kvm_create_vm_debugfs(structstruct dentry *dent;char dir_name[ITOA_MAX_LEN *2 ];struct kvm_stat_data *stat_data; -const struct _kvm_stats_desc *pdesc; +const struct kvm_stats_desc *pdesc;int i, ret = -ENOMEM ;int kvm_debugfs_num_entries = kvm_vm_stats_header.num_desc + kvm_vcpu_stats_header.num_desc;
@@ -6160,11 +6160,11 @@ static int kvm_stat_data_get(void *data,switch (stat_data->kind) {case KVM_STAT_VM : r =kvm_get_stat_per_vm (stat_data->kvm, - stat_data->desc->desc.offset, val); + stat_data->desc->offset, val);break ;case KVM_STAT_VCPU : r =kvm_get_stat_per_vcpu (stat_data->kvm, - stat_data->desc->desc.offset, val); + stat_data->desc->offset, val);break ; }
@@ -6182,11 +6182,11 @@ static int kvm_stat_data_clear(void *datswitch (stat_data->kind) {case KVM_STAT_VM : r =kvm_clear_stat_per_vm (stat_data->kvm, - stat_data->desc->desc.offset); + stat_data->desc->offset);break ;case KVM_STAT_VCPU : r =kvm_clear_stat_per_vcpu (stat_data->kvm, - stat_data->desc->desc.offset); + stat_data->desc->offset);break ; }
@@ -6334,7 +6334,7 @@ static void kvm_uevent_notify_change(unsstatic void kvm_init_debug (void ) {const struct file_operations *fops; -const struct _kvm_stats_desc *pdesc; +const struct kvm_stats_desc *pdesc;int i; kvm_debugfs_dir =debugfs_create_dir ("kvm" ,NULL );
@@ -6347,7 +6347,7 @@ static void kvm_init_debug(void) fops = &vm_stat_readonly_fops;debugfs_create_file (pdesc->name,kvm_stats_debugfs_mode (pdesc), kvm_debugfs_dir, - (void *)(long )pdesc->desc.offset, fops); + (void *)(long )pdesc->offset, fops); }for (i =0 ; i < kvm_vcpu_stats_header.num_desc; ++i) {
@@ -6358,7 +6358,7 @@ static void kvm_init_debug(void) fops = &vcpu_stat_readonly_fops;debugfs_create_file (pdesc->name,kvm_stats_debugfs_mode (pdesc), kvm_debugfs_dir, - (void *)(long )pdesc->desc.offset, fops); + (void *)(long )pdesc->offset, fops); } }
Greg Kroah-Hartman
maintainerPATCH 173/198 KVM: x86: Use __DECLARE_FLEX_ARRAY() for UAPI structures with VLAs
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Woodhouse <[email protected]>
[ Upstream commit 2619da73bb2f10d88f7e1087125c40144fdf0987 ]
Commit 94dfc73e7cf4 ("treewide: uapi: Replace zero-length arrays with flexible-array members") broke the userspace API for C++.
These structures ending in VLAs are typically a *header*, which can be followed by an arbitrary number of entries. Userspace typically creates a larger structure with some non-zero number of entries, for example in QEMU's kvm_arch_get_supported_msr_feature():
struct {
struct kvm_msrs info;
struct kvm_msr_entry entries[1];
} msr_data = {};While that works in C, it fails in C++ with an error like:
flexible array member 'kvm_msrs::entries' not at end of 'struct msr_data'
Fix this by using __DECLARE_FLEX_ARRAY() for the VLA, which uses [0] for C++ compilation.
--- arch/x86/include/uapi/asm/kvm.h | 12 ++++++------ include/uapi/linux/kvm.h | 11 ++++++----- 2 files changed, 12 insertions(+), 11 deletions(-)
arch/x86/include/uapi/asm/kvm.h +6 -6
@@ -197,13 +197,13 @@ struct kvm_msrs {__u32 nmsrs;/* number of msrs in entries */ __u32 pad; -struct kvm_msr_entry entries[]; + __DECLARE_FLEX_ARRAY(struct kvm_msr_entry, entries); };/* for KVM_GET_MSR_INDEX_LIST */ struct kvm_msr_list {__u32 nmsrs;/* number of msrs in entries */ -__u32 indices[]; + __DECLARE_FLEX_ARRAY(__u32, indices); };/* Maximum size of any access bitmap in bytes */
@@ -245,7 +245,7 @@ struct kvm_cpuid_entry {struct kvm_cpuid {__u32 nent;__u32 padding; -struct kvm_cpuid_entry entries[]; + __DECLARE_FLEX_ARRAY(struct kvm_cpuid_entry, entries); };struct kvm_cpuid_entry2 {
@@ -267,7 +267,7 @@ struct kvm_cpuid_entry2 {struct kvm_cpuid2 {__u32 nent;__u32 padding; -struct kvm_cpuid_entry2 entries[]; + __DECLARE_FLEX_ARRAY(struct kvm_cpuid_entry2, entries); };/* for KVM_GET_PIT and KVM_SET_PIT */
@@ -398,7 +398,7 @@ struct kvm_xsave {* the contents of CPUID leaf 0xD on the host. */ __u32 region[1024 ]; -__u32 extra[]; +__DECLARE_FLEX_ARRAY (__u32, extra); };#define KVM_MAX_XCRS 16
@@ -564,7 +564,7 @@ struct kvm_pmu_event_filter {__u32 fixed_counter_bitmap;__u32 flags;__u32 pad[4 ]; -__u64 events[]; +__DECLARE_FLEX_ARRAY (__u64, events); };#define KVM_PMU_EVENT_ALLOW 0
include/uapi/linux/kvm.h +6 -5
@@ -11,6 +11,7 @@#include <linux/const.h> #include <linux/types.h> #include <linux/compiler.h> +#include <linux/stddef.h> #include <linux/ioctl.h> #include <asm/kvm.h>
@@ -523,7 +524,7 @@ struct kvm_coalesced_mmio {struct kvm_coalesced_mmio_ring {__u32 first, last; -struct kvm_coalesced_mmio coalesced_mmio[]; + __DECLARE_FLEX_ARRAY(struct kvm_coalesced_mmio, coalesced_mmio); };#define KVM_COALESCED_MMIO_MAX \
@@ -573,7 +574,7 @@ struct kvm_clear_dirty_log {/* for KVM_SET_SIGNAL_MASK */ struct kvm_signal_mask {__u32 len; -__u8 sigset[]; + __DECLARE_FLEX_ARRAY(__u8, sigset); };/* for KVM_TPR_ACCESS_REPORTING */
@@ -1029,7 +1030,7 @@ struct kvm_irq_routing_entry {struct kvm_irq_routing {__u32 nr;__u32 flags; -struct kvm_irq_routing_entry entries[]; + __DECLARE_FLEX_ARRAY(struct kvm_irq_routing_entry, entries); };#define KVM_IRQFD_FLAG_DEASSIGN (1 << 0)
@@ -1120,7 +1121,7 @@ struct kvm_dirty_tlb {struct kvm_reg_list {__u64 n;/* number of regs */ -__u64 reg[]; + __DECLARE_FLEX_ARRAY(__u64, reg); };struct kvm_one_reg {
@@ -1575,7 +1576,7 @@ struct kvm_stats_desc {#ifdef __KERNEL__char name[KVM_STATS_NAME_SIZE ];#else -char name[]; +__DECLARE_FLEX_ARRAY (char, name);#endif };
Greg Kroah-Hartman
maintainerPATCH 174/198 ocfs2: add inline inode consistency check to ocfs2_validate_inode_block()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Antipov <[email protected]>
[ Upstream commit a2b1c419ff72ec62ff5831684e30cd1d4f0b09ee ]
In 'ocfs2_validate_inode_block()', add an extra check whether an inode with inline data (i.e. self-contained) has no clusters, thus preventing an invalid inode from being passed to 'ocfs2_evict_inode()' and below.
Stable-dep-of: 7bc5da4842be ("ocfs2: fix out-of-bounds write in ocfs2_write_end_inline")
--- fs/ocfs2/inode.c | 8 ++++++++ 1 file changed, 8 insertions(+)
fs/ocfs2/inode.c +8 -0
@@ -1505,6 +1505,14 @@ int ocfs2_validate_inode_block(struct su goto bail; } +if ((le16_to_cpu (di->i_dyn_features) &OCFS2_INLINE_DATA_FL ) && +le32_to_cpu (di->i_clusters)) { + rc =ocfs2_error (sb,"Invalid dinode %llu: %u clusters\n" , + (unsigned long long )bh->b_blocknr, +le32_to_cpu (di->i_clusters)); + goto bail; + } + rc =0 ; bail:
Greg Kroah-Hartman
maintainerPATCH 175/198 ocfs2: validate inline data i_size during inode read
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Deepanshu Kartikey <[email protected]>
[ Upstream commit 1524af3685b35feac76662cc551cbc37bd14775f ]
When reading an inode from disk, ocfs2_validate_inode_block() performs various sanity checks but does not validate the size of inline data. If the filesystem is corrupted, an inode's i_size can exceed the actual inline data capacity (id_count).
This causes ocfs2_dir_foreach_blk_id() to iterate beyond the inline data buffer, triggering a use-after-free when accessing directory entries from freed memory.
In the syzbot report:
- i_size was 1099511627576 bytes (~1TB)
- Actual inline data capacity (id_count) is typically <256 bytes
- A garbage rec_len (54648) caused ctx->pos to jump out of bounds
- This triggered a UAF in ocfs2_check_dir_entry()
Fix by adding a validation check in ocfs2_validate_inode_block() to ensure inodes with inline data have i_size <= id_count. This catches the corruption early during inode read and prevents all downstream code from operating on invalid data.
Stable-dep-of: 7bc5da4842be ("ocfs2: fix out-of-bounds write in ocfs2_write_end_inline")
--- fs/ocfs2/inode.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-)
fs/ocfs2/inode.c +19 -6
@@ -1505,12 +1505,25 @@ int ocfs2_validate_inode_block(struct su goto bail; } -if ((le16_to_cpu (di->i_dyn_features) &OCFS2_INLINE_DATA_FL ) && -le32_to_cpu (di->i_clusters)) { - rc =ocfs2_error (sb,"Invalid dinode %llu: %u clusters\n" , - (unsigned long long )bh->b_blocknr, -le32_to_cpu (di->i_clusters)); - goto bail; +if (le16_to_cpu (di->i_dyn_features) &OCFS2_INLINE_DATA_FL ) { +struct ocfs2_inline_data *data = &di->id2.i_data; + +if (le32_to_cpu (di->i_clusters)) { + rc =ocfs2_error (sb, +"Invalid dinode %llu: %u clusters\n" , + (unsigned long long )bh->b_blocknr, +le32_to_cpu (di->i_clusters)); + goto bail; + } + +if (le64_to_cpu (di->i_size) >le16_to_cpu (data->id_count)) { + rc =ocfs2_error (sb, +"Invalid dinode #%llu: inline data i_size %llu exceeds id_count %u\n" , + (unsigned long long )bh->b_blocknr, + (unsigned long long )le64_to_cpu (di->i_size), +le16_to_cpu (data->id_count)); + goto bail; + } } rc =0 ;
Greg Kroah-Hartman
maintainerPATCH 176/198 ocfs2: fix out-of-bounds write in ocfs2_write_end_inline
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Joseph Qi <[email protected]>
[ Upstream commit 7bc5da4842bed3252d26e742213741a4d0ac1b14 ]
KASAN reports a use-after-free write of 4086 bytes in ocfs2_write_end_inline, called from ocfs2_write_end_nolock during a copy_file_range splice fallback on a corrupted ocfs2 filesystem mounted on a loop device. The actual bug is an out-of-bounds write past the inode block buffer, not a true use-after-free. The write overflows into an adjacent freed page, which KASAN reports as UAF.
The root cause is that ocfs2_try_to_write_inline_data trusts the on-disk id_count field to determine whether a write fits in inline data. On a corrupted filesystem, id_count can exceed the physical maximum inline data capacity, causing writes to overflow the inode block buffer.
Call trace (crash path):
vfs_copy_file_range (fs/read_write.c:1634)
do_splice_direct
splice_direct_to_actor
iter_file_splice_write
ocfs2_file_write_iter
generic_perform_write
ocfs2_write_end
ocfs2_write_end_nolock (fs/ocfs2/aops.c:1949)
ocfs2_write_end_inline (fs/ocfs2/aops.c:1915)
memcpy_from_folio <-- KASAN: write OOBSo add id_count upper bound check in ocfs2_validate_inode_block() to alongside the existing i_size check to fix it.
--- fs/ocfs2/inode.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
fs/ocfs2/inode.c +10 -0
@@ -1516,6 +1516,16 @@ int ocfs2_validate_inode_block(struct su goto bail; } +if (le16_to_cpu (data->id_count) > +ocfs2_max_inline_data_with_xattr (sb, di)) { + rc =ocfs2_error (sb, +"Invalid dinode #%llu: inline data id_count %u exceeds max %d\n" , + (unsigned long long )bh->b_blocknr, +le16_to_cpu (data->id_count), +ocfs2_max_inline_data_with_xattr (sb, di)); + goto bail; + } +if (le64_to_cpu (di->i_size) >le16_to_cpu (data->id_count)) { rc = ocfs2_error(sb, "Invalid dinode #%llu: inline data i_size %llu exceeds id_count %u\n",
Greg Kroah-Hartman
maintainerPATCH 177/198 checkpatch: add support for Assisted-by tag
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sasha Levin <[email protected]>
commit d1db4118489fffd2b2f612140b7acbb477880839 upstream.
The Assisted-by tag was introduced in Documentation/process/coding-assistants.rst for attributing AI tool contributions to kernel patches. However, checkpatch.pl did not recognize this tag, causing two issues:
WARNING: Non-standard signature: Assisted-by:
ERROR: Unrecognized email address: 'AGENT_NAME:MODEL_VERSION'
Fix this by:
1. Adding Assisted-by to the recognized $signature_tags list
2. Skipping email validation for Assisted-by lines since they use the AGENT_NAME:MODEL_VERSION format instead of an email address
3. Warning when the Assisted-by value doesn't match the expected format
--- scripts/checkpatch.pl | 10 ++++++++++ 1 file changed, 10 insertions(+)
scripts/checkpatch.pl +10 -0
@@ -641,6 +641,7 @@ our $signature_tags = qr{(?xi: Reviewed-by:| Reported-by:| Suggested-by:| + Assisted-by:| To:| Cc: )};
@@ -3087,6 +3088,15 @@ sub process { } } + # Assisted-by uses AGENT_NAME:MODEL_VERSION format, not email + if ($sign_off =~ /^Assisted-by:/i) { + if ($email !~ /^\S+:\S+/) { + WARN("BAD_SIGN_OFF", + "Assisted-by expects 'AGENT_NAME:MODEL_VERSION [TOOL1] [TOOL2]' format\n" . $herecurr); + } + next; + } + my ($email_name, $name_comment, $email_address, $comment) = parse_email($email); my $suggested_email = format_email(($email_name, $name_comment, $email_address, $comment)); if ($suggested_email eq "") {
Greg Kroah-Hartman
maintainerPATCH 178/198 x86-64: rename misleadingly named __copy_user_nocache() function
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linus Torvalds <[email protected]>
commit d187a86de793f84766ea40b9ade7ac60aabbb4fe upstream.
This function was a masterclass in bad naming, for various historical reasons.
It claimed to be a non-cached user copy. It is literally _neither_ of those things. It's a specialty memory copy routine that uses non-temporal stores for the destination (but not the source), and that does exception handling for both source and destination accesses.
Also note that while it works for unaligned targets, any unaligned parts (whether at beginning or end) will not use non-temporal stores, since only words and quadwords can be non-temporal on x86.
The exception handling means that it _can_ be used for user space accesses, but not on its own - it needs all the normal "start user space access" logic around it.
But typically the user space access would be the source, not the non-temporal destination. That was the original intention of this, where the destination was some fragile persistent memory target that needed non-temporal stores in order to catch machine check exceptions synchronously and deal with them gracefully.
Thus that non-descriptive name: one use case was to copy from user space into a non-cached kernel buffer. However, the existing users are a mix of that intended use-case, and a couple of random drivers that just did this as a performance tweak.
Some of those random drivers then actively misused the user copying version (with STAC/CLAC and all) to do kernel copies without ever even caring about the exception handling, _just_ for the non-temporal destination.
Rename it as a first small step to actually make it halfway sane, and change the prototype to be more normal: it doesn't take a user pointer unless the caller has done the proper conversion, and the argument size is the full size_t (it still won't actually copy more than 4GB in one go, but there's also no reason to silently truncate the size argument in the caller).
Finally, use this now sanely named function in the NTB code, which mis-used a user copy version (with STAC/CLAC and all) of this interface despite it not actually being a user copy at all.
--- arch/x86/include/asm/uaccess_64.h | 5 +++-- arch/x86/lib/copy_user_uncached_64.S | 6 +++--- arch/x86/lib/usercopy_64.c | 4 ++-- drivers/infiniband/sw/rdmavt/qp.c | 8 +++----- drivers/ntb/ntb_transport.c | 7 ++++--- tools/objtool/check.c | 2 +- 6 files changed, 16 insertions(+), 16 deletions(-)
arch/x86/include/asm/uaccess_64.h +3 -2
@@ -147,7 +147,8 @@ raw_copy_to_user(void __user *dst, constreturn copy_user_generic ((__force void *)dst, src, size); } -extern long __copy_user_nocache (void *dst,const void __user *src,unsigned size); +#define copy_to_nontemporal copy_to_nontemporal +extern size_t copy_to_nontemporal (void *dst,const void *src,size_t size);extern long __copy_user_flushcache (void *dst,const void __user *src,unsigned size); static inline int
@@ -157,7 +158,7 @@ __copy_from_user_inatomic_nocache(void *long ret;kasan_check_write (dst, size);stac (); - ret =__copy_user_nocache (dst, src, size); + ret =copy_to_nontemporal (dst, (__force const void *)src, size);clac ();return ret; }
arch/x86/lib/copy_user_uncached_64.S +3 -3
@@ -27,7 +27,7 @@ * Output: * rax uncopied bytes or 0 if successful. */ -SYM_FUNC_START(__copy_user_nocache) +SYM_FUNC_START(copy_to_nontemporal) ANNOTATE_NOENDBR /* If destination is not 7-byte aligned, we'll have to align it */ testb $7,%dil
@@ -240,5 +240,5 @@ _ASM_EXTABLE_UA(95b, .Ldone) _ASM_EXTABLE_UA(52b, .Ldone0) _ASM_EXTABLE_UA(53b, .Ldone0) -SYM_FUNC_END(__copy_user_nocache) -EXPORT_SYMBOL(__copy_user_nocache) +SYM_FUNC_END(copy_to_nontemporal) +EXPORT_SYMBOL(copy_to_nontemporal)
arch/x86/lib/usercopy_64.c +2 -2
@@ -49,11 +49,11 @@ long __copy_user_flushcache(void *dst, clong rc;stac (); - rc =__copy_user_nocache (dst, src, size); + rc =copy_to_nontemporal (dst, (__force const void *)src, size);clac ();/* -* __copy_user_nocache() uses non-temporal stores for the bulk +* copy_to_nontemporal() uses non-temporal stores for the bulk * of the transfer, but we need to manually flush if the * transfer is unaligned. A cached memory copy is used when * destination or size is not naturally aligned. That is:
drivers/infiniband/sw/rdmavt/qp.c +3 -5
@@ -92,12 +92,10 @@ static int rvt_wss_llc_size(void)static void cacheless_memcpy (void *dst,void *src,size_t n) {/* -* Use the only available X64 cacheless copy. Add a __user cast -* to quiet sparse. The src agument is already in the kernel so -* there are no security issues. The extra fault recovery machinery -* is not invoked. +* Use the only available X64 cacheless copy. +* The extra fault recovery machinery is not invoked. */ -__copy_user_nocache (dst, (void __user *)src, n); +copy_to_nontemporal (dst, src, n); }void rvt_wss_exit (struct rvt_dev_info *rdi)
drivers/ntb/ntb_transport.c +4 -3
@@ -1810,12 +1810,13 @@ static void ntb_tx_copy_callback(void *dstatic void ntb_memcpy_tx (struct ntb_queue_entry *entry,void __iomem *offset) { -#ifdef ARCH_HAS_NOCACHE_UACCESS +#ifdef copy_to_nontemporal/* * Using non-temporal mov to improve performance on non-cached -* writes, even though we aren't actually copying from user space. +* writes. This only works if __iomem is strictly memory-like, +* but that is the case on x86-64 */ -__copy_from_user_inatomic_nocache (offset, entry->buf, entry->len); +copy_to_nontemporal (offset, entry->buf, entry->len);#else memcpy_toio (offset, entry->buf, entry->len);#endif
tools/objtool/check.c +1 -1
@@ -1207,7 +1207,7 @@ static const char *uaccess_safe_builtin["copy_mc_enhanced_fast_string" ,"rep_stos_alternative" ,"rep_movs_alternative" , -"__copy_user_nocache" , +"copy_to_nontemporal" , NULL };
Greg Kroah-Hartman
maintainerPATCH 179/198 x86: rename and clean up __copy_from_user_inatomic_nocache()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linus Torvalds <[email protected]>
commit 5de7bcaadf160c1716b20a263cf8f5b06f658959 upstream.
Similarly to the previous commit, this renames the somewhat confusingly named function. But in this case, it was at least less confusing: the __copy_from_user_inatomic_nocache is indeed copying from user memory, and it is indeed ok to be used in an atomic context, so it will not warn about it.
But the previous commit also removed the NTB mis-use of the __copy_from_user_inatomic_nocache() function, and as a result every call-site is now _actually_ doing a real user copy. That means that we can now do the proper user pointer verification too.
End result: add proper address checking, remove the double underscores, and change the "nocache" to "nontemporal" to more accurately describe what this x86-only function actually does. It might be worth noting that only the target is non-temporal: the actual user accesses are normal memory accesses.
Also worth noting is that non-x86 targets (and on older 32-bit x86 CPU's before XMM2 in the Pentium III) we end up just falling back on a regular user copy, so nothing can actually depend on the non-temporal semantics, but that has always been true.
--- arch/x86/include/asm/uaccess.h | 2 +- arch/x86/include/asm/uaccess_32.h | 8 +------- arch/x86/include/asm/uaccess_64.h | 3 ++- arch/x86/lib/usercopy_32.c | 9 +++++---- drivers/gpu/drm/i915/i915_gem.c | 2 +- drivers/gpu/drm/qxl/qxl_ioctl.c | 2 +- include/linux/uaccess.h | 11 ++++++++--- lib/iov_iter.c | 2 +- 8 files changed, 20 insertions(+), 19 deletions(-)
arch/x86/include/asm/uaccess.h +1 -1
@@ -507,7 +507,7 @@ extern struct movsl_mask { } ____cacheline_aligned_in_smp movsl_mask;#endif -#define ARCH_HAS_NOCACHE_UACCESS 1 +#define ARCH_HAS_NONTEMPORAL_UACCESS 1/* * The "unsafe" user accesses aren't really "unsafe", but the naming
arch/x86/include/asm/uaccess_32.h +1 -7
@@ -26,13 +26,7 @@ raw_copy_from_user(void *to, const voidreturn __copy_user_ll (to, (__force const void *)from, n); } -static __always_inline unsigned long -__copy_from_user_inatomic_nocache (void *to,const void __user *from, -unsigned long n) -{ -return __copy_from_user_ll_nocache_nozero (to, from, n); -} - +unsigned long __must_check copy_from_user_inatomic_nontemporal (void *,const void __user *,unsigned long n);unsigned long __must_check clear_user (void __user *mem,unsigned long len);unsigned long __must_check __clear_user (void __user *mem,unsigned long len);
arch/x86/include/asm/uaccess_64.h +2 -1
@@ -152,11 +152,12 @@ extern size_t copy_to_nontemporal(void *extern long __copy_user_flushcache (void *dst,const void __user *src,unsigned size);static inline int -__copy_from_user_inatomic_nocache (void *dst,const void __user *src, +copy_from_user_inatomic_nontemporal (void *dst,const void __user *src,unsigned size) {long ret;kasan_check_write (dst, size); + src =mask_user_address (src);stac (); ret =copy_to_nontemporal (dst, (__force const void *)src, size);clac ();
arch/x86/lib/usercopy_32.c +5 -4
@@ -322,10 +322,11 @@ unsigned long __copy_user_ll(void *to, c }EXPORT_SYMBOL (__copy_user_ll); -unsigned long __copy_from_user_ll_nocache_nozero (void *to,const void __user *from, +unsigned long copy_from_user_inatomic_nontemporal (void *to,const void __user *from,unsigned long n) { -__uaccess_begin_nospec (); +if (!user_access_begin (from, n)) +return n;#ifdef CONFIG_X86_INTEL_USERCOPY if (n >64 &&static_cpu_has (X86_FEATURE_XMM2 )) n =__copy_user_intel_nocache (to, from, n);
@@ -334,7 +335,7 @@ unsigned long __copy_from_user_ll_nocach#else __copy_user (to, from, n);#endif -__uaccess_end (); +user_access_end ();return n; } -EXPORT_SYMBOL (__copy_from_user_ll_nocache_nozero); +EXPORT_SYMBOL (copy_from_user_inatomic_nontemporal);
drivers/gpu/drm/i915/i915_gem.c +1 -1
@@ -519,7 +519,7 @@ ggtt_write(struct io_mapping *mapping,/* We can use the cpu mem copy function because this is X86. */ vaddr =io_mapping_map_atomic_wc (mapping, base); - unwritten =__copy_from_user_inatomic_nocache ((void __force *)vaddr + offset, + unwritten =copy_from_user_inatomic_nontemporal ((void __force *)vaddr + offset, user_data, length);io_mapping_unmap_atomic (vaddr);if (unwritten) {
drivers/gpu/drm/qxl/qxl_ioctl.c +1 -1
@@ -182,7 +182,7 @@ static int qxl_process_single_command(st/* TODO copy slow path code from i915 */ fb_cmd =qxl_bo_kmap_atomic_page (qdev, cmd_bo, (release->release_offset &PAGE_MASK )); - unwritten =__copy_from_user_inatomic_nocache + unwritten =copy_from_user_inatomic_nontemporal (fb_cmd +sizeof (union qxl_release_info ) + (release->release_offset & ~PAGE_MASK ),u64_to_user_ptr (cmd->command), cmd->command_size);
include/linux/uaccess.h +8 -3
@@ -320,16 +320,21 @@ static inline size_t probe_subpage_write#endif /* CONFIG_ARCH_HAS_SUBPAGE_FAULTS */ -#ifndef ARCH_HAS_NOCACHE_UACCESS +#ifndef ARCH_HAS_NONTEMPORAL_UACCESS static inline __must_check unsigned long -__copy_from_user_inatomic_nocache (void *to,const void __user *from, +copy_from_user_inatomic_nontemporal (void *to,const void __user *from,unsigned long n) { +if (can_do_masked_user_access ()) + from =mask_user_address (from); +else +if (!access_ok (from, n)) +return n;return __copy_from_user_inatomic (to, from, n); } -#endif /* ARCH_HAS_NOCACHE_UACCESS */ +#endif /* ARCH_HAS_NONTEMPORAL_UACCESS */ extern __must_check int check_zeroed_user (const void __user *from,size_t size);
lib/iov_iter.c +1 -1
@@ -265,7 +265,7 @@ static __always_inlinesize_t copy_from_user_iter_nocache (void __user *iter_from,size_t progress,size_t len,void *to,void *priv2) { -return __copy_from_user_inatomic_nocache (to + progress, iter_from, len); +return copy_from_user_inatomic_nontemporal (to + progress, iter_from, len); }size_t _copy_from_iter_nocache (void *addr,size_t bytes,struct iov_iter *i)
Greg Kroah-Hartman
maintainerPATCH 180/198 x86-64/arm64/powerpc: clean up and rename __copy_from_user_flushcache
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linus Torvalds <[email protected]>
commit 809b997a5ce945ab470f70c187048fe4f5df20bf upstream.
This finishes the work on these odd functions that were only implemented by a handful of architectures.
The 'flushcache' function was only used from the iterator code, and let's make it do the same thing that the nontemporal version does:
remove the two underscores and add the user address checking.
Yes, yes, the user address checking is also done at iovec import time, but we have long since walked away from the old double-underscore thing where we try to avoid address checking overhead at access time, and these functions shouldn't be so special and old-fashioned.
The arm64 version already did the address check, in fact, so there it's just a matter of renaming it. For powerpc and x86-64 we now do the proper user access boilerplate.
--- arch/arm64/include/asm/uaccess.h | 2 +- arch/powerpc/include/asm/uaccess.h | 3 +-- arch/powerpc/lib/pmem.c | 11 ++++++----- arch/x86/include/asm/uaccess_64.h | 8 ++++---- arch/x86/lib/usercopy_64.c | 8 ++++---- lib/iov_iter.c | 2 +- 6 files changed, 17 insertions(+), 17 deletions(-)
arch/arm64/include/asm/uaccess.h +1 -1
@@ -480,7 +480,7 @@ extern __must_check long strnlen_user(co#ifdef CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE extern unsigned long __must_check __copy_user_flushcache (void *to,const void __user *from,unsigned long n); -static inline int __copy_from_user_flushcache (void *dst,const void __user *src,unsigned size) +static inline size_t copy_from_user_flushcache (void *dst,const void __user *src,size_t size) {kasan_check_write (dst, size);return __copy_user_flushcache (dst,__uaccess_mask_ptr (src), size);
arch/powerpc/include/asm/uaccess.h +1 -2
@@ -407,8 +407,7 @@ copy_mc_to_user(void __user *to, const v }#endif -extern long __copy_from_user_flushcache (void *dst,const void __user *src, -unsigned size); +extern size_t copy_from_user_flushcache (void *dst,const void __user *src,size_t size); static __must_check __always_inline bool user_access_begin(const void __user *ptr, size_t len) {
arch/powerpc/lib/pmem.c +6 -5
@@ -66,15 +66,16 @@ EXPORT_SYMBOL_GPL(arch_invalidate_pmem);/* * CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE symbols */ -long __copy_from_user_flushcache (void *dest,const void __user *src, -unsigned size) +size_t copy_from_user_flushcache (void *dest,const void __user *src, +size_t size) { -unsigned long copied, start = (unsigned long ) dest; +unsigned long not_copied, start = (unsigned long ) dest; - copied =__copy_from_user (dest, src, size); + src =mask_user_address (src); + not_copied =__copy_from_user (dest, src, size);clean_pmem_range (start, start + size); -return copied; +return not_copied; }void memcpy_flushcache (void *dest,const void *src,size_t size)
arch/x86/include/asm/uaccess_64.h +4 -4
@@ -149,7 +149,7 @@ raw_copy_to_user(void __user *dst, const#define copy_to_nontemporal copy_to_nontemporalextern size_t copy_to_nontemporal (void *dst,const void *src,size_t size); -extern long __copy_user_flushcache (void *dst,const void __user *src,unsigned size); +extern size_t copy_user_flushcache (void *dst,const void __user *src,size_t size); static inline int copy_from_user_inatomic_nontemporal(void *dst, const void __user *src,
@@ -164,11 +164,11 @@ copy_from_user_inatomic_nontemporal(voidreturn ret; } -static inline int -__copy_from_user_flushcache (void *dst,const void __user *src,unsigned size) +static inline size_t +copy_from_user_flushcache (void *dst,const void __user *src,size_t size) {kasan_check_write (dst, size); -return __copy_user_flushcache (dst, src, size); +return copy_user_flushcache (dst, src, size); }/*
arch/x86/lib/usercopy_64.c +4 -4
@@ -43,14 +43,14 @@ void arch_wb_cache_pmem(void *addr, size }EXPORT_SYMBOL_GPL (arch_wb_cache_pmem); -long __copy_user_flushcache (void *dst,const void __user *src,unsigned size) +size_t copy_user_flushcache (void *dst,const void __user *src,size_t size) {unsigned long flushed, dest = (unsigned long ) dst; -long rc; +unsigned long rc; -stac (); + src =masked_user_access_begin (src); rc =copy_to_nontemporal (dst, (__force const void *)src, size); -clac (); +user_access_end ();/* * copy_to_nontemporal() uses non-temporal stores for the bulk
lib/iov_iter.c +1 -1
@@ -284,7 +284,7 @@ static __always_inlinesize_t copy_from_user_iter_flushcache (void __user *iter_from,size_t progress,size_t len,void *to,void *priv2) { -return __copy_from_user_flushcache (to + progress, iter_from, len); +return copy_from_user_flushcache (to + progress, iter_from, len); } static __always_inline
Greg Kroah-Hartman
maintainerPATCH 181/198 KVM: x86: Use scratch field in MMIO fragment to hold small write values
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Christopherson <[email protected]>
commit 0b16e69d17d8c35c5c9d5918bf596c75a44655d3 upstream.
When exiting to userspace to service an emulated MMIO write, copy the to-be-written value to a scratch field in the MMIO fragment if the size of the data payload is 8 bytes or less, i.e. can fit in a single chunk, instead of pointing the fragment directly at the source value.
This fixes a class of use-after-free bugs that occur when the emulator initiates a write using an on-stack, local variable as the source, the write splits a page boundary, *and* both pages are MMIO pages. Because KVM's ABI only allows for physically contiguous MMIO requests, accesses that split MMIO pages are separated into two fragments, and are sent to userspace one at a time. When KVM attempts to complete userspace MMIO in response to KVM_RUN after the first fragment, KVM will detect the second fragment and generate a second userspace exit, and reference the on-stack variable.
The issue is most visible if the second KVM_RUN is performed by a separate task, in which case the stack of the initiating task can show up as truly freed data.
==================================================================
BUG: KASAN: use-after-free in complete_emulated_mmio+0x305/0x420
Read of size 1 at addr ffff888009c378d1 by task syz-executor417/984
CPU: 1 PID: 984 Comm: syz-executor417 Not tainted 5.10.0-182.0.0.95.h2627.eulerosv2r13.x86_64 #3
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.15.0-0-g2dd4b9b3f840-prebuilt.qemu.org 04/01/2014 Call Trace:
dump_stack+0xbe/0xfd
print_address_description.constprop.0+0x19/0x170
__kasan_report.cold+0x6c/0x84
kasan_report+0x3a/0x50
check_memory_region+0xfd/0x1f0
memcpy+0x20/0x60
complete_emulated_mmio+0x305/0x420
kvm_arch_vcpu_ioctl_run+0x63f/0x6d0
kvm_vcpu_ioctl+0x413/0xb20
__se_sys_ioctl+0x111/0x160
do_syscall_64+0x30/0x40
entry_SYSCALL_64_after_hwframe+0x67/0xd1
RIP: 0033:0x42477d
Code: <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007faa8e6890e8 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 00000000004d7338 RCX: 000000000042477d
RDX: 0000000000000000 RSI: 000000000000ae80 RDI: 0000000000000005
RBP: 00000000004d7330 R08: 00007fff28d546df R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 00000000004d733c
R13: 0000000000000000 R14: 000000000040a200 R15: 00007fff28d54720
The buggy address belongs to the page:
page:0000000029f6a428 refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x9c37
flags: 0xfffffc0000000(node=0|zone=1|lastcpupid=0x1fffff)
raw: 000fffffc0000000 0000000000000000 ffffea0000270dc8 0000000000000000
raw: 0000000000000000 0000000000000000 00000000ffffffff 0000000000000000 page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff888009c37780: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
ffff888009c37800: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
>ffff888009c37880: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
^
ffff888009c37900: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
ffff888009c37980: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
==================================================================The bug can also be reproduced with a targeted KVM-Unit-Test by hacking KVM to fill a large on-stack variable in complete_emulated_mmio(), i.e. by overwrite the data value with garbage.
Limit the use of the scratch fields to 8-byte or smaller accesses, and to just writes, as larger accesses and reads are not affected thanks to implementation details in the emulator, but add a sanity check to ensure those details don't change in the future. Specifically, KVM never uses on-stack variables for accesses larger that 8 bytes, e.g. uses an operand in the emulator context, and *all* reads are buffered through the mem_read cache.
Note! Using the scratch field for reads is not only unnecessary, it's also extremely difficult to handle correctly. As above, KVM buffers all reads through the mem_read cache, and heavily relies on that behavior when re-emulating the instruction after a userspace MMIO read exit. If a read splits a page, the first page is NOT an MMIO page, and the second page IS an MMIO page, then the MMIO fragment needs to point at _just_ the second chunk of the destination, i.e. its position in the mem_read cache. Taking the "obvious" approach of copying the fragment value into the destination when re-emulating the instruction would clobber the first chunk of the destination, i.e. would clobber the data that was read from guest memory.
--- arch/x86/kvm/x86.c | 14 +++++++++++++- include/linux/kvm_host.h | 3 ++- 2 files changed, 15 insertions(+), 2 deletions(-)
arch/x86/kvm/x86.c +13 -1
@@ -8236,7 +8236,13 @@ static int emulator_read_write_onepage(uWARN_ON (vcpu->mmio_nr_fragments >=KVM_MAX_MMIO_FRAGMENTS ); frag = &vcpu->mmio_fragments[vcpu->mmio_nr_fragments++]; frag->gpa = gpa; - frag->data = val; +if (write && bytes <=8u ) { + frag->val =0 ; + frag->data = &frag->val; +memcpy (&frag->val, val, bytes); + }else { + frag->data = val; + } frag->len = bytes;return X86EMUL_CONTINUE ; }
@@ -8251,6 +8257,9 @@ static int emulator_read_write(struct x8gpa_t gpa;int rc; +if (WARN_ON_ONCE ((bytes >8u || !ops->write) &&object_is_on_stack (val))) +return X86EMUL_UNHANDLEABLE ; +if (ops->read_write_prepare && ops->read_write_prepare (vcpu, val, bytes))return X86EMUL_CONTINUE ;
@@ -11823,6 +11832,9 @@ static int complete_emulated_mmio(struct frag++; vcpu->mmio_cur_fragment++; }else { +if (WARN_ON_ONCE (frag->data == &frag->val)) +return -EIO ; +/* Go forward to the next mmio piece. */ frag->data += len; frag->gpa += len;
include/linux/kvm_host.h +2 -1
@@ -320,7 +320,8 @@ static inline bool kvm_vcpu_can_poll(ktistruct kvm_mmio_fragment {gpa_t gpa;void *data; -unsigned len; +u64 val; +unsigned int len; };struct kvm_vcpu {
Greg Kroah-Hartman
maintainerPATCH 182/198 ASoC: qcom: q6apm: move component registration to unmanaged version
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Srinivas Kandagatla <[email protected]>
commit 6ec1235fc941dac6c011b30ee01d9220ff87e0cd upstream.
q6apm component registers dais dynamically from ASoC toplology, which are allocated using device managed version apis. Allocating both component and dynamic dais using managed version could lead to incorrect free ordering, dai will be freed while component still holding references to it.
Fix this issue by moving component to unmanged version so that the dai pointers are only freeded after the component is removed.
==================================================================
BUG: KASAN: slab-use-after-free in snd_soc_del_component_unlocked+0x3d4/0x400 [snd_soc_core] Read of size 8 at addr ffff00084493a6e8 by task kworker/u48:0/3426 Tainted: [W]=WARN Hardware name: LENOVO 21N2ZC5PUS/21N2ZC5PUS, BIOS N42ET57W (1.31 ) 08/08/2024 Workqueue: pdr_notifier_wq pdr_notifier_work [pdr_interface] Call trace: show_stack+0x28/0x7c (C) dump_stack_lvl+0x60/0x80 print_report+0x160/0x4b4 kasan_report+0xac/0xfc __asan_report_load8_noabort+0x20/0x34 snd_soc_del_component_unlocked+0x3d4/0x400 [snd_soc_core] snd_soc_unregister_component_by_driver+0x50/0x88 [snd_soc_core] devm_component_release+0x30/0x5c [snd_soc_core] devres_release_all+0x13c/0x210 device_unbind_cleanup+0x20/0x190 device_release_driver_internal+0x350/0x468 device_release_driver+0x18/0x30 bus_remove_device+0x1a0/0x35c device_del+0x314/0x7f0 device_unregister+0x20/0xbc apr_remove_device+0x5c/0x7c [apr] device_for_each_child+0xd8/0x160 apr_pd_status+0x7c/0xa8 [apr] pdr_notifier_work+0x114/0x240 [pdr_interface] process_one_work+0x500/0xb70 worker_thread+0x630/0xfb0 kthread+0x370/0x6c0 ret_from_fork+0x10/0x20 Allocated by task 77: kasan_save_stack+0x40/0x68 kasan_save_track+0x20/0x40 kasan_save_alloc_info+0x44/0x58 __kasan_kmalloc+0xbc/0xdc __kmalloc_node_track_caller_noprof+0x1f4/0x620 devm_kmalloc+0x7c/0x1c8 snd_soc_register_dai+0x50/0x4f0 [snd_soc_core] soc_tplg_pcm_elems_load+0x55c/0x1eb8 [snd_soc_core] snd_soc_tplg_component_load+0x4f8/0xb60 [snd_soc_core] audioreach_tplg_init+0x124/0x1fc [snd_q6apm] q6apm_audio_probe+0x10/0x1c [snd_q6apm] snd_soc_component_probe+0x5c/0x118 [snd_soc_core] soc_probe_component+0x44c/0xaf0 [snd_soc_core] snd_soc_bind_card+0xad0/0x2370 [snd_soc_core] snd_soc_register_card+0x3b0/0x4c0 [snd_soc_core] devm_snd_soc_register_card+0x50/0xc8 [snd_soc_core] x1e80100_platform_probe+0x208/0x368 [snd_soc_x1e80100] platform_probe+0xc0/0x188 really_probe+0x188/0x804 __driver_probe_device+0x158/0x358 driver_probe_device+0x60/0x190 __device_attach_driver+0x16c/0x2a8 bus_for_each_drv+0x100/0x194 __device_attach+0x174/0x380 device_initial_probe+0x14/0x20 bus_probe_device+0x124/0x154 deferred_probe_work_func+0x140/0x220 process_one_work+0x500/0xb70 worker_thread+0x630/0xfb0 kthread+0x370/0x6c0 ret_from_fork+0x10/0x20 Freed by task 3426: kasan_save_stack+0x40/0x68 kasan_save_track+0x20/0x40 __kasan_save_free_info+0x4c/0x80 __kasan_slab_free+0x78/0xa0 kfree+0x100/0x4a4 devres_release_all+0x144/0x210 device_unbind_cleanup+0x20/0x190 device_release_driver_internal+0x350/0x468 device_release_driver+0x18/0x30 bus_remove_device+0x1a0/0x35c device_del+0x314/0x7f0 device_unregister+0x20/0xbc apr_remove_device+0x5c/0x7c [apr] device_for_each_child+0xd8/0x160 apr_pd_status+0x7c/0xa8 [apr] pdr_notifier_work+0x114/0x240 [pdr_interface] process_one_work+0x500/0xb70 worker_thread+0x630/0xfb0 kthread+0x370/0x6c0 ret_from_fork+0x10/0x20
--- sound/soc/qcom/qdsp6/q6apm.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)
sound/soc/qcom/qdsp6/q6apm.c +12 -2
@@ -767,13 +767,22 @@ static int apm_probe(gpr_device_t *gdev)q6apm_get_apm_state (apm); - ret =devm_snd_soc_register_component (dev, &q6apm_audio_component,NULL ,0 ); + ret =snd_soc_register_component (dev, &q6apm_audio_component,NULL ,0 );if (ret <0 ) {dev_err (dev,"failed to register q6apm: %d\n" , ret);return ret; } -return of_platform_populate (dev->of_node,NULL ,NULL , dev); + ret =of_platform_populate (dev->of_node,NULL ,NULL , dev); +if (ret) +snd_soc_unregister_component (dev); + +return ret; +} + +static void apm_remove (gpr_device_t *gdev) +{ +snd_soc_unregister_component (&gdev->dev); }struct audioreach_module *q6apm_find_module_by_mid (struct q6apm_graph *graph,uint32_t mid)
@@ -840,6 +849,7 @@ MODULE_DEVICE_TABLE(of, apm_device_id);static gpr_driver_t apm_driver = { .probe = apm_probe, + .remove = apm_remove, .gpr_callback = apm_callback, .driver = { .name ="qcom-apm" ,
Greg Kroah-Hartman
maintainerPATCH 183/198 mm/kasan: fix double free for kasan pXds
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ritesh Harjani (IBM) <[email protected]>
commit 51d8c78be0c27ddb91bc2c0263941d8b30a47d3b upstream.
kasan_free_pxd() assumes the page table is always struct page aligned. But that's not always the case for all architectures. E.g. In case of powerpc with 64K pagesize, PUD table (of size 4096) comes from slab cache named pgtable-2^9. Hence instead of page_to_virt(pxd_page()) let's just directly pass the start of the pxd table which is passed as the 1st argument.
This fixes the below double free kasan issue seen with PMEM:
radix-mmu: Mapped 0x0000047d10000000-0x0000047f90000000 with 2.00 MiB pages
==================================================================
BUG: KASAN: double-free in kasan_remove_zero_shadow+0x9c4/0xa20
Free of addr c0000003c38e0000 by task ndctl/2164
CPU: 34 UID: 0 PID: 2164 Comm: ndctl Not tainted 6.19.0-rc1-00048-gea1013c15392 #157 VOLUNTARY Hardware name: IBM,9080-HEX POWER10 (architected) 0x800200 0xf000006 of:IBM,FW1060.00 (NH1060_012) hv:phyp pSeries Call Trace: dump_stack_lvl+0x88/0xc4 (unreliable) print_report+0x214/0x63c kasan_report_invalid_free+0xe4/0x110 check_slab_allocation+0x100/0x150 kmem_cache_free+0x128/0x6e0 kasan_remove_zero_shadow+0x9c4/0xa20 memunmap_pages+0x2b8/0x5c0 devm_action_release+0x54/0x70 release_nodes+0xc8/0x1a0 devres_release_all+0xe0/0x140 device_unbind_cleanup+0x30/0x120 device_release_driver_internal+0x3e4/0x450 unbind_store+0xfc/0x110 drv_attr_store+0x78/0xb0 sysfs_kf_write+0x114/0x140 kernfs_fop_write_iter+0x264/0x3f0 vfs_write+0x3bc/0x7d0 ksys_write+0xa4/0x190 system_call_exception+0x190/0x480 system_call_vectored_common+0x15c/0x2ec ---- interrupt: 3000 at 0x7fff93b3d3f4 NIP: 00007fff93b3d3f4 LR: 00007fff93b3d3f4 CTR: 0000000000000000 REGS: c0000003f1b07e80 TRAP: 3000 Not tainted (6.19.0-rc1-00048-gea1013c15392) MSR: 800000000280f033 <SF,VEC,VSX,EE,PR,FP,ME,IR,DR,RI,LE> CR: 48888208 XER: 00000000
<...>
NIP [00007fff93b3d3f4] 0x7fff93b3d3f4
LR [00007fff93b3d3f4] 0x7fff93b3d3f4
---- interrupt: 3000
The buggy address belongs to the object at c0000003c38e0000 which belongs to the cache pgtable-2^9 of size 4096 The buggy address is located 0 bytes inside of 4096-byte region [c0000003c38e0000, c0000003c38e1000) The buggy address belongs to the physical page: page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x3c38c head: order:2 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0 memcg:c0000003bfd63e01 flags: 0x63ffff800000040(head|node=6|zone=0|lastcpupid=0x7ffff) page_type: f5(slab) raw: 063ffff800000040 c000000140058980 5deadbeef0000122 0000000000000000 raw: 0000000000000000 0000000080200020 00000000f5000000 c0000003bfd63e01 head: 063ffff800000040 c000000140058980 5deadbeef0000122 0000000000000000 head: 0000000000000000 0000000080200020 00000000f5000000 c0000003bfd63e01 head: 063ffff800000002 c00c000000f0e301 00000000ffffffff 00000000ffffffff head: ffffffffffffffff 0000000000000000 00000000ffffffff 0000000000000004 page dumped because: kasan: bad access detected
[ 138.953636] [ T2164] Memory state around the buggy address: [ 138.953643] [ T2164] c0000003c38dff00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 138.953652] [ T2164] c0000003c38dff80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 138.953661] [ T2164] >c0000003c38e0000: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 138.953669] [ T2164] ^ [ 138.953675] [ T2164] c0000003c38e0080: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 138.953684] [ T2164] c0000003c38e0100: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 138.953692] [ T2164] ================================================================== [ 138.953701] [ T2164] Disabling lock debugging due to kernel taint
--- mm/kasan/init.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
mm/kasan/init.c +4 -4
@@ -292,7 +292,7 @@ static void kasan_free_pte(pte_t *pte_streturn ; } -pte_free_kernel (&init_mm, (pte_t *)page_to_virt (pmd_page (*pmd))); +pte_free_kernel (&init_mm, pte_start);pmd_clear (pmd); }
@@ -307,7 +307,7 @@ static void kasan_free_pmd(pmd_t *pmd_streturn ; } -pmd_free (&init_mm, (pmd_t *)page_to_virt (pud_page (*pud))); +pmd_free (&init_mm, pmd_start);pud_clear (pud); }
@@ -322,7 +322,7 @@ static void kasan_free_pud(pud_t *pud_streturn ; } -pud_free (&init_mm, (pud_t *)page_to_virt (p4d_page (*p4d))); +pud_free (&init_mm, pud_start);p4d_clear (p4d); }
@@ -337,7 +337,7 @@ static void kasan_free_p4d(p4d_t *p4d_streturn ; } -p4d_free (&init_mm, (p4d_t *)page_to_virt (pgd_page (*pgd))); +p4d_free (&init_mm, p4d_start);pgd_clear (pgd); }
Greg Kroah-Hartman
maintainerPATCH 184/198 mm: blk-cgroup: fix use-after-free in cgwb_release_workfn()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Breno Leitao <[email protected]>
commit 8f5857be99f1ed1fa80991c72449541f634626ee upstream.
cgwb_release_workfn() calls css_put(wb->blkcg_css) and then later accesses wb->blkcg_css again via blkcg_unpin_online(). If css_put() drops the last reference, the blkcg can be freed asynchronously (css_free_rwork_fn -> blkcg_css_free -> kfree) before blkcg_unpin_online() dereferences the pointer to access blkcg->online_pin, resulting in a use-after-free:
BUG: KASAN: slab-use-after-free in blkcg_unpin_online (./include/linux/instrumented.h:112 ./include/linux/atomic/atomic-instrumented.h:400 ./include/linux/refcount.h:389 ./include/linux/refcount.h:432 ./include/linux/refcount.h:450 block/blk-cgroup.c:1367)
Write of size 4 at addr ff11000117aa6160 by task kworker/71:1/531
Workqueue: cgwb_release cgwb_release_workfn
Call Trace:
<TASK>
blkcg_unpin_online (./include/linux/instrumented.h:112 ./include/linux/atomic/atomic-instrumented.h:400 ./include/linux/refcount.h:389 ./include/linux/refcount.h:432 ./include/linux/refcount.h:450 block/blk-cgroup.c:1367)
cgwb_release_workfn (mm/backing-dev.c:629)
process_scheduled_works (kernel/workqueue.c:3278 kernel/workqueue.c:3385)
Freed by task 1016:
kfree (./include/linux/kasan.h:235 mm/slub.c:2689 mm/slub.c:6246 mm/slub.c:6561)
css_free_rwork_fn (kernel/cgroup/cgroup.c:5542)
process_scheduled_works (kernel/workqueue.c:3302 kernel/workqueue.c:3385)** Stack based on commit 66672af7a095 ("Add linux-next specific files for 20260410")
I am seeing this crash sporadically in Meta fleet across multiple kernel versions. A full reproducer is available at:
https://github.com/leitao/debug/blob/main/reproducers/repro_blkcg_uaf.sh
(The race window is narrow. To make it easily reproducible, inject a msleep(100) between css_put() and blkcg_unpin_online() in cgwb_release_workfn(). With that delay and a KASAN-enabled kernel, the reproducer triggers the splat reliably in less than a second.)
Fix this by moving blkcg_unpin_online() before css_put(), so the cgwb's CSS reference keeps the blkcg alive while blkcg_unpin_online() accesses it.
--- mm/backing-dev.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
mm/backing-dev.c +3 -2
@@ -618,12 +618,13 @@ static void cgwb_release_workfn(struct wwb_shutdown (wb);css_put (wb->memcg_css); -css_put (wb->blkcg_css); -mutex_unlock (&wb->bdi->cgwb_release_mutex);/* triggers blkg destruction if no online users left */ blkcg_unpin_online (wb->blkcg_css); +css_put (wb->blkcg_css); +mutex_unlock (&wb->bdi->cgwb_release_mutex); +fprop_local_destroy_percpu (&wb->memcg_completions);spin_lock_irq (&cgwb_lock);
Greg Kroah-Hartman
maintainerPATCH 185/198 media: vidtv: fix nfeeds state corruption on start_streaming failure
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ruslan Valiyev <[email protected]>
commit a0e5a598fe9a4612b852406b51153b881592aede upstream.
syzbot reported a memory leak in vidtv_psi_service_desc_init [1].
When vidtv_start_streaming() fails inside vidtv_start_feed(), the nfeeds counter is left incremented even though no feed was actually started. This corrupts the driver state: subsequent start_feed calls see nfeeds > 1 and skip starting the mux, while stop_feed calls eventually try to stop a non-existent stream.
This state corruption can also lead to memory leaks, since the mux and channel resources may be partially allocated during a failed start_streaming but never cleaned up, as the stop path finds dvb->streaming == false and returns early.
Fix by decrementing nfeeds back when start_streaming fails, keeping the counter in sync with the actual number of active feeds.
[1]
BUG: memory leak unreferenced object 0xffff888145b50820 (size 32): comm "syz.0.17", pid 6068, jiffies 4294944486 backtrace (crc 90a0c7d4): vidtv_psi_service_desc_init+0x74/0x1b0 drivers/media/test-drivers/vidtv/vidtv_psi.c:288 vidtv_channel_s302m_init+0xb1/0x2a0 drivers/media/test-drivers/vidtv/vidtv_channel.c:83 vidtv_channels_init+0x1b/0x40 drivers/media/test-drivers/vidtv/vidtv_channel.c:524 vidtv_mux_init+0x516/0xbe0 drivers/media/test-drivers/vidtv/vidtv_mux.c:518 vidtv_start_streaming drivers/media/test-drivers/vidtv/vidtv_bridge.c:194 [inline] vidtv_start_feed+0x33e/0x4d0 drivers/media/test-drivers/vidtv/vidtv_bridge.c:239
--- drivers/media/test-drivers/vidtv/vidtv_bridge.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/media/test-drivers/vidtv/vidtv_bridge.c +3 -1
@@ -237,8 +237,10 @@ static int vidtv_start_feed(struct dvb_dif (dvb->nfeeds ==1 ) { ret =vidtv_start_streaming (dvb); -if (ret <0 ) +if (ret <0 ) { + dvb->nfeeds--; rc = ret; + } }mutex_unlock (&dvb->feed_lock);
Greg Kroah-Hartman
maintainerPATCH 186/198 media: mediatek: vcodec: fix use-after-free in encoder release path
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fan Wu <[email protected]>
commit 76e35091ffc722ba39b303e48bc5d08abb59dd56 upstream.
The fops_vcodec_release() function frees the context structure (ctx) without first cancelling any pending or running work in ctx->encode_work. This creates a race window where the workqueue handler (mtk_venc_worker) may still be accessing the context memory after it has been freed.
Race condition:
CPU 0 (release path) CPU 1 (workqueue)
--------------------- ------------------
fops_vcodec_release()
v4l2_m2m_ctx_release()
v4l2_m2m_cancel_job()
// waits for m2m job "done"
mtk_venc_worker()
v4l2_m2m_job_finish()
// m2m job "done"
// BUT worker still running!
// post-job_finish access:
other ctx dereferences
// UAF if ctx already freed
// returns (job "done")
kfree(ctx) // ctx freedRoot cause: The v4l2_m2m_ctx_release() only waits for the m2m job lifecycle (via TRANS_RUNNING flag), not the workqueue lifecycle. After v4l2_m2m_job_finish() is called, the m2m framework considers the job complete and v4l2_m2m_ctx_release() returns, but the worker function continues executing and may still access ctx.
The work is queued during encode operations via:
queue_work(ctx->dev->encode_workqueue, &ctx->encode_work)
The worker function accesses ctx->m2m_ctx, ctx->dev, and other ctx fields even after calling v4l2_m2m_job_finish().
This vulnerability was confirmed with KASAN by running an instrumented test module that widens the post-job_finish race window. KASAN detected:
BUG: KASAN: slab-use-after-free in mtk_venc_worker+0x159/0x180
Read of size 4 at addr ffff88800326e000 by task kworker/u8:0/12
Workqueue: mtk_vcodec_enc_wq mtk_venc_worker
Allocated by task 47:
__kasan_kmalloc+0x7f/0x90
fops_vcodec_open+0x85/0x1a0
Freed by task 47:
__kasan_slab_free+0x43/0x70
kfree+0xee/0x3a0
fops_vcodec_release+0xb7/0x190Fix this by calling cancel_work_sync(&ctx->encode_work) before kfree(ctx). This ensures the workqueue handler is both cancelled (if pending) and synchronized (waits for any running handler to complete) before the context is freed.
Placement rationale: The fix is placed after v4l2_ctrl_handler_free() and before list_del_init(&ctx->list). At this point, all m2m operations are done (v4l2_m2m_ctx_release() has returned), and we need to ensure the workqueue is synchronized before removing ctx from the list and freeing it.
Note: The open error path does NOT need cancel_work_sync() because INIT_WORK() only initializes the work structure - it does not schedule it. Work is only scheduled later during device_run() operations.
--- drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.c | 9 +++++++++ 1 file changed, 9 insertions(+)
drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.c +9 -0
@@ -215,6 +215,15 @@ static int fops_vcodec_release(struct fiv4l2_fh_exit (&ctx->fh);v4l2_ctrl_handler_free (&ctx->ctrl_hdl); +/* +* Cancel any pending encode work before freeing the context. +* Although v4l2_m2m_ctx_release() waits for m2m job completion, +* the workqueue handler (mtk_venc_worker) may still be accessing +* the context after v4l2_m2m_job_finish() returns. Without this, +* a use-after-free occurs when the worker accesses ctx after kfree. +*/ +cancel_work_sync (&ctx->encode_work); +spin_lock_irqsave (&dev->dev_ctx_lock, flags);list_del_init (&ctx->list);spin_unlock_irqrestore (&dev->dev_ctx_lock, flags);
Greg Kroah-Hartman
maintainerPATCH 187/198 media: em28xx: fix use-after-free in em28xx_v4l2_open()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abhishek Kumar <[email protected]>
commit a66485a934c7187ae8e36517d40615fa2e961cff upstream.
em28xx_v4l2_open() reads dev->v4l2 without holding dev->lock, creating a race with em28xx_v4l2_init()'s error path and em28xx_v4l2_fini(), both of which free the em28xx_v4l2 struct and set dev->v4l2 to NULL under dev->lock.
This race leads to two issues:
- use-after-free in v4l2_fh_init() when accessing vdev->ctrl_handler, since the video_device is embedded in the freed em28xx_v4l2 struct.
- NULL pointer dereference in em28xx_resolution_set() when accessing v4l2->norm, since dev->v4l2 has been set to NULL.
Fix this by moving the mutex_lock() before the dev->v4l2 read and adding a NULL check for dev->v4l2 under the lock.
--- drivers/media/usb/em28xx/em28xx-video.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
drivers/media/usb/em28xx/em28xx-video.c +10 -4
@@ -2126,7 +2126,7 @@ static int em28xx_v4l2_open(struct file {struct video_device *vdev =video_devdata (filp);struct em28xx *dev =video_drvdata (filp); -struct em28xx_v4l2 *v4l2 = dev->v4l2; +struct em28xx_v4l2 *v4l2;enum v4l2_buf_type fh_type =0 ;int ret;
@@ -2143,13 +2143,19 @@ static int em28xx_v4l2_open(struct filereturn -EINVAL ; } +if (mutex_lock_interruptible (&dev->lock)) +return -ERESTARTSYS ; + + v4l2 = dev->v4l2; +if (!v4l2) { +mutex_unlock (&dev->lock); +return -ENODEV ; + } +em28xx_videodbg ("open dev=%s type=%s users=%d\n" ,video_device_node_name (vdev), v4l2_type_names[fh_type], v4l2->users); -if (mutex_lock_interruptible (&dev->lock)) -return -ERESTARTSYS ; - ret =v4l2_fh_open (filp);if (ret) { dev_err(&dev->intf->dev,
Greg Kroah-Hartman
maintainerPATCH 188/198 hwmon: (powerz) Fix use-after-free on USB disconnect
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sanman Pradhan <[email protected]>
commit 08e57f5e1a9067d5fbf33993aa7f51d60b3d13a4 upstream.
After powerz_disconnect() frees the URB and releases the mutex, a subsequent powerz_read() call can acquire the mutex and call powerz_read_data(), which dereferences the freed URB pointer.
Fix by:
- Setting priv->urb to NULL in powerz_disconnect() so that powerz_read_data() can detect the disconnected state.
- Adding a !priv->urb check at the start of powerz_read_data() to return -ENODEV on a disconnected device.
- Moving usb_set_intfdata() before hwmon registration so the disconnect handler can always find the priv pointer.
--- drivers/hwmon/powerz.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/hwmon/powerz.c +6 -2
@@ -108,6 +108,9 @@ static int powerz_read_data(struct usb_d {int ret; +if (!priv->urb) +return -ENODEV ; + priv->status = -ETIMEDOUT ;reinit_completion (&priv->completion);
@@ -224,6 +227,8 @@ static int powerz_probe(struct usb_intermutex_init (&priv->mutex);init_completion (&priv->completion); +usb_set_intfdata (intf, priv); + hwmon_dev =devm_hwmon_device_register_with_info (parent,DRIVER_NAME , priv, &powerz_chip_info,NULL );
@@ -232,8 +237,6 @@ static int powerz_probe(struct usb_interreturn PTR_ERR (hwmon_dev); } -usb_set_intfdata (intf, priv); -return 0 ; }
@@ -244,6 +247,7 @@ static void powerz_disconnect(struct usbmutex_lock (&priv->mutex);usb_kill_urb (priv->urb);usb_free_urb (priv->urb); + priv->urb =NULL ;mutex_unlock (&priv->mutex); }
Greg Kroah-Hartman
maintainerPATCH 189/198 ALSA: 6fire: fix use-after-free on disconnect
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Berk Cem Goksel <[email protected]>
commit b9c826916fdce6419b94eb0cd8810fdac18c2386 upstream.
In usb6fire_chip_abort(), the chip struct is allocated as the card's private data (via snd_card_new with sizeof(struct sfire_chip)). When snd_card_free_when_closed() is called and no file handles are open, the card and embedded chip are freed synchronously. The subsequent chip->card = NULL write then hits freed slab memory.
Call trace: usb6fire_chip_abort sound/usb/6fire/chip.c:59 [inline] usb6fire_chip_disconnect+0x348/0x358 sound/usb/6fire/chip.c:182 usb_unbind_interface+0x1a8/0x88c drivers/usb/core/driver.c:458 ... hub_event+0x1a04/0x4518 drivers/usb/core/hub.c:5953
Fix by moving the card lifecycle out of usb6fire_chip_abort() and into usb6fire_chip_disconnect(). The card pointer is saved in a local before any teardown, snd_card_disconnect() is called first to prevent new opens, URBs are aborted while chip is still valid, and snd_card_free_when_closed() is called last so chip is never accessed after the card may be freed.
--- sound/usb/6fire/chip.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-)
sound/usb/6fire/chip.c +12 -5
@@ -53,11 +53,6 @@ static void usb6fire_chip_abort(struct susb6fire_comm_abort (chip);if (chip->control)usb6fire_control_abort (chip); -if (chip->card) { -snd_card_disconnect (chip->card); -snd_card_free_when_closed (chip->card); - chip->card =NULL ; - } } }
@@ -168,6 +163,7 @@ destroy_chip:static void usb6fire_chip_disconnect (struct usb_interface *intf) {struct sfire_chip *chip; +struct snd_card *card; chip =usb_get_intfdata (intf);if (chip) {/* if !chip, fw upload has been performed */
@@ -178,8 +174,19 @@ static void usb6fire_chip_disconnect(str chips[chip->regidx] =NULL ; } +/* +* Save card pointer before teardown. +* snd_card_free_when_closed() may free card (and +* the embedded chip) immediately, so it must be +* called last and chip must not be accessed after. +*/ + card = chip->card; chip->shutdown = true; +if (card) +snd_card_disconnect (card);usb6fire_chip_abort (chip); +if (card) +snd_card_free_when_closed (card); } } }
Greg Kroah-Hartman
maintainerPATCH 190/198 bcache: fix cached_dev.sb_bio use-after-free and crash
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mingzhe Zou <[email protected]>
commit fec114a98b8735ee89c75216c45a78e28be0f128 upstream.
In our production environment, we have received multiple crash reports regarding libceph, which have caught our attention:
``` [6888366.280350] Call Trace: [6888366.280452] blk_update_request+0x14e/0x370 [6888366.280561] blk_mq_end_request+0x1a/0x130 [6888366.280671] rbd_img_handle_request+0x1a0/0x1b0 [rbd] [6888366.280792] rbd_obj_handle_request+0x32/0x40 [rbd] [6888366.280903] __complete_request+0x22/0x70 [libceph] [6888366.281032] osd_dispatch+0x15e/0xb40 [libceph] [6888366.281164] ? inet_recvmsg+0x5b/0xd0 [6888366.281272] ? ceph_tcp_recvmsg+0x6f/0xa0 [libceph] [6888366.281405] ceph_con_process_message+0x79/0x140 [libceph] [6888366.281534] ceph_con_v1_try_read+0x5d7/0xf30 [libceph] [6888366.281661] ceph_con_workfn+0x329/0x680 [libceph] ```
After analyzing the coredump file, we found that the address of dc->sb_bio has been freed. We know that cached_dev is only freed when it is stopped.
Since sb_bio is a part of struct cached_dev, rather than an alloc every time. If the device is stopped while writing to the superblock, the released address will be accessed at endio.
This patch hopes to wait for sb_write to complete in cached_dev_free.
It should be noted that we analyzed the cause of the problem, then tell all details to the QWEN and adopted the modifications it made.
--- drivers/md/bcache/super.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/md/bcache/super.c +7 -0
@@ -1373,6 +1373,13 @@ static CLOSURE_CALLBACK(cached_dev_free)mutex_unlock (&bch_register_lock); +/* +* Wait for any pending sb_write to complete before free. +* The sb_bio is embedded in struct cached_dev, so we must +* ensure no I/O is in progress. +*/ +closure_sync (&dc->sb_write); +if (dc->sb_disk)folio_put (virt_to_folio (dc->sb_disk));
Greg Kroah-Hartman
maintainerPATCH 191/198 wireguard: device: use exit_rtnl callback instead of manual rtnl_lock in pre_exit
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shardul Bankar <[email protected]>
commit 60a25ef8dacb3566b1a8c4de00572a498e2a3bf9 upstream.
wg_netns_pre_exit() manually acquires rtnl_lock() inside the pernet .pre_exit callback. This causes a hung task when another thread holds rtnl_mutex - the cleanup_net workqueue (or the setup_net failure rollback path) blocks indefinitely in wg_netns_pre_exit() waiting to acquire the lock.
Convert to .exit_rtnl, introduced in commit 7a60d91c690b ("net:
Add ->exit_rtnl() hook to struct pernet_operations."), where the framework already holds RTNL and batches all callbacks under a single rtnl_lock()/rtnl_unlock() pair, eliminating the contention window.
The rcu_assign_pointer(wg->creating_net, NULL) is safe to move from .pre_exit to .exit_rtnl (which runs after synchronize_rcu()) because all RCU readers of creating_net either use maybe_get_net()
- which returns NULL for a dying namespace with zero refcount - or access net->user_ns which remains valid throughout the entire ops_undo_list sequence.
--- drivers/net/wireguard/device.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-)
drivers/net/wireguard/device.c +3 -5
@@ -411,12 +411,11 @@ static struct rtnl_link_ops link_ops __r .newlink = wg_newlink, }; -static void wg_netns_pre_exit (struct net *net) +static void __net_exit wg_netns_exit_rtnl(struct net *net, struct list_head *dev_kill_list) {struct wg_device *wg;struct wg_peer *peer; -rtnl_lock ();list_for_each_entry (wg, &device_list, device_list) {if (rcu_access_pointer (wg->creating_net) == net) {pr_debug ("%s: Creating namespace exiting\n" , wg->dev->name);
@@ -429,11 +428,10 @@ static void wg_netns_pre_exit(struct netmutex_unlock (&wg->device_update_lock); } } -rtnl_unlock (); } -static struct pernet_operations pernet_ops = { - .pre_exit = wg_netns_pre_exit +static struct pernet_operations pernet_ops__read_mostly = { + .exit_rtnl = wg_netns_exit_rtnl };int __init wg_device_init (void )
Greg Kroah-Hartman
maintainerPATCH 192/198 media: as102: fix to not free memory after the device is registered in as102_usb_probe()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeongjun Park <[email protected]>
commit 8bd29dbe03fc5b0f039ab2395ff37b64236d2f0c upstream.
In as102_usb driver, the following race condition occurs:
```
CPU0 CPU1
as102_usb_probe()
kzalloc(); // alloc as102_dev_t
....
usb_register_dev();
fd = sys_open("/path/to/dev"); // open as102 fd
....
usb_deregister_dev();
....
kfree(); // free as102_dev_t
....
sys_close(fd);
as102_release() // UAF!!
as102_usb_release()
kfree(); // DFB!!
```When a USB character device registered with usb_register_dev() is later unregistered (via usb_deregister_dev() or disconnect), the device node is removed so new open() calls fail. However, file descriptors that are already open do not go away immediately: they remain valid until the last reference is dropped and the driver's .release() is invoked.
In as102, as102_usb_probe() calls usb_register_dev() and then, on an error path, does usb_deregister_dev() and frees as102_dev_t right away. If userspace raced a successful open() before the deregistration, that open FD will later hit as102_release() --> as102_usb_release() and access or free as102_dev_t again, occur a race to use-after-free and double-free vuln.
The fix is to never kfree(as102_dev_t) directly once usb_register_dev() has succeeded. After deregistration, defer freeing memory to .release().
In other words, let release() perform the last kfree when the final open FD is closed.
--- drivers/media/usb/as102/as102_usb_drv.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/media/usb/as102/as102_usb_drv.c +2 -0
@@ -403,7 +403,9 @@ static int as102_usb_probe(struct usb_in failed_dvb:as102_free_usb_stream_buffer (as102_dev); failed_stream: +usb_set_intfdata (intf,NULL );usb_deregister_dev (intf, &as102_usb_class_driver); +return ret; failed:usb_put_dev (as102_dev->bus_adap.usb_dev);usb_set_intfdata (intf,NULL );
Greg Kroah-Hartman
maintainerPATCH 193/198 nilfs2: fix NULL i_assoc_inode dereference in nilfs_mdt_save_to_shadow_map
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Deepanshu Kartikey <[email protected]>
commit 4a4e0328edd9e9755843787d28f16dd4165f8b48 upstream.
The DAT inode's btree node cache (i_assoc_inode) is initialized lazily during btree operations. However, nilfs_mdt_save_to_shadow_map() assumes i_assoc_inode is already initialized when copying dirty pages to the shadow map during GC.
If NILFS_IOCTL_CLEAN_SEGMENTS is called immediately after mount before any btree operation has occurred on the DAT inode, i_assoc_inode is NULL leading to a general protection fault.
Fix this by calling nilfs_attach_btree_node_cache() on the DAT inode in nilfs_dat_read() at mount time, ensuring i_assoc_inode is always initialized before any GC operation can use it.
--- fs/nilfs2/dat.c | 3 +++ 1 file changed, 3 insertions(+)
fs/nilfs2/dat.c +3 -0
@@ -524,6 +524,9 @@ int nilfs_dat_read(struct super_block *sif (err) goto failed; + err =nilfs_attach_btree_node_cache (dat); +if (err) + goto failed; err =nilfs_read_inode_common (dat, raw_inode);if (err) goto failed;
Greg Kroah-Hartman
maintainerPATCH 194/198 media: vidtv: fix pass-by-value structs causing MSAN warnings
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abd-Alrhman Masalkhi <[email protected]>
commit 5f8e73bde67e931468bc2a1860d78d72f0c6ba41 upstream.
vidtv_ts_null_write_into() and vidtv_ts_pcr_write_into() take their argument structs by value, causing MSAN to report uninit-value warnings. While only vidtv_ts_null_write_into() has triggered a report so far, both functions share the same issue.
Fix by passing both structs by const pointer instead, avoiding the stack copy of the struct along with its MSAN shadow and origin metadata. The functions do not modify the structs, which is enforced by the const qualifier.
--- drivers/media/test-drivers/vidtv/vidtv_mux.c | 4 +- drivers/media/test-drivers/vidtv/vidtv_ts.c | 50 +++++++++++++-------------- drivers/media/test-drivers/vidtv/vidtv_ts.h | 4 +- 3 files changed, 29 insertions(+), 29 deletions(-)
drivers/media/test-drivers/vidtv/vidtv_mux.c +2 -2
@@ -233,7 +233,7 @@ static u32 vidtv_mux_push_pcr(struct vid/* the 27Mhz clock will feed both parts of the PCR bitfield */ args.pcr = m->timing.clk; - nbytes +=vidtv_ts_pcr_write_into (args); + nbytes +=vidtv_ts_pcr_write_into (&args); m->mux_buf_offset += nbytes; m->num_streamed_pcr++;
@@ -363,7 +363,7 @@ static u32 vidtv_mux_pad_with_nulls(stru args.continuity_counter = &ctx->cc;for (i =0 ; i < npkts; ++i) { - m->mux_buf_offset +=vidtv_ts_null_write_into (args); + m->mux_buf_offset +=vidtv_ts_null_write_into (&args); args.dest_offset = m->mux_buf_offset; }
drivers/media/test-drivers/vidtv/vidtv_ts.c +25 -25
97 lines not on this page · raw message
drivers/media/test-drivers/vidtv/vidtv_ts.h +2 -2
@@ -90,7 +90,7 @@ void vidtv_ts_inc_cc(u8 *continuity_coun* * Return: The number of bytes written into the buffer. */ -u32 vidtv_ts_null_write_into (struct null_packet_write_args args); +u32 vidtv_ts_null_write_into (const struct null_packet_write_args *args);/** * vidtv_ts_pcr_write_into - Write a PCR packet into a buffer.
@@ -101,6 +101,6 @@ u32 vidtv_ts_null_write_into(struct null* * Return: The number of bytes written into the buffer. */ -u32 vidtv_ts_pcr_write_into (struct pcr_write_args args); +u32 vidtv_ts_pcr_write_into (const struct pcr_write_args *args);#endif //VIDTV_TS_H
Greg Kroah-Hartman
maintainerPATCH 195/198 media: hackrf: fix to not free memory after the device is registered in hackrf_probe()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeongjun Park <[email protected]>
commit 3b7da2b4d0fe014eff181ed37e3bf832eb8ed258 upstream.
In hackrf driver, the following race condition occurs:
```
CPU0 CPU1
hackrf_probe()
kzalloc(); // alloc hackrf_dev
....
v4l2_device_register();
....
fd = sys_open("/path/to/dev"); // open hackrf fd
....
v4l2_device_unregister();
....
kfree(); // free hackrf_dev
....
sys_ioctl(fd, ...);
v4l2_ioctl();
video_is_registered() // UAF!!
....
sys_close(fd);
v4l2_release() // UAF!!
hackrf_video_release()
kfree(); // DFB!!
```When a V4L2 or video device is unregistered, the device node is removed so new open() calls are blocked.
However, file descriptors that are already open-and any in-flight I/O-do not terminate immediately; they remain valid until the last reference is dropped and the driver's release() is invoked.
Therefore, freeing device memory on the error path after hackrf_probe() has registered dev it will lead to a race to use-after-free vuln, since those already-open handles haven't been released yet.
And since release() free memory too, race to use-after-free and double-free vuln occur.
To prevent this, if device is registered from probe(), it should be modified to free memory only through release() rather than calling kfree() directly.
--- drivers/media/usb/hackrf/hackrf.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/media/usb/hackrf/hackrf.c +4 -3
@@ -1485,7 +1485,7 @@ static int hackrf_probe(struct usb_interif (ret) {dev_err (dev->dev,"Failed to register as video device (%d)\n" , ret); - goto err_v4l2_device_unregister; + goto err_v4l2_device_put; }dev_info (dev->dev,"Registered as %s\n" ,video_device_node_name (&dev->rx_vdev));
@@ -1513,8 +1513,9 @@ static int hackrf_probe(struct usb_interreturn 0 ; err_video_unregister_device_rx:video_unregister_device (&dev->rx_vdev); -err_v4l2_device_unregister: -v4l2_device_unregister (&dev->v4l2_dev); +err_v4l2_device_put: +v4l2_device_put (&dev->v4l2_dev); +return ret; err_v4l2_ctrl_handler_free_tx:v4l2_ctrl_handler_free (&dev->tx_ctrl_handler); err_v4l2_ctrl_handler_free_rx:
Greg Kroah-Hartman
maintainerPATCH 196/198 mm/userfaultfd: fix hugetlb fault mutex hash calculation
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jianhui Zhou <[email protected]>
commit 0217c7fb4de4a40cee667eb21901f3204effe5ac upstream.
In mfill_atomic_hugetlb(), linear_page_index() is used to calculate the page index for hugetlb_fault_mutex_hash(). However, linear_page_index() returns the index in PAGE_SIZE units, while hugetlb_fault_mutex_hash() expects the index in huge page units. This mismatch means that different addresses within the same huge page can produce different hash values, leading to the use of different mutexes for the same huge page. This can cause races between faulting threads, which can corrupt the reservation map and trigger the BUG_ON in resv_map_release().
Fix this by introducing hugetlb_linear_page_index(), which returns the page index in huge page granularity, and using it in place of linear_page_index().
--- include/linux/hugetlb.h | 17 +++++++++++++++++ mm/userfaultfd.c | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-)
include/linux/hugetlb.h +17 -0
@@ -793,6 +793,23 @@ static inline unsigned huge_page_shift(sreturn h->order +PAGE_SHIFT ; } +/** +* hugetlb_linear_page_index() - linear_page_index() but in hugetlb +* page size granularity. +* @vma: the hugetlb VMA +* @address: the virtual address within the VMA +* +* Return: the page offset within the mapping in huge page units. +*/ +static inline pgoff_t hugetlb_linear_page_index (struct vm_area_struct *vma, +unsigned long address) +{ +struct hstate *h =hstate_vma (vma); + +return ((address - vma->vm_start) >>huge_page_shift (h)) + + (vma->vm_pgoff >>huge_page_order (h)); +} +static inline bool order_is_gigantic (unsigned int order) {return order >MAX_PAGE_ORDER ;
mm/userfaultfd.c +1 -1
@@ -569,7 +569,7 @@ retry:* in the case of shared pmds. fault mutex prevents * races with other faulting threads. */ - idx =linear_page_index (dst_vma, dst_addr); + idx =hugetlb_linear_page_index (dst_vma, dst_addr); mapping = dst_vma->vm_file->f_mapping; hash =hugetlb_fault_mutex_hash (mapping, idx);mutex_lock (&hugetlb_fault_mutex_table[hash]);
Greg Kroah-Hartman
maintainerPATCH 197/198 dma-debug: Allow multiple invocations of overlapping entries
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Romanovsky <[email protected]>
commit eca58535b154e6951327319afda94ac80eae7dc3 upstream.
Repeated DMA mappings with DMA_ATTR_CPU_CACHE_CLEAN trigger the following splat. This prevents using the attribute in cases where a DMA region is shared and reused more than seven times.
------------[ cut here ]------------ DMA-API: exceeded 7 overlapping mappings of cacheline 0x000000000438c440 WARNING: kernel/dma/debug.c:467 at add_dma_entry+0x219/0x280, CPU#4: ibv_rc_pingpong/1644 Modules linked in: xt_conntrack xt_MASQUERADE nf_conntrack_netlink nfnetlink iptable_nat nf_nat xt_addrtype br_netfilter rpcsec_gss_krb5 auth_rpcgss oid_registry overlay mlx5_fwctl zram zsmalloc mlx5_ib fuse rpcrdma rdma_ucm ib_uverbs ib_iser libiscsi scsi_transport_iscsi ib_umad rdma_cm ib_ipoib iw_cm ib_cm mlx5_core ib_core CPU: 4 UID: 2733 PID: 1644 Comm: ibv_rc_pingpong Not tainted 6.19.0+ #129 PREEMPT Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014 RIP: 0010:add_dma_entry+0x221/0x280 Code: c0 0f 84 f2 fe ff ff 83 e8 01 89 05 6d 99 11 01 e9 e4 fe ff ff 0f 8e 1f ff ff ff 48 8d 3d 07 ef 2d 01 be 07 00 00 00 48 89 e2 <67> 48 0f b9 3a e9 06 ff ff ff 48 c7 c7 98 05 2b 82 c6 05 72 92 28 RSP: 0018:ff1100010e657970 EFLAGS: 00010002 RAX: 0000000000000007 RBX: ff1100010234eb00 RCX: 0000000000000000 RDX: ff1100010e657970 RSI: 0000000000000007 RDI: ffffffff82678660 RBP: 000000000438c440 R08: 0000000000000228 R09: 0000000000000000 R10: 00000000000001be R11: 000000000000089d R12: 0000000000000800 R13: 00000000ffffffef R14: 0000000000000202 R15: ff1100010234eb00 FS: 00007fb15f3f6740(0000) GS:ff110008dcc19000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007fb15f32d3a0 CR3: 0000000116f59001 CR4: 0000000000373eb0 Call Trace: <TASK> debug_dma_map_sg+0x1b4/0x390 __dma_map_sg_attrs+0x6d/0x1a0 dma_map_sgtable+0x19/0x30 ib_umem_get+0x284/0x3b0 [ib_uverbs] mlx5_ib_reg_user_mr+0x68/0x2a0 [mlx5_ib] ib_uverbs_reg_mr+0x17f/0x2a0 [ib_uverbs] ib_uverbs_handler_UVERBS_METHOD_INVOKE_WRITE+0xc2/0x130 [ib_uverbs] ib_uverbs_cmd_verbs+0xa0b/0xae0 [ib_uverbs] ? ib_uverbs_handler_UVERBS_METHOD_QUERY_PORT_SPEED+0xe0/0xe0 [ib_uverbs] ? mmap_region+0x7a/0xb0 ? do_mmap+0x3b8/0x5c0 ib_uverbs_ioctl+0xa7/0x110 [ib_uverbs] __x64_sys_ioctl+0x14f/0x8b0 ? ksys_mmap_pgoff+0xc5/0x190 do_syscall_64+0x8c/0xbf0 entry_SYSCALL_64_after_hwframe+0x4b/0x53 RIP: 0033:0x7fb15f5e4eed Code: 04 25 28 00 00 00 48 89 45 c8 31 c0 48 8d 45 10 c7 45 b0 10 00 00 00 48 89 45 b8 48 8d 45 d0 48 89 45 c0 b8 10 00 00 00 0f 05 <89> c2 3d 00 f0 ff ff 77 1a 48 8b 45 c8 64 48 2b 04 25 28 00 00 00 RSP: 002b:00007ffe09a5c540 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 RAX: ffffffffffffffda RBX: 00007ffe09a5c5d0 RCX: 00007fb15f5e4eed RDX: 00007ffe09a5c5f0 RSI: 00000000c0181b01 RDI: 0000000000000003 RBP: 00007ffe09a5c590 R08: 0000000000000028 R09: 00007ffe09a5c794 R10: 0000000000000001 R11: 0000000000000246 R12: 00007ffe09a5c794 R13: 000000000000000c R14: 0000000025a49170 R15: 000000000000000c </TASK> ---[ end trace 0000000000000000 ]---
--- kernel/dma/debug.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
kernel/dma/debug.c +3 -3
@@ -453,7 +453,7 @@ static int active_cacheline_set_overlap(return overlap; } -static void active_cacheline_inc_overlap (phys_addr_t cln) +static void active_cacheline_inc_overlap (phys_addr_t cln,bool is_cache_clean) {int overlap =active_cacheline_read_overlap (cln);
@@ -462,7 +462,7 @@ static void active_cacheline_inc_overlap/* If we overflowed the overlap counter then we're potentially * leaking dma-mappings. */ -WARN_ONCE (overlap >ACTIVE_CACHELINE_MAX_OVERLAP , +WARN_ONCE (!is_cache_clean && overlap >ACTIVE_CACHELINE_MAX_OVERLAP ,pr_fmt ("exceeded %d overlapping mappings of cacheline %pa\n" ),ACTIVE_CACHELINE_MAX_OVERLAP , &cln); }
@@ -495,7 +495,7 @@ static int active_cacheline_insert(strucif (rc == -EEXIST ) {struct dma_debug_entry *existing; -active_cacheline_inc_overlap (cln); +active_cacheline_inc_overlap (cln, entry->is_cache_clean); existing =radix_tree_lookup (&dma_active_cacheline, cln);/* A lookup failure here after we got -EEXIST is unexpected. */ WARN_ON (!existing);
Greg Kroah-Hartman
maintainerPATCH 198/198 dma-mapping: handle DMA_ATTR_CPU_CACHE_CLEAN in trace output
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Romanovsky <[email protected]>
commit 6f45b1604cf43945ef472ae4ef30354025307c19 upstream.
Tracing prints decoded DMA attribute flags, but it does not yet include the recently added DMA_ATTR_CPU_CACHE_CLEAN. Add support for decoding and displaying this attribute in the trace output.
--- include/trace/events/dma.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
include/trace/events/dma.h +2 -1
@@ -32,7 +32,8 @@ TRACE_DEFINE_ENUM(DMA_NONE); { DMA_ATTR_ALLOC_SINGLE_PAGES, "ALLOC_SINGLE_PAGES" }, \ { DMA_ATTR_NO_WARN, "NO_WARN" }, \ { DMA_ATTR_PRIVILEGED, "PRIVILEGED" }, \ - { DMA_ATTR_MMIO, "MMIO" }) + { DMA_ATTR_MMIO, "MMIO" }, \ + { DMA_ATTR_CPU_CACHE_CLEAN, "CACHE_CLEAN" }) DECLARE_EVENT_CLASS(dma_map, TP_PROTO(struct device *dev, phys_addr_t phys_addr, dma_addr_t dma_addr,
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.18.24 release. There are 198 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 22 Apr 2026 15:38:57 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.18.24-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.18.y
and the diffstat can be found below.thanks,
greg k-h
On ARCH_BRCMSTB using 32-bit and 64-bit ARM kernels, build tested on BMIPS_GENERIC:
Signature · 1 line
Florian
Am 20.04.2026 um 17:39 schrieb Greg Kroah-Hartman:
Quoted 4 lines
This is the start of the stable review cycle for the 6.18.24 release. There are 198 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Builds, boots and works on my 2-socket Ivy Bridge Xeon E5-2697 v2 server. No dmesg oddities or regressions found.
Beste Grüße,
Peter Schneider
Signature · 8 lines
Climb the mountain not to plant your flag, but to embrace the challenge, enjoy the air and behold the view. Climb it so you can see the world, not so the world can see you. -- David McCullough Jr. OpenPGP: 0xA3828BD796CCE11A8CADE8866E3A92C92C3FF244 Download: https://www.peters-netzplatz.de/download/pschneider1968_pub.asc https://keys.mailvelope.com/pks/lookup?op=get&[email protected] https://keys.mailvelope.com/pks/lookup?op=get&[email protected]
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.18.24 release. There are 198 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 22 Apr 2026 15:38:57 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.18.24-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.18.y
and the diffstat can be found below.thanks,
greg k-h
Built and booted successfully on RISC-V RV64 (HiFive Unmatched).
# Librecast Test Results
020/020 [ OK ] liblcrq
010/010 [ OK ] libmld
120/120 [ OK ] liblibrecast
CPU/kernel: Linux auntie 6.18.24-rc1-g79c8a3af6b8b #1 SMP PREEMPT_DYNAMIC Tue Apr 21 07:48:45 -00 2026 x86_64 AMD Ryzen 9 9950X 16-Core Processor AuthenticAMD GNU/Linux
Quoted 8 lines · On Mon, 20 Apr 2026 17:39:39 +0200 Greg Kroah-Hartman…
This is the start of the stable review cycle for the 6.18.24 release. There are 198 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 22 Apr 2026 15:38:57 +0000. Anything received after that time might be too late.
Boot-tested under QEMU for Rust x86_64, arm64 and riscv64; built-tested for loongarch64:
For UML (x86_64) I am seeing:
In file included from arch/um/kernel/asm-offsets.c:3:
In file included from ./arch/x86/um/shared/sysdep/kernel-offsets.h:5:
In file included from ./include/linux/crypto.h:18:
In file included from ./include/linux/slab.h:16:
In file included from ./include/linux/gfp.h:7:
In file included from ./include/linux/mmzone.h:1538:
In file included from ./include/linux/memory_hotplug.h:7:
In file included from ./include/linux/notifier.h:16:
In file included from ./include/linux/srcu.h:59:
./include/linux/srcutiny.h:14:10: fatal error: 'linux/irq_work_types.h' file not found
14 | #include <linux/irq_work_types.h>
| ^~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
Caused by commit 95721c9fb3a1 ("srcu: Use irq_work to start GP in tiny SRCU"). The header seems to simply not be there, i.e. either the #include is changed or commit c809f081fe40 ("irqwork: Move data struct to a types header") is backported.
I hope that helps!
Cheers,
Miguel
Greg KH
maintainerQuoted 50 lines · Miguel Ojeda
Quoted 8 lines · On Mon, 20 Apr 2026 17:39:39 +0200 Greg Kroah-Hartman…
This is the start of the stable review cycle for the 6.18.24 release. There are 198 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 22 Apr 2026 15:38:57 +0000. Anything received after that time might be too late.
Boot-tested under QEMU for Rust
x86_64, arm64 and riscv64; built-tested for loongarch64:Tested-by Miguel Ojeda <[email protected]>For UML (
x86_64) I am seeing:In file included from
arch/um/kernel/asm-offsets.c:3:
In file included from./arch/x86/um/shared/sysdep/kernel-offsets.h:5:
In file included from./include/linux/crypto.h:18:
In file included from./include/linux/slab.h:16:
In file included from./include/linux/gfp.h:7:
In file included from./include/linux/mmzone.h:1538:
In file included from./include/linux/memory_hotplug.h:7:
In file included from./include/linux/notifier.h:16:
In file included from./include/linux/srcu.h:59:
./include/linux/srcutiny.h:14:10: fatal error: 'linux/irq_work_types.h' file not found
14 | #include <linux/irq_work_types.h>
| ^~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.Caused by commit
95721c9fb3a1("srcu: Useirq_workto start GP in tiny SRCU"). The header seems to simply not be there, i.e. either the#includeis changed or commitc809f081fe40("irqwork: Move data struct to a types header") is backported.Cc Joel Fernandes <[email protected]>Cc Paul E. McKenney <[email protected]>Cc Boqun Feng <[email protected]>Cc Sasha Levin <[email protected]>Cc Josh Triplett <[email protected]>Cc Lai Jiangshan <[email protected]>Cc Mathieu Desnoyers <[email protected]>Cc Peter Zijlstra (Intel) <[email protected]>Cc Steven Rostedt <[email protected]>Cc Thomas Gleixner <[email protected]>Cc Uladzislau Rezki <[email protected]>Cc Zqiang <[email protected]>
Quoted 4 lines
Cc Richard Weinberger <[email protected]>Cc Anton Ivanov <[email protected]>Cc Johannes Berg <[email protected]>
Thanks, I'll just drop this commit from 6.18 and older trees for now.
greg k-h
Build tested in our x86,arm64,loongarch,riscv config successfully without error.
BRs
Wentao Guan
defconfigs:
https://gist.github.com/opsiff/decbc7d88fbf68488a7d90e46f6d3e59
Log:
Linux version 6.18.24-rc1-g79c8a3af6b8b (guanwentao@uos-PC) (aarch64-linux-gnu-gcc-12 (Deepin 12.3.0-17deepin8) 12.3.0, GNU ld (GNU Binutils for Deepin) 2.41) # SMP PREEMPT_DYNAMIC
Linux version 6.18.24-rc1-g79c8a3af6b8b (guanwentao@uos-PC) (aarch64-linux-gnu-gcc-12 (Deepin 12.3.0-17deepin8) 12.3.0, GNU ld (GNU Binutils for Deepin) 2.41) #2 SMP PREEMPT_DYNAMIC Tue Apr 21 16:18:20 CST 2026 Linux version 6.18.24-rc1-loong64-desktop-hwe-g79c8a3af6b8b (guanwentao@uos-PC) (loongarch64-linux-gnu-gcc-12 (Deepin 12.3.0-17deepin8) 12.3.0, GNU ld (GNU Binutils for Deepin) 2.41) # SMP PREEMPT_DYNAMIC Linux version 6.18.24-rc1-loong64-desktop-hwe-g79c8a3af6b8b (guanwentao@uos-PC) (loongarch64-linux-gnu-gcc-12 (Deepin 12.3.0-17deepin8) 12.3.0, GNU ld (GNU Binutils for Deepin) 2.41) #3 SMP PREEMPT_DYNAMIC Tue Apr 21 16:42:38 CST 2026 Linux version 6.18.24-rc1+ (guanwentao@uos-PC) (riscv64-linux-gnu-gcc-12 (Deepin 12.3.0-17deepin8) 12.3.0, GNU ld (GNU Binutils for Deepin) 2.41) # SMP PREEMPT
Linux version 6.18.24-rc1+ (guanwentao@uos-PC) (riscv64-linux-gnu-gcc-12 (Deepin 12.3.0-17deepin8) 12.3.0, GNU ld (GNU Binutils for Deepin) 2.41) #4 SMP PREEMPT Tue Apr 21 17:08:51 CST 2026
Linux version 6.18.24-rc1-g79c8a3af6b8b (guanwentao@uos-PC) (gcc (Deepin 12.3.0-17deepin15) 12.3.0, GNU ld (GNU Binutils for Deepin) 2.41) # SMP PREEMPT_DYNAMIC
Linux version 6.18.24-rc1-g79c8a3af6b8b (guanwentao@uos-PC) (gcc (Deepin 12.3.0-17deepin15) 12.3.0, GNU ld (GNU Binutils for Deepin) 2.41) #1 SMP PREEMPT_DYNAMIC Tue Apr 21 15:52:00 CST 2026
Quoted 4 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.18.24 release. There are 198 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
This doesn't build for arm multi_v5_defconfig or bcm2835_defconfig:
In file included from /build/stage/linux/include/linux/srcu.h:59,
from /build/stage/linux/include/linux/notifier.h:16, from /build/stage/linux/include/linux/memory_hotplug.h:7, from /build/stage/linux/include/linux/mmzone.h:1538, from /build/stage/linux/include/linux/gfp.h:7, from /build/stage/linux/include/linux/mm.h:7,
from /build/stage/linux/arch/arm/kernel/asm-offsets.c:14:
/build/stage/linux/include/linux/srcutiny.h:14:10: fatal error: linux/irq_work_t ypes.h: No such file or directory
14 | #include <linux/irq_work_types.h>
| ^~~~~~~~~~~~~~~~~~~~~~~~
Greg Kroah-Hartman
maintainerQuoted 18 lines · Mark Brown
Quoted 4 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.18.24 release. There are 198 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
This doesn't build for arm
multi_v5_defconfigorbcm2835_defconfig:In file included from /build/stage/linux/include/linux/srcu.h:59,
from /build/stage/linux/include/linux/notifier.h:16, from /build/stage/linux/include/linux/memory_hotplug.h:7, from /build/stage/linux/include/linux/mmzone.h:1538, from /build/stage/linux/include/linux/gfp.h:7, from /build/stage/linux/include/linux/mm.h:7,
from /build/stage/linux/arch/arm/kernel/asm-offsets.c:14:
/build/stage/linux/include/linux/srcutiny.h:14:10: fatal error: linux/irq_work_types.h: No such file or directory
14 | #include <linux/irq_work_types.h>
Quoted 1 line
| ^~~~~~~~~~~~~~~~~~~~~~~~
I'll go drop the offending commit,t hanks.
greg k-h
Quoted 15 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.18.24 release. There are 198 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 22 Apr 2026 15:38:57 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.18.24-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.18.y
and the diffstat can be found below.
Quoted 5 lines
thanks,
greg k-h
-------------
tested kernel version 6.18.24-rc1 by building and booting it in a virtual environment on both x86_64 and arm64 architectures.
Build:
The kernel was built using the default configurations:
x86_64_defconfig for x86_64
defconfig for arm64
The build completed successfully on both architectures without any errors.
Boot:
The generated kernel images were booted in a QEMU-based virtual environment. The system booted successfully to userspace on both x86_64 and arm64.
Post-boot checks:
No kernel panics were observed.
No obvious errors or regressions were seen in dmesg. Basic system functionality appears to be working as expected.
Overall, 6.18.24-rc1 builds and boots successfully on x86_64 and arm64 in a virtual setup.
Regards,
Dileep Malepu.
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.18.24 release. There are 198 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 22 Apr 2026 15:38:57 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 9 lines
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.18.24-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.18.y
and the diffstat can be found below.thanks,
greg k-h
Compiled and booted on my test system. No dmesg regressions.
thanks,
-- Shuah
Hi!
Quoted 4 lines
This is the start of the stable review cycle for the 6.18.24 release. There are 198 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
CIP testing did not find any problems here:
https://gitlab.com/cip-project/cip-testing/linux-stable-rc-ci/-/tree/linux-6.18.y
Best regards,
Pavel
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.18.24 release. There are 198 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 22 Apr 2026 15:38:57 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.18.24-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.18.y
and the diffstat can be found below.thanks,
greg k-h
I tested 6.18.24-rc1 with srcu-use-irq_work-to-start-gp-in-tiny-srcu.patch and clockevents-prevent-timer-interrupt-starvation.patch reverted (since these two patches were reverted in the 6.18.y stable-queue) on an arm64 virtual machine. Working well, no regressions observed.
Signature · 1 line
-Barry K. Nathan <[email protected]>