| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/07/21 22:10 | flow | patch-triage |
0mArgs:null Results: {
"EnableConfigs": [
"SYSCALL_USER_DISPATCH",
"COMPAT"
],
"FocusSymbols": [
"arch_syscall_is_vdso_sigreturn",
"user_enable_single_step",
"user_disable_single_step"
],
"Reasoning": "The patch converts arm64 to use the generic entry infrastructure and adds support for Syscall User Dispatch. This involves functional changes to the core syscall entry/exit paths, ptrace single-stepping, and VDSO sigreturn detection.",
"WorthFuzzing": true
} |
| 1/1 | 2026/07/21 22:10 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit f3cf04b1cde90d9204c697c562524187a39c2df1\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Tue Jul 21 22:10:36 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig\nindex fb15037b5e3c7e..efef07857d3884 100644\n--- a/arch/arm64/Kconfig\n+++ b/arch/arm64/Kconfig\n@@ -87,6 +87,7 @@ config ARM64\n \tselect ARCH_SUPPORTS_SCHED_SMT\n \tselect ARCH_SUPPORTS_SCHED_CLUSTER\n \tselect ARCH_SUPPORTS_SCHED_MC\n+\tselect ARCH_SUPPORTS_SYSCALL_USER_DISPATCH\n \tselect ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH\n \tselect ARCH_WANT_COMPAT_IPC_PARSE_VERSION if COMPAT\n \tselect ARCH_WANT_DEFAULT_BPF_JIT\n@@ -129,9 +130,9 @@ config ARM64\n \tselect GENERIC_CPU_DEVICES\n \tselect GENERIC_CPU_VULNERABILITIES\n \tselect GENERIC_EARLY_IOREMAP\n+\tselect GENERIC_ENTRY\n \tselect GENERIC_IDLE_POLL_SETUP\n \tselect GENERIC_IOREMAP\n-\tselect GENERIC_IRQ_ENTRY\n \tselect GENERIC_IRQ_IPI\n \tselect GENERIC_IRQ_KEXEC_CLEAR_VM_FORWARD\n \tselect GENERIC_IRQ_PROBE\ndiff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h\nindex d2779d604c7be2..a8b232c5c6d9f8 100644\n--- a/arch/arm64/include/asm/elf.h\n+++ b/arch/arm64/include/asm/elf.h\n@@ -293,6 +293,7 @@ static inline int arch_check_elf(void *ehdr, bool has_interp,\n \treturn 0;\n }\n \n+extern bool arch_syscall_is_vdso_sigreturn(struct pt_regs *regs);\n #endif /* !__ASSEMBLER__ */\n \n #endif\ndiff --git a/arch/arm64/include/asm/entry-common.h b/arch/arm64/include/asm/entry-common.h\nindex cab8cd78f69385..2b053acbe10fea 100644\n--- a/arch/arm64/include/asm/entry-common.h\n+++ b/arch/arm64/include/asm/entry-common.h\n@@ -3,14 +3,21 @@\n #ifndef _ASM_ARM64_ENTRY_COMMON_H\n #define _ASM_ARM64_ENTRY_COMMON_H\n \n+#include \u003clinux/ptrace.h\u003e\n #include \u003clinux/thread_info.h\u003e\n \n+#include \u003casm/compat.h\u003e\n #include \u003casm/cpufeature.h\u003e\n #include \u003casm/daifflags.h\u003e\n #include \u003casm/fpsimd.h\u003e\n #include \u003casm/mte.h\u003e\n #include \u003casm/stacktrace.h\u003e\n \n+enum ptrace_syscall_dir {\n+\tPTRACE_SYSCALL_ENTER = 0,\n+\tPTRACE_SYSCALL_EXIT,\n+};\n+\n #define ARCH_EXIT_TO_USER_MODE_WORK (_TIF_MTE_ASYNC_FAULT | _TIF_FOREIGN_FPSTATE)\n \n static __always_inline void arch_exit_to_user_mode_work(struct pt_regs *regs,\n@@ -54,4 +61,74 @@ static inline bool arch_irqentry_exit_need_resched(void)\n \n #define arch_irqentry_exit_need_resched arch_irqentry_exit_need_resched\n \n+static __always_inline unsigned long ptrace_save_reg(struct pt_regs *regs,\n+\t\t\t\t\t\t enum ptrace_syscall_dir dir,\n+\t\t\t\t\t\t int *regno)\n+{\n+\tunsigned long saved_reg;\n+\n+\t/*\n+\t * We have some ABI weirdness here in the way that we handle syscall\n+\t * exit stops because we indicate whether or not the stop has been\n+\t * signalled from syscall entry or syscall exit by clobbering a general\n+\t * purpose register (ip/r12 for AArch32, x7 for AArch64) in the tracee\n+\t * and restoring its old value after the stop. This means that:\n+\t *\n+\t * - Any writes by the tracer to this register during the stop are\n+\t * ignored/discarded.\n+\t *\n+\t * - The actual value of the register is not available during the stop,\n+\t * so the tracer cannot save it and restore it later.\n+\t *\n+\t * - Syscall stops behave differently to seccomp and pseudo-step traps\n+\t * (the latter do not nobble any registers).\n+\t */\n+\t*regno = (is_compat_task() ? 12 : 7);\n+\tsaved_reg = regs-\u003eregs[*regno];\n+\tregs-\u003eregs[*regno] = dir;\n+\n+\treturn saved_reg;\n+}\n+\n+static __always_inline bool arch_ptrace_report_syscall_permit_entry(struct pt_regs *regs)\n+{\n+\tunsigned long saved_reg;\n+\tbool permit;\n+\tint regno;\n+\n+\tsaved_reg = ptrace_save_reg(regs, PTRACE_SYSCALL_ENTER, \u0026regno);\n+\tpermit = ptrace_report_syscall_permit_entry(regs);\n+\tif (!permit)\n+\t\tforget_syscall(regs);\n+\tregs-\u003eregs[regno] = saved_reg;\n+\n+\treturn permit;\n+}\n+\n+#define arch_ptrace_report_syscall_permit_entry arch_ptrace_report_syscall_permit_entry\n+\n+static __always_inline void arch_ptrace_report_syscall_exit(struct pt_regs *regs,\n+\t\t\t\t\t\t\t int step)\n+{\n+\tunsigned long saved_reg;\n+\tint regno;\n+\n+\tsaved_reg = ptrace_save_reg(regs, PTRACE_SYSCALL_EXIT, \u0026regno);\n+\tif (!step) {\n+\t\tptrace_report_syscall_exit(regs, 0);\n+\t\tregs-\u003eregs[regno] = saved_reg;\n+\t} else {\n+\t\tregs-\u003eregs[regno] = saved_reg;\n+\n+\t\t/*\n+\t\t * Signal a pseudo-step exception since we are stepping but\n+\t\t * tracer modifications to the registers may have rewound the\n+\t\t * state machine.\n+\t\t */\n+\t\tptrace_report_syscall_exit(regs, 1);\n+\t}\n+}\n+\n+#define arch_ptrace_report_syscall_exit arch_ptrace_report_syscall_exit\n+\n #endif /* _ASM_ARM64_ENTRY_COMMON_H */\ndiff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h\nindex 5e4c7fc44f7315..e3e71657584646 100644\n--- a/arch/arm64/include/asm/syscall.h\n+++ b/arch/arm64/include/asm/syscall.h\n@@ -8,6 +8,7 @@\n #include \u003cuapi/linux/audit.h\u003e\n #include \u003clinux/compat.h\u003e\n #include \u003clinux/err.h\u003e\n+#include \u003clinux/rseq.h\u003e\n \n typedef long (*syscall_fn_t)(const struct pt_regs *regs);\n \n@@ -119,8 +120,4 @@ static inline int syscall_get_arch(struct task_struct *task)\n \n \treturn AUDIT_ARCH_AARCH64;\n }\n-\n-int syscall_trace_enter(struct pt_regs *regs);\n-void syscall_trace_exit(struct pt_regs *regs);\n-\n #endif\t/* __ASM_SYSCALL_H */\ndiff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h\nindex 5d7fe3e153c850..3f621ba0f96137 100644\n--- a/arch/arm64/include/asm/thread_info.h\n+++ b/arch/arm64/include/asm/thread_info.h\n@@ -46,6 +46,7 @@ struct thread_info {\n \tu64\t\t\tmpam_partid_pmg;\n #endif\n \tu32\t\t\tcpu;\n+\tunsigned long\t\tsyscall_work; /* SYSCALL_WORK_ flags */\n };\n \n #define thread_saved_pc(tsk)\t\\\n@@ -68,11 +69,6 @@ void arch_setup_new_exec(void);\n #define TIF_UPROBE\t\t5\t/* uprobe breakpoint or singlestep */\n #define TIF_MTE_ASYNC_FAULT\t6\t/* MTE Asynchronous Tag Check Fault */\n #define TIF_NOTIFY_SIGNAL\t7\t/* signal notifications exist */\n-#define TIF_SYSCALL_TRACE\t8\t/* syscall trace active */\n-#define TIF_SYSCALL_AUDIT\t9\t/* syscall auditing */\n-#define TIF_SYSCALL_TRACEPOINT\t10\t/* syscall tracepoint for ftrace */\n-#define TIF_SECCOMP\t\t11\t/* syscall secure computing */\n-#define TIF_SYSCALL_EMU\t\t12\t/* syscall emulation active */\n #define TIF_PATCH_PENDING\t13\t/* pending live patching update */\n #define TIF_MEMDIE\t\t18\t/* is terminating due to OOM killer */\n #define TIF_FREEZE\t\t19\n@@ -94,24 +90,14 @@ void arch_setup_new_exec(void);\n #define _TIF_NEED_RESCHED_LAZY\t(1 \u003c\u003c TIF_NEED_RESCHED_LAZY)\n #define _TIF_NOTIFY_RESUME\t(1 \u003c\u003c TIF_NOTIFY_RESUME)\n #define _TIF_FOREIGN_FPSTATE\t(1 \u003c\u003c TIF_FOREIGN_FPSTATE)\n-#define _TIF_SYSCALL_TRACE\t(1 \u003c\u003c TIF_SYSCALL_TRACE)\n-#define _TIF_SYSCALL_AUDIT\t(1 \u003c\u003c TIF_SYSCALL_AUDIT)\n-#define _TIF_SYSCALL_TRACEPOINT\t(1 \u003c\u003c TIF_SYSCALL_TRACEPOINT)\n-#define _TIF_SECCOMP\t\t(1 \u003c\u003c TIF_SECCOMP)\n-#define _TIF_SYSCALL_EMU\t(1 \u003c\u003c TIF_SYSCALL_EMU)\n #define _TIF_PATCH_PENDING\t(1 \u003c\u003c TIF_PATCH_PENDING)\n #define _TIF_UPROBE\t\t(1 \u003c\u003c TIF_UPROBE)\n-#define _TIF_SINGLESTEP\t\t(1 \u003c\u003c TIF_SINGLESTEP)\n #define _TIF_32BIT\t\t(1 \u003c\u003c TIF_32BIT)\n #define _TIF_SVE\t\t(1 \u003c\u003c TIF_SVE)\n #define _TIF_MTE_ASYNC_FAULT\t(1 \u003c\u003c TIF_MTE_ASYNC_FAULT)\n #define _TIF_NOTIFY_SIGNAL\t(1 \u003c\u003c TIF_NOTIFY_SIGNAL)\n #define _TIF_TSC_SIGSEGV\t(1 \u003c\u003c TIF_TSC_SIGSEGV)\n \n-#define _TIF_SYSCALL_WORK\t(_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \\\n-\t\t\t\t _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP | \\\n-\t\t\t\t _TIF_SYSCALL_EMU)\n-\n #ifdef CONFIG_SHADOW_CALL_STACK\n #define INIT_SCS\t\t\t\t\t\t\t\\\n \t.scs_base\t= init_shadow_call_stack,\t\t\t\\\ndiff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c\nindex 29307642f4c904..c5368383915536 100644\n--- a/arch/arm64/kernel/debug-monitors.c\n+++ b/arch/arm64/kernel/debug-monitors.c\n@@ -385,11 +385,19 @@ void user_enable_single_step(struct task_struct *task)\n \n \tif (!test_and_set_ti_thread_flag(ti, TIF_SINGLESTEP))\n \t\tset_regs_spsr_ss(task_pt_regs(task));\n+\n+\t/*\n+\t * Ensure that the generic entry code triggers a trap once stepping\n+\t * out of a system call prior to executing any user instruction,\n+\t * as the generic entry code does not natively check for TIF_SINGLESTEP.\n+\t */\n+\tset_task_syscall_work(task, SYSCALL_EXIT_TRAP);\n }\n NOKPROBE_SYMBOL(user_enable_single_step);\n \n void user_disable_single_step(struct task_struct *task)\n {\n \tclear_ti_thread_flag(task_thread_info(task), TIF_SINGLESTEP);\n+\tclear_task_syscall_work(task, SYSCALL_EXIT_TRAP);\n }\n NOKPROBE_SYMBOL(user_disable_single_step);\ndiff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c\nindex ceb4eb11232a61..9eac76804bd9ae 100644\n--- a/arch/arm64/kernel/entry-common.c\n+++ b/arch/arm64/kernel/entry-common.c\n@@ -6,7 +6,7 @@\n */\n \n #include \u003clinux/context_tracking.h\u003e\n-#include \u003clinux/irq-entry-common.h\u003e\n+#include \u003clinux/entry-common.h\u003e\n #include \u003clinux/kasan.h\u003e\n #include \u003clinux/linkage.h\u003e\n #include \u003clinux/livepatch.h\u003e\ndiff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c\nindex 5709e9d3c321a5..61a66868294715 100644\n--- a/arch/arm64/kernel/ptrace.c\n+++ b/arch/arm64/kernel/ptrace.c\n@@ -8,7 +8,6 @@\n * Copyright (C) 2012 ARM Ltd.\n */\n \n-#include \u003clinux/audit.h\u003e\n #include \u003clinux/compat.h\u003e\n #include \u003clinux/kernel.h\u003e\n #include \u003clinux/sched/signal.h\u003e\n@@ -18,7 +17,6 @@\n #include \u003clinux/smp.h\u003e\n #include \u003clinux/ptrace.h\u003e\n #include \u003clinux/user.h\u003e\n-#include \u003clinux/seccomp.h\u003e\n #include \u003clinux/security.h\u003e\n #include \u003clinux/init.h\u003e\n #include \u003clinux/signal.h\u003e\n@@ -28,7 +26,6 @@\n #include \u003clinux/hw_breakpoint.h\u003e\n #include \u003clinux/regset.h\u003e\n #include \u003clinux/elf.h\u003e\n-#include \u003clinux/rseq.h\u003e\n \n #include \u003casm/compat.h\u003e\n #include \u003casm/cpufeature.h\u003e\n@@ -38,13 +35,9 @@\n #include \u003casm/mte.h\u003e\n #include \u003casm/pointer_auth.h\u003e\n #include \u003casm/stacktrace.h\u003e\n-#include \u003casm/syscall.h\u003e\n #include \u003casm/traps.h\u003e\n #include \u003casm/system_misc.h\u003e\n \n-#define CREATE_TRACE_POINTS\n-#include \u003ctrace/events/syscalls.h\u003e\n-\n struct pt_regs_offset {\n \tconst char *name;\n \tint offset;\n@@ -2339,114 +2332,6 @@ long arch_ptrace(struct task_struct *child, long request,\n \treturn ptrace_request(child, request, addr, data);\n }\n \n-enum ptrace_syscall_dir {\n-\tPTRACE_SYSCALL_ENTER = 0,\n-\tPTRACE_SYSCALL_EXIT,\n-};\n-\n-static __always_inline unsigned long ptrace_save_reg(struct pt_regs *regs,\n-\t\t\t\t\t\t enum ptrace_syscall_dir dir,\n-\t\t\t\t\t\t int *regno)\n-{\n-\tunsigned long saved_reg;\n-\n-\t/*\n-\t * We have some ABI weirdness here in the way that we handle syscall\n-\t * exit stops because we indicate whether or not the stop has been\n-\t * signalled from syscall entry or syscall exit by clobbering a general\n-\t * purpose register (ip/r12 for AArch32, x7 for AArch64) in the tracee\n-\t * and restoring its old value after the stop. This means that:\n-\t *\n-\t * - Any writes by the tracer to this register during the stop are\n-\t * ignored/discarded.\n-\t *\n-\t * - The actual value of the register is not available during the stop,\n-\t * so the tracer cannot save it and restore it later.\n-\t *\n-\t * - Syscall stops behave differently to seccomp and pseudo-step traps\n-\t * (the latter do not nobble any registers).\n-\t */\n-\t*regno = (is_compat_task() ? 12 : 7);\n-\tsaved_reg = regs-\u003eregs[*regno];\n-\tregs-\u003eregs[*regno] = dir;\n-\n-\treturn saved_reg;\n-}\n-\n-static int report_syscall_entry(struct pt_regs *regs)\n-{\n-\tunsigned long saved_reg;\n-\tint regno, ret;\n-\n-\tsaved_reg = ptrace_save_reg(regs, PTRACE_SYSCALL_ENTER, \u0026regno);\n-\tret = !ptrace_report_syscall_permit_entry(regs);\n-\tif (ret)\n-\t\tforget_syscall(regs);\n-\tregs-\u003eregs[regno] = saved_reg;\n-\n-\treturn ret;\n-}\n-\n-static void report_syscall_exit(struct pt_regs *regs)\n-{\n-\tunsigned long saved_reg;\n-\tint regno;\n-\n-\tsaved_reg = ptrace_save_reg(regs, PTRACE_SYSCALL_EXIT, \u0026regno);\n-\tif (!test_thread_flag(TIF_SINGLESTEP)) {\n-\t\tptrace_report_syscall_exit(regs, 0);\n-\t\tregs-\u003eregs[regno] = saved_reg;\n-\t} else {\n-\t\tregs-\u003eregs[regno] = saved_reg;\n-\n-\t\t/*\n-\t\t * Signal a pseudo-step exception since we are stepping but\n-\t\t * tracer modifications to the registers may have rewound the\n-\t\t * state machine.\n-\t\t */\n-\t\tptrace_report_syscall_exit(regs, 1);\n-\t}\n-}\n-\n-int syscall_trace_enter(struct pt_regs *regs)\n-{\n-\tunsigned long flags = read_thread_flags();\n-\tint ret;\n-\n-\tif (flags \u0026 (_TIF_SYSCALL_EMU | _TIF_SYSCALL_TRACE)) {\n-\t\tret = report_syscall_entry(regs);\n-\t\tif (ret || (flags \u0026 _TIF_SYSCALL_EMU))\n-\t\t\treturn NO_SYSCALL;\n-\t}\n-\n-\t/* Do the secure computing after ptrace; failures should be fast. */\n-\tif (!seccomp_permit_syscall())\n-\t\treturn NO_SYSCALL;\n-\n-\tif (test_thread_flag(TIF_SYSCALL_TRACEPOINT))\n-\t\ttrace_sys_enter(regs, regs-\u003esyscallno);\n-\n-\taudit_syscall_entry(regs-\u003esyscallno, regs-\u003eorig_x0, regs-\u003eregs[1],\n-\t\t\t regs-\u003eregs[2], regs-\u003eregs[3]);\n-\n-\treturn regs-\u003esyscallno;\n-}\n-\n-void syscall_trace_exit(struct pt_regs *regs)\n-{\n-\tunsigned long flags = read_thread_flags();\n-\n-\taudit_syscall_exit(regs);\n-\n-\tif (flags \u0026 _TIF_SYSCALL_TRACEPOINT)\n-\t\ttrace_sys_exit(regs, syscall_get_return_value(current, regs));\n-\n-\tif (flags \u0026 (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP))\n-\t\treport_syscall_exit(regs);\n-\n-\trseq_syscall(regs);\n-}\n-\n /*\n * SPSR_ELx bits which are always architecturally RES0 per ARM DDI 0487D.a.\n * We permit userspace to set SSBS (AArch64 bit 12, AArch32 bit 23) which is\ndiff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c\nindex 38e6fa204c17b5..093eebb9d764ac 100644\n--- a/arch/arm64/kernel/signal.c\n+++ b/arch/arm64/kernel/signal.c\n@@ -8,8 +8,8 @@\n \n #include \u003clinux/cache.h\u003e\n #include \u003clinux/compat.h\u003e\n+#include \u003clinux/entry-common.h\u003e\n #include \u003clinux/errno.h\u003e\n-#include \u003clinux/irq-entry-common.h\u003e\n #include \u003clinux/kernel.h\u003e\n #include \u003clinux/signal.h\u003e\n #include \u003clinux/freezer.h\u003e\ndiff --git a/arch/arm64/kernel/syscall.c b/arch/arm64/kernel/syscall.c\nindex 358ddfbf1401ac..2535cae9413d8a 100644\n--- a/arch/arm64/kernel/syscall.c\n+++ b/arch/arm64/kernel/syscall.c\n@@ -2,6 +2,7 @@\n \n #include \u003clinux/compiler.h\u003e\n #include \u003clinux/context_tracking.h\u003e\n+#include \u003clinux/entry-common.h\u003e\n #include \u003clinux/errno.h\u003e\n #include \u003clinux/nospec.h\u003e\n #include \u003clinux/ptrace.h\u003e\n@@ -54,15 +55,11 @@ static void invoke_syscall(struct pt_regs *regs, unsigned int scno,\n \tsyscall_set_return_value(current, regs, 0, ret);\n }\n \n-static inline bool has_syscall_work(unsigned long flags)\n-{\n-\treturn unlikely(flags \u0026 _TIF_SYSCALL_WORK);\n-}\n-\n-static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr,\n-\t\t\t const syscall_fn_t syscall_table[])\n+static __always_inline void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr,\n+\t\t\t\t\t const syscall_fn_t syscall_table[])\n {\n \tunsigned long flags = read_thread_flags();\n+\tunsigned long work;\n \n \tregs-\u003eorig_x0 = regs-\u003eregs[0];\n \tregs-\u003esyscallno = scno;\n@@ -95,7 +92,8 @@ static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr,\n \t\treturn;\n \t}\n \n-\tif (has_syscall_work(flags)) {\n+\twork = READ_ONCE(current_thread_info()-\u003esyscall_work);\n+\tif (unlikely(work \u0026 SYSCALL_WORK_ENTER)) {\n \t\t/*\n \t\t * The de-facto standard way to skip a system call using ptrace\n \t\t * is to set the system call to -1 (NO_SYSCALL) and set x0 to a\n@@ -113,26 +111,18 @@ static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr,\n \t\t */\n \t\tif (scno == NO_SYSCALL)\n \t\t\tsyscall_set_return_value(current, regs, -ENOSYS, 0);\n-\t\tscno = syscall_trace_enter(regs);\n+\t\tif (!syscall_trace_enter(regs, work, scno))\n+\t\t\tgoto trace_exit;\n+\n+\t\t/* Reread the syscall number as it might have been modified */\n+\t\tscno = syscall_get_nr(current, regs);\n \t\tif (scno == NO_SYSCALL)\n \t\t\tgoto trace_exit;\n \t}\n \n \tinvoke_syscall(regs, scno, sc_nr, syscall_table);\n-\n-\t/*\n-\t * The tracing status may have changed under our feet, so we have to\n-\t * check again. However, if we were tracing entry, then we always trace\n-\t * exit regardless, as the old entry assembly did.\n-\t */\n-\tif (!has_syscall_work(flags) \u0026\u0026 !IS_ENABLED(CONFIG_DEBUG_RSEQ)) {\n-\t\tflags = read_thread_flags();\n-\t\tif (!has_syscall_work(flags) \u0026\u0026 !(flags \u0026 _TIF_SINGLESTEP))\n-\t\t\treturn;\n-\t}\n-\n trace_exit:\n-\tsyscall_trace_exit(regs);\n+\tsyscall_exit_to_user_mode_work(regs);\n }\n \n void do_el0_svc(struct pt_regs *regs)\ndiff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c\nindex 592dd8668de463..37cdc7c72e15c3 100644\n--- a/arch/arm64/kernel/vdso.c\n+++ b/arch/arm64/kernel/vdso.c\n@@ -343,3 +343,19 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)\n \n \treturn ret;\n }\n+\n+bool arch_syscall_is_vdso_sigreturn(struct pt_regs *regs)\n+{\n+\tunsigned long landing_pad;\n+\n+#ifdef CONFIG_COMPAT\n+\tif (is_compat_task()) {\n+\t\tunsigned long sigpage = (unsigned long)current-\u003emm-\u003econtext.sigpage;\n+\n+\t\treturn regs-\u003epc \u003e= sigpage \u0026\u0026 regs-\u003epc \u003c (sigpage + PAGE_SIZE);\n+\t}\n+#endif\n+\tlanding_pad = (unsigned long)VDSO_SYMBOL(current-\u003emm-\u003econtext.vdso, sigreturn_landing_pad);\n+\n+\treturn regs-\u003epc == landing_pad;\n+}\ndiff --git a/arch/arm64/kernel/vdso/sigreturn.S b/arch/arm64/kernel/vdso/sigreturn.S\nindex 0e18729abc3b78..8d2d413ff45e8b 100644\n--- a/arch/arm64/kernel/vdso/sigreturn.S\n+++ b/arch/arm64/kernel/vdso/sigreturn.S\n@@ -73,6 +73,7 @@ SYM_CODE_START(__kernel_rt_sigreturn)\n \tmov\tx8, #__NR_rt_sigreturn\n //\tPLEASE DO NOT MODIFY\n \tsvc\t#0\n+\tSYM_INNER_LABEL(__sigreturn_landing_pad, SYM_L_GLOBAL)\n //\tPLEASE DO NOT MODIFY\n //\t.cfi_endproc\n SYM_CODE_END(__kernel_rt_sigreturn)\ndiff --git a/arch/arm64/kernel/vdso/vdso.lds.S b/arch/arm64/kernel/vdso/vdso.lds.S\nindex 52314be2919121..da61d6fc6fe9f3 100644\n--- a/arch/arm64/kernel/vdso/vdso.lds.S\n+++ b/arch/arm64/kernel/vdso/vdso.lds.S\n@@ -112,3 +112,4 @@ VERSION\n * Make the sigreturn code visible to the kernel.\n */\n VDSO_sigtramp\t\t= __kernel_rt_sigreturn;\n+VDSO_sigreturn_landing_pad\t= __sigreturn_landing_pad;\n"
} |
| 2/1 | 2026/07/21 22:10 | agent | patch-evaluator |
0mModel:best-expensive Args: null Results: {
"EnableConfigs": [
"SYSCALL_USER_DISPATCH",
"COMPAT"
],
"FocusSymbols": [
"arch_syscall_is_vdso_sigreturn",
"user_enable_single_step",
"user_disable_single_step"
],
"Reasoning": "The patch converts arm64 to use the generic entry infrastructure and adds support for Syscall User Dispatch. This involves functional changes to the core syscall entry/exit paths, ptrace single-stepping, and VDSO sigreturn detection.",
"WorthFuzzing": true
}Instruction: You are an expert Linux kernel maintainer. Your job is to review a provided patch series and determine if it makes functional changes to the kernel that should be fuzzed. IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively use your code access tools to examine the actual source code and confirm any assumptions. Return WorthFuzzing=false if the patch only contains: - Modifications to Documentation/, Kconfig files, or code comments. - Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints. - Changes to numeric constants or macros that do not functionally alter execution flow. - Code paths that are impossible to reach in virtualized environments like GCE or QEMU, even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim). If it modifies reachable core kernel logic, drivers, or architectures, use your code search tools to verify the code can be executed, then return WorthFuzzing=true. When returning WorthFuzzing=true, you MUST ALSO: 1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols. Avoid listing generic hot-path functions to prevent skewed test distributions. 2. Identify any specific CONFIG_ options required to properly test this new/modified feature. Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions. Do not list too generic configs (we already have them enabled). Only list those that specifically cover the modified code. List them in the EnableConfigs output array, and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4"). Prefer calling several tools at the same time to save round-trips. Use set-results tool to provide results of the analysis. It must be called exactly once before the final reply. Ignore results of this tool. Prompt: For your convenience, here is the diff of the changes:
commit f3cf04b1cde90d9204c697c562524187a39c2df1
Author: syz-cluster <triage@syzkaller.com>
Date: Tue Jul 21 22:10:36 2026 +0000
syz-cluster: applied patch under review
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index fb15037b5e3c7e..efef07857d3884 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -87,6 +87,7 @@ config ARM64
select ARCH_SUPPORTS_SCHED_SMT
select ARCH_SUPPORTS_SCHED_CLUSTER
select ARCH_SUPPORTS_SCHED_MC
+ select ARCH_SUPPORTS_SYSCALL_USER_DISPATCH
select ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH
select ARCH_WANT_COMPAT_IPC_PARSE_VERSION if COMPAT
select ARCH_WANT_DEFAULT_BPF_JIT
@@ -129,9 +130,9 @@ config ARM64
select GENERIC_CPU_DEVICES
select GENERIC_CPU_VULNERABILITIES
select GENERIC_EARLY_IOREMAP
+ select GENERIC_ENTRY
select GENERIC_IDLE_POLL_SETUP
select GENERIC_IOREMAP
- select GENERIC_IRQ_ENTRY
select GENERIC_IRQ_IPI
select GENERIC_IRQ_KEXEC_CLEAR_VM_FORWARD
select GENERIC_IRQ_PROBE
diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
index d2779d604c7be2..a8b232c5c6d9f8 100644
--- a/arch/arm64/include/asm/elf.h
+++ b/arch/arm64/include/asm/elf.h
@@ -293,6 +293,7 @@ static inline int arch_check_elf(void *ehdr, bool has_interp,
return 0;
}
+extern bool arch_syscall_is_vdso_sigreturn(struct pt_regs *regs);
#endif /* !__ASSEMBLER__ */
#endif
diff --git a/arch/arm64/include/asm/entry-common.h b/arch/arm64/include/asm/entry-common.h
index cab8cd78f69385..2b053acbe10fea 100644
--- a/arch/arm64/include/asm/entry-common.h
+++ b/arch/arm64/include/asm/entry-common.h
@@ -3,14 +3,21 @@
#ifndef _ASM_ARM64_ENTRY_COMMON_H
#define _ASM_ARM64_ENTRY_COMMON_H
+#include <linux/ptrace.h>
#include <linux/thread_info.h>
+#include <asm/compat.h>
#include <asm/cpufeature.h>
#include <asm/daifflags.h>
#include <asm/fpsimd.h>
#include <asm/mte.h>
#include <asm/stacktrace.h>
+enum ptrace_syscall_dir {
+ PTRACE_SYSCALL_ENTER = 0,
+ PTRACE_SYSCALL_EXIT,
+};
+
#define ARCH_EXIT_TO_USER_MODE_WORK (_TIF_MTE_ASYNC_FAULT | _TIF_FOREIGN_FPSTATE)
static __always_inline void arch_exit_to_user_mode_work(struct pt_regs *regs,
@@ -54,4 +61,74 @@ static inline bool arch_irqentry_exit_need_resched(void)
#define arch_irqentry_exit_need_resched arch_irqentry_exit_need_resched
+static __always_inline unsigned long ptrace_save_reg(struct pt_regs *regs,
+ enum ptrace_syscall_dir dir,
+ int *regno)
+{
+ unsigned long saved_reg;
+
+ /*
+ * We have some ABI weirdness here in the way that we handle syscall
+ * exit stops because we indicate whether or not the stop has been
+ * signalled from syscall entry or syscall exit by clobbering a general
+ * purpose register (ip/r12 for AArch32, x7 for AArch64) in the tracee
+ * and restoring its old value after the stop. This means that:
+ *
+ * - Any writes by the tracer to this register during the stop are
+ * ignored/discarded.
+ *
+ * - The actual value of the register is not available during the stop,
+ * so the tracer cannot save it and restore it later.
+ *
+ * - Syscall stops behave differently to seccomp and pseudo-step traps
+ * (the latter do not nobble any registers).
+ */
+ *regno = (is_compat_task() ? 12 : 7);
+ saved_reg = regs->regs[*regno];
+ regs->regs[*regno] = dir;
+
+ return saved_reg;
+}
+
+static __always_inline bool arch_ptrace_report_syscall_permit_entry(struct pt_regs *regs)
+{
+ unsigned long saved_reg;
+ bool permit;
+ int regno;
+
+ saved_reg = ptrace_save_reg(regs, PTRACE_SYSCALL_ENTER, ®no);
+ permit = ptrace_report_syscall_permit_entry(regs);
+ if (!permit)
+ forget_syscall(regs);
+ regs->regs[regno] = saved_reg;
+
+ return permit;
+}
+
+#define arch_ptrace_report_syscall_permit_entry arch_ptrace_report_syscall_permit_entry
+
+static __always_inline void arch_ptrace_report_syscall_exit(struct pt_regs *regs,
+ int step)
+{
+ unsigned long saved_reg;
+ int regno;
+
+ saved_reg = ptrace_save_reg(regs, PTRACE_SYSCALL_EXIT, ®no);
+ if (!step) {
+ ptrace_report_syscall_exit(regs, 0);
+ regs->regs[regno] = saved_reg;
+ } else {
+ regs->regs[regno] = saved_reg;
+
+ /*
+ * Signal a pseudo-step exception since we are stepping but
+ * tracer modifications to the registers may have rewound the
+ * state machine.
+ */
+ ptrace_report_syscall_exit(regs, 1);
+ }
+}
+
+#define arch_ptrace_report_syscall_exit arch_ptrace_report_syscall_exit
+
#endif /* _ASM_ARM64_ENTRY_COMMON_H */
diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h
index 5e4c7fc44f7315..e3e71657584646 100644
--- a/arch/arm64/include/asm/syscall.h
+++ b/arch/arm64/include/asm/syscall.h
@@ -8,6 +8,7 @@
#include <uapi/linux/audit.h>
#include <linux/compat.h>
#include <linux/err.h>
+#include <linux/rseq.h>
typedef long (*syscall_fn_t)(const struct pt_regs *regs);
@@ -119,8 +120,4 @@ static inline int syscall_get_arch(struct task_struct *task)
return AUDIT_ARCH_AARCH64;
}
-
-int syscall_trace_enter(struct pt_regs *regs);
-void syscall_trace_exit(struct pt_regs *regs);
-
#endif /* __ASM_SYSCALL_H */
diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
index 5d7fe3e153c850..3f621ba0f96137 100644
--- a/arch/arm64/include/asm/thread_info.h
+++ b/arch/arm64/include/asm/thread_info.h
@@ -46,6 +46,7 @@ struct thread_info {
u64 mpam_partid_pmg;
#endif
u32 cpu;
+ unsigned long syscall_work; /* SYSCALL_WORK_ flags */
};
#define thread_saved_pc(tsk) \
@@ -68,11 +69,6 @@ void arch_setup_new_exec(void);
#define TIF_UPROBE 5 /* uprobe breakpoint or singlestep */
#define TIF_MTE_ASYNC_FAULT 6 /* MTE Asynchronous Tag Check Fault */
#define TIF_NOTIFY_SIGNAL 7 /* signal notifications exist */
-#define TIF_SYSCALL_TRACE 8 /* syscall trace active */
-#define TIF_SYSCALL_AUDIT 9 /* syscall auditing */
-#define TIF_SYSCALL_TRACEPOINT 10 /* syscall tracepoint for ftrace */
-#define TIF_SECCOMP 11 /* syscall secure computing */
-#define TIF_SYSCALL_EMU 12 /* syscall emulation active */
#define TIF_PATCH_PENDING 13 /* pending live patching update */
#define TIF_MEMDIE 18 /* is terminating due to OOM killer */
#define TIF_FREEZE 19
@@ -94,24 +90,14 @@ void arch_setup_new_exec(void);
#define _TIF_NEED_RESCHED_LAZY (1 << TIF_NEED_RESCHED_LAZY)
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
#define _TIF_FOREIGN_FPSTATE (1 << TIF_FOREIGN_FPSTATE)
-#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
-#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
-#define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT)
-#define _TIF_SECCOMP (1 << TIF_SECCOMP)
-#define _TIF_SYSCALL_EMU (1 << TIF_SYSCALL_EMU)
#define _TIF_PATCH_PENDING (1 << TIF_PATCH_PENDING)
#define _TIF_UPROBE (1 << TIF_UPROBE)
-#define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP)
#define _TIF_32BIT (1 << TIF_32BIT)
#define _TIF_SVE (1 << TIF_SVE)
#define _TIF_MTE_ASYNC_FAULT (1 << TIF_MTE_ASYNC_FAULT)
#define _TIF_NOTIFY_SIGNAL (1 << TIF_NOTIFY_SIGNAL)
#define _TIF_TSC_SIGSEGV (1 << TIF_TSC_SIGSEGV)
-#define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
- _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP | \
- _TIF_SYSCALL_EMU)
-
#ifdef CONFIG_SHADOW_CALL_STACK
#define INIT_SCS \
.scs_base = init_shadow_call_stack, \
diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
index 29307642f4c904..c5368383915536 100644
--- a/arch/arm64/kernel/debug-monitors.c
+++ b/arch/arm64/kernel/debug-monitors.c
@@ -385,11 +385,19 @@ void user_enable_single_step(struct task_struct *task)
if (!test_and_set_ti_thread_flag(ti, TIF_SINGLESTEP))
set_regs_spsr_ss(task_pt_regs(task));
+
+ /*
+ * Ensure that the generic entry code triggers a trap once stepping
+ * out of a system call prior to executing any user instruction,
+ * as the generic entry code does not natively check for TIF_SINGLESTEP.
+ */
+ set_task_syscall_work(task, SYSCALL_EXIT_TRAP);
}
NOKPROBE_SYMBOL(user_enable_single_step);
void user_disable_single_step(struct task_struct *task)
{
clear_ti_thread_flag(task_thread_info(task), TIF_SINGLESTEP);
+ clear_task_syscall_work(task, SYSCALL_EXIT_TRAP);
}
NOKPROBE_SYMBOL(user_disable_single_step);
diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
index ceb4eb11232a61..9eac76804bd9ae 100644
--- a/arch/arm64/kernel/entry-common.c
+++ b/arch/arm64/kernel/entry-common.c
@@ -6,7 +6,7 @@
*/
#include <linux/context_tracking.h>
-#include <linux/irq-entry-common.h>
+#include <linux/entry-common.h>
#include <linux/kasan.h>
#include <linux/linkage.h>
#include <linux/livepatch.h>
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index 5709e9d3c321a5..61a66868294715 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -8,7 +8,6 @@
* Copyright (C) 2012 ARM Ltd.
*/
-#include <linux/audit.h>
#include <linux/compat.h>
#include <linux/kernel.h>
#include <linux/sched/signal.h>
@@ -18,7 +17,6 @@
#include <linux/smp.h>
#include <linux/ptrace.h>
#include <linux/user.h>
-#include <linux/seccomp.h>
#include <linux/security.h>
#include <linux/init.h>
#include <linux/signal.h>
@@ -28,7 +26,6 @@
#include <linux/hw_breakpoint.h>
#include <linux/regset.h>
#include <linux/elf.h>
-#include <linux/rseq.h>
#include <asm/compat.h>
#include <asm/cpufeature.h>
@@ -38,13 +35,9 @@
#include <asm/mte.h>
#include <asm/pointer_auth.h>
#include <asm/stacktrace.h>
-#include <asm/syscall.h>
#include <asm/traps.h>
#include <asm/system_misc.h>
-#define CREATE_TRACE_POINTS
-#include <trace/events/syscalls.h>
-
struct pt_regs_offset {
const char *name;
int offset;
@@ -2339,114 +2332,6 @@ long arch_ptrace(struct task_struct *child, long request,
return ptrace_request(child, request, addr, data);
}
-enum ptrace_syscall_dir {
- PTRACE_SYSCALL_ENTER = 0,
- PTRACE_SYSCALL_EXIT,
-};
-
-static __always_inline unsigned long ptrace_save_reg(struct pt_regs *regs,
- enum ptrace_syscall_dir dir,
- int *regno)
-{
- unsigned long saved_reg;
-
- /*
- * We have some ABI weirdness here in the way that we handle syscall
- * exit stops because we indicate whether or not the stop has been
- * signalled from syscall entry or syscall exit by clobbering a general
- * purpose register (ip/r12 for AArch32, x7 for AArch64) in the tracee
- * and restoring its old value after the stop. This means that:
- *
- * - Any writes by the tracer to this register during the stop are
- * ignored/discarded.
- *
- * - The actual value of the register is not available during the stop,
- * so the tracer cannot save it and restore it later.
- *
- * - Syscall stops behave differently to seccomp and pseudo-step traps
- * (the latter do not nobble any registers).
- */
- *regno = (is_compat_task() ? 12 : 7);
- saved_reg = regs->regs[*regno];
- regs->regs[*regno] = dir;
-
- return saved_reg;
-}
-
-static int report_syscall_entry(struct pt_regs *regs)
-{
- unsigned long saved_reg;
- int regno, ret;
-
- saved_reg = ptrace_save_reg(regs, PTRACE_SYSCALL_ENTER, ®no);
- ret = !ptrace_report_syscall_permit_entry(regs);
- if (ret)
- forget_syscall(regs);
- regs->regs[regno] = saved_reg;
-
- return ret;
-}
-
-static void report_syscall_exit(struct pt_regs *regs)
-{
- unsigned long saved_reg;
- int regno;
-
- saved_reg = ptrace_save_reg(regs, PTRACE_SYSCALL_EXIT, ®no);
- if (!test_thread_flag(TIF_SINGLESTEP)) {
- ptrace_report_syscall_exit(regs, 0);
- regs->regs[regno] = saved_reg;
- } else {
- regs->regs[regno] = saved_reg;
-
- /*
- * Signal a pseudo-step exception since we are stepping but
- * tracer modifications to the registers may have rewound the
- * state machine.
- */
- ptrace_report_syscall_exit(regs, 1);
- }
-}
-
-int syscall_trace_enter(struct pt_regs *regs)
-{
- unsigned long flags = read_thread_flags();
- int ret;
-
- if (flags & (_TIF_SYSCALL_EMU | _TIF_SYSCALL_TRACE)) {
- ret = report_syscall_entry(regs);
- if (ret || (flags & _TIF_SYSCALL_EMU))
- return NO_SYSCALL;
- }
-
- /* Do the secure computing after ptrace; failures should be fast. */
- if (!seccomp_permit_syscall())
- return NO_SYSCALL;
-
- if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
- trace_sys_enter(regs, regs->syscallno);
-
- audit_syscall_entry(regs->syscallno, regs->orig_x0, regs->regs[1],
- regs->regs[2], regs->regs[3]);
-
- return regs->syscallno;
-}
-
-void syscall_trace_exit(struct pt_regs *regs)
-{
- unsigned long flags = read_thread_flags();
-
- audit_syscall_exit(regs);
-
- if (flags & _TIF_SYSCALL_TRACEPOINT)
- trace_sys_exit(regs, syscall_get_return_value(current, regs));
-
- if (flags & (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP))
- report_syscall_exit(regs);
-
- rseq_syscall(regs);
-}
-
/*
* SPSR_ELx bits which are always architecturally RES0 per ARM DDI 0487D.a.
* We permit userspace to set SSBS (AArch64 bit 12, AArch32 bit 23) which is
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index 38e6fa204c17b5..093eebb9d764ac 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -8,8 +8,8 @@
#include <linux/cache.h>
#include <linux/compat.h>
+#include <linux/entry-common.h>
#include <linux/errno.h>
-#include <linux/irq-entry-common.h>
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/freezer.h>
diff --git a/arch/arm64/kernel/syscall.c b/arch/arm64/kernel/syscall.c
index 358ddfbf1401ac..2535cae9413d8a 100644
--- a/arch/arm64/kernel/syscall.c
+++ b/arch/arm64/kernel/syscall.c
@@ -2,6 +2,7 @@
#include <linux/compiler.h>
#include <linux/context_tracking.h>
+#include <linux/entry-common.h>
#include <linux/errno.h>
#include <linux/nospec.h>
#include <linux/ptrace.h>
@@ -54,15 +55,11 @@ static void invoke_syscall(struct pt_regs *regs, unsigned int scno,
syscall_set_return_value(current, regs, 0, ret);
}
-static inline bool has_syscall_work(unsigned long flags)
-{
- return unlikely(flags & _TIF_SYSCALL_WORK);
-}
-
-static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr,
- const syscall_fn_t syscall_table[])
+static __always_inline void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr,
+ const syscall_fn_t syscall_table[])
{
unsigned long flags = read_thread_flags();
+ unsigned long work;
regs->orig_x0 = regs->regs[0];
regs->syscallno = scno;
@@ -95,7 +92,8 @@ static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr,
return;
}
- if (has_syscall_work(flags)) {
+ work = READ_ONCE(current_thread_info()->syscall_work);
+ if (unlikely(work & SYSCALL_WORK_ENTER)) {
/*
* The de-facto standard way to skip a system call using ptrace
* is to set the system call to -1 (NO_SYSCALL) and set x0 to a
@@ -113,26 +111,18 @@ static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr,
*/
if (scno == NO_SYSCALL)
syscall_set_return_value(current, regs, -ENOSYS, 0);
- scno = syscall_trace_enter(regs);
+ if (!syscall_trace_enter(regs, work, scno))
+ goto trace_exit;
+
+ /* Reread the syscall number as it might have been modified */
+ scno = syscall_get_nr(current, regs);
if (scno == NO_SYSCALL)
goto trace_exit;
}
invoke_syscall(regs, scno, sc_nr, syscall_table);
-
- /*
- * The tracing status may have changed under our feet, so we have to
- * check again. However, if we were tracing entry, then we always trace
- * exit regardless, as the old entry assembly did.
- */
- if (!has_syscall_work(flags) && !IS_ENABLED(CONFIG_DEBUG_RSEQ)) {
- flags = read_thread_flags();
- if (!has_syscall_work(flags) && !(flags & _TIF_SINGLESTEP))
- return;
- }
-
trace_exit:
- syscall_trace_exit(regs);
+ syscall_exit_to_user_mode_work(regs);
}
void do_el0_svc(struct pt_regs *regs)
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index 592dd8668de463..37cdc7c72e15c3 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -343,3 +343,19 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
return ret;
}
+
+bool arch_syscall_is_vdso_sigreturn(struct pt_regs *regs)
+{
+ unsigned long landing_pad;
+
+#ifdef CONFIG_COMPAT
+ if (is_compat_task()) {
+ unsigned long sigpage = (unsigned long)current->mm->context.sigpage;
+
+ return regs->pc >= sigpage && regs->pc < (sigpage + PAGE_SIZE);
+ }
+#endif
+ landing_pad = (unsigned long)VDSO_SYMBOL(current->mm->context.vdso, sigreturn_landing_pad);
+
+ return regs->pc == landing_pad;
+}
diff --git a/arch/arm64/kernel/vdso/sigreturn.S b/arch/arm64/kernel/vdso/sigreturn.S
index 0e18729abc3b78..8d2d413ff45e8b 100644
--- a/arch/arm64/kernel/vdso/sigreturn.S
+++ b/arch/arm64/kernel/vdso/sigreturn.S
@@ -73,6 +73,7 @@ SYM_CODE_START(__kernel_rt_sigreturn)
mov x8, #__NR_rt_sigreturn
// PLEASE DO NOT MODIFY
svc #0
+ SYM_INNER_LABEL(__sigreturn_landing_pad, SYM_L_GLOBAL)
// PLEASE DO NOT MODIFY
// .cfi_endproc
SYM_CODE_END(__kernel_rt_sigreturn)
diff --git a/arch/arm64/kernel/vdso/vdso.lds.S b/arch/arm64/kernel/vdso/vdso.lds.S
index 52314be2919121..da61d6fc6fe9f3 100644
--- a/arch/arm64/kernel/vdso/vdso.lds.S
+++ b/arch/arm64/kernel/vdso/vdso.lds.S
@@ -112,3 +112,4 @@ VERSION
* Make the sigreturn code visible to the kernel.
*/
VDSO_sigtramp = __kernel_rt_sigreturn;
+VDSO_sigreturn_landing_pad = __sigreturn_landing_pad;
|
| 3/2 | 2026/07/21 22:10 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 8775 output: 22 thoughts: 609 Thoughts: **Analyzing a Patch: arm64 Syscall Entry Changes** Okay, so I'm looking at this patch that fundamentally alters the arm64 architecture, specifically how system calls are handled. The patch is enabling `ARCH_SUPPORTS_SYSCALL_USER_DISPATCH` and `GENERIC_ENTRY`, which is a significant shift in how the kernel interacts with user-space applications. It looks like they are moving away from the more specific `GENERIC_IRQ_ENTRY` in favor of this `GENERIC_ENTRY` approach. This patch touches a vast number of files, indicating its broad impact. I can see changes across include files, the Kconfig, and the core kernel components. The core of the change seems to center around `arch/arm64/kernel/syscall.c`, particularly the `el0_svc_common` function – the syscall entry point – and the `arch_syscall_is_vdso_sigreturn` function. I see they have implemented this new `arch_syscall_is_vdso_sigreturn`. This has to be a functional change to the core architecture code (syscall entry/exit). The first thing I'm doing is flagging this for serious fuzzing. The syscall entry/exit path is a critical security-sensitive area. I need to make sure this is robust. Let's see. This `el0_svc_common` function. It's the primary syscall entry point, which means it's definitely a hot-path function. The prompt specifically warns about hot-path functions. `el0_svc_common` is the most important one that was changed. Hmm, perhaps I shouldn't list it directly because it's so hot. We don't want to get distracted with noise in the callgraph. So, let's zoom in on `arch_syscall_is_vdso_sigreturn`. This likely gets called during syscall user dispatch to determine if it's a `vdso` sigreturn. Let's check `Kconfig` for `SYSCALL_USER_DISPATCH`. |
| 4/2 | 2026/07/21 22:10 | tool | grepper |
0mArgs:{
"Expression": "SYSCALL_USER_DISPATCH"
}Results: {
"Output": "Documentation/admin-guide/syscall-user-dispatch.rst=52=following prctl:\nDocumentation/admin-guide/syscall-user-dispatch.rst-53-\nDocumentation/admin-guide/syscall-user-dispatch.rst:54: prctl(PR_SET_SYSCALL_USER_DISPATCH, \u003cop\u003e, \u003coffset\u003e, \u003clength\u003e, [selector])\nDocumentation/admin-guide/syscall-user-dispatch.rst-55-\n--\nDocumentation/admin-guide/syscall-user-dispatch.rst=81=Additionally, a tasks syscall user dispatch configuration can be peeked\nDocumentation/admin-guide/syscall-user-dispatch.rst:82:and poked via the PTRACE_(GET|SET)_SYSCALL_USER_DISPATCH_CONFIG ptrace\nDocumentation/admin-guide/syscall-user-dispatch.rst-83-requests. This is useful for checkpoint/restart software.\n--\nDocumentation/admin-guide/sysctl/kernel.rst=1408=Controls whether userspace may arm Syscall User Dispatch via\nDocumentation/admin-guide/sysctl/kernel.rst:1409:``prctl(PR_SET_SYSCALL_USER_DISPATCH, ...)`` or the\nDocumentation/admin-guide/sysctl/kernel.rst:1410:``PTRACE_SET_SYSCALL_USER_DISPATCH_CONFIG`` ptrace request:\nDocumentation/admin-guide/sysctl/kernel.rst-1411-\n--\nDocumentation/admin-guide/sysctl/kernel.rst-1417-\nDocumentation/admin-guide/sysctl/kernel.rst:1418:Only present when the kernel is built with ``CONFIG_SYSCALL_USER_DISPATCH``\nDocumentation/admin-guide/sysctl/kernel.rst-1419-and ``CONFIG_PROC_SYSCTL``.\n--\narch/Kconfig=112=config GENERIC_ENTRY\n--\narch/Kconfig-116-\narch/Kconfig:117:config ARCH_SUPPORTS_SYSCALL_USER_DISPATCH\narch/Kconfig-118-\tbool\narch/Kconfig-119-\narch/Kconfig:120:config SYSCALL_USER_DISPATCH\narch/Kconfig-121-\tbool \"Syscall User Dispatch\"\narch/Kconfig:122:\tdepends on ARCH_SUPPORTS_SYSCALL_USER_DISPATCH\narch/Kconfig-123-\tdepends on GENERIC_ENTRY\n--\narch/arm64/Kconfig=2=config ARM64\n--\narch/arm64/Kconfig-89-\tselect ARCH_SUPPORTS_SCHED_MC\narch/arm64/Kconfig:90:\tselect ARCH_SUPPORTS_SYSCALL_USER_DISPATCH\narch/arm64/Kconfig-91-\tselect ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH\n--\narch/x86/Kconfig=58=config X86\n--\narch/x86/Kconfig-338-\tselect ARCH_SUPPORTS_SCHED_MC\t\tif SMP\narch/x86/Kconfig:339:\tselect ARCH_SUPPORTS_SYSCALL_USER_DISPATCH\narch/x86/Kconfig-340-\tselect HAVE_SINGLE_FTRACE_DIRECT_OPS\tif X86_64 \u0026\u0026 DYNAMIC_FTRACE_WITH_DIRECT_CALLS\n--\ninclude/linux/entry-common.h-29-\t\t\t\t SYSCALL_WORK_SYSCALL_AUDIT |\t\t\\\ninclude/linux/entry-common.h:30:\t\t\t\t SYSCALL_WORK_SYSCALL_USER_DISPATCH |\t\\\ninclude/linux/entry-common.h-31-\t\t\t\t SYSCALL_WORK_SYSCALL_RSEQ_SLICE)\n--\ninclude/linux/entry-common.h-37-\t\t\t\t SYSCALL_WORK_SYSCALL_AUDIT |\t\t\\\ninclude/linux/entry-common.h:38:\t\t\t\t SYSCALL_WORK_SYSCALL_USER_DISPATCH |\t\\\ninclude/linux/entry-common.h-39-\t\t\t\t SYSCALL_WORK_SYSCALL_EXIT_TRAP)\n--\ninclude/linux/entry-common.h=65=static __always_inline long syscall_trace_enter(struct pt_regs *regs, unsigned long work,\n--\ninclude/linux/entry-common.h-72-\t */\ninclude/linux/entry-common.h:73:\tif (work \u0026 SYSCALL_WORK_SYSCALL_USER_DISPATCH) {\ninclude/linux/entry-common.h-74-\t\tif (syscall_user_dispatch(regs))\n--\ninclude/linux/entry-common.h=244=static __always_inline void syscall_exit_work(struct pt_regs *regs, unsigned long work)\n--\ninclude/linux/entry-common.h-253-\t */\ninclude/linux/entry-common.h:254:\tif (work \u0026 SYSCALL_WORK_SYSCALL_USER_DISPATCH) {\ninclude/linux/entry-common.h-255-\t\tif (syscall_user_dispatch_clear_on_dispatch())\n--\ninclude/linux/syscall_user_dispatch.h-4- */\ninclude/linux/syscall_user_dispatch.h:5:#ifndef _SYSCALL_USER_DISPATCH_H\ninclude/linux/syscall_user_dispatch.h:6:#define _SYSCALL_USER_DISPATCH_H\ninclude/linux/syscall_user_dispatch.h-7-\n--\ninclude/linux/syscall_user_dispatch.h=12=struct pt_regs;\ninclude/linux/syscall_user_dispatch.h-13-\ninclude/linux/syscall_user_dispatch.h:14:#ifdef CONFIG_SYSCALL_USER_DISPATCH\ninclude/linux/syscall_user_dispatch.h-15-\n--\ninclude/linux/syscall_user_dispatch.h=27=int set_syscall_user_dispatch(unsigned long mode, unsigned long offset,\n--\ninclude/linux/syscall_user_dispatch.h-30-#define clear_syscall_work_syscall_user_dispatch(tsk) \\\ninclude/linux/syscall_user_dispatch.h:31:\tclear_task_syscall_work(tsk, SYSCALL_USER_DISPATCH)\ninclude/linux/syscall_user_dispatch.h-32-\n--\ninclude/linux/syscall_user_dispatch.h=67=static inline int syscall_user_dispatch_set_config(struct task_struct *task,\n--\ninclude/linux/syscall_user_dispatch.h-72-\ninclude/linux/syscall_user_dispatch.h:73:#endif /* CONFIG_SYSCALL_USER_DISPATCH */\ninclude/linux/syscall_user_dispatch.h-74-\ninclude/linux/syscall_user_dispatch.h:75:#endif /* _SYSCALL_USER_DISPATCH_H */\n--\ninclude/linux/syscall_user_dispatch_types.h-1-/* SPDX-License-Identifier: GPL-2.0 */\ninclude/linux/syscall_user_dispatch_types.h:2:#ifndef _SYSCALL_USER_DISPATCH_TYPES_H\ninclude/linux/syscall_user_dispatch_types.h:3:#define _SYSCALL_USER_DISPATCH_TYPES_H\ninclude/linux/syscall_user_dispatch_types.h-4-\n--\ninclude/linux/syscall_user_dispatch_types.h-6-\ninclude/linux/syscall_user_dispatch_types.h:7:#ifdef CONFIG_SYSCALL_USER_DISPATCH\ninclude/linux/syscall_user_dispatch_types.h-8-\n--\ninclude/linux/syscall_user_dispatch_types.h=18=struct syscall_user_dispatch {};\n--\ninclude/linux/syscall_user_dispatch_types.h-21-\ninclude/linux/syscall_user_dispatch_types.h:22:#endif /* _SYSCALL_USER_DISPATCH_TYPES_H */\n--\ninclude/linux/thread_info.h=41=enum syscall_work_bit {\n--\ninclude/linux/thread_info.h-46-\tSYSCALL_WORK_BIT_SYSCALL_AUDIT,\ninclude/linux/thread_info.h:47:\tSYSCALL_WORK_BIT_SYSCALL_USER_DISPATCH,\ninclude/linux/thread_info.h-48-\tSYSCALL_WORK_BIT_SYSCALL_EXIT_TRAP,\n--\ninclude/linux/thread_info.h-56-#define SYSCALL_WORK_SYSCALL_AUDIT\t\tBIT(SYSCALL_WORK_BIT_SYSCALL_AUDIT)\ninclude/linux/thread_info.h:57:#define SYSCALL_WORK_SYSCALL_USER_DISPATCH\tBIT(SYSCALL_WORK_BIT_SYSCALL_USER_DISPATCH)\ninclude/linux/thread_info.h-58-#define SYSCALL_WORK_SYSCALL_EXIT_TRAP\t\tBIT(SYSCALL_WORK_BIT_SYSCALL_EXIT_TRAP)\n--\ninclude/uapi/linux/prctl.h=134=struct prctl_mm_map {\n--\ninclude/uapi/linux/prctl.h-267-/* Dispatch syscalls to a userspace handler */\ninclude/uapi/linux/prctl.h:268:#define PR_SET_SYSCALL_USER_DISPATCH\t59\ninclude/uapi/linux/prctl.h-269-# define PR_SYS_DISPATCH_OFF\t\t0\n--\ninclude/uapi/linux/ptrace.h=110=struct ptrace_rseq_configuration {\n--\ninclude/uapi/linux/ptrace.h-117-\ninclude/uapi/linux/ptrace.h:118:#define PTRACE_SET_SYSCALL_USER_DISPATCH_CONFIG 0x4210\ninclude/uapi/linux/ptrace.h:119:#define PTRACE_GET_SYSCALL_USER_DISPATCH_CONFIG 0x4211\ninclude/uapi/linux/ptrace.h-120-\n--\nkernel/entry/Makefile=16=obj-$(CONFIG_GENERIC_SYSCALL) \t\t+= syscall-common.o\nkernel/entry/Makefile:17:obj-$(CONFIG_SYSCALL_USER_DISPATCH)\t+= syscall_user_dispatch.o\nkernel/entry/Makefile-18-obj-$(CONFIG_VIRT_XFER_TO_GUEST_WORK)\t+= virt.o\n--\nkernel/entry/syscall_user_dispatch.c=73=static int task_set_syscall_user_dispatch(struct task_struct *task, unsigned long mode,\n--\nkernel/entry/syscall_user_dispatch.c-128-\tif (mode != PR_SYS_DISPATCH_OFF)\nkernel/entry/syscall_user_dispatch.c:129:\t\tset_task_syscall_work(task, SYSCALL_USER_DISPATCH);\nkernel/entry/syscall_user_dispatch.c-130-\telse\nkernel/entry/syscall_user_dispatch.c:131:\t\tclear_task_syscall_work(task, SYSCALL_USER_DISPATCH);\nkernel/entry/syscall_user_dispatch.c-132-\n--\nkernel/entry/syscall_user_dispatch.c=142=int syscall_user_dispatch_get_config(struct task_struct *task, unsigned long size,\n--\nkernel/entry/syscall_user_dispatch.c-150-\nkernel/entry/syscall_user_dispatch.c:151:\tif (test_task_syscall_work(task, SYSCALL_USER_DISPATCH))\nkernel/entry/syscall_user_dispatch.c-152-\t\tcfg.mode = PR_SYS_DISPATCH_ON;\n--\nkernel/ptrace.c=1162=int ptrace_request(struct task_struct *child, long request,\n--\nkernel/ptrace.c-1397-\nkernel/ptrace.c:1398:\tcase PTRACE_SET_SYSCALL_USER_DISPATCH_CONFIG:\nkernel/ptrace.c-1399-\t\tret = syscall_user_dispatch_set_config(child, addr, datavp);\n--\nkernel/ptrace.c-1401-\nkernel/ptrace.c:1402:\tcase PTRACE_GET_SYSCALL_USER_DISPATCH_CONFIG:\nkernel/ptrace.c-1403-\t\tret = syscall_user_dispatch_get_config(child, addr, datavp);\n--\nkernel/sys.c=2534=SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,\n--\nkernel/sys.c-2801-\t\tbreak;\nkernel/sys.c:2802:\tcase PR_SET_SYSCALL_USER_DISPATCH:\nkernel/sys.c-2803-\t\terror = set_syscall_user_dispatch(arg2, arg3, arg4,\n--\ntools/include/uapi/linux/prctl.h=134=struct prctl_mm_map {\n--\ntools/include/uapi/linux/prctl.h-255-/* Dispatch syscalls to a userspace handler */\ntools/include/uapi/linux/prctl.h:256:#define PR_SET_SYSCALL_USER_DISPATCH\t59\ntools/include/uapi/linux/prctl.h-257-# define PR_SYS_DISPATCH_OFF\t\t0\n--\ntools/perf/trace/beauty/include/uapi/linux/prctl.h=134=struct prctl_mm_map {\n--\ntools/perf/trace/beauty/include/uapi/linux/prctl.h-267-/* Dispatch syscalls to a userspace handler */\ntools/perf/trace/beauty/include/uapi/linux/prctl.h:268:#define PR_SET_SYSCALL_USER_DISPATCH\t59\ntools/perf/trace/beauty/include/uapi/linux/prctl.h-269-# define PR_SYS_DISPATCH_OFF\t\t0\n--\ntools/testing/selftests/ptrace/get_set_sud.c=18=TEST(get_set_sud)\n--\ntools/testing/selftests/ptrace/get_set_sud.c-39-\ntools/testing/selftests/ptrace/get_set_sud.c:40:\tret = sys_ptrace(PTRACE_GET_SYSCALL_USER_DISPATCH_CONFIG, child,\ntools/testing/selftests/ptrace/get_set_sud.c-41-\t\t\t (void *)sizeof(config), \u0026config);\n--\ntools/testing/selftests/ptrace/get_set_sud.c-53-\ntools/testing/selftests/ptrace/get_set_sud.c:54:\tret = sys_ptrace(PTRACE_SET_SYSCALL_USER_DISPATCH_CONFIG, child,\ntools/testing/selftests/ptrace/get_set_sud.c-55-\t\t\t (void *)sizeof(config), \u0026config);\n--\ntools/testing/selftests/ptrace/get_set_sud.c-59-\tmemset(\u0026config, 1, sizeof(config));\ntools/testing/selftests/ptrace/get_set_sud.c:60:\tret = sys_ptrace(PTRACE_GET_SYSCALL_USER_DISPATCH_CONFIG, child,\ntools/testing/selftests/ptrace/get_set_sud.c-61-\t\t\t (void *)sizeof(config), \u0026config);\n--\ntools/testing/selftests/syscall_user_dispatch/config:1:CONFIG_SYSCALL_USER_DISPATCH=y\n--\ntools/testing/selftests/syscall_user_dispatch/sud_benchmark.c-20-\ntools/testing/selftests/syscall_user_dispatch/sud_benchmark.c:21:#ifndef PR_SET_SYSCALL_USER_DISPATCH\ntools/testing/selftests/syscall_user_dispatch/sud_benchmark.c:22:# define PR_SET_SYSCALL_USER_DISPATCH\t59\ntools/testing/selftests/syscall_user_dispatch/sud_benchmark.c-23-# define PR_SYS_DISPATCH_OFF\t0\n--\ntools/testing/selftests/syscall_user_dispatch/sud_benchmark.c=136=int main(void)\n--\ntools/testing/selftests/syscall_user_dispatch/sud_benchmark.c-162-\ntools/testing/selftests/syscall_user_dispatch/sud_benchmark.c:163:\tif (prctl(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_ON,\ntools/testing/selftests/syscall_user_dispatch/sud_benchmark.c-164-\t\t syscall_dispatcher_start,\n--\ntools/testing/selftests/syscall_user_dispatch/sud_test.c-18-\ntools/testing/selftests/syscall_user_dispatch/sud_test.c:19:#ifndef PR_SET_SYSCALL_USER_DISPATCH\ntools/testing/selftests/syscall_user_dispatch/sud_test.c:20:# define PR_SET_SYSCALL_USER_DISPATCH\t59\ntools/testing/selftests/syscall_user_dispatch/sud_test.c-21-# define PR_SYS_DISPATCH_OFF\t0\n--\ntools/testing/selftests/syscall_user_dispatch/sud_test.c-45- *\ntools/testing/selftests/syscall_user_dispatch/sud_test.c:46: * - dispatch_trigger_sigsys: Verify if PR_SET_SYSCALL_USER_DISPATCH is\ntools/testing/selftests/syscall_user_dispatch/sud_test.c-47- * able to trigger SIGSYS on a syscall.\n--\ntools/testing/selftests/syscall_user_dispatch/sud_test.c=65=TEST_SIGNAL(dispatch_trigger_sigsys, SIGSYS)\n--\ntools/testing/selftests/syscall_user_dispatch/sud_test.c-73-\ntools/testing/selftests/syscall_user_dispatch/sud_test.c:74:\tret = prctl(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_EXCLUSIVE_ON, 0, 0, \u0026sel);\ntools/testing/selftests/syscall_user_dispatch/sud_test.c-75-\tASSERT_EQ(0, ret) {\ntools/testing/selftests/syscall_user_dispatch/sud_test.c:76:\t\tTH_LOG(\"Kernel does not support CONFIG_SYSCALL_USER_DISPATCH\");\ntools/testing/selftests/syscall_user_dispatch/sud_test.c-77-\t}\n--\ntools/testing/selftests/syscall_user_dispatch/sud_test.c=88=static void prctl_valid(struct __test_metadata *_metadata,\n--\ntools/testing/selftests/syscall_user_dispatch/sud_test.c-91-{\ntools/testing/selftests/syscall_user_dispatch/sud_test.c:92:\tEXPECT_EQ(0, prctl(PR_SET_SYSCALL_USER_DISPATCH, op, off, size, sel));\ntools/testing/selftests/syscall_user_dispatch/sud_test.c-93-}\n--\ntools/testing/selftests/syscall_user_dispatch/sud_test.c=95=static void prctl_invalid(struct __test_metadata *_metadata,\n--\ntools/testing/selftests/syscall_user_dispatch/sud_test.c-98-{\ntools/testing/selftests/syscall_user_dispatch/sud_test.c:99:\tEXPECT_EQ(-1, prctl(PR_SET_SYSCALL_USER_DISPATCH, op, off, size, sel));\ntools/testing/selftests/syscall_user_dispatch/sud_test.c-100-\tEXPECT_EQ(err, errno);\n--\ntools/testing/selftests/syscall_user_dispatch/sud_test.c=210=TEST(dispatch_and_return)\n--\ntools/testing/selftests/syscall_user_dispatch/sud_test.c-223-\ntools/testing/selftests/syscall_user_dispatch/sud_test.c:224:\tret = prctl(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_EXCLUSIVE_ON, 0, 0, \u0026glob_sel);\ntools/testing/selftests/syscall_user_dispatch/sud_test.c-225-\tASSERT_EQ(0, ret) {\ntools/testing/selftests/syscall_user_dispatch/sud_test.c:226:\t\tTH_LOG(\"Kernel does not support CONFIG_SYSCALL_USER_DISPATCH\");\ntools/testing/selftests/syscall_user_dispatch/sud_test.c-227-\t}\n--\ntools/testing/selftests/syscall_user_dispatch/sud_test.c=255=TEST_SIGNAL(bad_selector, SIGSYS)\n--\ntools/testing/selftests/syscall_user_dispatch/sud_test.c-279-\ntools/testing/selftests/syscall_user_dispatch/sud_test.c:280:\tret = prctl(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_EXCLUSIVE_ON, 0, 0, \u0026glob_sel);\ntools/testing/selftests/syscall_user_dispatch/sud_test.c-281-\tASSERT_EQ(0, ret) {\ntools/testing/selftests/syscall_user_dispatch/sud_test.c:282:\t\tTH_LOG(\"Kernel does not support CONFIG_SYSCALL_USER_DISPATCH\");\ntools/testing/selftests/syscall_user_dispatch/sud_test.c-283-\t}\n--\ntools/testing/selftests/syscall_user_dispatch/sud_test.c=298=TEST(disable_dispatch)\n--\ntools/testing/selftests/syscall_user_dispatch/sud_test.c-303-\ntools/testing/selftests/syscall_user_dispatch/sud_test.c:304:\tret = prctl(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_EXCLUSIVE_ON, 0, 0, \u0026sel);\ntools/testing/selftests/syscall_user_dispatch/sud_test.c-305-\tASSERT_EQ(0, ret) {\ntools/testing/selftests/syscall_user_dispatch/sud_test.c:306:\t\tTH_LOG(\"Kernel does not support CONFIG_SYSCALL_USER_DISPATCH\");\ntools/testing/selftests/syscall_user_dispatch/sud_test.c-307-\t}\n--\ntools/testing/selftests/syscall_user_dispatch/sud_test.c-311-\ntools/testing/selftests/syscall_user_dispatch/sud_test.c:312:\tret = prctl(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_OFF, 0, 0, 0);\ntools/testing/selftests/syscall_user_dispatch/sud_test.c-313-\tEXPECT_EQ(0, ret) {\n--\ntools/testing/selftests/syscall_user_dispatch/sud_test.c=326=TEST(direct_dispatch_range)\n--\ntools/testing/selftests/syscall_user_dispatch/sud_test.c-335-\t */\ntools/testing/selftests/syscall_user_dispatch/sud_test.c:336:\tret = prctl(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_EXCLUSIVE_ON, 0, -1L, \u0026sel);\ntools/testing/selftests/syscall_user_dispatch/sud_test.c-337-\tASSERT_EQ(0, ret) {\ntools/testing/selftests/syscall_user_dispatch/sud_test.c:338:\t\tTH_LOG(\"Kernel does not support CONFIG_SYSCALL_USER_DISPATCH\");\ntools/testing/selftests/syscall_user_dispatch/sud_test.c-339-\t}\n--\ntools/testing/selftests/syscall_user_dispatch/sud_test.c=349=static void test_range(struct __test_metadata *_metadata,\n--\ntools/testing/selftests/syscall_user_dispatch/sud_test.c-354-\tSYSCALL_DISPATCH_OFF(glob_sel);\ntools/testing/selftests/syscall_user_dispatch/sud_test.c:355:\tEXPECT_EQ(0, prctl(PR_SET_SYSCALL_USER_DISPATCH, op, off, size, \u0026glob_sel));\ntools/testing/selftests/syscall_user_dispatch/sud_test.c-356-\tSYSCALL_DISPATCH_ON(glob_sel);\n"
} |
| 5/2 | 2026/07/21 22:10 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 16004 output: 126 thoughts: 2396 Thoughts: **My Analysis of the Syscall User Dispatch Patch for arm64** Okay, so this patch is all about enabling `SYSCALL_USER_DISPATCH` on arm64. The main dependency is that `ARCH_SUPPORTS_SYSCALL_USER_DISPATCH` is enabled, which this patch does. Crucially, it also enables `GENERIC_ENTRY` which is essential for this feature. Because of this, we *must* ensure that `SYSCALL_USER_DISPATCH` is explicitly enabled. Also, since arm64 is now using `GENERIC_ENTRY` the config is no longer needed. Looking at the code changes, the heart of the syscall entry is `el0_svc_common`, but that's a *hot path*, so it's probably not useful to directly fuzz. The patch replaces tracing with `syscall_trace_enter` and `syscall_exit_to_user_mode_work`, and the ptrace logic has changed to report syscall entry and exit. The key new function is `arch_syscall_is_vdso_sigreturn` in `arch/arm64/kernel/vdso.c`. This is essential because it checks if a syscall is a `sigreturn`, which is handled differently under syscall user dispatch. This function is a prime target for fuzzing. Furthermore, changes were made to `user_enable_single_step` and `user_disable_single_step` in `arch/arm64/kernel/debug-monitors.c`. These aren't hot-path functions, but they're still relevant to ptrace and single-stepping, so they should be targeted too. Now, concerning configurations, `SYSCALL_USER_DISPATCH` is essential. We should also include `COMPAT` because `arch_syscall_is_vdso_sigreturn` uses it. So, in conclusion, the important things to look at for fuzzing are: * **`arch_syscall_is_vdso_sigreturn`**: This is the single most important function added and central to correct functionality. * **`user_enable_single_step`**: Relevant to ptrace and single-stepping interaction. * **`user_disable_single_step`**: Part of single stepping logic. Also the following configs should be explicitly enabled: * **`SYSCALL_USER_DISPATCH`**: Required for this patch's core functionality. * **`COMPAT`**: to test the compat path in `arch_syscall_is_vdso_sigreturn`. |
| 6/2 | 2026/07/21 22:11 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"SYSCALL_USER_DISPATCH",
"COMPAT"
],
"FocusSymbols": [
"arch_syscall_is_vdso_sigreturn",
"user_enable_single_step",
"user_disable_single_step"
],
"Reasoning": "The patch converts arm64 to use the generic entry infrastructure and adds support for Syscall User Dispatch. This involves functional changes to the core syscall entry/exit paths, ptrace single-stepping, and VDSO sigreturn detection.",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"SYSCALL_USER_DISPATCH",
"COMPAT"
],
"FocusSymbols": [
"arch_syscall_is_vdso_sigreturn",
"user_enable_single_step",
"user_disable_single_step"
],
"Reasoning": "The patch converts arm64 to use the generic entry infrastructure and adds support for Syscall User Dispatch. This involves functional changes to the core syscall entry/exit paths, ptrace single-stepping, and VDSO sigreturn detection.",
"WorthFuzzing": true
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|