Skip site navigation (1)Skip section navigation (2)
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>