Fun with buffer overrruns.
In get_option(): don't read past the end of the option buffer.
Also add a small unittest to verify sane behaviour for the above.
The dhcpcd code is not easily refactored into a library, nor is it
entirely possible to include some header files directly since some
structures use C++ reserved keywords ("new") for variable names.
In print_option(): use of snprintf() returns the length that
/would/ have been written. Add checks that the output buffer
is not overrun when printing.
Bug: 18356137
Bug: 18356135
Change-Id: I0f907b8a952208749226ba034a416d773e068f8a
diff --git a/dhcp.c b/dhcp.c
index 53f4795..0a1d220 100644
--- a/dhcp.c
+++ b/dhcp.c
@@ -313,7 +313,11 @@
const uint8_t *op = NULL;
int bl = 0;
- while (p < e) {
+ /* DHCP Options are in TLV format with T and L each being a single
+ * byte. In general, here we have p -> T, ol=p+1 -> L, op -> V.
+ * We must make sure there is enough room to read both T and L.
+ */
+ while (p + 1 < e) {
o = *p++;
if (o == opt) {
if (op) {
@@ -328,7 +332,7 @@
memcpy(bp, op, ol);
bp += ol;
}
- ol = *p;
+ ol = (p + *p < e) ? *p : e - (p + 1);
op = p + 1;
bl += ol;
}
@@ -1362,6 +1366,10 @@
data += sizeof(addr.s_addr);
} else
l = 0;
+ if (len <= l) {
+ bytes += len;
+ break;
+ }
len -= l;
bytes += l;
s += l;