signal/ptrace: Don’t leak unitialized kernel memory with PTRACE_PEEK_SIGINFO [Linux 4.14.128]

signal/ptrace: Don’t leak unitialized kernel memory with PTRACE_PEEK_SIGINFO [Linux 4.14.128]

This Linux kernel change "signal/ptrace: Don’t leak unitialized kernel memory with PTRACE_PEEK_SIGINFO" is included in the Linux 4.14.128 release. This change is authored by Eric W. Biederman <ebiederm [at]> on Tue May 28 18:46:37 2019 -0500. The commit for this change in Linux stable tree is 50f806a (patch) which is from upstream commit f6e2aa9. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream f6e2aa9.

signal/ptrace: Don't leak unitialized kernel memory with PTRACE_PEEK_SIGINFO

[ Upstream commit f6e2aa91a46d2bc79fce9b93a988dbe7655c90c0 ]

Recently syzbot in conjunction with KMSAN reported that
ptrace_peek_siginfo can copy an uninitialized siginfo to userspace.
Inspecting ptrace_peek_siginfo confirms this.

The problem is that off when initialized from can be
initialized to a negaive value.  At which point the "if (off >= 0)"
test to see if off became negative fails because off started off

Prevent the core problem by adding a variable found that is only true
if a siginfo is found and copied to a temporary in preparation for
being copied to userspace.

Prevent from being truncated when being assigned to off by
testing that off is <= the maximum possible value of off.  Convert off
to an unsigned long so that we should not have to truncate,
we have well defined overflow behavior so if we add another check we
won't risk fighting undefined compiler behavior, and so that we have a
type whose maximum value is easy to test for.

Cc: Andrei Vagin <>
Fixes: 84c751bd4aeb ("ptrace: add ability to retrieve signals without removing from a queue (v4)")
Signed-off-by: "Eric W. Biederman" <>
Signed-off-by: Sasha Levin <>

There are 10 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 kernel/ptrace.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index f1c85b6..f6b452e 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -704,6 +704,10 @@ static int ptrace_peek_siginfo(struct task_struct *child,
    if ( < 0)
        return -EINVAL;

+   /* Ensure fits in an unsigned long */
+   if ( > ULONG_MAX)
+       return 0;
    if (arg.flags & PTRACE_PEEKSIGINFO_SHARED)
        pending = &child->signal->shared_pending;
@@ -711,18 +715,20 @@ static int ptrace_peek_siginfo(struct task_struct *child,

    for (i = 0; i <; ) {
        siginfo_t info;
-       s32 off = + i;
+       unsigned long off = + i;
+       bool found = false;

        list_for_each_entry(q, &pending->list, list) {
            if (!off--) {
+               found = true;
                copy_siginfo(&info, &q->info);

-       if (off >= 0) /* beyond the end of the list */
+       if (!found) /* beyond the end of the list */


Leave a Reply

Your email address will not be published. Required fields are marked *