Date: Sun, 25 Jan 2015 13:15:12 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r277698 - in stable/10: lib/libc/sys sys/compat/freebsd32 sys/kern sys/sys Message-ID: <201501251315.t0PDFCuj064152@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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 *);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201501251315.t0PDFCuj064152>