diff options
author | Todd C. Miller <Todd.Miller@sudo.ws> | 2023-04-26 13:23:31 -0600 |
---|---|---|
committer | Todd C. Miller <Todd.Miller@sudo.ws> | 2023-04-26 13:23:31 -0600 |
commit | 28f4506ea2d2beaa12d9492ad18249a8d99460ab (patch) | |
tree | b7e93621f5f0a97dba07273c8154f0c802de940e | |
parent | 802c59f1a6aed8732d73893a126b43c38f3d1258 (diff) | |
download | sudo-28f4506ea2d2beaa12d9492ad18249a8d99460ab.tar.gz |
Avoid NULL deref in stub getaddrinfo() when nodename is NULL.
Also add support for parsing servname. We only need to support a
subset of getaddrinfo() functionality in the fuzzer.
-rw-r--r-- | logsrvd/regress/fuzz/fuzz_logsrvd_conf.c | 29 | ||||
-rw-r--r-- | plugins/sudoers/regress/fuzz/fuzz_policy.c | 28 |
2 files changed, 47 insertions, 10 deletions
diff --git a/logsrvd/regress/fuzz/fuzz_logsrvd_conf.c b/logsrvd/regress/fuzz/fuzz_logsrvd_conf.c index 85e38c274..07d318e9c 100644 --- a/logsrvd/regress/fuzz/fuzz_logsrvd_conf.c +++ b/logsrvd/regress/fuzz/fuzz_logsrvd_conf.c @@ -25,6 +25,7 @@ #include <stdlib.h> #include <string.h> #include <fcntl.h> +#include <limits.h> #include <netdb.h> #include <regex.h> #include <time.h> @@ -69,8 +70,8 @@ sudo_regex_compile_v1(void *v, const char *pattern, const char **errstr) /* * The fuzzing environment may not have DNS available, this may result - * in long delays that cause a timeout when fuzzing. This getaddrinfo() - * can look up "localhost" and returns an error for anything else. + * in long delays that cause a timeout when fuzzing. + * This getaddrinfo() resolves every name as "localhost" (127.0.0.1). */ #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION /* Avoid compilation errors if getaddrinfo() or freeaddrinfo() are macros. */ @@ -88,12 +89,30 @@ sudo_getaddrinfo( { struct addrinfo *ai; struct in_addr addr; + unsigned short port = 0; /* Stub getaddrinfo(3) to avoid a DNS timeout in CIfuzz. */ - if (strcmp(nodename, "localhost") != 0 || servname != NULL) - return EAI_FAIL; + if (servname == NULL) { + /* Must have either nodename or servname. */ + if (nodename == NULL) + return EAI_NONAME; + } else { + struct servent *servent; + const char *errstr; + + /* Parse servname as a port number or IPv4 TCP service name. */ + port = sudo_strtonum(servname, 0, USHRT_MAX, &errstr); + if (errstr != NULL && errno == ERANGE) + return EAI_SERVICE; + if (flags & AI_NUMERICSERV) + return EAI_NONAME; + servent = getservbyname(servname, "tcp"); + if (servent == NULL) + return EAI_NONAME; + port = htons(servent->s_port); + } - /* Hard-code localhost. */ + /* Hard-code IPv4 localhost for fuzzing. */ ai = calloc(1, sizeof(*ai) + sizeof(struct sockaddr_in)); if (ai == NULL) return EAI_MEMORY; diff --git a/plugins/sudoers/regress/fuzz/fuzz_policy.c b/plugins/sudoers/regress/fuzz/fuzz_policy.c index 5e39c3160..9d84e6b9c 100644 --- a/plugins/sudoers/regress/fuzz/fuzz_policy.c +++ b/plugins/sudoers/regress/fuzz/fuzz_policy.c @@ -173,8 +173,8 @@ fuzz_hook_stub(struct sudo_hook *hook) /* * The fuzzing environment may not have DNS available, this may result - * in long delays that cause a timeout when fuzzing. This getaddrinfo() - * can look up "localhost" and returns an error for anything else. + * in long delays that cause a timeout when fuzzing. + * This getaddrinfo() resolves every name as "localhost" (127.0.0.1). */ #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION /* Avoid compilation errors if getaddrinfo() or freeaddrinfo() are macros. */ @@ -192,12 +192,30 @@ sudo_getaddrinfo( { struct addrinfo *ai; struct in_addr addr; + unsigned short port = 0; /* Stub getaddrinfo(3) to avoid a DNS timeout in CIfuzz. */ - if (strcmp(nodename, "localhost") != 0 || servname != NULL) - return EAI_FAIL; + if (servname == NULL) { + /* Must have either nodename or servname. */ + if (nodename == NULL) + return EAI_NONAME; + } else { + struct servent *servent; + const char *errstr; + + /* Parse servname as a port number or IPv4 TCP service name. */ + port = sudo_strtonum(servname, 0, USHRT_MAX, &errstr); + if (errstr != NULL && errno == ERANGE) + return EAI_SERVICE; + if (flags & AI_NUMERICSERV) + return EAI_NONAME; + servent = getservbyname(servname, "tcp"); + if (servent == NULL) + return EAI_NONAME; + port = htons(servent->s_port); + } - /* Hard-code localhost. */ + /* Hard-code IPv4 localhost for fuzzing. */ ai = calloc(1, sizeof(*ai) + sizeof(struct sockaddr_in)); if (ai == NULL) return EAI_MEMORY; |