cpucontrol: Be more strict with input validation
Avoid truncating 32-bit values. This would have saved me a bit of time when I was looking at a cpuid leaf on my system and typed 0x80000001f instead of 0x8000001f. Reviewed by: kib MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D54919
This commit is contained in:
@@ -36,7 +36,9 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <inttypes.h>
|
||||||
#include <paths.h>
|
#include <paths.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -112,6 +114,21 @@ usage(void)
|
|||||||
exit(EX_USAGE);
|
exit(EX_USAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t
|
||||||
|
strtouint32(const char *str, char **endptr, int base)
|
||||||
|
{
|
||||||
|
uintmax_t val;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
val = strtoumax(str, endptr, base);
|
||||||
|
if (*str == '\0' || errno == ERANGE || val > UINT32_MAX) {
|
||||||
|
WARNX(0, "invalid operand: %s", str);
|
||||||
|
exit(EX_USAGE);
|
||||||
|
/* NOTREACHED */
|
||||||
|
}
|
||||||
|
return ((uint32_t)val);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
do_cpuid(const char *cmdarg, const char *dev)
|
do_cpuid(const char *cmdarg, const char *dev)
|
||||||
{
|
{
|
||||||
@@ -123,7 +140,7 @@ do_cpuid(const char *cmdarg, const char *dev)
|
|||||||
assert(cmdarg != NULL);
|
assert(cmdarg != NULL);
|
||||||
assert(dev != NULL);
|
assert(dev != NULL);
|
||||||
|
|
||||||
level = strtoul(cmdarg, &endptr, 16);
|
level = strtouint32(cmdarg, &endptr, 16);
|
||||||
if (*cmdarg == '\0' || *endptr != '\0') {
|
if (*cmdarg == '\0' || *endptr != '\0') {
|
||||||
WARNX(0, "incorrect operand: %s", cmdarg);
|
WARNX(0, "incorrect operand: %s", cmdarg);
|
||||||
usage();
|
usage();
|
||||||
@@ -162,7 +179,7 @@ do_cpuid_count(const char *cmdarg, const char *dev)
|
|||||||
assert(cmdarg != NULL);
|
assert(cmdarg != NULL);
|
||||||
assert(dev != NULL);
|
assert(dev != NULL);
|
||||||
|
|
||||||
level = strtoul(cmdarg, &endptr, 16);
|
level = strtouint32(cmdarg, &endptr, 16);
|
||||||
if (*cmdarg == '\0' || *endptr == '\0') {
|
if (*cmdarg == '\0' || *endptr == '\0') {
|
||||||
WARNX(0, "incorrect or missing operand: %s", cmdarg);
|
WARNX(0, "incorrect or missing operand: %s", cmdarg);
|
||||||
usage();
|
usage();
|
||||||
@@ -172,7 +189,7 @@ do_cpuid_count(const char *cmdarg, const char *dev)
|
|||||||
cmdarg1 = strstr(endptr, ",");
|
cmdarg1 = strstr(endptr, ",");
|
||||||
/* ... and skip past it */
|
/* ... and skip past it */
|
||||||
cmdarg1 += 1;
|
cmdarg1 += 1;
|
||||||
level_type = strtoul(cmdarg1, &endptr1, 16);
|
level_type = strtouint32(cmdarg1, &endptr1, 16);
|
||||||
if (*cmdarg1 == '\0' || *endptr1 != '\0') {
|
if (*cmdarg1 == '\0' || *endptr1 != '\0') {
|
||||||
WARNX(0, "incorrect or missing operand: %s", cmdarg);
|
WARNX(0, "incorrect or missing operand: %s", cmdarg);
|
||||||
usage();
|
usage();
|
||||||
@@ -228,7 +245,7 @@ do_msr(const char *cmdarg, const char *dev)
|
|||||||
/*
|
/*
|
||||||
* Parse command string.
|
* Parse command string.
|
||||||
*/
|
*/
|
||||||
msr = strtoul(cmdarg, &endptr, 16);
|
msr = strtouint32(cmdarg, &endptr, 16);
|
||||||
switch (*endptr) {
|
switch (*endptr) {
|
||||||
case '\0':
|
case '\0':
|
||||||
op = OP_READ;
|
op = OP_READ;
|
||||||
|
|||||||
Reference in New Issue
Block a user