Fix OOB read in dhcpcd.

Should have done this sooner, but hey, late is better than never.

Based on https://googleplex-android-review.git.corp.google.com/#/c/588010/.

BUG=chromium:433078
TEST=Deploy to Chromebook, connect to network, get DHCP lease.

Change-Id: I951788f8494b57328716e0246e984c1788085e1b
Reviewed-on: https://chromium-review.googlesource.com/242880
Tested-by: Jorge Lucangeli Obes <jorgelo@chromium.org>
Reviewed-by: Paul Stewart <pstew@chromium.org>
Reviewed-by: Kees Cook <keescook@chromium.org>
Commit-Queue: Jorge Lucangeli Obes <jorgelo@chromium.org>
diff --git a/dhcp.c b/dhcp.c
index 1f591e1..25c24a2 100644
--- a/dhcp.c
+++ b/dhcp.c
@@ -310,7 +310,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) {
@@ -325,7 +329,7 @@
 				memcpy(bp, op, ol);
 				bp += ol;
 			}
-			ol = *p;
+			ol = (p + *p < e) ? *p : e - (p + 1);
 			op = p + 1;
 			bl += ol;
 		}
@@ -1335,6 +1339,10 @@
 			data += sizeof(addr.s_addr);
 		} else
 			l = 0;
+		if (len <= l) {
+			bytes += len;
+			break;
+		}
 		len -= l;
 		bytes += l;
 		s += l;