summaryrefslogtreecommitdiff
path: root/libndp
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 /libndp
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>
Diffstat (limited to 'libndp')
-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;
}