summaryrefslogtreecommitdiff
path: root/lib/syscall.c
diff options
context:
space:
mode:
authorWilly Tarreau <w@1wt.eu>2020-11-30 08:36:48 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-12-11 13:23:32 +0100
commit867fbf2bb739bc7ba02cca09093f2d35ed7eadc5 (patch)
tree7c0b6051ce8ae8de5aefa9c4bbe14fbc51cea5ed /lib/syscall.c
parentf68f5bdfefd9da1834b9ed01fcb02334eb56bfcd (diff)
lib/syscall: fix syscall registers retrieval on 32-bit platforms
commit 4f134b89a24b965991e7c345b9a4591821f7c2a6 upstream. 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 <greg@kroah.com> Reviewed-by: Kees Cook <keescook@chromium.org> Tested-by: Michael Ellerman <mpe@ellerman.id.au> (ppc32) Signed-off-by: Willy Tarreau <w@1wt.eu> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'lib/syscall.c')
-rw-r--r--lib/syscall.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/lib/syscall.c b/lib/syscall.c
index fb328e7ccb08..71ffcf5aff12 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;