Date: Wed, 21 Sep 2016 08:23:33 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r306081 - in head/sys: compat/freebsd32 kern sys Message-ID: <201609210823.u8L8NX7Y051340@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kib Date: Wed Sep 21 08:23:33 2016 New Revision: 306081 URL: https://svnweb.freebsd.org/changeset/base/306081 Log: Add PROC_TRAPCAP procctl(2) controls and global sysctl kern.trap_enocap. Both can be used to cause processes in capability mode to receive SIGTRAP when ENOTCAPABLE or ECAPMODE errors are returned from syscalls. Idea by: emaste Reviewed by: oshogbo (previous version), emaste Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D7965 Modified: head/sys/compat/freebsd32/freebsd32_misc.c head/sys/kern/kern_fork.c head/sys/kern/kern_procctl.c head/sys/kern/subr_syscall.c head/sys/kern/sys_capability.c head/sys/sys/capsicum.h head/sys/sys/proc.h head/sys/sys/procctl.h head/sys/sys/signal.h Modified: head/sys/compat/freebsd32/freebsd32_misc.c ============================================================================== --- head/sys/compat/freebsd32/freebsd32_misc.c Wed Sep 21 08:14:55 2016 (r306080) +++ head/sys/compat/freebsd32/freebsd32_misc.c Wed Sep 21 08:23:33 2016 (r306081) @@ -3048,6 +3048,7 @@ freebsd32_procctl(struct thread *td, str switch (uap->com) { case PROC_SPROTECT: case PROC_TRACE_CTL: + case PROC_TRAPCAP_CTL: error = copyin(PTRIN(uap->data), &flags, sizeof(flags)); if (error != 0) return (error); @@ -3077,6 +3078,7 @@ freebsd32_procctl(struct thread *td, str data = &x.rk; break; case PROC_TRACE_STATUS: + case PROC_TRAPCAP_STATUS: data = &flags; break; default: @@ -3095,6 +3097,7 @@ freebsd32_procctl(struct thread *td, str error = error1; break; case PROC_TRACE_STATUS: + case PROC_TRAPCAP_STATUS: if (error == 0) error = copyout(&flags, uap->data, sizeof(flags)); break; Modified: head/sys/kern/kern_fork.c ============================================================================== --- head/sys/kern/kern_fork.c Wed Sep 21 08:14:55 2016 (r306080) +++ head/sys/kern/kern_fork.c Wed Sep 21 08:23:33 2016 (r306081) @@ -497,7 +497,7 @@ do_fork(struct thread *td, struct fork_r * Increase reference counts on shared objects. */ p2->p_flag = P_INMEM; - p2->p_flag2 = p1->p_flag2 & (P2_NOTRACE | P2_NOTRACE_EXEC); + p2->p_flag2 = p1->p_flag2 & (P2_NOTRACE | P2_NOTRACE_EXEC | P2_TRAPCAP); p2->p_swtick = ticks; if (p1->p_flag & P_PROFIL) startprofclock(p2); Modified: head/sys/kern/kern_procctl.c ============================================================================== --- head/sys/kern/kern_procctl.c Wed Sep 21 08:14:55 2016 (r306080) +++ head/sys/kern/kern_procctl.c Wed Sep 21 08:23:33 2016 (r306081) @@ -336,6 +336,34 @@ trace_status(struct thread *td, struct p return (0); } +static int +trapcap_ctl(struct thread *td, struct proc *p, int state) +{ + + PROC_LOCK_ASSERT(p, MA_OWNED); + + switch (state) { + case PROC_TRAPCAP_CTL_ENABLE: + p->p_flag2 |= P2_TRAPCAP; + break; + case PROC_TRAPCAP_CTL_DISABLE: + p->p_flag2 &= ~P2_TRAPCAP; + break; + default: + return (EINVAL); + } + return (0); +} + +static int +trapcap_status(struct thread *td, struct proc *p, int *data) +{ + + *data = (p->p_flag2 & P2_TRAPCAP) != 0 ? PROC_TRAPCAP_CTL_ENABLE : + PROC_TRAPCAP_CTL_DISABLE; + return (0); +} + #ifndef _SYS_SYSPROTO_H_ struct procctl_args { idtype_t idtype; @@ -359,6 +387,7 @@ sys_procctl(struct thread *td, struct pr switch (uap->com) { case PROC_SPROTECT: case PROC_TRACE_CTL: + case PROC_TRAPCAP_CTL: error = copyin(uap->data, &flags, sizeof(flags)); if (error != 0) return (error); @@ -386,6 +415,7 @@ sys_procctl(struct thread *td, struct pr data = &x.rk; break; case PROC_TRACE_STATUS: + case PROC_TRAPCAP_STATUS: data = &flags; break; default: @@ -403,6 +433,7 @@ sys_procctl(struct thread *td, struct pr error = error1; break; case PROC_TRACE_STATUS: + case PROC_TRAPCAP_STATUS: if (error == 0) error = copyout(&flags, uap->data, sizeof(flags)); break; @@ -432,6 +463,10 @@ kern_procctl_single(struct thread *td, s return (trace_ctl(td, p, *(int *)data)); case PROC_TRACE_STATUS: return (trace_status(td, p, data)); + case PROC_TRAPCAP_CTL: + return (trapcap_ctl(td, p, *(int *)data)); + case PROC_TRAPCAP_STATUS: + return (trapcap_status(td, p, data)); default: return (EINVAL); } @@ -452,6 +487,7 @@ kern_procctl(struct thread *td, idtype_t case PROC_REAP_GETPIDS: case PROC_REAP_KILL: case PROC_TRACE_STATUS: + case PROC_TRAPCAP_STATUS: if (idtype != P_PID) return (EINVAL); } @@ -462,6 +498,7 @@ kern_procctl(struct thread *td, idtype_t case PROC_REAP_GETPIDS: case PROC_REAP_KILL: case PROC_TRACE_CTL: + case PROC_TRAPCAP_CTL: sx_slock(&proctree_lock); tree_locked = true; break; @@ -471,6 +508,7 @@ kern_procctl(struct thread *td, idtype_t tree_locked = true; break; case PROC_TRACE_STATUS: + case PROC_TRAPCAP_STATUS: tree_locked = false; break; default: Modified: head/sys/kern/subr_syscall.c ============================================================================== --- head/sys/kern/subr_syscall.c Wed Sep 21 08:14:55 2016 (r306080) +++ head/sys/kern/subr_syscall.c Wed Sep 21 08:23:33 2016 (r306081) @@ -165,12 +165,25 @@ static inline void syscallret(struct thread *td, int error, struct syscall_args *sa) { struct proc *p, *p2; - int traced; + ksiginfo_t ksi; + int traced, error1; KASSERT((td->td_pflags & TDP_FORKING) == 0, ("fork() did not clear TDP_FORKING upon completion")); p = td->td_proc; + if ((trap_enotcap || (p->p_flag2 & P2_TRAPCAP) != 0) && + IN_CAPABILITY_MODE(td)) { + error1 = (td->td_pflags & TDP_NERRNO) == 0 ? error : + td->td_errno; + if (error1 == ENOTCAPABLE || error1 == ECAPMODE) { + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = SIGTRAP; + ksi.ksi_errno = error1; + ksi.ksi_code = TRAP_CAP; + trapsignal(td, &ksi); + } + } /* * Handle reschedule and other end-of-syscall issues Modified: head/sys/kern/sys_capability.c ============================================================================== --- head/sys/kern/sys_capability.c Wed Sep 21 08:14:55 2016 (r306080) +++ head/sys/kern/sys_capability.c Wed Sep 21 08:23:33 2016 (r306081) @@ -83,6 +83,10 @@ __FBSDID("$FreeBSD$"); #include <vm/uma.h> #include <vm/vm.h> +int trap_enotcap; +SYSCTL_INT(_kern, OID_AUTO, trap_enotcap, CTLFLAG_RW, &trap_enotcap, 0, + "Deliver SIGTRAP on ENOTCAPABLE"); + #ifdef CAPABILITY_MODE FEATURE(security_capability_mode, "Capsicum Capability Mode"); Modified: head/sys/sys/capsicum.h ============================================================================== --- head/sys/sys/capsicum.h Wed Sep 21 08:14:55 2016 (r306080) +++ head/sys/sys/capsicum.h Wed Sep 21 08:23:33 2016 (r306081) @@ -368,6 +368,8 @@ int cap_ioctl_check(struct filedesc *fdp int cap_fcntl_check_fde(struct filedescent *fde, int cmd); int cap_fcntl_check(struct filedesc *fdp, int fd, int cmd); +extern int trap_enotcap; + #else /* !_KERNEL */ __BEGIN_DECLS Modified: head/sys/sys/proc.h ============================================================================== --- head/sys/sys/proc.h Wed Sep 21 08:14:55 2016 (r306080) +++ head/sys/sys/proc.h Wed Sep 21 08:23:33 2016 (r306081) @@ -716,6 +716,7 @@ struct proc { #define P2_NOTRACE_EXEC 0x00000004 /* Keep P2_NOPTRACE on exec(2). */ #define P2_AST_SU 0x00000008 /* Handles SU ast for kthreads. */ #define P2_PTRACE_FSTP 0x00000010 /* SIGSTOP from PT_ATTACH not yet handled. */ +#define P2_TRAPCAP 0x00000020 /* SIGTRAP on ENOTCAPABLE */ /* Flags protected by proctree_lock, kept in p_treeflags. */ #define P_TREE_ORPHANED 0x00000001 /* Reparented, on orphan list */ Modified: head/sys/sys/procctl.h ============================================================================== --- head/sys/sys/procctl.h Wed Sep 21 08:14:55 2016 (r306080) +++ head/sys/sys/procctl.h Wed Sep 21 08:23:33 2016 (r306081) @@ -43,6 +43,8 @@ #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 */ +#define PROC_TRAPCAP_CTL 9 /* trap capability errors */ +#define PROC_TRAPCAP_STATUS 10 /* query trap capability status */ /* Operations for PROC_SPROTECT (passed in integer arg). */ #define PPROT_OP(x) ((x) & 0xf) @@ -102,6 +104,9 @@ struct procctl_reaper_kill { #define PROC_TRACE_CTL_DISABLE 2 #define PROC_TRACE_CTL_DISABLE_EXEC 3 +#define PROC_TRAPCAP_CTL_ENABLE 1 +#define PROC_TRAPCAP_CTL_DISABLE 2 + #ifndef _KERNEL __BEGIN_DECLS int procctl(idtype_t, id_t, int, void *); Modified: head/sys/sys/signal.h ============================================================================== --- head/sys/sys/signal.h Wed Sep 21 08:14:55 2016 (r306080) +++ head/sys/sys/signal.h Wed Sep 21 08:23:33 2016 (r306081) @@ -291,6 +291,7 @@ typedef struct __siginfo { #define TRAP_BRKPT 1 /* Process breakpoint. */ #define TRAP_TRACE 2 /* Process trace trap. */ #define TRAP_DTRACE 3 /* DTrace induced trap. */ +#define TRAP_CAP 4 /* Capabilities protective trap. */ /* codes for SIGCHLD */ #define CLD_EXITED 1 /* Child has exited */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201609210823.u8L8NX7Y051340>