diff --git a/lib/libc/gen/signal.3 b/lib/libc/gen/signal.3 --- a/lib/libc/gen/signal.3 +++ b/lib/libc/gen/signal.3 @@ -133,6 +133,7 @@ .It 31 Ta Dv SIGUSR2 Ta "terminate process" Ta "User defined signal 2" .It 32 Ta Dv SIGTHR Ta "terminate process" Ta "thread interrupt" .It 33 Ta Dv SIGLIBRT Ta "terminate process" Ta "real-time library interrupt" +.It 34 Ta Dv SIGCAP Ta "terminate process" Ta "Capsicum violation" .El .Pp The @@ -260,6 +261,7 @@ .Xr fpsetmask 3 , .Xr setjmp 3 , .Xr siginterrupt 3 , +.Xr capsicum 4 , .Xr tty 4 .Sh HISTORY The diff --git a/lib/libc/sys/procctl.2 b/lib/libc/sys/procctl.2 --- a/lib/libc/sys/procctl.2 +++ b/lib/libc/sys/procctl.2 @@ -430,15 +430,21 @@ .Er ECAPMODE error. If the control is enabled, such errors from the syscalls cause -delivery of the synchronous +synchronous delivery of either a .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 +452,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 diff --git a/sys/kern/kern_procctl.c b/sys/kern/kern_procctl.c --- a/sys/kern/kern_procctl.c +++ b/sys/kern/kern_procctl.c @@ -616,12 +616,27 @@ PROC_LOCK_ASSERT(p, MA_OWNED); state = *(int *)data; - switch (state) { + if ((state & ~3) == 0) { + return (EINVAL); + } + + /* + * 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_TRAPCAP | P2_SIGCAP); break; default: return (EINVAL); @@ -635,8 +650,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); } diff --git a/sys/kern/subr_syscall.c b/sys/kern/subr_syscall.c --- a/sys/kern/subr_syscall.c +++ b/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; diff --git a/sys/sys/proc.h b/sys/sys/proc.h --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -880,6 +880,7 @@ #define P2_WEXIT 0x00040000 /* exit just started, no external thread_single() is permitted */ +#define P2_SIGCAP 0x00080000 /* SIGCAP on ENOTCAPABLE */ /* Flags protected by proctree_lock, kept in p_treeflags. */ #define P_TREE_ORPHANED 0x00000001 /* Reparented, on orphan list */ diff --git a/sys/sys/procctl.h b/sys/sys/procctl.h --- a/sys/sys/procctl.h +++ b/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 diff --git a/sys/sys/signal.h b/sys/sys/signal.h --- a/sys/sys/signal.h +++ b/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 diff --git a/usr.bin/proccontrol/proccontrol.c b/usr.bin/proccontrol/proccontrol.c --- a/usr.bin/proccontrol/proccontrol.c +++ b/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");