CVE-2026-45993
Description
In the Linux kernel, the following vulnerability has been resolved:
LoongArch: Add spectre boundry for syscall dispatch table
The LoongArch syscall number is directly controlled by userspace, but does not have a array_index_nospec() boundry to prevent access past the syscall function pointer tables.
Affected products
1Patches
10108f2cd13577LoongArch: Add spectre boundry for syscall dispatch table
2 files changed · +4 −4
arch/loongarch/kernel/syscall.c+2 −2 modifieddiff --git a/arch/loongarch/kernel/syscall.c b/arch/loongarch/kernel/syscall.c index b4c5acd7aa3b32..f4e3bd219b1d7e 100644 --- a/arch/loongarch/kernel/syscall.c +++ b/arch/loongarch/kernel/syscall.c @@ -9,6 +9,7 @@ #include <linux/entry-common.h> #include <linux/errno.h> #include <linux/linkage.h> +#include <linux/nospec.h> #include <linux/syscalls.h> #include <linux/unistd.h> @@ -55,7 +56,7 @@ void noinstr do_syscall(struct pt_regs *regs) nr = syscall_enter_from_user_mode(regs, nr); if (nr < NR_syscalls) { - syscall_fn = sys_call_table[nr]; + syscall_fn = sys_call_table[array_index_nospec(nr, NR_syscalls)]; regs->regs[4] = syscall_fn(regs->orig_a0, regs->regs[5], regs->regs[6], regs->regs[7], regs->regs[8], regs->regs[9]); } -- cgit 1.3-korg
arch/loongarch/kernel/syscall.c+2 −2 modifieddiff --git a/arch/loongarch/kernel/syscall.c b/arch/loongarch/kernel/syscall.c index b4c5acd7aa3b32..f4e3bd219b1d7e 100644 --- a/arch/loongarch/kernel/syscall.c +++ b/arch/loongarch/kernel/syscall.c @@ -9,6 +9,7 @@ #include <linux/entry-common.h> #include <linux/errno.h> #include <linux/linkage.h> +#include <linux/nospec.h> #include <linux/syscalls.h> #include <linux/unistd.h> @@ -55,7 +56,7 @@ void noinstr do_syscall(struct pt_regs *regs) nr = syscall_enter_from_user_mode(regs, nr); if (nr < NR_syscalls) { - syscall_fn = sys_call_table[nr]; + syscall_fn = sys_call_table[array_index_nospec(nr, NR_syscalls)]; regs->regs[4] = syscall_fn(regs->orig_a0, regs->regs[5], regs->regs[6], regs->regs[7], regs->regs[8], regs->regs[9]); } -- cgit 1.3-korg
0c965d2784fbLoongArch: Add spectre boundry for syscall dispatch table
1 file changed · +2 −2
arch/loongarch/kernel/syscall.c+2 −2 modifieddiff --git a/arch/loongarch/kernel/syscall.c b/arch/loongarch/kernel/syscall.c index 1249d82c1cd0ac..dac435c3274337 100644 --- a/arch/loongarch/kernel/syscall.c +++ b/arch/loongarch/kernel/syscall.c @@ -9,6 +9,7 @@ #include <linux/entry-common.h> #include <linux/errno.h> #include <linux/linkage.h> +#include <linux/nospec.h> #include <linux/objtool.h> #include <linux/randomize_kstack.h> #include <linux/syscalls.h> @@ -74,7 +75,7 @@ void noinstr __no_stack_protector do_syscall(struct pt_regs *regs) add_random_kstack_offset(); if (nr < NR_syscalls) { - syscall_fn = sys_call_table[nr]; + syscall_fn = sys_call_table[array_index_nospec(nr, NR_syscalls)]; regs->regs[4] = syscall_fn(regs->orig_a0, regs->regs[5], regs->regs[6], regs->regs[7], regs->regs[8], regs->regs[9]); } -- cgit 1.3-korg
07040904ad21LoongArch: Add spectre boundry for syscall dispatch table
1 file changed · +2 −2
arch/loongarch/kernel/syscall.c+2 −2 modifieddiff --git a/arch/loongarch/kernel/syscall.c b/arch/loongarch/kernel/syscall.c index 168bd97540f8cf..d0257935078ebc 100644 --- a/arch/loongarch/kernel/syscall.c +++ b/arch/loongarch/kernel/syscall.c @@ -9,6 +9,7 @@ #include <linux/entry-common.h> #include <linux/errno.h> #include <linux/linkage.h> +#include <linux/nospec.h> #include <linux/objtool.h> #include <linux/randomize_kstack.h> #include <linux/syscalls.h> @@ -61,7 +62,7 @@ void noinstr __no_stack_protector do_syscall(struct pt_regs *regs) add_random_kstack_offset(); if (nr < NR_syscalls) { - syscall_fn = sys_call_table[nr]; + syscall_fn = sys_call_table[array_index_nospec(nr, NR_syscalls)]; regs->regs[4] = syscall_fn(regs->orig_a0, regs->regs[5], regs->regs[6], regs->regs[7], regs->regs[8], regs->regs[9]); } -- cgit 1.3-korg
85cbf7fb568aLoongArch: Add spectre boundry for syscall dispatch table
1 file changed · +2 −2
arch/loongarch/kernel/syscall.c+2 −2 modifieddiff --git a/arch/loongarch/kernel/syscall.c b/arch/loongarch/kernel/syscall.c index 168bd97540f8cf..d0257935078ebc 100644 --- a/arch/loongarch/kernel/syscall.c +++ b/arch/loongarch/kernel/syscall.c @@ -9,6 +9,7 @@ #include <linux/entry-common.h> #include <linux/errno.h> #include <linux/linkage.h> +#include <linux/nospec.h> #include <linux/objtool.h> #include <linux/randomize_kstack.h> #include <linux/syscalls.h> @@ -61,7 +62,7 @@ void noinstr __no_stack_protector do_syscall(struct pt_regs *regs) add_random_kstack_offset(); if (nr < NR_syscalls) { - syscall_fn = sys_call_table[nr]; + syscall_fn = sys_call_table[array_index_nospec(nr, NR_syscalls)]; regs->regs[4] = syscall_fn(regs->orig_a0, regs->regs[5], regs->regs[6], regs->regs[7], regs->regs[8], regs->regs[9]); } -- cgit 1.3-korg
bc84a109c208LoongArch: Add spectre boundry for syscall dispatch table
1 file changed · +2 −2
arch/loongarch/kernel/syscall.c+2 −2 modifieddiff --git a/arch/loongarch/kernel/syscall.c b/arch/loongarch/kernel/syscall.c index 1249d82c1cd0ac..dac435c3274337 100644 --- a/arch/loongarch/kernel/syscall.c +++ b/arch/loongarch/kernel/syscall.c @@ -9,6 +9,7 @@ #include <linux/entry-common.h> #include <linux/errno.h> #include <linux/linkage.h> +#include <linux/nospec.h> #include <linux/objtool.h> #include <linux/randomize_kstack.h> #include <linux/syscalls.h> @@ -74,7 +75,7 @@ void noinstr __no_stack_protector do_syscall(struct pt_regs *regs) add_random_kstack_offset(); if (nr < NR_syscalls) { - syscall_fn = sys_call_table[nr]; + syscall_fn = sys_call_table[array_index_nospec(nr, NR_syscalls)]; regs->regs[4] = syscall_fn(regs->orig_a0, regs->regs[5], regs->regs[6], regs->regs[7], regs->regs[8], regs->regs[9]); } -- cgit 1.3-korg
108f2cd13577LoongArch: Add spectre boundry for syscall dispatch table
2 files changed · +4 −4
arch/loongarch/kernel/syscall.c+2 −2 modifieddiff --git a/arch/loongarch/kernel/syscall.c b/arch/loongarch/kernel/syscall.c index b4c5acd7aa3b32..f4e3bd219b1d7e 100644 --- a/arch/loongarch/kernel/syscall.c +++ b/arch/loongarch/kernel/syscall.c @@ -9,6 +9,7 @@ #include <linux/entry-common.h> #include <linux/errno.h> #include <linux/linkage.h> +#include <linux/nospec.h> #include <linux/syscalls.h> #include <linux/unistd.h> @@ -55,7 +56,7 @@ void noinstr do_syscall(struct pt_regs *regs) nr = syscall_enter_from_user_mode(regs, nr); if (nr < NR_syscalls) { - syscall_fn = sys_call_table[nr]; + syscall_fn = sys_call_table[array_index_nospec(nr, NR_syscalls)]; regs->regs[4] = syscall_fn(regs->orig_a0, regs->regs[5], regs->regs[6], regs->regs[7], regs->regs[8], regs->regs[9]); } -- cgit 1.3-korg
arch/loongarch/kernel/syscall.c+2 −2 modifieddiff --git a/arch/loongarch/kernel/syscall.c b/arch/loongarch/kernel/syscall.c index b4c5acd7aa3b32..f4e3bd219b1d7e 100644 --- a/arch/loongarch/kernel/syscall.c +++ b/arch/loongarch/kernel/syscall.c @@ -9,6 +9,7 @@ #include <linux/entry-common.h> #include <linux/errno.h> #include <linux/linkage.h> +#include <linux/nospec.h> #include <linux/syscalls.h> #include <linux/unistd.h> @@ -55,7 +56,7 @@ void noinstr do_syscall(struct pt_regs *regs) nr = syscall_enter_from_user_mode(regs, nr); if (nr < NR_syscalls) { - syscall_fn = sys_call_table[nr]; + syscall_fn = sys_call_table[array_index_nospec(nr, NR_syscalls)]; regs->regs[4] = syscall_fn(regs->orig_a0, regs->regs[5], regs->regs[6], regs->regs[7], regs->regs[8], regs->regs[9]); } -- cgit 1.3-korg
85cbf7fb568aLoongArch: Add spectre boundry for syscall dispatch table
2 files changed · +4 −4
arch/loongarch/kernel/syscall.c+2 −2 modifieddiff --git a/arch/loongarch/kernel/syscall.c b/arch/loongarch/kernel/syscall.c index 168bd97540f8cf..d0257935078ebc 100644 --- a/arch/loongarch/kernel/syscall.c +++ b/arch/loongarch/kernel/syscall.c @@ -9,6 +9,7 @@ #include <linux/entry-common.h> #include <linux/errno.h> #include <linux/linkage.h> +#include <linux/nospec.h> #include <linux/objtool.h> #include <linux/randomize_kstack.h> #include <linux/syscalls.h> @@ -61,7 +62,7 @@ void noinstr __no_stack_protector do_syscall(struct pt_regs *regs) add_random_kstack_offset(); if (nr < NR_syscalls) { - syscall_fn = sys_call_table[nr]; + syscall_fn = sys_call_table[array_index_nospec(nr, NR_syscalls)]; regs->regs[4] = syscall_fn(regs->orig_a0, regs->regs[5], regs->regs[6], regs->regs[7], regs->regs[8], regs->regs[9]); } -- cgit 1.3-korg
arch/loongarch/kernel/syscall.c+2 −2 modifieddiff --git a/arch/loongarch/kernel/syscall.c b/arch/loongarch/kernel/syscall.c index 168bd97540f8cf..d0257935078ebc 100644 --- a/arch/loongarch/kernel/syscall.c +++ b/arch/loongarch/kernel/syscall.c @@ -9,6 +9,7 @@ #include <linux/entry-common.h> #include <linux/errno.h> #include <linux/linkage.h> +#include <linux/nospec.h> #include <linux/objtool.h> #include <linux/randomize_kstack.h> #include <linux/syscalls.h> @@ -61,7 +62,7 @@ void noinstr __no_stack_protector do_syscall(struct pt_regs *regs) add_random_kstack_offset(); if (nr < NR_syscalls) { - syscall_fn = sys_call_table[nr]; + syscall_fn = sys_call_table[array_index_nospec(nr, NR_syscalls)]; regs->regs[4] = syscall_fn(regs->orig_a0, regs->regs[5], regs->regs[6], regs->regs[7], regs->regs[8], regs->regs[9]); } -- cgit 1.3-korg
bc84a109c208LoongArch: Add spectre boundry for syscall dispatch table
2 files changed · +4 −4
arch/loongarch/kernel/syscall.c+2 −2 modifieddiff --git a/arch/loongarch/kernel/syscall.c b/arch/loongarch/kernel/syscall.c index 1249d82c1cd0ac..dac435c3274337 100644 --- a/arch/loongarch/kernel/syscall.c +++ b/arch/loongarch/kernel/syscall.c @@ -9,6 +9,7 @@ #include <linux/entry-common.h> #include <linux/errno.h> #include <linux/linkage.h> +#include <linux/nospec.h> #include <linux/objtool.h> #include <linux/randomize_kstack.h> #include <linux/syscalls.h> @@ -74,7 +75,7 @@ void noinstr __no_stack_protector do_syscall(struct pt_regs *regs) add_random_kstack_offset(); if (nr < NR_syscalls) { - syscall_fn = sys_call_table[nr]; + syscall_fn = sys_call_table[array_index_nospec(nr, NR_syscalls)]; regs->regs[4] = syscall_fn(regs->orig_a0, regs->regs[5], regs->regs[6], regs->regs[7], regs->regs[8], regs->regs[9]); } -- cgit 1.3-korg
arch/loongarch/kernel/syscall.c+2 −2 modifieddiff --git a/arch/loongarch/kernel/syscall.c b/arch/loongarch/kernel/syscall.c index 1249d82c1cd0ac..dac435c3274337 100644 --- a/arch/loongarch/kernel/syscall.c +++ b/arch/loongarch/kernel/syscall.c @@ -9,6 +9,7 @@ #include <linux/entry-common.h> #include <linux/errno.h> #include <linux/linkage.h> +#include <linux/nospec.h> #include <linux/objtool.h> #include <linux/randomize_kstack.h> #include <linux/syscalls.h> @@ -74,7 +75,7 @@ void noinstr __no_stack_protector do_syscall(struct pt_regs *regs) add_random_kstack_offset(); if (nr < NR_syscalls) { - syscall_fn = sys_call_table[nr]; + syscall_fn = sys_call_table[array_index_nospec(nr, NR_syscalls)]; regs->regs[4] = syscall_fn(regs->orig_a0, regs->regs[5], regs->regs[6], regs->regs[7], regs->regs[8], regs->regs[9]); } -- cgit 1.3-korg
0c965d2784fbLoongArch: Add spectre boundry for syscall dispatch table
2 files changed · +4 −4
arch/loongarch/kernel/syscall.c+2 −2 modifieddiff --git a/arch/loongarch/kernel/syscall.c b/arch/loongarch/kernel/syscall.c index 1249d82c1cd0ac..dac435c3274337 100644 --- a/arch/loongarch/kernel/syscall.c +++ b/arch/loongarch/kernel/syscall.c @@ -9,6 +9,7 @@ #include <linux/entry-common.h> #include <linux/errno.h> #include <linux/linkage.h> +#include <linux/nospec.h> #include <linux/objtool.h> #include <linux/randomize_kstack.h> #include <linux/syscalls.h> @@ -74,7 +75,7 @@ void noinstr __no_stack_protector do_syscall(struct pt_regs *regs) add_random_kstack_offset(); if (nr < NR_syscalls) { - syscall_fn = sys_call_table[nr]; + syscall_fn = sys_call_table[array_index_nospec(nr, NR_syscalls)]; regs->regs[4] = syscall_fn(regs->orig_a0, regs->regs[5], regs->regs[6], regs->regs[7], regs->regs[8], regs->regs[9]); } -- cgit 1.3-korg
arch/loongarch/kernel/syscall.c+2 −2 modifieddiff --git a/arch/loongarch/kernel/syscall.c b/arch/loongarch/kernel/syscall.c index 1249d82c1cd0ac..dac435c3274337 100644 --- a/arch/loongarch/kernel/syscall.c +++ b/arch/loongarch/kernel/syscall.c @@ -9,6 +9,7 @@ #include <linux/entry-common.h> #include <linux/errno.h> #include <linux/linkage.h> +#include <linux/nospec.h> #include <linux/objtool.h> #include <linux/randomize_kstack.h> #include <linux/syscalls.h> @@ -74,7 +75,7 @@ void noinstr __no_stack_protector do_syscall(struct pt_regs *regs) add_random_kstack_offset(); if (nr < NR_syscalls) { - syscall_fn = sys_call_table[nr]; + syscall_fn = sys_call_table[array_index_nospec(nr, NR_syscalls)]; regs->regs[4] = syscall_fn(regs->orig_a0, regs->regs[5], regs->regs[6], regs->regs[7], regs->regs[8], regs->regs[9]); } -- cgit 1.3-korg
07040904ad21LoongArch: Add spectre boundry for syscall dispatch table
2 files changed · +4 −4
arch/loongarch/kernel/syscall.c+2 −2 modifieddiff --git a/arch/loongarch/kernel/syscall.c b/arch/loongarch/kernel/syscall.c index 168bd97540f8cf..d0257935078ebc 100644 --- a/arch/loongarch/kernel/syscall.c +++ b/arch/loongarch/kernel/syscall.c @@ -9,6 +9,7 @@ #include <linux/entry-common.h> #include <linux/errno.h> #include <linux/linkage.h> +#include <linux/nospec.h> #include <linux/objtool.h> #include <linux/randomize_kstack.h> #include <linux/syscalls.h> @@ -61,7 +62,7 @@ void noinstr __no_stack_protector do_syscall(struct pt_regs *regs) add_random_kstack_offset(); if (nr < NR_syscalls) { - syscall_fn = sys_call_table[nr]; + syscall_fn = sys_call_table[array_index_nospec(nr, NR_syscalls)]; regs->regs[4] = syscall_fn(regs->orig_a0, regs->regs[5], regs->regs[6], regs->regs[7], regs->regs[8], regs->regs[9]); } -- cgit 1.3-korg
arch/loongarch/kernel/syscall.c+2 −2 modifieddiff --git a/arch/loongarch/kernel/syscall.c b/arch/loongarch/kernel/syscall.c index 168bd97540f8cf..d0257935078ebc 100644 --- a/arch/loongarch/kernel/syscall.c +++ b/arch/loongarch/kernel/syscall.c @@ -9,6 +9,7 @@ #include <linux/entry-common.h> #include <linux/errno.h> #include <linux/linkage.h> +#include <linux/nospec.h> #include <linux/objtool.h> #include <linux/randomize_kstack.h> #include <linux/syscalls.h> @@ -61,7 +62,7 @@ void noinstr __no_stack_protector do_syscall(struct pt_regs *regs) add_random_kstack_offset(); if (nr < NR_syscalls) { - syscall_fn = sys_call_table[nr]; + syscall_fn = sys_call_table[array_index_nospec(nr, NR_syscalls)]; regs->regs[4] = syscall_fn(regs->orig_a0, regs->regs[5], regs->regs[6], regs->regs[7], regs->regs[8], regs->regs[9]); } -- cgit 1.3-korg
Vulnerability mechanics
Root cause
"Missing Spectre-variant bounds check (array_index_nospec) on the user-controlled syscall number before indexing the syscall function pointer table."
Attack vector
On LoongArch, the syscall number (nr) is supplied directly by userspace via a register. The do_syscall() function in arch/loongarch/kernel/syscall.c validates that nr is less than NR_syscalls, but before the patch this check was not hardened against Spectre-variant speculative execution. An attacker who can control the syscall number can train the branch predictor so that during speculative execution the CPU indexes sys_call_table[nr] with an out-of-bounds nr value, speculatively reading arbitrary kernel memory through a function-pointer dereference side channel [patch_id=2660613].
Affected code
The vulnerable code is in the do_syscall() function in arch/loongarch/kernel/syscall.c. The original code indexed sys_call_table[nr] after a bounds check but without a speculation barrier [patch_id=2660613].
What the fix does
The patch adds an #include <linux/nospec.h> and wraps the sys_call_table index with array_index_nospec(nr, NR_syscalls) [patch_id=2660613]. This macro inserts a speculation barrier (e.g., a CSDB or similar instruction on LoongArch) that prevents the CPU from speculatively executing the array access with a value that failed the bounds check. The bounds check (nr < NR_syscalls) remains, but now even if the branch predictor mispredicts, the index passed to the load is clamped to a safe range, closing the Spectre-variant gadget.
Preconditions
- authAttacker must be able to execute userspace code on a LoongArch system (i.e., have local user access).
- inputThe CPU must be vulnerable to Spectre-variant speculative execution (all current LoongArch cores are presumed affected).
Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- git.kernel.org/stable/c/07040904ad217545be096d4280ed33c02f6a3750nvd
- git.kernel.org/stable/c/0c965d2784fbbd7f8e3b96d875c9cfdf7c00da3dnvd
- git.kernel.org/stable/c/108f2cd13577a410c0ad6ea00708596d9d0dfc90nvd
- git.kernel.org/stable/c/85cbf7fb568af5358aae61925c4e66b8f5e1439dnvd
- git.kernel.org/stable/c/bc84a109c2082dd0c4b38e8d923c046b41977533nvd
News mentions
0No linked articles in our index yet.