summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_fork.c2
-rw-r--r--sys/kern/kern_lockf.c6
-rw-r--r--sys/kern/kern_procctl.c40
-rw-r--r--sys/kern/kern_sendfile.c13
-rw-r--r--sys/kern/subr_bus.c27
-rw-r--r--sys/kern/subr_rtc.c4
-rw-r--r--sys/kern/subr_syscall.c15
-rw-r--r--sys/kern/sys_capability.c4
8 files changed, 103 insertions, 8 deletions
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_lockf.c b/sys/kern/kern_lockf.c
index fcc8c57..c8a2345 100644
--- a/sys/kern/kern_lockf.c
+++ b/sys/kern/kern_lockf.c
@@ -83,7 +83,9 @@ __FBSDID("$FreeBSD$");
#ifdef LOCKF_DEBUG
#include <sys/sysctl.h>
+#include <ufs/ufs/extattr.h>
#include <ufs/ufs/quota.h>
+#include <ufs/ufs/ufsmount.h>
#include <ufs/ufs/inode.h>
static int lockf_debug = 0; /* control debug output */
@@ -2500,7 +2502,7 @@ lf_print(char *tag, struct lockf_entry *lock)
if (lock->lf_inode != (struct inode *)0)
printf(" in ino %ju on dev <%s>,",
(uintmax_t)lock->lf_inode->i_number,
- devtoname(lock->lf_inode->i_dev));
+ devtoname(ITODEV(lock->lf_inode)));
printf(" %s, start %jd, end ",
lock->lf_type == F_RDLCK ? "shared" :
lock->lf_type == F_WRLCK ? "exclusive" :
@@ -2528,7 +2530,7 @@ lf_printlist(char *tag, struct lockf_entry *lock)
printf("%s: Lock list for ino %ju on dev <%s>:\n",
tag, (uintmax_t)lock->lf_inode->i_number,
- devtoname(lock->lf_inode->i_dev));
+ devtoname(ITODEV(lock->lf_inode)));
LIST_FOREACH(lf, &lock->lf_vnode->v_lockf->ls_active, lf_link) {
printf("\tlock %p for ",(void *)lf);
lf_print_owner(lock->lf_owner);
diff --git a/sys/kern/kern_procctl.c b/sys/kern/kern_procctl.c
index 8ef72901..c3d290a 100644
--- a/sys/kern/kern_procctl.c
+++ b/sys/kern/kern_procctl.c
@@ -1,6 +1,6 @@
/*-
* Copyright (c) 2014 John Baldwin
- * Copyright (c) 2014 The FreeBSD Foundation
+ * Copyright (c) 2014, 2016 The FreeBSD Foundation
*
* Portions of this software were developed by Konstantin Belousov
* under sponsorship from the FreeBSD Foundation.
@@ -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/kern_sendfile.c b/sys/kern/kern_sendfile.c
index 7ee7780..05be5f6 100644
--- a/sys/kern/kern_sendfile.c
+++ b/sys/kern/kern_sendfile.c
@@ -656,10 +656,18 @@ retry_space:
if (hdr_uio != NULL && hdr_uio->uio_resid > 0) {
hdr_uio->uio_td = td;
hdr_uio->uio_rw = UIO_WRITE;
- hdr_uio->uio_resid = min(hdr_uio->uio_resid, space);
- mh = m_uiotombuf(hdr_uio, M_WAITOK, 0, 0, 0);
+ mh = m_uiotombuf(hdr_uio, M_WAITOK, space, 0, 0);
hdrlen = m_length(mh, &mhtail);
space -= hdrlen;
+ /*
+ * If header consumed all the socket buffer space,
+ * don't waste CPU cycles and jump to the end.
+ */
+ if (space == 0) {
+ sfio = NULL;
+ nios = 0;
+ goto prepend_header;
+ }
hdr_uio = NULL;
}
@@ -806,6 +814,7 @@ retry_space:
/* Prepend header, if any. */
if (hdrlen) {
+prepend_header:
mhtail->m_next = m;
m = mh;
mh = NULL;
diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c
index af3ca57..b28a8cb 100644
--- a/sys/kern/subr_bus.c
+++ b/sys/kern/subr_bus.c
@@ -2146,6 +2146,12 @@ device_probe_child(device_t dev, device_t child)
}
/*
+ * Reset DF_QUIET in case this driver doesn't
+ * end up as the best driver.
+ */
+ device_verbose(child);
+
+ /*
* Probes that return BUS_PROBE_NOWILDCARD or lower
* only match on devices whose driver was explicitly
* specified.
@@ -2970,6 +2976,7 @@ device_detach(device_t dev)
if (!(dev->flags & DF_FIXEDCLASS))
devclass_delete_device(dev->devclass, dev);
+ device_verbose(dev);
dev->state = DS_NOTPRESENT;
(void)device_set_driver(dev, NULL);
device_sysctl_fini(dev);
@@ -5427,6 +5434,7 @@ devctl2_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
case DEV_SUSPEND:
case DEV_RESUME:
case DEV_SET_DRIVER:
+ case DEV_CLEAR_DRIVER:
case DEV_RESCAN:
case DEV_DELETE:
error = priv_check(td, PRIV_DRIVER);
@@ -5592,6 +5600,25 @@ devctl2_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
error = device_probe_and_attach(dev);
break;
}
+ case DEV_CLEAR_DRIVER:
+ if (!(dev->flags & DF_FIXEDCLASS)) {
+ error = 0;
+ break;
+ }
+ if (device_is_attached(dev)) {
+ if (req->dr_flags & DEVF_CLEAR_DRIVER_DETACH)
+ error = device_detach(dev);
+ else
+ error = EBUSY;
+ if (error)
+ break;
+ }
+
+ dev->flags &= ~DF_FIXEDCLASS;
+ dev->flags |= DF_WILDCARD;
+ devclass_delete_device(dev->devclass, dev);
+ error = device_probe_and_attach(dev);
+ break;
case DEV_RESCAN:
if (!device_is_attached(dev)) {
error = ENXIO;
diff --git a/sys/kern/subr_rtc.c b/sys/kern/subr_rtc.c
index 4bac324..dee839d 100644
--- a/sys/kern/subr_rtc.c
+++ b/sys/kern/subr_rtc.c
@@ -75,7 +75,7 @@ __FBSDID("$FreeBSD$");
static device_t clock_dev = NULL;
static long clock_res;
static struct timespec clock_adj;
-static struct mtx resettodr_lock;
+struct mtx resettodr_lock;
MTX_SYSINIT(resettodr_init, &resettodr_lock, "tod2rl", MTX_DEF);
/* XXX: should be kern. now, it's no longer machdep. */
@@ -132,7 +132,9 @@ inittodr(time_t base)
goto wrong_time;
}
/* XXX: We should poll all registered RTCs in case of failure */
+ mtx_lock(&resettodr_lock);
error = CLOCK_GETTIME(clock_dev, &ts);
+ mtx_unlock(&resettodr_lock);
if (error != 0 && error != EINVAL) {
printf("warning: clock_gettime failed (%d), the system time "
"will not be set accurately\n", error);
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");
OpenPOWER on IntegriCloud