Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-8]: src/sys/kern Pull up following revision(s) (requ...



details:   https://anonhg.NetBSD.org/src/rev/c6ccdc96fe15
branches:  netbsd-8
changeset: 318804:c6ccdc96fe15
user:      martin <martin%NetBSD.org@localhost>
date:      Sat May 05 19:13:21 2018 +0000
description:
Pull up following revision(s) (requested by kamil in ticket #792):

        sys/kern/sys_ptrace_common.c: revision 1.38

Harden the NetBSD PT_TRACE_ME operation

You can't say to the parent of a process to start tracing if:
        (1) the parent is initproc,
        (2) the child is already traced.

Rationale:
 (1) - It has a side effect of being an anti-debugger functionality,
       as we cannot kill initproc (PID1) and reset the traced flag.
     - initproc is not a debugger, raising debugging events from a child
       to initproc can result in at least a stopped/hanging process
       in the system.
 (2) - It does not make sense to be simultanously traced by two debuggers
     - It does not make sense to be traced twice by the same debugger.

Permit enable tracing for a parent that has been chroot(8)ed, as this is
harmless and the parent is already monitoring for child signals.
The same semantics exist in FreeBSD.

If you are looking for an antidebugging trick for old NetBSD (pre 8.0)
or other popular kernels, here is an example:

$ cat antidebug.c
int
main(int argc, char **argv)
{
        pid_t child;
        int rv;
        int n =3D 0;
        child =3D fork();
        if (child =3D=3D 0) {
                while (getppid() !=3D 1)
                        continue;
                rv =3D ptrace(PT_TRACE_ME, 0, 0, 0);
                if (rv !=3D 0)
                        abort();
                printf("Try to detach to me with a debugger!! ");
                printf("haha My PID is %d\n", getpid());
                while (1) {
                        printf("%d\n", n++);
                        sleep(1);
                }
        }
        exit(0);
}

A developer is no longer able to attach GDB, strace or LLDB to this program
without killing the initproc (your favourite system daemon).. this action
would be fatal for the operation of the whole Operating System stability.

Examples from a current non-NetBSD popular kernel:
$ ps -o ppid=3D -p 17904
    1
$ strace -p 17904
strace: attach: ptrace(PTRACE_SEIZE, 17904): Operation not permitted
$ gdb -p 17904
[...]
Attaching to process 17904
warning: process 17904 is already traced by process 1
ptrace: Operation not permitted.
(gdb)
$ lldb-3.9 -p 17904
(lldb) process attach --pid 17904
error: attach failed: unable to attach

On NetBSD 8.0 and newer it is now guaranteed to have an option to kill
a malevolent (fake?) debugger and attach with a new tracer to the process

Sponsored by <The NetBSD Foundation>

diffstat:

 sys/kern/sys_ptrace_common.c |  20 ++++++++++++++++----
 1 files changed, 16 insertions(+), 4 deletions(-)

diffs (48 lines):

diff -r 6d34d960b77c -r c6ccdc96fe15 sys/kern/sys_ptrace_common.c
--- a/sys/kern/sys_ptrace_common.c      Sat May 05 19:07:51 2018 +0000
+++ b/sys/kern/sys_ptrace_common.c      Sat May 05 19:13:21 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sys_ptrace_common.c,v 1.22.2.2 2018/04/12 13:42:48 martin Exp $        */
+/*     $NetBSD: sys_ptrace_common.c,v 1.22.2.3 2018/05/05 19:13:21 martin Exp $        */
 
 /*-
  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -118,7 +118,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sys_ptrace_common.c,v 1.22.2.2 2018/04/12 13:42:48 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_ptrace_common.c,v 1.22.2.3 2018/05/05 19:13:21 martin Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_ptrace.h"
@@ -377,7 +377,19 @@
        /* Make sure we can operate on it. */
        switch (req) {
        case PT_TRACE_ME:
-               /* Saying that you're being traced is always legal. */
+               /*
+                * You can't say to the parent of a process to start tracing if:
+                *      (1) the parent is initproc,
+                */
+               if (p->p_pptr == initproc)
+                       return EPERM;
+
+               /*
+                *      (2) the child is already traced.
+                */
+               if (ISSET(p->p_slflag, PSL_TRACED))
+                       return EBUSY;
+
                return 0;
 
        case PT_ATTACH:
@@ -389,7 +401,7 @@
                        return EINVAL;
 
                /*
-                *  (2) it's a system process
+                *      (2) it's a system process
                 */
                if (t->p_flag & PK_SYSTEM)
                        return EPERM;



Home | Main Index | Thread Index | Old Index