summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/kern/kern_sysctl.c
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2013-11-06 16:20:21 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2013-11-11 10:08:08 +0100
commit66659ff1ad6831b0ea7425fa6ecd8a8687523658 (patch)
tree48e22b475fa8854128e0861a33fed6f78c8094b5 /freebsd/sys/kern/kern_sysctl.c
parentDefine __GLOBL1() and __GLOBL() (diff)
downloadrtems-libbsd-66659ff1ad6831b0ea7425fa6ecd8a8687523658.tar.bz2
Update to FreeBSD 9.2
Diffstat (limited to 'freebsd/sys/kern/kern_sysctl.c')
-rw-r--r--freebsd/sys/kern/kern_sysctl.c98
1 files changed, 76 insertions, 22 deletions
diff --git a/freebsd/sys/kern/kern_sysctl.c b/freebsd/sys/kern/kern_sysctl.c
index 2fb986bb..0903dd74 100644
--- a/freebsd/sys/kern/kern_sysctl.c
+++ b/freebsd/sys/kern/kern_sysctl.c
@@ -40,12 +40,14 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <rtems/bsd/local/opt_capsicum.h>
#include <rtems/bsd/local/opt_compat.h>
#include <rtems/bsd/local/opt_ktrace.h>
#include <rtems/bsd/sys/param.h>
#include <sys/fail.h>
#include <sys/systm.h>
+#include <sys/capability.h>
#include <sys/kernel.h>
#include <sys/sysctl.h>
#include <sys/malloc.h>
@@ -367,10 +369,31 @@ sysctl_remove_oid(struct sysctl_oid *oidp, int del, int recurse)
return (error);
}
+int
+sysctl_remove_name(struct sysctl_oid *parent, const char *name,
+ int del, int recurse)
+{
+ struct sysctl_oid *p, *tmp;
+ int error;
+
+ error = ENOENT;
+ SYSCTL_XLOCK();
+ SLIST_FOREACH_SAFE(p, SYSCTL_CHILDREN(parent), oid_link, tmp) {
+ if (strcmp(p->oid_name, name) == 0) {
+ error = sysctl_remove_oid_locked(p, del, recurse);
+ break;
+ }
+ }
+ SYSCTL_XUNLOCK();
+
+ return (error);
+}
+
+
static int
sysctl_remove_oid_locked(struct sysctl_oid *oidp, int del, int recurse)
{
- struct sysctl_oid *p;
+ struct sysctl_oid *p, *tmp;
int error;
SYSCTL_ASSERT_XLOCKED();
@@ -389,7 +412,8 @@ sysctl_remove_oid_locked(struct sysctl_oid *oidp, int del, int recurse)
*/
if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
if (oidp->oid_refcnt == 1) {
- SLIST_FOREACH(p, SYSCTL_CHILDREN(oidp), oid_link) {
+ SLIST_FOREACH_SAFE(p,
+ SYSCTL_CHILDREN(oidp), oid_link, tmp) {
if (!recurse)
return (ENOTEMPTY);
error = sysctl_remove_oid_locked(p, del,
@@ -430,14 +454,13 @@ sysctl_remove_oid_locked(struct sysctl_oid *oidp, int del, int recurse)
}
return (0);
}
-
/*
* Create new sysctls at run time.
* clist may point to a valid context initialized with sysctl_ctx_init().
*/
struct sysctl_oid *
sysctl_add_oid(struct sysctl_ctx_list *clist, struct sysctl_oid_list *parent,
- int number, const char *name, int kind, void *arg1, int arg2,
+ int number, const char *name, int kind, void *arg1, intptr_t arg2,
int (*handler)(SYSCTL_HANDLER_ARGS), const char *fmt, const char *descr)
{
struct sysctl_oid *oidp;
@@ -475,6 +498,7 @@ sysctl_add_oid(struct sysctl_ctx_list *clist, struct sysctl_oid_list *parent,
SYSCTL_CHILDREN_SET(oidp, malloc(sizeof(struct sysctl_oid_list),
M_SYSCTLOID, M_WAITOK));
SLIST_INIT(SYSCTL_CHILDREN(oidp));
+ oidp->oid_arg2 = arg2;
} else {
oidp->oid_arg1 = arg1;
oidp->oid_arg2 = arg2;
@@ -603,8 +627,12 @@ sysctl_sysctl_debug_dump_node(struct sysctl_oid_list *l, int i)
}
break;
case CTLTYPE_INT: printf(" Int\n"); break;
+ case CTLTYPE_UINT: printf(" u_int\n"); break;
+ case CTLTYPE_LONG: printf(" Long\n"); break;
+ case CTLTYPE_ULONG: printf(" u_long\n"); break;
case CTLTYPE_STRING: printf(" String\n"); break;
- case CTLTYPE_QUAD: printf(" Quad\n"); break;
+ case CTLTYPE_U64: printf(" uint64_t\n"); break;
+ case CTLTYPE_S64: printf(" int64_t\n"); break;
case CTLTYPE_OPAQUE: printf(" Opaque/struct\n"); break;
default: printf("\n");
}
@@ -687,7 +715,12 @@ sysctl_sysctl_name(SYSCTL_HANDLER_ARGS)
return (error);
}
-static SYSCTL_NODE(_sysctl, 1, name, CTLFLAG_RD, sysctl_sysctl_name, "");
+/*
+ * XXXRW/JA: Shouldn't return name data for nodes that we don't permit in
+ * capability mode.
+ */
+static SYSCTL_NODE(_sysctl, 1, name, CTLFLAG_RD | CTLFLAG_CAPRD,
+ sysctl_sysctl_name, "");
static int
sysctl_sysctl_next_ls(struct sysctl_oid_list *lsp, int *name, u_int namelen,
@@ -768,7 +801,12 @@ sysctl_sysctl_next(SYSCTL_HANDLER_ARGS)
return (error);
}
-static SYSCTL_NODE(_sysctl, 2, next, CTLFLAG_RD, sysctl_sysctl_next, "");
+/*
+ * XXXRW/JA: Shouldn't return next data for nodes that we don't permit in
+ * capability mode.
+ */
+static SYSCTL_NODE(_sysctl, 2, next, CTLFLAG_RD | CTLFLAG_CAPRD,
+ sysctl_sysctl_next, "");
static int
name2oid(char *name, int *oid, int *len, struct sysctl_oid **oidpp)
@@ -813,7 +851,7 @@ static int
sysctl_sysctl_name2oid(SYSCTL_HANDLER_ARGS)
{
char *p;
- int error, oid[CTL_MAXNAME], len;
+ int error, oid[CTL_MAXNAME], len = 0;
struct sysctl_oid *op = 0;
if (!req->newlen)
@@ -830,7 +868,7 @@ sysctl_sysctl_name2oid(SYSCTL_HANDLER_ARGS)
}
p [req->newlen] = '\0';
- len = 0;
+
SYSCTL_XLOCK();
error = name2oid(p, oid, &len, &op);
SYSCTL_XUNLOCK();
@@ -844,8 +882,13 @@ sysctl_sysctl_name2oid(SYSCTL_HANDLER_ARGS)
return (error);
}
-SYSCTL_PROC(_sysctl, 3, name2oid, CTLFLAG_RW|CTLFLAG_ANYBODY|CTLFLAG_MPSAFE,
- 0, 0, sysctl_sysctl_name2oid, "I", "");
+/*
+ * XXXRW/JA: Shouldn't return name2oid data for nodes that we don't permit in
+ * capability mode.
+ */
+SYSCTL_PROC(_sysctl, 3, name2oid,
+ CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MPSAFE
+ | CTLFLAG_CAPRW, 0, 0, sysctl_sysctl_name2oid, "I", "");
static int
sysctl_sysctl_oidfmt(SYSCTL_HANDLER_ARGS)
@@ -872,7 +915,7 @@ sysctl_sysctl_oidfmt(SYSCTL_HANDLER_ARGS)
}
-static SYSCTL_NODE(_sysctl, 4, oidfmt, CTLFLAG_RD|CTLFLAG_MPSAFE,
+static SYSCTL_NODE(_sysctl, 4, oidfmt, CTLFLAG_RD|CTLFLAG_MPSAFE|CTLFLAG_CAPRD,
sysctl_sysctl_oidfmt, "");
static int
@@ -896,7 +939,8 @@ sysctl_sysctl_oiddescr(SYSCTL_HANDLER_ARGS)
return (error);
}
-static SYSCTL_NODE(_sysctl, 5, oiddescr, CTLFLAG_RD, sysctl_sysctl_oiddescr, "");
+static SYSCTL_NODE(_sysctl, 5, oiddescr, CTLFLAG_RD|CTLFLAG_CAPRD,
+ sysctl_sysctl_oiddescr, "");
/*
* Default "handler" functions.
@@ -1012,9 +1056,8 @@ sysctl_handle_long(SYSCTL_HANDLER_ARGS)
* a variable: point arg1 at it.
* a constant: pass it in arg2.
*/
-
int
-sysctl_handle_quad(SYSCTL_HANDLER_ARGS)
+sysctl_handle_64(SYSCTL_HANDLER_ARGS)
{
int error = 0;
uint64_t tmpout;
@@ -1198,7 +1241,7 @@ kernel_sysctl(struct thread *td, int *name, u_int namelen, void *old,
req.oldfunc = sysctl_old_kernel;
req.newfunc = sysctl_new_kernel;
- req.lock = REQ_LOCKED;
+ req.lock = REQ_UNWIRED;
SYSCTL_XLOCK();
error = sysctl_root(0, name, namelen, &req);
@@ -1314,7 +1357,7 @@ sysctl_wire_old_buffer(struct sysctl_req *req, size_t len)
wiredlen = (len > 0 && len < req->oldlen) ? len : req->oldlen;
ret = 0;
- if (req->lock == REQ_LOCKED && req->oldptr &&
+ if (req->lock != REQ_WIRED && req->oldptr &&
req->oldfunc == sysctl_old_user) {
if (wiredlen != 0) {
ret = vslock(req->oldptr, wiredlen);
@@ -1350,8 +1393,6 @@ sysctl_find_oid(int *name, u_int namelen, struct sysctl_oid **noid,
return (ENOENT);
indx++;
- if (oid->oid_kind & CTLFLAG_NOLOCK)
- req->lock = REQ_UNLOCKED;
if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
if (oid->oid_handler != NULL || indx == namelen) {
*noid = oid;
@@ -1410,6 +1451,19 @@ sysctl_root(SYSCTL_HANDLER_ARGS)
#ifndef __rtems__
KASSERT(req->td != NULL, ("sysctl_root(): req->td == NULL"));
+#ifdef CAPABILITY_MODE
+ /*
+ * If the process is in capability mode, then don't permit reading or
+ * writing unless specifically granted for the node.
+ */
+ if (IN_CAPABILITY_MODE(req->td)) {
+ if (req->oldptr && !(oid->oid_kind & CTLFLAG_CAPRD))
+ return (EPERM);
+ if (req->newptr && !(oid->oid_kind & CTLFLAG_CAPWR))
+ return (EPERM);
+ }
+#endif
+
/* Is this sysctl sensitive to securelevels? */
if (req->newptr && (oid->oid_kind & CTLFLAG_SECURE)) {
lvl = (oid->oid_kind & CTLMASK_SECURE) >> CTLSHIFT_SECURE;
@@ -1487,7 +1541,7 @@ struct sysctl_args {
};
#endif
int
-__sysctl(struct thread *td, struct sysctl_args *uap)
+sys___sysctl(struct thread *td, struct sysctl_args *uap)
{
int error, i, name[CTL_MAXNAME];
size_t j;
@@ -1555,7 +1609,7 @@ userland_sysctl(struct thread *td, int *name, u_int namelen, void *old,
req.oldfunc = sysctl_old_user;
req.newfunc = sysctl_new_user;
- req.lock = REQ_LOCKED;
+ req.lock = REQ_UNWIRED;
#ifdef KTRACE
if (KTRPOINT(curthread, KTR_SYSCTL))
@@ -1577,7 +1631,7 @@ userland_sysctl(struct thread *td, int *name, u_int namelen, void *old,
SYSCTL_XUNLOCK();
if (error != EAGAIN)
break;
- uio_yield();
+ kern_yield(PRI_USER);
}
CURVNET_RESTORE();