Source-Changes-HG archive

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

[src/trunk]: src/sys Add support for PTRACE_POSIX_SPAWN to report posix_spawn...



details:   https://anonhg.NetBSD.org/src/rev/d7f65eb578d5
branches:  trunk
changeset: 451909:d7f65eb578d5
user:      kamil <kamil%NetBSD.org@localhost>
date:      Tue Jun 11 23:18:55 2019 +0000

description:
Add support for PTRACE_POSIX_SPAWN to report posix_spawn(3) events

posix_spawn(3) is a first class syscall in NetBSD, different to
(V)FORK+EXEC as these operations are executed in one go. This differs to
Linux and FreeBSD, where posix_spawn(3) is implemented with existing kernel
primitives (clone(2), vfork(2), exec(3)) inside libc.

Typically LLDB and GDB software is aware of FORK/VFORK events. As discussed
with the LLDB community, instead of slicing the posix_spawn(3) operation
into phases emulating (V)FORK+EXEC(+VFORK_DONE) and returning intermediate
state to the debugger, that might have abnormal state, introduce new event
type: PTRACE_POSIX_SPAWN.

A debugger implementor can easily map it into existing fork+exec semantics
or treat as a distinct event.

There is no functional change for existing debuggers as there was no
support for reporting posix_spawn(3) events on the kernel side.

diffstat:

 sys/kern/kern_exec.c         |  77 +++++++++++++++++++++++++++++++++----------
 sys/kern/kern_proc.c         |   5 +-
 sys/kern/sys_ptrace_common.c |  16 ++++++++-
 sys/sys/proc.h               |   5 ++-
 sys/sys/ptrace.h             |   3 +-
 5 files changed, 81 insertions(+), 25 deletions(-)

diffs (truncated from 323 to 300 lines):

diff -r a01d9dc97ea6 -r d7f65eb578d5 sys/kern/kern_exec.c
--- a/sys/kern/kern_exec.c      Tue Jun 11 17:26:09 2019 +0000
+++ b/sys/kern/kern_exec.c      Tue Jun 11 23:18:55 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_exec.c,v 1.465 2019/05/09 20:50:14 kamil Exp $    */
+/*     $NetBSD: kern_exec.c,v 1.466 2019/06/11 23:18:55 kamil Exp $    */
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -59,7 +59,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.465 2019/05/09 20:50:14 kamil Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.466 2019/06/11 23:18:55 kamil Exp $");
 
 #include "opt_exec.h"
 #include "opt_execfmt.h"
@@ -74,6 +74,7 @@
 #include <sys/filedesc.h>
 #include <sys/kernel.h>
 #include <sys/proc.h>
+#include <sys/ptrace.h>
 #include <sys/mount.h>
 #include <sys/kmem.h>
 #include <sys/namei.h>
@@ -1269,7 +1270,8 @@
 
        mutex_enter(proc_lock);
 
