Index: head/sys/compat/freebsd32/freebsd32_misc.c =================================================================== --- head/sys/compat/freebsd32/freebsd32_misc.c +++ head/sys/compat/freebsd32/freebsd32_misc.c @@ -3048,6 +3048,7 @@ 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 @@ data = &x.rk; break; case PROC_TRACE_STATUS: + case PROC_TRAPCAP_STATUS: data = &flags; break; default: @@ -3095,6 +3097,7 @@ error = error1; break; case PROC_TRACE_STATUS: + case PROC_TRAPCAP_STATUS: if (error == 0) error = copyout(&flags, uap->data, sizeof(flags)); break; Index: head/sys/kern/kern_fork.c =================================================================== --- head/sys/kern/kern_fork.c +++ head/sys/kern/kern_fork.c @@ -497,7 +497,7 @@ * 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); Index: head/sys/kern/kern_procctl.c =================================================================== --- head/sys/kern/kern_procctl.c +++ head/sys/kern/kern_procctl.c @@ -336,6 +336,34 @@ 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 @@ 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 @@ data = &x.rk; break; case PROC_TRACE_STATUS: + case PROC_TRAPCAP_STATUS: data = &flags; break; default: @@ -403,6 +433,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ tree_locked = true; break; case PROC_TRACE_STATUS: + case PROC_TRAPCAP_STATUS: tree_locked = false; break; default: Index: head/sys/kern/subr_syscall.c =================================================================== --- head/sys/kern/subr_syscall.c +++ head/sys/kern/subr_syscall.c @@ -165,12 +165,25 @@ 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 Index: head/sys/kern/sys_capability.c =================================================================== --- head/sys/kern/sys_capability.c +++ head/sys/kern/sys_capability.c @@ -83,6 +83,10 @@ #include #include +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"); Index: head/sys/sys/capsicum.h =================================================================== --- head/sys/sys/capsicum.h +++ head/sys/sys/capsicum.h @@ -368,6 +368,8 @@ 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 Index: head/sys/sys/proc.h =================================================================== --- head/sys/sys/proc.h +++ head/sys/sys/proc.h @@ -716,6 +716,7 @@ #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 */ Index: head/sys/sys/procctl.h =================================================================== --- head/sys/sys/procctl.h +++ head/sys/sys/procctl.h @@ -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 @@ #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 *); Index: head/sys/sys/signal.h =================================================================== --- head/sys/sys/signal.h +++ head/sys/sys/signal.h @@ -291,6 +291,7 @@ #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 */