summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd C. Miller <Todd.Miller@sudo.ws>2023-04-26 13:23:31 -0600
committerTodd C. Miller <Todd.Miller@sudo.ws>2023-04-26 13:23:31 -0600
commit28f4506ea2d2beaa12d9492ad18249a8d99460ab (patch)
treeb7e93621f5f0a97dba07273c8154f0c802de940e
parent802c59f1a6aed8732d73893a126b43c38f3d1258 (diff)
downloadsudo-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.c29
-rw-r--r--plugins/sudoers/regress/fuzz/fuzz_policy.c28
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;