-       if (p->p_slflag & PSL_TRACED) {
+       /* posix_spawn(3) reports a single event with implied exec(3) */
+       if ((p->p_slflag & PSL_TRACED) && !is_spawn) {
                mutex_enter(p->p_lock);
                eventswitch(TRAP_EXEC);
                mutex_enter(proc_lock);
@@ -1984,6 +1986,7 @@
 {
        struct spawn_exec_data *spawn_data = arg;
        struct lwp *l = curlwp;
+       struct proc *p = l->l_proc;
        int error, newfd;
        int ostat;
        size_t i;
@@ -2013,7 +2016,7 @@
        }
 
        /* don't allow debugger access yet */
-       rw_enter(&l->l_proc->p_reflock, RW_WRITER);
+       rw_enter(&p->p_reflock, RW_WRITER);
        have_reflock = true;
 
        error = 0;
@@ -2072,16 +2075,16 @@
                 * parent's p_nstopchild here.  For safety, just make
                 * we're on the good side of SDEAD before we adjust.
                 */
-               ostat = l->l_proc->p_stat;
+               ostat = p->p_stat;
                KASSERT(ostat < SSTOP);
-               l->l_proc->p_stat = SSTOP;
-               l->l_proc->p_waited = 0;
-               l->l_proc->p_pptr->p_nstopchild++;
+               p->p_stat = SSTOP;
+               p->p_waited = 0;
+               p->p_pptr->p_nstopchild++;
                mutex_exit(proc_lock);
 
                /* Set process group */
                if (spawn_data->sed_attrs->sa_flags & POSIX_SPAWN_SETPGROUP) {
-                       pid_t mypid = l->l_proc->p_pid,
+                       pid_t mypid = p->p_pid,
                             pgrp = spawn_data->sed_attrs->sa_pgroup;
 
                        if (pgrp == 0)
@@ -2095,7 +2098,7 @@
 
                /* Set scheduler policy */
                if (spawn_data->sed_attrs->sa_flags & POSIX_SPAWN_SETSCHEDULER)
-                       error = do_sched_setparam(l->l_proc->p_pid, 0,
+                       error = do_sched_setparam(p->p_pid, 0,
                            spawn_data->sed_attrs->sa_schedpolicy,
                            &spawn_data->sed_attrs->sa_schedparam);
                else if (spawn_data->sed_attrs->sa_flags
@@ -2122,10 +2125,10 @@
 
                /* Set signal masks/defaults */
                if (spawn_data->sed_attrs->sa_flags & POSIX_SPAWN_SETSIGMASK) {
-                       mutex_enter(l->l_proc->p_lock);
+                       mutex_enter(p->p_lock);
                        error = sigprocmask1(l, SIG_SETMASK,
                            &spawn_data->sed_attrs->sa_sigmask, NULL);
-                       mutex_exit(l->l_proc->p_lock);
+                       mutex_exit(p->p_lock);
                        if (error)
                                goto report_error_stopped;
                }
@@ -2149,8 +2152,8 @@
                        }
                }
                mutex_enter(proc_lock);
-               l->l_proc->p_stat = ostat;
-               l->l_proc->p_pptr->p_nstopchild--;
+               p->p_stat = ostat;
+               p->p_pptr->p_nstopchild--;
                mutex_exit(proc_lock);
        }
 
@@ -2172,6 +2175,19 @@
        /* release our refcount on the data */
        spawn_exec_data_release(spawn_data);
 
+       if (p->p_slflag & PSL_TRACED) {
+               /* Paranoid check */
+               mutex_enter(proc_lock);
+               if (!(p->p_slflag & PSL_TRACED)) {
+                       mutex_exit(proc_lock);
+                       goto cpu_return;
+               }
+
+               mutex_enter(p->p_lock);
+               eventswitch(TRAP_CHLD);
+       }
+
+ cpu_return:
        /* and finally: leave to userland for the first time */
        cpu_spawn_return(l);
 
@@ -2180,8 +2196,8 @@
 
  report_error_stopped:
        mutex_enter(proc_lock);
-       l->l_proc->p_stat = ostat;
-       l->l_proc->p_pptr->p_nstopchild--;
+       p->p_stat = ostat;
+       p->p_pptr->p_nstopchild--;
        mutex_exit(proc_lock);
  report_error:
        if (have_reflock) {
@@ -2191,7 +2207,7 @@
                 * taken ownership of the sed_exec part of spawn_data,
                 * so release/free both here.
                 */
-               rw_exit(&l->l_proc->p_reflock);
+               rw_exit(&p->p_reflock);
                execve_free_data(&spawn_data->sed_exec);
        }
 
@@ -2209,7 +2225,7 @@
        spawn_exec_data_release(spawn_data);
 
        /* done, exit */
-       mutex_enter(l->l_proc->p_lock);
+       mutex_enter(p->p_lock);
        /*
         * Posix explicitly asks for an exit code of 127 if we report
         * errors from the child process - so, unfortunately, there
@@ -2545,6 +2561,13 @@
        LIST_INSERT_HEAD(&p1->p_children, p2, p_sibling);
        p2->p_exitsig = SIGCHLD;        /* signal for parent on exit */
 
+       if ((p1->p_slflag & (PSL_TRACEPOSIX_SPAWN|PSL_TRACED)) ==
+           (PSL_TRACEPOSIX_SPAWN|PSL_TRACED)) {
+               proc_changeparent(p2, p1->p_pptr);
+               p1->p_pspid = p2->p_pid;
+               p2->p_pspid = p1->p_pid;
+       }
+
        LIST_INSERT_AFTER(p1, p2, p_pglist);
        LIST_INSERT_HEAD(&allproc, p2, p_list);
 
@@ -2582,7 +2605,23 @@
        have_exec_lock = false;
 
        *pid_res = pid;
-       return error;
+
+       if (error)
+               return error;
+
+       if (p1->p_slflag & PSL_TRACED) {
+               /* Paranoid check */
+               mutex_enter(proc_lock);
+               if ((p1->p_slflag & (PSL_TRACEPOSIX_SPAWN|PSL_TRACED)) !=
+                   (PSL_TRACEPOSIX_SPAWN|PSL_TRACED)) {
+                       mutex_exit(proc_lock);
+                       return 0;
+               }
+
+               mutex_enter(p1->p_lock);
+               eventswitch(TRAP_CHLD);
+       }
+       return 0;
 
  error_exit:
        if (have_exec_lock) {
diff -r a01d9dc97ea6 -r d7f65eb578d5 sys/kern/kern_proc.c
--- a/sys/kern/kern_proc.c      Tue Jun 11 17:26:09 2019 +0000
+++ b/sys/kern/kern_proc.c      Tue Jun 11 23:18:55 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_proc.c,v 1.232 2019/06/01 19:48:29 kamil Exp $    */
+/*     $NetBSD: kern_proc.c,v 1.233 2019/06/11 23:18:55 kamil Exp $    */
 
 /*-
  * Copyright (c) 1999, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_proc.c,v 1.232 2019/06/01 19:48:29 kamil Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_proc.c,v 1.233 2019/06/11 23:18:55 kamil Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_kstack.h"
@@ -2266,6 +2266,7 @@
        p->p_vfpid_done = psrc->p_vfpid_done;
        p->p_lwp_created = psrc->p_lwp_created;
        p->p_lwp_exited = psrc->p_lwp_exited;
+       p->p_pspid = psrc->p_pspid;
        COND_SET_VALUE(p->p_path, psrc->p_path, allowaddr);
        COND_SET_VALUE(p->p_sigctx, psrc->p_sigctx, allowaddr);
        p->p_nice = psrc->p_nice;
diff -r a01d9dc97ea6 -r d7f65eb578d5 sys/kern/sys_ptrace_common.c
--- a/sys/kern/sys_ptrace_common.c      Tue Jun 11 17:26:09 2019 +0000
+++ b/sys/kern/sys_ptrace_common.c      Tue Jun 11 23:18:55 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sys_ptrace_common.c,v 1.54 2019/05/25 03:20:43 kamil Exp $     */
+/*     $NetBSD: sys_ptrace_common.c,v 1.55 2019/06/11 23:18:55 kamil 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.54 2019/05/25 03:20:43 kamil Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_ptrace_common.c,v 1.55 2019/06/11 23:18:55 kamil Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_ptrace.h"
@@ -627,6 +627,8 @@
            PTRACE_LWP_CREATE : 0;
        pe.pe_set_event |= ISSET(t->p_slflag, PSL_TRACELWP_EXIT) ?
            PTRACE_LWP_EXIT : 0;
+       pe.pe_set_event |= ISSET(t->p_slflag, PSL_TRACEPOSIX_SPAWN) ?
+           PTRACE_POSIX_SPAWN : 0;
        DPRINTF(("%s: lwp=%d event=%#x\n", __func__,
            t->p_sigctx.ps_lwp, pe.pe_set_event));
        return copyout(&pe, addr, sizeof(pe));
@@ -671,6 +673,12 @@
                SET(t->p_slflag, PSL_TRACELWP_EXIT);
        else
                CLR(t->p_slflag, PSL_TRACELWP_EXIT);
+
+       if (pe.pe_set_event & PTRACE_POSIX_SPAWN)
+               SET(t->p_slflag, PSL_TRACEPOSIX_SPAWN);
+       else
+               CLR(t->p_slflag, PSL_TRACEPOSIX_SPAWN);
+
        return 0;
 }
 
@@ -700,6 +708,9 @@
        } else if (t->p_lwp_exited) {
                ps.pe_report_event = PTRACE_LWP_EXIT;
                ps.pe_lwp = t->p_lwp_exited;
+       } else if (t->p_pspid) {
+               ps.pe_report_event = PTRACE_POSIX_SPAWN;
+               ps.pe_other_pid = t->p_pspid;
        }
        DPRINTF(("%s: lwp=%d event=%#x pid=%d lwp=%d\n", __func__,
            t->p_sigctx.ps_lwp, ps.pe_report_event,
@@ -885,6 +896,7 @@
        t->p_vfpid_done = 0;
        t->p_lwp_created = 0;
        t->p_lwp_exited = 0;
+       t->p_pspid = 0;
 
        /* Finally, deliver the requested signal (or none). */
        if (t->p_stat == SSTOP) {
diff -r a01d9dc97ea6 -r d7f65eb578d5 sys/sys/proc.h
--- a/sys/sys/proc.h    Tue Jun 11 17:26:09 2019 +0000
+++ b/sys/sys/proc.h    Tue Jun 11 23:18:55 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: proc.h,v 1.352 2019/04/06 11:54:21 kamil Exp $ */
+/*     $NetBSD: proc.h,v 1.353 2019/06/11 23:18:55 kamil Exp $ */
 
 /*-
  * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -316,6 +316,7 @@
        pid_t           p_vfpid_done;   /* :: vforked done pid */
        lwpid_t         p_lwp_created;  /* :: lwp created */
        lwpid_t         p_lwp_exited;   /* :: lwp exited */
+       pid_t           p_pspid;        /* :: posix_spawn pid */
        char            *p_path;        /* :: full pathname of executable */
 
 /*
@@ -411,6 +412,8 @@
                        0x00000008 /* traced process wants LWP create events */
 #define        PSL_TRACELWP_EXIT       \



Home | Main Index | Thread Index | Old Index