diff options
author | rwatson <rwatson@FreeBSD.org> | 2003-06-15 06:26:08 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2003-06-15 06:26:08 +0000 |
commit | 09805820842e7c37a7760b83e23874d446f42f85 (patch) | |
tree | 2617834aa077b214d80fd0f0e881e79caeddf04f /sbin | |
parent | e164cda7708817893926cdab4cf838b29d218f8f (diff) | |
download | FreeBSD-src-09805820842e7c37a7760b83e23874d446f42f85.zip FreeBSD-src-09805820842e7c37a7760b83e23874d446f42f85.tar.gz |
Tighten up the string->integer conversion in sysctl(8):
(1) Reject zero-length strings for CTLTYPE_INT, _UINT, _LONG,
_ULONG. Do not silently convert to 0.
(2) When converting CTLTYPE_INT, _UINT, _LONG, and _ULONG, check the
end pointer generated by strtol() and strtoul() rather than
discarding it. Reject the string if either none of the string
was useful for conversion to an integer, or if there was
trailing garbage.
I.e., we will not allow you to set a numeric sysctl to a value unless
we can completely convert the string argument to a numeric value.
I tripped over this when I put the following in /etc/sysctl.conf:
kern.maxfiles="4000"
Ouch.
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/sysctl/sysctl.c | 30 |
1 files changed, 25 insertions, 5 deletions
diff --git a/sbin/sysctl/sysctl.c b/sbin/sysctl/sysctl.c index 7442a32..787a489 100644 --- a/sbin/sysctl/sysctl.c +++ b/sbin/sysctl/sysctl.c @@ -163,7 +163,7 @@ parse(char *string) size_t newsize = 0; quad_t quadval; int mib[CTL_MAXNAME]; - char *cp, *bufp, buf[BUFSIZ], fmt[BUFSIZ]; + char *cp, *bufp, buf[BUFSIZ], *endptr, fmt[BUFSIZ]; u_int kind; bufp = buf; @@ -198,25 +198,45 @@ parse(char *string) if (!(kind&CTLFLAG_WR)) errx(1, "oid '%s' is read only", bufp); + + if ((kind & CTLTYPE) == CTLTYPE_INT || + (kind & CTLTYPE) == CTLTYPE_UINT || + (kind & CTLTYPE) == CTLTYPE_LONG || + (kind & CTLTYPE) == CTLTYPE_ULONG) { + if (strlen(newval) == 0) + errx(1, "empty numeric value"); + } switch (kind & CTLTYPE) { case CTLTYPE_INT: - intval = (int) strtol(newval, NULL, 0); + intval = (int) strtol(newval, &endptr, 0); + if (endptr == newval || *endptr != '\0') + errx(1, "invalid integer '%s'", + newval); newval = &intval; newsize = sizeof(intval); break; case CTLTYPE_UINT: - uintval = (int) strtoul(newval, NULL, 0); + uintval = (int) strtoul(newval, &endptr, 0); + if (endptr == newval || *endptr != '\0') + errx(1, "invalid unsigned integer '%s'", + newval); newval = &uintval; newsize = sizeof uintval; break; case CTLTYPE_LONG: - longval = strtol(newval, NULL, 0); + longval = strtol(newval, &endptr, 0); + if (endptr == newval || *endptr != '\0') + errx(1, "invalid long integer '%s'", + newval); newval = &longval; newsize = sizeof longval; break; case CTLTYPE_ULONG: - ulongval = strtoul(newval, NULL, 0); + ulongval = strtoul(newval, &endptr, 0); + if (endptr == newval || *endptr != '\0') + errx(1, "invalid unsigned long integer" + " '%s'", newval); newval = &ulongval; newsize = sizeof ulongval; break; |