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                     */
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to