summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2016-09-28 09:28:26 +0000
committerkib <kib@FreeBSD.org>2016-09-28 09:28:26 +0000
commit99323399e34db51f6f54d27305ecdefe904a61cd (patch)
treebd9571099164439fc094a0b984670e3a87bca3f9
parent71f3313e4975419065fd53a1c4cb6a135a94a686 (diff)
downloadFreeBSD-src-99323399e34db51f6f54d27305ecdefe904a61cd.zip
FreeBSD-src-99323399e34db51f6f54d27305ecdefe904a61cd.tar.gz
MFC r306081:
Add PROC_TRAPCAP procctl(2) controls and global sysctl kern.trap_enocap.
-rw-r--r--sys/compat/freebsd32/freebsd32_misc.c3
-rw-r--r--sys/kern/kern_fork.c2
-rw-r--r--sys/kern/kern_procctl.c38
-rw-r--r--sys/kern/subr_syscall.c15
-rw-r--r--sys/kern/sys_capability.c4
-rw-r--r--sys/sys/capsicum.h2
-rw-r--r--sys/sys/proc.h1
-rw-r--r--sys/sys/procctl.h5
-rw-r--r--sys/sys/signal.h1
9 files changed, 69 insertions, 2 deletions
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c
index 893ad98..838d1aa 100644
--- a/sys/compat/freebsd32/freebsd32_misc.c
+++ b/sys/compat/freebsd32/freebsd32_misc.c
@@ -3048,6 +3048,7 @@ freebsd32_procctl(struct thread *td, struct freebsd32_procctl_args *uap)
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, struct freebsd32_procctl_args *uap)
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, struct freebsd32_procctl_args *uap)
error = error1;
break;
case PROC_TRACE_STATUS:
+ case PROC_TRAPCAP_STATUS:
if (error == 0)
error = copyout(&flags, uap->data, sizeof(flags));
break;
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index 818f44b..b288314 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -499,7 +499,7 @@ do_fork(struct thread *td, struct fork_req *fr, struct proc *p2, struct thread *
* 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);
diff --git a/sys/kern/kern_procctl.c b/sys/kern/kern_procctl.c
index 8ef72901..d028e25 100644
--- a/sys/kern/kern_procctl.c
+++ b/sys/kern/kern_procctl.c
@@ -336,6 +336,34 @@ trace_status(struct thread *td, struct proc *p, int *data)
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 procctl_args *uap)
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 procctl_args *uap)
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 procctl_args *uap)
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, struct proc *p, int com, void *data)
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 idtype, id_t id, int com, void *data)
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 idtype, id_t id, int com, void *data)
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 idtype, id_t id, int com, void *data)
tree_locked = true;
break;
case PROC_TRACE_STATUS:
+ case PROC_TRAPCAP_STATUS:
tree_locked = false;
break;
default:
diff --git a/sys/kern/subr_syscall.c b/sys/kern/subr_syscall.c
index 3e2a3b3..822976e 100644
--- a/sys/kern/subr_syscall.c
+++ b/sys/kern/subr_syscall.c
@@ -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
diff --git a/sys/kern/sys_capability.c b/sys/kern/sys_capability.c
index e87f0b1..584d7ee 100644
--- a/sys/kern/sys_capability.c
+++ b/sys/kern/sys_capability.c
@@ -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");
diff --git a/sys/sys/capsicum.h b/sys/sys/capsicum.h
index 8720166..0675100 100644
--- a/sys/sys/capsicum.h
+++ b/sys/sys/capsicum.h
@@ -368,6 +368,8 @@ int cap_ioctl_check(struct filedesc *fdp, int fd, u_long cmd);
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
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index 6252ad0..ebe8302 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -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 */
diff --git a/sys/sys/procctl.h b/sys/sys/procctl.h
index c6f1e94..8d0afc2 100644
--- a/sys/sys/procctl.h
+++ b/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 @@ 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 *);
diff --git a/sys/sys/signal.h b/sys/sys/signal.h
index 86a07e1..a844465 100644
--- a/sys/sys/signal.h
+++ b/sys/sys/signal.h
@@ -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 */
OpenPOWER on IntegriCloud