Author: kib
Date: Sun Jan 25 13:15:12 2015
New Revision: 277698
URL: https://svnweb.freebsd.org/changeset/base/277698

Log:
  MFC r277322:
  Add procctl(2) PROC_TRACE_CTL command to enable or disable debugger
  attachment to the process.

Modified:
  stable/10/lib/libc/sys/procctl.2
  stable/10/sys/compat/freebsd32/freebsd32_misc.c
  stable/10/sys/kern/kern_exec.c
  stable/10/sys/kern/kern_fork.c
  stable/10/sys/kern/kern_procctl.c
  stable/10/sys/kern/kern_prot.c
  stable/10/sys/kern/kern_sig.c
  stable/10/sys/sys/priv.h
  stable/10/sys/sys/proc.h
  stable/10/sys/sys/procctl.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/lib/libc/sys/procctl.2
==============================================================================
--- stable/10/lib/libc/sys/procctl.2    Sun Jan 25 13:09:53 2015        
(r277697)
+++ stable/10/lib/libc/sys/procctl.2    Sun Jan 25 13:15:12 2015        
(r277698)
@@ -29,7 +29,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd December 16, 2014
+.Dd December 29, 2014
 .Dt PROCCTL 2
 .Os
 .Sh NAME
@@ -275,7 +275,61 @@ delivery failed, e.g. due to the permiss
 If no such process exist, the
 .Fa rk_fpid
 field is set to -1.
+.It Dv PROC_TRACE_CTL
+Enable or disable tracing of the specified process(es), according to the
+value of the integer argument.
+Tracing includes attachment to the process using
+.Xr ptrace 2
+and
+.Xr ktrace 2 ,
+debugging sysctls,
+.Xr hwpmc 4 ,
+.Xr dtrace 1
+and core dumping.
+Possible values for the
+.Fa data
+argument are:
+.Bl -tag -width "Dv PROC_TRACE_CTL_DISABLE_EXEC"
+.It Dv PROC_TRACE_CTL_ENABLE
+Enable tracing, after it was disabled by
+.Dv PROC_TRACE_CTL_DISABLE .
+Only allowed for self.
+.It Dv PROC_TRACE_CTL_DISABLE
+Disable tracing for the specified process.
+Tracing is re-enabled when the process changes the executing
+program with
+.Xr execve 2
+syscall.
+A child inherits the trace settings from the parent on
+.Xr fork 2 .
+.It Dv PROC_TRACE_CTL_DISABLE_EXEC
+Same as
+.Dv PROC_TRACE_CTL_DISABLE ,
+but the setting persist for the process even after
+.Xr execve 2 .
+.El
+.It Dv PROC_TRACE_STATUS
+Returns the current tracing status for the specified process in
+the integer variable pointed to by
+.Fa data .
+If tracing is disabled,
+.Fa data
+is set to -1.
+If tracing is enabled, but no debugger is attached by
+.Xr ptrace 2
+syscall,
+.Fa data
+is set to 0.
+If a debugger is attached,
+.Fa data
+is set to the pid of the debugger process.
 .El
+.Sh NOTES
+Disabling tracing on a process should not be considered a security
+feature, as it is bypassable both by the kernel and privileged processes,
+and via other system mechanisms.
+As such, it should not be relied on to reliably protect cryptographic
+keying material or other confidential data.
 .Sh RETURN VALUES
 If an error occurs, a value of -1 is returned and
 .Va errno
@@ -343,11 +397,34 @@ The
 .Dv PROC_REAP_ACQUIRE
 request was issued by a process that had already acquired reaper status
 and has not yet released it.
+.It Bq Er EBUSY
+The
+.Dv PROC_TRACE_CTL
+request was issued for a process already being traced.
+.It Bq Er EPERM
+The
+.Dv PROC_TRACE_CTL
+request to re-enable tracing of the process (
+.Dv PROC_TRACE_CTL_ENABLE ) ,
+or to disable persistence of the
+.Dv PROC_TRACE_CTL_DISABLE
+on
+.Xr execve 2
+was issued for a non-current process.
+.It Bq Er EINVAL
+The value of the integer
+.Fa data
+parameter for the
+.Dv PROC_TRACE_CTL
+request is invalid.
 .El
 .Sh SEE ALSO
+.Xr dtrace 1 ,
 .Xr kill 2 ,
