]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
x86/events, x86/insn-eval: Remove incorrect current->active_mm references
authorAndy Lutomirski <luto@kernel.org>
Wed, 2 Apr 2025 09:45:35 +0000 (11:45 +0200)
committerIngo Molnar <mingo@kernel.org>
Sat, 12 Apr 2025 08:05:46 +0000 (10:05 +0200)
When decoding an instruction or handling a perf event that references an
LDT segment, if we don't have a valid user context, trying to access the
LDT by any means other than SLDT is racy.  Certainly, using
current->active_mm is wrong, as active_mm can point to a real user mm when
CR3 and LDTR no longer reference that mm.

Clean up the code.  If nmi_uaccess_okay() says we don't have a valid
context, just fail.  Otherwise use current->mm.

Signed-off-by: Andy Lutomirski <luto@kernel.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Cc: Rik van Riel <riel@surriel.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Link: https://lore.kernel.org/r/20250402094540.3586683-3-mingo@kernel.org
arch/x86/events/core.c
arch/x86/lib/insn-eval.c

index 6866cc5acb0b57f2995b059382440fc36f6eba57..95118b52b606a1819b5f2e983372edeb1b367d6a 100644 (file)
@@ -2803,8 +2803,15 @@ static unsigned long get_segment_base(unsigned int segment)
 #ifdef CONFIG_MODIFY_LDT_SYSCALL
                struct ldt_struct *ldt;
 
+               /*
+                * If we're not in a valid context with a real (not just lazy)
+                * user mm, then don't even try.
+                */
+               if (!nmi_uaccess_okay())
+                       return 0;
+
                /* IRQs are off, so this synchronizes with smp_store_release */
-               ldt = READ_ONCE(current->active_mm->context.ldt);
+               ldt = smp_load_acquire(&current->mm->context.ldt);
                if (!ldt || idx >= ldt->nr_entries)
                        return 0;
 
index 98631c0e7a11f887307e484db9ae8bc643ffaa72..f786401ac15da072ab5b5c9aa5ddc31bc2889baa 100644 (file)
@@ -631,14 +631,21 @@ static bool get_desc(struct desc_struct *out, unsigned short sel)
                /* Bits [15:3] contain the index of the desired entry. */
                sel >>= 3;
 
-               mutex_lock(&current->active_mm->context.lock);
-               ldt = current->active_mm->context.ldt;
+               /*
+                * If we're not in a valid context with a real (not just lazy)
+                * user mm, then don't even try.
+                */
+               if (!nmi_uaccess_okay())
+                       return false;
+
+               mutex_lock(&current->mm->context.lock);
+               ldt = current->mm->context.ldt;
                if (ldt && sel < ldt->nr_entries) {
                        *out = ldt->entries[sel];
                        success = true;
                }
 
-               mutex_unlock(&current->active_mm->context.lock);
+               mutex_unlock(&current->mm->context.lock);
 
                return success;
        }