Index: lib/libc/sys/procctl.2 =================================================================== --- lib/libc/sys/procctl.2 +++ lib/libc/sys/procctl.2 @@ -430,15 +430,20 @@ .Er ECAPMODE error. If the control is enabled, such errors from the syscalls cause -delivery of the synchronous +delivery of either a synchronous .Dv SIGTRAP +or +.Dv SIGCAP signal to the thread immediately before returning from the syscalls. +The former is useful for debugging processes that are unexpectedly failing in +capability mode, the latter is intended to be caught by the process and used to +handle the failure within the process. .Pp Possible values for the .Fa data argument are: .Bl -tag -width PROC_TRAPCAP_CTL_DISABLE -.It Dv PROC_TRAPCAP_CTL_ENABLE +.It Dv PROC_TRAPCAP_CTL_ENABLE_SIGTRAP Enable the .Dv SIGTRAP signal delivery on capability mode access violations. @@ -446,6 +451,18 @@ and is kept after .Xr fexecve 2 calls. +.It Dv PROC_TRAPCAP_CTL_ENABLE +is an alias for +.Dv PROC_TRAPCAP_CTL_ENABLE_SIGTRAP +for legacy compatibility. +.It Dv PROC_TRAPCAP_CTL_ENABLE_SIGCAP +Enable the +.Dv SIGCAP +signal delivery on capability mode access violations. +The enabled mode is inherited by the children of the process, +and is kept after +.Xr fexecve 2 +calls. .It Dv PROC_TRAPCAP_CTL_DISABLE Disable the signal delivery on capability mode access violations. Note that the global sysctl Index: sys/kern/kern_procctl.c =================================================================== --- sys/kern/kern_procctl.c +++ sys/kern/kern_procctl.c @@ -408,12 +408,24 @@ PROC_LOCK_ASSERT(p, MA_OWNED); state = *(int *)data; - switch (state) { + /* + * The low two bits of the state indicate whether trapping should be + * enabled or disabled (0b01 enable, 0b10 disable). In the enable + * commands, bit 2 indicates whether the signal should be SIGTRAP (0) or + * SIGCAP (1). + */ + switch (state & 3) { case PROC_TRAPCAP_CTL_ENABLE: p->p_flag2 |= P2_TRAPCAP; + if (state == PROC_TRAPCAP_CTL_ENABLE_SIGCAP) { + p->p_flag2 |= P2_SIGCAP; + } else { + p->p_flag2 &= ~P2_SIGCAP; + } break; case PROC_TRAPCAP_CTL_DISABLE: p->p_flag2 &= ~P2_TRAPCAP; + p->p_flag2 &= ~P2_SIGCAP; break; default: return (EINVAL); @@ -427,8 +439,10 @@ int *status; status = data; - *status = (p->p_flag2 & P2_TRAPCAP) != 0 ? PROC_TRAPCAP_CTL_ENABLE : - PROC_TRAPCAP_CTL_DISABLE; + *status = (p->p_flag2 & P2_TRAPCAP) != 0 ? + (((p->p_flag2 & P2_SIGCAP) != 0) ? + PROC_TRAPCAP_CTL_ENABLE_SIGCAP : PROC_TRAPCAP_CTL_ENABLE) : + PROC_TRAPCAP_CTL_DISABLE; return (0); } Index: sys/kern/subr_syscall.c =================================================================== --- sys/kern/subr_syscall.c +++ sys/kern/subr_syscall.c @@ -225,7 +225,8 @@ if ((trap_enotcap || (p->p_flag2 & P2_TRAPCAP) != 0) && IN_CAPABILITY_MODE(td)) { ksiginfo_init_trap(&ksi); - ksi.ksi_signo = SIGTRAP; + ksi.ksi_signo = + ((p->p_flag2 & P2_SIGCAP) == 0) ? SIGTRAP : SIGCAP; ksi.ksi_errno = td->td_errno; ksi.ksi_code = TRAP_CAP; ksi.ksi_info.si_syscall = sa->original_code; Index: sys/sys/proc.h =================================================================== --- sys/sys/proc.h +++ sys/sys/proc.h @@ -841,6 +841,7 @@ #define P2_NO_NEW_PRIVS 0x00008000 /* Ignore setuid */ #define P2_WXORX_DISABLE 0x00010000 /* WX mappings enabled */ #define P2_WXORX_ENABLE_EXEC 0x00020000 /* WXORX enabled after exec */ +#define P2_SIGCAP 0x00040000 /* SIGCAP on ENOTCAPABLE */ /* Flags protected by proctree_lock, kept in p_treeflags. */ #define P_TREE_ORPHANED 0x00000001 /* Reparented, on orphan list */ Index: sys/sys/procctl.h =================================================================== --- sys/sys/procctl.h +++ sys/sys/procctl.h @@ -67,6 +67,8 @@ #define PROC_NO_NEW_PRIVS_STATUS 20 /* query suid/sgid disabled status */ #define PROC_WXMAP_CTL 21 /* control W^X */ #define PROC_WXMAP_STATUS 22 /* query W^X */ +#define PROC_SIGCAP_CTL 23 /* signal on capability errors */ +#define PROC_SIGCAP_STATUS 24 /* query signal on capability status */ /* Operations for PROC_SPROTECT (passed in integer arg). */ #define PPROT_OP(x) ((x) & 0xf) @@ -129,6 +131,8 @@ #define PROC_TRAPCAP_CTL_ENABLE 1 #define PROC_TRAPCAP_CTL_DISABLE 2 +#define PROC_TRAPCAP_CTL_ENABLE_SIGTRAP PROC_TRAPCAP_CTL_ENABLE +#define PROC_TRAPCAP_CTL_ENABLE_SIGCAP (PROC_TRAPCAP_CTL_ENABLE | 4) #define PROC_ASLR_FORCE_ENABLE 1 #define PROC_ASLR_FORCE_DISABLE 2 Index: sys/sys/signal.h =================================================================== --- sys/sys/signal.h +++ sys/sys/signal.h @@ -131,6 +131,7 @@ #define SIGTHR 32 /* reserved by thread library. */ #define SIGLWP SIGTHR #define SIGLIBRT 33 /* reserved by real-time library. */ +#define SIGCAP 34 /* Capsicum violation. */ #endif #define SIGRTMIN 65 Index: usr.bin/proccontrol/proccontrol.c =================================================================== --- usr.bin/proccontrol/proccontrol.c +++ usr.bin/proccontrol/proccontrol.c @@ -232,8 +232,11 @@ break; case MODE_TRAPCAP: switch (arg) { - case PROC_TRAPCAP_CTL_ENABLE: - printf("enabled\n"); + case PROC_TRAPCAP_CTL_ENABLE_SIGTRAP: + printf("enabled, delivering SIGTRAP\n"); + break; + case PROC_TRAPCAP_CTL_ENABLE_SIGCAP: + printf("enabled, delivering SIGCAP\n"); break; case PROC_TRAPCAP_CTL_DISABLE: printf("disabled\n");