+.Xr ktrace 2 ,
 .Xr ptrace 2 ,
 .Xr wait 2 ,
+.Xr hwpmc 4 ,
 .Xr init 8
 .Sh HISTORY
 The

Modified: stable/10/sys/compat/freebsd32/freebsd32_misc.c
==============================================================================
--- stable/10/sys/compat/freebsd32/freebsd32_misc.c     Sun Jan 25 13:09:53 
2015        (r277697)
+++ stable/10/sys/compat/freebsd32/freebsd32_misc.c     Sun Jan 25 13:15:12 
2015        (r277698)
@@ -3074,6 +3074,7 @@ freebsd32_procctl(struct thread *td, str
 
        switch (uap->com) {
        case PROC_SPROTECT:
+       case PROC_TRACE_CTL:
                error = copyin(PTRIN(uap->data), &flags, sizeof(flags));
                if (error != 0)
                        return (error);
@@ -3102,6 +3103,9 @@ freebsd32_procctl(struct thread *td, str
                        return (error);
                data = &x.rk;
                break;
+       case PROC_TRACE_STATUS:
+               data = &flags;
+               break;
        default:
                return (EINVAL);
        }
@@ -3117,6 +3121,10 @@ freebsd32_procctl(struct thread *td, str
                if (error == 0)
                        error = error1;
                break;
+       case PROC_TRACE_STATUS:
+               if (error == 0)
+                       error = copyout(&flags, uap->data, sizeof(flags));
+               break;
        }
        return (error);
 }

Modified: stable/10/sys/kern/kern_exec.c
==============================================================================
--- stable/10/sys/kern/kern_exec.c      Sun Jan 25 13:09:53 2015        
(r277697)
+++ stable/10/sys/kern/kern_exec.c      Sun Jan 25 13:15:12 2015        
(r277698)
@@ -658,6 +658,8 @@ interpret:
         * it that it now has its own resources back
         */
        p->p_flag |= P_EXEC;
+       if ((p->p_flag2 & P2_NOTRACE_EXEC) == 0)
+               p->p_flag2 &= ~P2_NOTRACE;
        if (p->p_flag & P_PPWAIT) {
                p->p_flag &= ~(P_PPWAIT | P_PPTRACE);
                cv_broadcast(&p->p_pwait);

Modified: stable/10/sys/kern/kern_fork.c
==============================================================================
--- stable/10/sys/kern/kern_fork.c      Sun Jan 25 13:09:53 2015        
(r277697)
+++ stable/10/sys/kern/kern_fork.c      Sun Jan 25 13:15:12 2015        
(r277698)
@@ -501,7 +501,7 @@ do_fork(struct thread *td, int flags, st
         * Increase reference counts on shared objects.
         */
        p2->p_flag = P_INMEM;
-       p2->p_flag2 = 0;
+       p2->p_flag2 = p1->p_flag2 & (P2_NOTRACE | P2_NOTRACE_EXEC);
        p2->p_swtick = ticks;
        if (p1->p_flag & P_PROFIL)
                startprofclock(p2);

Modified: stable/10/sys/kern/kern_procctl.c
==============================================================================
--- stable/10/sys/kern/kern_procctl.c   Sun Jan 25 13:09:53 2015        
(r277697)
+++ stable/10/sys/kern/kern_procctl.c   Sun Jan 25 13:15:12 2015        
(r277698)
@@ -280,6 +280,62 @@ reap_kill(struct thread *td, struct proc
        return (error);
 }
 
+static int
+trace_ctl(struct thread *td, struct proc *p, int state)
+{
+
+       PROC_LOCK_ASSERT(p, MA_OWNED);
+
+       /*
+        * Ktrace changes p_traceflag from or to zero under the
+        * process lock, so the test does not need to acquire ktrace
+        * mutex.
+        */
+       if ((p->p_flag & P_TRACED) != 0 || p->p_traceflag != 0)
+               return (EBUSY);
+
+       switch (state) {
+       case PROC_TRACE_CTL_ENABLE:
+               if (td->td_proc != p)
+                       return (EPERM);
+               p->p_flag2 &= ~(P2_NOTRACE | P2_NOTRACE_EXEC);
+               break;
+       case PROC_TRACE_CTL_DISABLE_EXEC:
+               p->p_flag2 |= P2_NOTRACE_EXEC | P2_NOTRACE;
+               break;
+       case PROC_TRACE_CTL_DISABLE:
+               if ((p->p_flag2 & P2_NOTRACE_EXEC) != 0) {
+                       KASSERT((p->p_flag2 & P2_NOTRACE) != 0,
+                           ("dandling P2_NOTRACE_EXEC"));
+                       if (td->td_proc != p)
+                               return (EPERM);
+                       p->p_flag2 &= ~P2_NOTRACE_EXEC;
+               } else {
+                       p->p_flag2 |= P2_NOTRACE;
+               }
+               break;
+       default:
+               return (EINVAL);
+       }
+       return (0);
+}
+
+static int
+trace_status(struct thread *td, struct proc *p, int *data)
+{
+
+       if ((p->p_flag2 & P2_NOTRACE) != 0) {
+               KASSERT((p->p_flag & P_TRACED) == 0,
+                   ("%d traced but tracing disabled", p->p_pid));
+               *data = -1;
+       } else if ((p->p_flag & P_TRACED) != 0) {
+               *data = p->p_pptr->p_pid;
+       } else {
+               *data = 0;
+       }
+       return (0);
+}
+
 #ifndef _SYS_SYSPROTO_H_
 struct procctl_args {
        idtype_t idtype;
@@ -302,6 +358,7 @@ sys_procctl(struct thread *td, struct pr
 
        switch (uap->com) {
        case PROC_SPROTECT:
+       case PROC_TRACE_CTL:
                error = copyin(uap->data, &flags, sizeof(flags));
                if (error != 0)
                        return (error);
@@ -328,6 +385,9 @@ sys_procctl(struct thread *td, struct pr
                        return (error);
                data = &x.rk;
                break;
+       case PROC_TRACE_STATUS:
+               data = &flags;
+               break;
        default:
                return (EINVAL);
        }
@@ -342,6 +402,10 @@ sys_procctl(struct thread *td, struct pr
                if (error == 0)
                        error = error1;
                break;
+       case PROC_TRACE_STATUS:
+               if (error == 0)
+                       error = copyout(&flags, uap->data, sizeof(flags));
+               break;
        }
        return (error);
 }
@@ -364,6 +428,10 @@ kern_procctl_single(struct thread *td, s
                return (reap_getpids(td, p, data));
        case PROC_REAP_KILL:
                return (reap_kill(td, p, data));
+       case PROC_TRACE_CTL:
+               return (trace_ctl(td, p, *(int *)data));
+       case PROC_TRACE_STATUS:
+               return (trace_status(td, p, data));
        default:
                return (EINVAL);
        }
@@ -375,6 +443,7 @@ kern_procctl(struct thread *td, idtype_t
        struct pgrp *pg;
        struct proc *p;
        int error, first_error, ok;
+       bool tree_locked;
 
        switch (com) {
        case PROC_REAP_ACQUIRE:
@@ -382,6 +451,7 @@ kern_procctl(struct thread *td, idtype_t
        case PROC_REAP_STATUS:
        case PROC_REAP_GETPIDS:
        case PROC_REAP_KILL:
+       case PROC_TRACE_STATUS:
                if (idtype != P_PID)
                        return (EINVAL);
        }
@@ -391,11 +461,17 @@ kern_procctl(struct thread *td, idtype_t
        case PROC_REAP_STATUS:
        case PROC_REAP_GETPIDS:
        case PROC_REAP_KILL:
+       case PROC_TRACE_CTL:
                sx_slock(&proctree_lock);
+               tree_locked = true;
                break;
        case PROC_REAP_ACQUIRE:
        case PROC_REAP_RELEASE:
                sx_xlock(&proctree_lock);
+               tree_locked = true;
+               break;
+       case PROC_TRACE_STATUS:
+               tree_locked = false;
                break;
        default:
                return (EINVAL);
@@ -456,6 +532,7 @@ kern_procctl(struct thread *td, idtype_t
                error = EINVAL;
                break;
        }
-       sx_unlock(&proctree_lock);
+       if (tree_locked)
+               sx_unlock(&proctree_lock);
        return (error);
 }

Modified: stable/10/sys/kern/kern_prot.c
==============================================================================
--- stable/10/sys/kern/kern_prot.c      Sun Jan 25 13:09:53 2015        
(r277697)
+++ stable/10/sys/kern/kern_prot.c      Sun Jan 25 13:15:12 2015        
(r277698)
@@ -1711,6 +1711,13 @@ p_candebug(struct thread *td, struct pro
        if ((p->p_flag & P_INEXEC) != 0)
                return (EBUSY);
 
+       /* Denied explicitely */
+       if ((p->p_flag2 & P2_NOTRACE) != 0) {
+               error = priv_check(td, PRIV_DEBUG_DENIED);
+               if (error != 0)
+                       return (error);
+       }
+
        return (0);
 }
 

Modified: stable/10/sys/kern/kern_sig.c
==============================================================================
--- stable/10/sys/kern/kern_sig.c       Sun Jan 25 13:09:53 2015        
(r277697)
+++ stable/10/sys/kern/kern_sig.c       Sun Jan 25 13:15:12 2015        
(r277698)
@@ -3257,7 +3257,8 @@ coredump(struct thread *td)
        MPASS((p->p_flag & P_HADTHREADS) == 0 || p->p_singlethread == td);
        _STOPEVENT(p, S_CORE, 0);
 
-       if (!do_coredump || (!sugid_coredump && (p->p_flag & P_SUGID) != 0)) {
+       if (!do_coredump || (!sugid_coredump && (p->p_flag & P_SUGID) != 0) ||
+           (p->p_flag2 & P2_NOTRACE) != 0) {
                PROC_UNLOCK(p);
                return (EFAULT);
        }

Modified: stable/10/sys/sys/priv.h
==============================================================================
--- stable/10/sys/sys/priv.h    Sun Jan 25 13:09:53 2015        (r277697)
+++ stable/10/sys/sys/priv.h    Sun Jan 25 13:15:12 2015        (r277698)
@@ -111,6 +111,7 @@
 #define        PRIV_DEBUG_DIFFCRED     80      /* Exempt debugging other 
users. */
 #define        PRIV_DEBUG_SUGID        81      /* Exempt debugging setuid 
proc. */
 #define        PRIV_DEBUG_UNPRIV       82      /* Exempt unprivileged debug 
limit. */
+#define        PRIV_DEBUG_DENIED       83      /* Exempt P2_NOTRACE. */
 
 /*
  * Dtrace privileges.

Modified: stable/10/sys/sys/proc.h
==============================================================================
--- stable/10/sys/sys/proc.h    Sun Jan 25 13:09:53 2015        (r277697)
+++ stable/10/sys/sys/proc.h    Sun Jan 25 13:15:12 2015        (r277698)
@@ -651,6 +651,8 @@ struct proc {
 
 /* These flags are kept in p_flag2. */
 #define        P2_INHERIT_PROTECTED 0x00000001 /* New children get 
P_PROTECTED. */
+#define        P2_NOTRACE      0x00000002      /* No ptrace(2) attach or 
coredumps. */
+#define        P2_NOTRACE_EXEC 0x00000004      /* Keep P2_NOPTRACE on exec(2). 
*/
 
 /* Flags protected by proctree_lock, kept in p_treeflags. */
 #define        P_TREE_ORPHANED         0x00000001      /* Reparented, on 
orphan list */

Modified: stable/10/sys/sys/procctl.h
==============================================================================
--- stable/10/sys/sys/procctl.h Sun Jan 25 13:09:53 2015        (r277697)
+++ stable/10/sys/sys/procctl.h Sun Jan 25 13:15:12 2015        (r277698)
@@ -41,6 +41,8 @@
 #define        PROC_REAP_STATUS        4       /* reaping status */
 #define        PROC_REAP_GETPIDS       5       /* get descendants */
 #define        PROC_REAP_KILL          6       /* kill descendants */
+#define        PROC_TRACE_CTL          7       /* en/dis ptrace and coredumps 
*/
+#define        PROC_TRACE_STATUS       8       /* query tracing status */
 
 /* Operations for PROC_SPROTECT (passed in integer arg). */
 #define        PPROT_OP(x)     ((x) & 0xf)
@@ -96,6 +98,10 @@ struct procctl_reaper_kill {
 #define        REAPER_KILL_CHILDREN    0x00000001
 #define        REAPER_KILL_SUBTREE     0x00000002
 
+#define        PROC_TRACE_CTL_ENABLE           1
+#define        PROC_TRACE_CTL_DISABLE          2
+#define        PROC_TRACE_CTL_DISABLE_EXEC     3
+
 #ifndef _KERNEL
 __BEGIN_DECLS
 int    procctl(idtype_t, id_t, int, void *);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to