projects/linux·commit 0a4e3e97

ARM: signal: check the FDPIC function descriptor address

0a4e3e97 · Linus Torvalds <[email protected]> · 2026-10-20 09:49:35 -10:00

When a task has FDPIC_FUNCPTRS in its personality, setup_return() treats
the signal handler as a pointer to a function descriptor and reads the
entry point and GOT pointer from it with __get_user().  Nothing checks
that pointer: it is whatever the task passed to sigaction(), and any
task can set FDPIC_FUNCPTRS with personality(2).  BINFMT_ELF_FDPIC is
not limited to !MMU on ARM.

On most configurations this is harmless only by accident.  With
CPU_SPECTRE (ARMv7) __get_user() is get_user().  With CPU_USE_DOMAINS
(ARMv5 and older) it uses the unprivileged ldrt, but that only stops at
kernel memory when software PAN has put the kernel domain in client
mode; with ARM_PAN=n the kernel domain stays in manager mode, where
permissions are not checked.  So on an ARMv6-only MMU kernel, or an
ARMv5 or older one without ARM_PAN, it reads two words of kernel memory
that end up in the task's PC and r9.

Use get_user(), which checks the address.  This goes back to commit
5c16595353e0 ("ARM: signal handling support for FDPIC_FUNCPTRS
functions").

Signed-off-by: Linus Torvalds <[email protected]>
Commit
0a4e3e979b5ecb2460ab8eb8f4f8aba3590a4043
Parents
7318a05d

Changes

1 files changed · +2 −2

FileStatusAddDelContent
arch/arm/kernel/signal.cmodified+2−2View file

arch/arm/kernel/signal.c

View file
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 7be9188..d5d15b9 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -332,8 +332,8 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig,
if (fdpic) {
unsigned long __user *fdpic_func_desc =
(unsigned long __user *)handler;
- if (__get_user(handler, &fdpic_func_desc[0]) ||
- __get_user(handler_fdpic_GOT, &fdpic_func_desc[1]))
+ if (get_user(handler, &fdpic_func_desc[0]) ||
+ get_user(handler_fdpic_GOT, &fdpic_func_desc[1]))
return 1;
}