diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-08-09 13:04:41 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-09-21 10:29:37 +0200 |
commit | e4a8065910cd6b2e7e0448cc6431ca2906322389 (patch) | |
tree | 73492991cfa40f994c20d761d476e6bc16304536 /freebsd/sys/kern/kern_sysctl.c | |
parent | Update to FreeBSD head 2017-08-01 (diff) | |
download | rtems-libbsd-e4a8065910cd6b2e7e0448cc6431ca2906322389.tar.bz2 |
Update to FreeBSD head 2017-10-01
Git mirror commit b2f0376b45428f13151d229c5ae9d4d8f74acbd1.
Update #3472.
Diffstat (limited to 'freebsd/sys/kern/kern_sysctl.c')
-rw-r--r-- | freebsd/sys/kern/kern_sysctl.c | 100 |
1 files changed, 89 insertions, 11 deletions
diff --git a/freebsd/sys/kern/kern_sysctl.c b/freebsd/sys/kern/kern_sysctl.c index 90b15444..e99a8bd6 100644 --- a/freebsd/sys/kern/kern_sysctl.c +++ b/freebsd/sys/kern/kern_sysctl.c @@ -90,7 +90,7 @@ static MALLOC_DEFINE(M_SYSCTLTMP, "sysctltmp", "sysctl temp output buffer"); * sysctl requests larger than a single page via an exclusive lock. */ static struct rmlock sysctllock; -static struct sx sysctlmemlock; +static struct sx __exclusive_cache_line sysctlmemlock; #define SYSCTL_WLOCK() rm_wlock(&sysctllock) #define SYSCTL_WUNLOCK() rm_wunlock(&sysctllock) @@ -327,6 +327,91 @@ sysctl_load_tunable_by_oid_locked(struct sysctl_oid *oidp) } #endif /* __rtems__ */ +static int +sbuf_printf_drain(void *arg __unused, const char *data, int len) +{ + + return (printf("%.*s", len, data)); +} + +/* + * Locate the path to a given oid. Returns the length of the resulting path, + * or -1 if the oid was not found. nodes must have room for CTL_MAXNAME + * elements and be NULL initialized. + */ +static int +sysctl_search_oid(struct sysctl_oid **nodes, struct sysctl_oid *needle) +{ + int indx; + + SYSCTL_ASSERT_LOCKED(); + indx = 0; + while (indx < CTL_MAXNAME && indx >= 0) { + if (nodes[indx] == NULL && indx == 0) + nodes[indx] = SLIST_FIRST(&sysctl__children); + else if (nodes[indx] == NULL) + nodes[indx] = SLIST_FIRST(&nodes[indx - 1]->oid_children); + else + nodes[indx] = SLIST_NEXT(nodes[indx], oid_link); + + if (nodes[indx] == needle) + return (indx + 1); + + if (nodes[indx] == NULL) { + indx--; + continue; + } + + if ((nodes[indx]->oid_kind & CTLTYPE) == CTLTYPE_NODE) { + indx++; + continue; + } + } + return (-1); +} + +static void +sysctl_warn_reuse(const char *func, struct sysctl_oid *leaf) +{ + struct sysctl_oid *nodes[CTL_MAXNAME]; + char buf[128]; + struct sbuf sb; + int rc, i; + + (void)sbuf_new(&sb, buf, sizeof(buf), SBUF_FIXEDLEN | SBUF_INCLUDENUL); + sbuf_set_drain(&sb, sbuf_printf_drain, NULL); + + sbuf_printf(&sb, "%s: can't re-use a leaf (", __func__); + + memset(nodes, 0, sizeof(nodes)); + rc = sysctl_search_oid(nodes, leaf); + if (rc > 0) { + for (i = 0; i < rc; i++) + sbuf_printf(&sb, "%s%.*s", nodes[i]->oid_name, + i != (rc - 1), "."); + } else { + sbuf_printf(&sb, "%s", leaf->oid_name); + } + sbuf_printf(&sb, ")!\n"); + + (void)sbuf_finish(&sb); +} + +#ifdef SYSCTL_DEBUG +static int +sysctl_reuse_test(SYSCTL_HANDLER_ARGS) +{ + struct rm_priotracker tracker; + + SYSCTL_RLOCK(&tracker); + sysctl_warn_reuse(__func__, oidp); + SYSCTL_RUNLOCK(&tracker); + return (0); +} +SYSCTL_PROC(_sysctl, 0, reuse_test, CTLTYPE_STRING|CTLFLAG_RD|CTLFLAG_MPSAFE, + 0, 0, sysctl_reuse_test, "-", ""); +#endif + void sysctl_register_oid(struct sysctl_oid *oidp) { @@ -347,7 +432,7 @@ sysctl_register_oid(struct sysctl_oid *oidp) p->oid_refcnt++; return; } else { - printf("can't re-use a leaf (%s)!\n", p->oid_name); + sysctl_warn_reuse(__func__, p); return; } } @@ -721,8 +806,8 @@ sysctl_add_oid(struct sysctl_ctx_list *clist, struct sysctl_oid_list *parent, SYSCTL_WUNLOCK(); return (oidp); } else { + sysctl_warn_reuse(__func__, oidp); SYSCTL_WUNLOCK(); - printf("can't re-use a leaf (%s)!\n", name); return (NULL); } } @@ -2005,16 +2090,9 @@ userland_sysctl(struct thread *td, int *name, u_int namelen, void *old, } } req.validlen = req.oldlen; - - if (old) { - if (!useracc(old, req.oldlen, VM_PROT_WRITE)) - return (EFAULT); - req.oldptr= old; - } + req.oldptr = old; if (new != NULL) { - if (!useracc(new, newlen, VM_PROT_READ)) - return (EFAULT); req.newlen = newlen; req.newptr = new; } |