[openssh-commits] [openssh] 01/01: bounds checking for getrrsetbyname() replacement;

git+noreply at mindrot.org git+noreply at mindrot.org
Fri Mar 10 16:03:24 AEDT 2023


This is an automated email from the git hooks/post-receive script.

djm pushed a commit to branch master
in repository openssh.

commit 0fda9d704d3bbf54a5e64ce02a6fecb11fe7f047
Author: Damien Miller <djm at mindrot.org>
Date:   Fri Mar 10 15:59:46 2023 +1100

    bounds checking for getrrsetbyname() replacement;
    
    Spotted by Coverity in CID 405033; ok millert@
---
 openbsd-compat/getrrsetbyname.c | 49 +++++++++++++++++++++++++++++++++--------
 1 file changed, 40 insertions(+), 9 deletions(-)

diff --git a/openbsd-compat/getrrsetbyname.c b/openbsd-compat/getrrsetbyname.c
index 73de5e94..8f593984 100644
--- a/openbsd-compat/getrrsetbyname.c
+++ b/openbsd-compat/getrrsetbyname.c
@@ -390,6 +390,9 @@ parse_dns_response(const u_char *answer, int size)
 	struct dns_response *resp;
 	const u_char *cp;
 
+	if (size < HFIXEDSZ)
+		return (NULL);
+
 	/* allocate memory for the response */
 	resp = calloc(1, sizeof(*resp));
 	if (resp == NULL)
@@ -456,14 +459,22 @@ parse_dns_qsection(const u_char *answer, int size, const u_char **cp, int count)
 	int i, length;
 	char name[MAXDNAME];
 
-	for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) {
+#define NEED(need) \
+	do { \
+		if (*cp + need > answer + size) \
+			goto fail; \
+	} while (0)
 
+	for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) {
+		if (*cp >= answer + size) {
+ fail:
+			free_dns_query(head);
+			return (NULL);
+		}
 		/* allocate and initialize struct */
 		curr = calloc(1, sizeof(struct dns_query));
-		if (curr == NULL) {
-			free_dns_query(head);
-			return (NULL);
-		}
+		if (curr == NULL)
+			goto fail;
 		if (head == NULL)
 			head = curr;
 		if (prev != NULL)
@@ -481,16 +492,20 @@ parse_dns_qsection(const u_char *answer, int size, const u_char **cp, int count)
 			free_dns_query(head);
 			return (NULL);
 		}
+		NEED(length);
 		*cp += length;
 
 		/* type */
+		NEED(INT16SZ);
 		curr->type = _getshort(*cp);
 		*cp += INT16SZ;
 
 		/* class */
+		NEED(INT16SZ);
 		curr->class = _getshort(*cp);
 		*cp += INT16SZ;
 	}
+#undef NEED
 
 	return (head);
 }
@@ -503,14 +518,23 @@ parse_dns_rrsection(const u_char *answer, int size, const u_char **cp,
 	int i, length;
 	char name[MAXDNAME];
 
+#define NEED(need) \
+	do { \
+		if (*cp + need > answer + size) \
+			goto fail; \
+	} while (0)
+
 	for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) {
+		if (*cp >= answer + size) {
+ fail:
+			free_dns_rr(head);
+			return (NULL);
+		}
 
 		/* allocate and initialize struct */
 		curr = calloc(1, sizeof(struct dns_rr));
-		if (curr == NULL) {
-			free_dns_rr(head);
-			return (NULL);
-		}
+		if (curr == NULL)
+			goto fail;
 		if (head == NULL)
 			head = curr;
 		if (prev != NULL)
@@ -528,25 +552,31 @@ parse_dns_rrsection(const u_char *answer, int size, const u_char **cp,
 			free_dns_rr(head);
 			return (NULL);
 		}
+		NEED(length);
 		*cp += length;
 
 		/* type */
+		NEED(INT16SZ);
 		curr->type = _getshort(*cp);
 		*cp += INT16SZ;
 
 		/* class */
+		NEED(INT16SZ);
 		curr->class = _getshort(*cp);
 		*cp += INT16SZ;
 
 		/* ttl */
+		NEED(INT32SZ);
 		curr->ttl = _getlong(*cp);
 		*cp += INT32SZ;
 
 		/* rdata size */
+		NEED(INT16SZ);
 		curr->size = _getshort(*cp);
 		*cp += INT16SZ;
 
 		/* rdata itself */
+		NEED(curr->size);
 		curr->rdata = malloc(curr->size);
 		if (curr->rdata == NULL) {
 			free_dns_rr(head);
@@ -555,6 +585,7 @@ parse_dns_rrsection(const u_char *answer, int size, const u_char **cp,
 		memcpy(curr->rdata, *cp, curr->size);
 		*cp += curr->size;
 	}
+#undef NEED
 
 	return (head);
 }

-- 
To stop receiving notification emails like this one, please contact
djm at mindrot.org.


More information about the openssh-commits mailing list