svn commit: r367283 - in stable/12: sbin/sysctl sys/kern sys/sys usr.bin/truss
Ryan Moeller
freqlabs at FreeBSD.org
Mon Nov 2 20:00:52 UTC 2020
Author: freqlabs
Date: Mon Nov 2 20:00:50 2020
New Revision: 367283
URL: https://svnweb.freebsd.org/changeset/base/367283
Log:
MFC r366465, r367003, r367006, r367009
Enable iterating all sysctls, even ones with CTLFLAG_SKIP
kern_sysctl: Misc code cleanup
sysctl: Misc code cleanup
sysctl+kern_sysctl: Honor SKIP for descendant nodes
Modified:
stable/12/sbin/sysctl/sysctl.c
stable/12/sys/kern/kern_sysctl.c
stable/12/sys/sys/sysctl.h
stable/12/usr.bin/truss/syscalls.c
Directory Properties:
stable/12/ (props changed)
Modified: stable/12/sbin/sysctl/sysctl.c
==============================================================================
--- stable/12/sbin/sysctl/sysctl.c Mon Nov 2 19:56:15 2020 (r367282)
+++ stable/12/sbin/sysctl/sysctl.c Mon Nov 2 20:00:50 2020 (r367283)
@@ -29,20 +29,9 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)from: sysctl.c 8.1 (Berkeley) 6/6/93";
-#endif
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <sys/param.h>
#include <sys/time.h>
#include <sys/resource.h>
@@ -81,7 +70,7 @@ static int Nflag, nflag, oflag, qflag, tflag, Tflag, W
static int oidfmt(int *, int, char *, u_int *);
static int parsefile(const char *);
static int parse(const char *, int);
-static int show_var(int *, int);
+static int show_var(int *, int, bool);
static int sysctl_all(int *oid, int len);
static int name2oid(const char *, int *);
@@ -221,7 +210,7 @@ main(int argc, char **argv)
if (Nflag && nflag)
usage();
if (aflag && argc == 0)
- exit(sysctl_all(0, 0));
+ exit(sysctl_all(NULL, 0));
if (argc == 0 && conffile == NULL)
usage();
@@ -369,6 +358,13 @@ parse(const char *string, int lineno)
else
line[0] = '\0';
+ /*
+ * Split the string into name and value.
+ *
+ * Either = or : may be used as the delimiter.
+ * Whitespace surrounding the delimiter is trimmed.
+ * Quotes around the value are stripped.
+ */
cp = buf;
if (snprintf(buf, BUFSIZ, "%s", string) >= BUFSIZ) {
warnx("oid too long: '%s'%s", string, line);
@@ -381,6 +377,7 @@ parse(const char *string, int lineno)
warnx("Can't set variables when using -T or -W");
usage();
}
+ /* Trim whitespace before the value. */
while (isspace(*cp))
cp++;
/* Strip a pair of " or ' if any. */
@@ -394,14 +391,17 @@ parse(const char *string, int lineno)
newvalstr = cp;
newsize = strlen(cp);
}
- /* Trim spaces */
+ /* Trim whitespace after the name. */
cp = bufp + strlen(bufp) - 1;
while (cp >= bufp && isspace((int)*cp)) {
*cp = '\0';
cp--;
}
- len = name2oid(bufp, mib);
+ /*
+ * Check the name is a useable oid.
+ */
+ len = name2oid(bufp, mib);
if (len < 0) {
if (iflag)
return (0);
@@ -425,118 +425,126 @@ parse(const char *string, int lineno)
exit(1);
}
+ /*
+ * We have a useable oid to work with. If there is no value given,
+ * show the node and its children. Otherwise, set the new value.
+ */
if (newvalstr == NULL || dflag) {
if ((kind & CTLTYPE) == CTLTYPE_NODE) {
if (dflag) {
- i = show_var(mib, len);
+ i = show_var(mib, len, false);
if (!i && !bflag)
putchar('\n');
}
sysctl_all(mib, len);
} else {
- i = show_var(mib, len);
+ i = show_var(mib, len, false);
if (!i && !bflag)
putchar('\n');
}
- } else {
- if ((kind & CTLTYPE) == CTLTYPE_NODE) {
- warnx("oid '%s' isn't a leaf node%s", bufp, line);
- return (1);
- }
+ return (0);
+ }
- if (!(kind & CTLFLAG_WR)) {
- if (kind & CTLFLAG_TUN) {
- warnx("oid '%s' is a read only tunable%s", bufp, line);
- warnx("Tunable values are set in /boot/loader.conf");
- } else
- warnx("oid '%s' is read only%s", bufp, line);
- return (1);
- }
+ /*
+ * We have a new value to set. Check its validity and parse if numeric.
+ */
+ if ((kind & CTLTYPE) == CTLTYPE_NODE) {
+ warnx("oid '%s' isn't a leaf node%s", bufp, line);
+ return (1);
+ }
- switch (kind & CTLTYPE) {
- case CTLTYPE_INT:
- case CTLTYPE_UINT:
- case CTLTYPE_LONG:
- case CTLTYPE_ULONG:
- case CTLTYPE_S8:
- case CTLTYPE_S16:
- case CTLTYPE_S32:
- case CTLTYPE_S64:
- case CTLTYPE_U8:
- case CTLTYPE_U16:
- case CTLTYPE_U32:
- case CTLTYPE_U64:
- if (strlen(newvalstr) == 0) {
- warnx("empty numeric value");
- return (1);
- }
- /* FALLTHROUGH */
- case CTLTYPE_STRING:
- break;
- default:
- warnx("oid '%s' is type %d,"
- " cannot set that%s", bufp,
- kind & CTLTYPE, line);
+ if (!(kind & CTLFLAG_WR)) {
+ if (kind & CTLFLAG_TUN) {
+ warnx("oid '%s' is a read only tunable%s", bufp, line);
+ warnx("Tunable values are set in /boot/loader.conf");
+ } else
+ warnx("oid '%s' is read only%s", bufp, line);
+ return (1);
+ }
+
+ switch (kind & CTLTYPE) {
+ case CTLTYPE_INT:
+ case CTLTYPE_UINT:
+ case CTLTYPE_LONG:
+ case CTLTYPE_ULONG:
+ case CTLTYPE_S8:
+ case CTLTYPE_S16:
+ case CTLTYPE_S32:
+ case CTLTYPE_S64:
+ case CTLTYPE_U8:
+ case CTLTYPE_U16:
+ case CTLTYPE_U32:
+ case CTLTYPE_U64:
+ if (strlen(newvalstr) == 0) {
+ warnx("empty numeric value");
return (1);
}
+ /* FALLTHROUGH */
+ case CTLTYPE_STRING:
+ break;
+ default:
+ warnx("oid '%s' is type %d, cannot set that%s",
+ bufp, kind & CTLTYPE, line);
+ return (1);
+ }
- newbuf = NULL;
+ newbuf = NULL;
- switch (kind & CTLTYPE) {
- case CTLTYPE_STRING:
- newval = newvalstr;
- break;
- default:
- newsize = 0;
- while ((cp = strsep(&newvalstr, " ,")) != NULL) {
- if (*cp == '\0')
- continue;
- if (!parse_numeric(cp, fmt, kind, &newbuf,
- &newsize)) {
- warnx("invalid %s '%s'%s",
- ctl_typename[kind & CTLTYPE],
- cp, line);
- free(newbuf);
- return (1);
- }
- }
- newval = newbuf;
- break;
- }
-
- i = show_var(mib, len);
- if (sysctl(mib, len, 0, 0, newval, newsize) == -1) {
- free(newbuf);
- if (!i && !bflag)
- putchar('\n');
- switch (errno) {
- case EOPNOTSUPP:
- warnx("%s: value is not available%s",
- string, line);
+ switch (kind & CTLTYPE) {
+ case CTLTYPE_STRING:
+ newval = newvalstr;
+ break;
+ default:
+ newsize = 0;
+ while ((cp = strsep(&newvalstr, " ,")) != NULL) {
+ if (*cp == '\0')
+ continue;
+ if (!parse_numeric(cp, fmt, kind, &newbuf, &newsize)) {
+ warnx("invalid %s '%s'%s",
+ ctl_typename[kind & CTLTYPE], cp, line);
+ free(newbuf);
return (1);
- case ENOTDIR:
- warnx("%s: specification is incomplete%s",
- string, line);
- return (1);
- case ENOMEM:
- warnx("%s: type is unknown to this program%s",
- string, line);
- return (1);
- default:
- warn("%s%s", string, line);
- return (1);
}
}
+ newval = newbuf;
+ break;
+ }
+
+ /*
+ * Show the current value, then set and show the new value.
+ */
+ i = show_var(mib, len, false);
+ if (sysctl(mib, len, 0, 0, newval, newsize) == -1) {
free(newbuf);
- if (!bflag)
- printf(" -> ");
- i = nflag;
- nflag = 1;
- j = show_var(mib, len);
- if (!j && !bflag)
+ if (!i && !bflag)
putchar('\n');
- nflag = i;
+ switch (errno) {
+ case EOPNOTSUPP:
+ warnx("%s: value is not available%s",
+ string, line);
+ return (1);
+ case ENOTDIR:
+ warnx("%s: specification is incomplete%s",
+ string, line);
+ return (1);
+ case ENOMEM:
+ warnx("%s: type is unknown to this program%s",
+ string, line);
+ return (1);
+ default:
+ warn("%s%s", string, line);
+ return (1);
+ }
}
+ free(newbuf);
+ if (!bflag)
+ printf(" -> ");
+ i = nflag;
+ nflag = 1;
+ j = show_var(mib, len, false);
+ if (!j && !bflag)
+ putchar('\n');
+ nflag = i;
return (0);
}
@@ -875,8 +883,8 @@ name2oid(const char *name, int *oidp)
int i;
size_t j;
- oid[0] = 0;
- oid[1] = 3;
+ oid[0] = CTL_SYSCTL;
+ oid[1] = CTL_SYSCTL_NAME2OID;
j = CTL_MAXNAME * sizeof(int);
i = sysctl(oid, 2, oidp, &j, name, strlen(name));
@@ -894,8 +902,8 @@ oidfmt(int *oid, int len, char *fmt, u_int *kind)
int i;
size_t j;
- qoid[0] = 0;
- qoid[1] = 4;
+ qoid[0] = CTL_SYSCTL;
+ qoid[1] = CTL_SYSCTL_OIDFMT;
memcpy(qoid + 2, oid, len * sizeof(int));
j = sizeof(buf);
@@ -919,8 +927,9 @@ oidfmt(int *oid, int len, char *fmt, u_int *kind)
* Return minus one if we had errors.
*/
static int
-show_var(int *oid, int nlen)
+show_var(int *oid, int nlen, bool honor_skip)
{
+ static int skip_len = 0, skip_oid[CTL_MAXNAME];
u_char buf[BUFSIZ], *val, *oval, *p;
char name[BUFSIZ], fmt[BUFSIZ];
const char *sep, *sep1, *prntype;
@@ -941,10 +950,10 @@ show_var(int *oid, int nlen)
bzero(buf, BUFSIZ);
bzero(fmt, BUFSIZ);
bzero(name, BUFSIZ);
- qoid[0] = 0;
+ qoid[0] = CTL_SYSCTL;
memcpy(qoid + 2, oid, nlen * sizeof(int));
- qoid[1] = 1;
+ qoid[1] = CTL_SYSCTL_NAME;
j = sizeof(name);
i = sysctl(qoid, nlen + 2, name, &j, 0, 0);
if (i || !j)
@@ -953,11 +962,11 @@ show_var(int *oid, int nlen)
oidfmt(oid, nlen, fmt, &kind);
/* if Wflag then only list sysctls that are writeable and not stats. */
if (Wflag && ((kind & CTLFLAG_WR) == 0 || (kind & CTLFLAG_STATS) != 0))
- return 1;
+ return (1);
/* if Tflag then only list sysctls that are tuneables. */
if (Tflag && (kind & CTLFLAG_TUN) == 0)
- return 1;
+ return (1);
if (Nflag) {
printf("%s", name);
@@ -983,13 +992,29 @@ show_var(int *oid, int nlen)
printf("%s", prntype);
return (0);
}
- qoid[1] = 5;
+ qoid[1] = CTL_SYSCTL_OIDDESCR;
j = sizeof(buf);
i = sysctl(qoid, nlen + 2, buf, &j, 0, 0);
printf("%s", buf);
return (0);
}
+ /* keep track of encountered skip nodes, ignoring descendants */
+ if (skip_len == 0 && (kind & CTLFLAG_SKIP) != 0) {
+ /* Save this oid so we can skip descendants. */
+ skip_len = nlen * sizeof(int);
+ memcpy(skip_oid, oid, skip_len);
+ }
+
+ /* bail before fetching the value if we're honoring skip */
+ if (honor_skip) {
+ if (0 < skip_len && skip_len <= nlen * (int)sizeof(int) &&
+ memcmp(skip_oid, oid, skip_len) == 0)
+ return (1);
+ /* Not a skip node or descendant of a skip node. */
+ skip_len = 0;
+ }
+
/* don't fetch opaques that we don't know how to print */
if (ctltype == CTLTYPE_OPAQUE) {
if (strcmp(fmt, "S,clockinfo") == 0)
@@ -1170,15 +1195,17 @@ sysctl_all(int *oid, int len)
int name1[22], name2[22];
int i, j;
size_t l1, l2;
+ bool honor_skip = false;
- name1[0] = 0;
- name1[1] = 2;
+ name1[0] = CTL_SYSCTL;
+ name1[1] = (oid != NULL || Nflag || dflag || tflag) ?
+ CTL_SYSCTL_NEXTNOSKIP : CTL_SYSCTL_NEXT;
l1 = 2;
if (len) {
- memcpy(name1+2, oid, len * sizeof(int));
+ memcpy(name1 + 2, oid, len * sizeof(int));
l1 += len;
} else {
- name1[2] = 1;
+ name1[2] = CTL_KERN;
l1++;
}
for (;;) {
@@ -1196,15 +1223,15 @@ sysctl_all(int *oid, int len)
if (len < 0 || l2 < (unsigned int)len)
return (0);
- for (i = 0; i < len; i++)
- if (name2[i] != oid[i])
- return (0);
+ if (memcmp(name2, oid, len * sizeof(int)) != 0)
+ return (0);
- i = show_var(name2, l2);
+ i = show_var(name2, l2, honor_skip);
if (!i && !bflag)
putchar('\n');
- memcpy(name1+2, name2, l2 * sizeof(int));
+ memcpy(name1 + 2, name2, l2 * sizeof(int));
l1 = 2 + l2;
+ honor_skip = true;
}
}
Modified: stable/12/sys/kern/kern_sysctl.c
==============================================================================
--- stable/12/sys/kern/kern_sysctl.c Mon Nov 2 19:56:15 2020 (r367282)
+++ stable/12/sys/kern/kern_sysctl.c Mon Nov 2 20:00:50 2020 (r367283)
@@ -937,7 +937,8 @@ SYSINIT(sysctl, SI_SUB_KMEM, SI_ORDER_FIRST, sysctl_re
* {CTL_SYSCTL, CTL_SYSCTL_DEBUG} printf the entire MIB-tree.
* {CTL_SYSCTL, CTL_SYSCTL_NAME, ...} return the name of the "..."
* OID.
- * {CTL_SYSCTL, CTL_SYSCTL_NEXT, ...} return the next OID.
+ * {CTL_SYSCTL, CTL_SYSCTL_NEXT, ...} return the next OID, honoring
+ * CTLFLAG_SKIP.
* {CTL_SYSCTL, CTL_SYSCTL_NAME2OID} return the OID of the name in
* "new"
* {CTL_SYSCTL, CTL_SYSCTL_OIDFMT, ...} return the kind & format info
@@ -946,6 +947,8 @@ SYSINIT(sysctl, SI_SUB_KMEM, SI_ORDER_FIRST, sysctl_re
* "..." OID.
* {CTL_SYSCTL, CTL_SYSCTL_OIDLABEL, ...} return the aggregation label of
* the "..." OID.
+ * {CTL_SYSCTL, CTL_SYSCTL_NEXTNOSKIP, ...} return the next OID, ignoring
+ * CTLFLAG_SKIP.
*/
#ifdef SYSCTL_DEBUG
@@ -1086,9 +1089,13 @@ sysctl_sysctl_name(SYSCTL_HANDLER_ARGS)
static SYSCTL_NODE(_sysctl, CTL_SYSCTL_NAME, name, CTLFLAG_RD |
CTLFLAG_MPSAFE | CTLFLAG_CAPRD, sysctl_sysctl_name, "");
+/*
+ * Walk the sysctl subtree at lsp until we find the given name,
+ * and return the next name in order by oid_number.
+ */
static int
sysctl_sysctl_next_ls(struct sysctl_oid_list *lsp, int *name, u_int namelen,
- int *next, int *len, int level, struct sysctl_oid **oidpp)
+ int *next, int *len, int level, bool honor_skip)
{
struct sysctl_oid *oidp;
@@ -1096,54 +1103,95 @@ sysctl_sysctl_next_ls(struct sysctl_oid_list *lsp, int
*len = level;
SLIST_FOREACH(oidp, lsp, oid_link) {
*next = oidp->oid_number;
- *oidpp = oidp;
- if ((oidp->oid_kind & (CTLFLAG_SKIP | CTLFLAG_DORMANT)) != 0)
+ if ((oidp->oid_kind & CTLFLAG_DORMANT) != 0)
continue;
- if (!namelen) {
+ if (honor_skip && (oidp->oid_kind & CTLFLAG_SKIP) != 0)
+ continue;
+
+ if (namelen == 0) {
+ /*
+ * We have reached a node with a full name match and are
+ * looking for the next oid in its children.
+ *
+ * For CTL_SYSCTL_NEXTNOSKIP we are done.
+ *
+ * For CTL_SYSCTL_NEXT we skip CTLTYPE_NODE (unless it
+ * has a handler) and move on to the children.
+ */
+ if (!honor_skip)
+ return (0);
if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE)
return (0);
if (oidp->oid_handler)
- /* We really should call the handler here...*/
return (0);
lsp = SYSCTL_CHILDREN(oidp);
- if (!sysctl_sysctl_next_ls(lsp, 0, 0, next+1,
- len, level+1, oidpp))
+ if (!sysctl_sysctl_next_ls(lsp, NULL, 0, next + 1, len,
+ level + 1, honor_skip))
return (0);
+ /*
+ * There were no useable children in this node.
+ * Continue searching for the next oid at this level.
+ */
goto emptynode;
}
+ /*
+ * No match yet. Continue seeking the given name.
+ *
+ * We are iterating in order by oid_number, so skip oids lower
+ * than the one we are looking for.
+ *
+ * When the current oid_number is higher than the one we seek,
+ * that means we have reached the next oid in the sequence and
+ * should return it.
+ *
+ * If the oid_number matches the name at this level then we
+ * have to find a node to continue searching at the next level.
+ */
if (oidp->oid_number < *name)
continue;
-
if (oidp->oid_number > *name) {
+ /*
+ * We have reached the next oid.
+ *
+ * For CTL_SYSCTL_NEXTNOSKIP we are done.
+ *
+ * For CTL_SYSCTL_NEXT we skip CTLTYPE_NODE (unless it
+ * has a handler) and move on to the children.
+ */
+ if (!honor_skip)
+ return (0);
if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE)
return (0);
if (oidp->oid_handler)
return (0);
lsp = SYSCTL_CHILDREN(oidp);
- if (!sysctl_sysctl_next_ls(lsp, name+1, namelen-1,
- next+1, len, level+1, oidpp))
+ if (!sysctl_sysctl_next_ls(lsp, name + 1, namelen - 1,
+ next + 1, len, level + 1, honor_skip))
return (0);
goto next;
}
if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE)
continue;
-
if (oidp->oid_handler)
continue;
-
lsp = SYSCTL_CHILDREN(oidp);
- if (!sysctl_sysctl_next_ls(lsp, name+1, namelen-1, next+1,
- len, level+1, oidpp))
+ if (!sysctl_sysctl_next_ls(lsp, name + 1, namelen - 1,
+ next + 1, len, level + 1, honor_skip))
return (0);
next:
+ /*
+ * There were no useable children in this node.
+ * Continue searching for the next oid at the root level.
+ */
namelen = 1;
emptynode:
+ /* Reset len in case a failed recursive call changed it. */
*len = level;
}
- return (1);
+ return (ENOENT);
}
static int
@@ -1151,18 +1199,18 @@ sysctl_sysctl_next(SYSCTL_HANDLER_ARGS)
{
int *name = (int *) arg1;
u_int namelen = arg2;
- int i, j, error;
- struct sysctl_oid *oid;
+ int len, error;
struct sysctl_oid_list *lsp = &sysctl__children;
struct rm_priotracker tracker;
- int newoid[CTL_MAXNAME];
+ int next[CTL_MAXNAME];
SYSCTL_RLOCK(&tracker);
- i = sysctl_sysctl_next_ls(lsp, name, namelen, newoid, &j, 1, &oid);
+ error = sysctl_sysctl_next_ls(lsp, name, namelen, next, &len, 1,
+ oidp->oid_number == CTL_SYSCTL_NEXT);
SYSCTL_RUNLOCK(&tracker);
- if (i)
- return (ENOENT);
- error = SYSCTL_OUT(req, newoid, j * sizeof (int));
+ if (error)
+ return (error);
+ error = SYSCTL_OUT(req, next, len * sizeof (int));
return (error);
}
@@ -1171,6 +1219,9 @@ sysctl_sysctl_next(SYSCTL_HANDLER_ARGS)
* capability mode.
*/
static SYSCTL_NODE(_sysctl, CTL_SYSCTL_NEXT, next, CTLFLAG_RD |
+ CTLFLAG_MPSAFE | CTLFLAG_CAPRD, sysctl_sysctl_next, "");
+
+static SYSCTL_NODE(_sysctl, CTL_SYSCTL_NEXTNOSKIP, nextnoskip, CTLFLAG_RD |
CTLFLAG_MPSAFE | CTLFLAG_CAPRD, sysctl_sysctl_next, "");
static int
Modified: stable/12/sys/sys/sysctl.h
==============================================================================
--- stable/12/sys/sys/sysctl.h Mon Nov 2 19:56:15 2020 (r367282)
+++ stable/12/sys/sys/sysctl.h Mon Nov 2 20:00:50 2020 (r367283)
@@ -867,11 +867,12 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_entry);
*/
#define CTL_SYSCTL_DEBUG 0 /* printf all nodes */
#define CTL_SYSCTL_NAME 1 /* string name of OID */
-#define CTL_SYSCTL_NEXT 2 /* next OID */
+#define CTL_SYSCTL_NEXT 2 /* next OID, honoring CTLFLAG_SKIP */
#define CTL_SYSCTL_NAME2OID 3 /* int array of name */
#define CTL_SYSCTL_OIDFMT 4 /* OID's kind and format */
#define CTL_SYSCTL_OIDDESCR 5 /* OID's description */
#define CTL_SYSCTL_OIDLABEL 6 /* aggregation label */
+#define CTL_SYSCTL_NEXTNOSKIP 7 /* next OID, ignoring CTLFLAG_SKIP */
/*
* CTL_KERN identifiers
Modified: stable/12/usr.bin/truss/syscalls.c
==============================================================================
--- stable/12/usr.bin/truss/syscalls.c Mon Nov 2 19:56:15 2020 (r367282)
+++ stable/12/usr.bin/truss/syscalls.c Mon Nov 2 20:00:50 2020 (r367283)
@@ -2339,6 +2339,9 @@ print_arg(struct syscall_args *sc, unsigned long *args
fprintf(fp, "oidlabel ");
print_sysctl(fp, oid + 2, len - 2);
break;
+ case CTL_SYSCTL_NEXTNOSKIP:
+ fprintf(fp, "nextnoskip");
+ break;
default:
print_sysctl(fp, oid + 1, len - 1);
}
More information about the svn-src-stable
mailing list