diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2013-11-06 16:20:21 +0100 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2013-11-11 10:08:08 +0100 |
commit | 66659ff1ad6831b0ea7425fa6ecd8a8687523658 (patch) | |
tree | 48e22b475fa8854128e0861a33fed6f78c8094b5 /freebsd/sys/kern/kern_sysctl.c | |
parent | Define __GLOBL1() and __GLOBL() (diff) | |
download | rtems-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.c | 98 |
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(); |