x86/fpu: Fix NULL dereference in avx512_status()
authorFushuai Wang <wangfushuai@baidu.com>
Mon, 11 Aug 2025 18:50:44 +0000 (11:50 -0700)
committerDave Hansen <dave.hansen@linux.intel.com>
Mon, 11 Aug 2025 20:28:07 +0000 (13:28 -0700)
Problem
-------
With CONFIG_X86_DEBUG_FPU enabled, reading /proc/[kthread]/arch_status
causes a warning and a NULL pointer dereference.

This is because the AVX-512 timestamp code uses x86_task_fpu() but
doesn't check it for NULL. CONFIG_X86_DEBUG_FPU addles that function
for kernel threads (PF_KTHREAD specifically), making it return NULL.

The point of the warning was to ensure that kernel threads only access
task->fpu after going through kernel_fpu_begin()/_end(). Note: all
kernel tasks exposed in /proc have a valid task->fpu.

Solution
--------
One option is to silence the warning and check for NULL from
x86_task_fpu(). However, that warning is fairly fresh and seems like a
defense against misuse of the FPU state in kernel threads.

Instead, stop outputting AVX-512_elapsed_ms for kernel threads
altogether. The data was garbage anyway because avx512_timestamp is
only updated for user threads, not kernel threads.

If anyone ever wants to track kernel thread AVX-512 use, they can come
back later and do it properly, separate from this bug fix.

[ dhansen: mostly rewrite changelog ]

Fixes: 22aafe3bcb67 ("x86/fpu: Remove init_task FPU state dependencies, add debugging warning for PF_KTHREAD tasks")
Co-developed-by: Sohil Mehta <sohil.mehta@intel.com>
Signed-off-by: Sohil Mehta <sohil.mehta@intel.com>
Signed-off-by: Fushuai Wang <wangfushuai@baidu.com>
Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/all/20250811185044.2227268-1-sohil.mehta%40intel.com
arch/x86/kernel/fpu/xstate.c

index 12ed75c1b56751229e172c02c35fb0937c08cab2..28e4fd65c9da712eec3b32d3503651e046824997 100644 (file)
@@ -1881,19 +1881,20 @@ long fpu_xstate_prctl(int option, unsigned long arg2)
 #ifdef CONFIG_PROC_PID_ARCH_STATUS
 /*
  * Report the amount of time elapsed in millisecond since last AVX512
- * use in the task.
+ * use in the task. Report -1 if no AVX-512 usage.
  */
 static void avx512_status(struct seq_file *m, struct task_struct *task)
 {
-       unsigned long timestamp = READ_ONCE(x86_task_fpu(task)->avx512_timestamp);
-       long delta;
+       unsigned long timestamp;
+       long delta = -1;
 
-       if (!timestamp) {
-               /*
-                * Report -1 if no AVX512 usage
-                */
-               delta = -1;
-       } else {
+       /* AVX-512 usage is not tracked for kernel threads. Don't report anything. */
+       if (task->flags & (PF_KTHREAD | PF_USER_WORKER))
+               return;
+
+       timestamp = READ_ONCE(x86_task_fpu(task)->avx512_timestamp);
+
+       if (timestamp) {
                delta = (long)(jiffies - timestamp);
                /*
                 * Cap to LONG_MAX if time difference > LONG_MAX