summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Ayer <agwa@andrewayer.name>2014-07-09 13:23:02 -0700
committerJiri Pirko <jiri@resnulli.us>2014-07-29 15:16:06 +0200
commite93d565950129a31ac1141b6589afc4e35d1cde3 (patch)
tree0445b6614164e1e21c9d851df8998d49adcff494
parentd438bc9c4c01b12f3a50d869f87565b6e3f17531 (diff)
downloadlibndp-e93d565950129a31ac1141b6589afc4e35d1cde3.tar.gz
libndp: fix buffer overflow in ndp_msg_opt_dnssl_domain()
The buf array would overflow when processing a malformed DNSSL option containing a domain name whose labels' combined length exceeded 255 bytes. To facilitate the bounds checking, the code has been restructured slightly to be simpler and avoid repeated calls to strlen and strcat. Signed-off-by: Andrew Ayer <agwa@andrewayer.name> Signed-off-by: Jiri Pirko <jiri@resnulli.us>
-rw-r--r--libndp/libndp.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/libndp/libndp.c b/libndp/libndp.c
index e510e2e..cd67356 100644
--- a/libndp/libndp.c
+++ b/libndp/libndp.c
@@ -1527,7 +1527,7 @@ char *ndp_msg_opt_dnssl_domain(struct ndp_msg *msg, int offset,
i = 0;
while (len > 0) {
- *buf = '\0';
+ size_t buf_len = 0;
while (len > 0) {
uint8_t dom_len = *ptr;
@@ -1539,15 +1539,18 @@ char *ndp_msg_opt_dnssl_domain(struct ndp_msg *msg, int offset,
if (dom_len > len)
return NULL;
- if (strlen(buf))
- strcat(buf, ".");
- buf[strlen(buf) + dom_len] = '\0';
- memcpy(buf + strlen(buf), ptr, dom_len);
+ if (buf_len + dom_len + 1 > sizeof(buf))
+ return NULL;
+
+ memcpy(buf + buf_len, ptr, dom_len);
+ buf[buf_len + dom_len] = '.';
ptr += dom_len;
len -= dom_len;
+ buf_len += dom_len + 1;
}
- if (!strlen(buf))
+ if (!buf_len)
break;
+ buf[buf_len - 1] = '\0'; /* overwrite final '.' */
if (i++ == domain_index)
return buf;
}