summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2023-03-10 15:59:46 +1100
committerDamien Miller <djm@mindrot.org>2023-03-10 15:59:46 +1100
commit0fda9d704d3bbf54a5e64ce02a6fecb11fe7f047 (patch)
tree2f7fa19fa61c4d3507f41aceacff7a4cd9a0d92e
parent89b8df518f21677045599df0ad3e5dd0f39909b5 (diff)
bounds checking for getrrsetbyname() replacement;
Spotted by Coverity in CID 405033; ok millert@
-rw-r--r--openbsd-compat/getrrsetbyname.c47
1 files changed, 39 insertions, 8 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)
- /* allocate and initialize struct */
- curr = calloc(1, sizeof(struct dns_query));
- if (curr == NULL) {
+ 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)
+ 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];
- 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)
- /* allocate and initialize struct */
- curr = calloc(1, sizeof(struct dns_rr));
- if (curr == NULL) {
+ 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)
+ 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);
}