diff options
author | Willy Tarreau <[email protected]> | 2020-11-30 08:36:48 +0100 |
---|---|---|
committer | Linus Torvalds <[email protected]> | 2020-12-03 09:52:44 -0800 |
commit | 4f134b89a24b965991e7c345b9a4591821f7c2a6 (patch) | |
tree | 3f65307ed6e24b0f227f00b3dc301ad8f36dea3e | |
parent | 34816d20f173a90389c8a7e641166d8ea9dce70a (diff) |
lib/syscall: fix syscall registers retrieval on 32-bit platforms
Lilith >_> and Claudio Bozzato of Cisco Talos security team reported
that collect_syscall() improperly casts the syscall registers to 64-bit
values leaking the uninitialized last 24 bytes on 32-bit platforms, that
are visible in /proc/self/syscall.
The cause is that info->data.args are u64 while syscall_get_arguments()
uses longs, as hinted by the bogus pointer cast in the function.
Let's just proceed like the other call places, by retrieving the
registers into an array of longs before assigning them to the caller's
array. This was successfully tested on x86_64, i386 and ppc32.
Reference: CVE-2020-28588, TALOS-2020-1211
Fixes: 631b7abacd02 ("ptrace: Remove maxargs from task_current_syscall()")
Cc: Greg KH <[email protected]>
Reviewed-by: Kees Cook <[email protected]>
Tested-by: Michael Ellerman <[email protected]> (ppc32)
Signed-off-by: Willy Tarreau <[email protected]>
Reviewed-by: Thomas Gleixner <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
-rw-r--r-- | lib/syscall.c | 11 |
1 files changed, 9 insertions, 2 deletions
diff --git a/lib/syscall.c b/lib/syscall.c index 8533d2fea2d7..ba13e924c430 100644 --- a/lib/syscall.c +++ b/lib/syscall.c @@ -7,6 +7,7 @@ static int collect_syscall(struct task_struct *target, struct syscall_info *info) { + unsigned long args[6] = { }; struct pt_regs *regs; if (!try_get_task_stack(target)) { @@ -27,8 +28,14 @@ static int collect_syscall(struct task_struct *target, struct syscall_info *info info->data.nr = syscall_get_nr(target, regs); if (info->data.nr != -1L) - syscall_get_arguments(target, regs, - (unsigned long *)&info->data.args[0]); + syscall_get_arguments(target, regs, args); + + info->data.args[0] = args[0]; + info->data.args[1] = args[1]; + info->data.args[2] = args[2]; + info->data.args[3] = args[3]; + info->data.args[4] = args[4]; + info->data.args[5] = args[5]; put_task_stack(target); return 0; |