⬢ DragonFlyBSD Kernel Audit
DF-3046 / fix_combined.diff
← back to finding ↓ download raw
--- a/sys/vfs/nfs/bootp_subr.c
+++ b/sys/vfs/nfs/bootp_subr.c
@@ -588,6 +588,7 @@
 	int retry;
 	const char *s;
 	char hexstr[64];
+	struct sockaddr *fromp = NULL;
 	
 	/*
 	 * Create socket and set its recieve timeout.
@@ -717,7 +718,7 @@
 				}
 				hexncpy((u_char *)LLADDR(ifctx->sdl),
 				    ifctx->sdl->sdl_alen, hexstr,
-				    HEX_NCPYLEN(ifctx->sdl->sdl_alen), ":");
+				    sizeof(hexstr), ":");
 				kprintf("Sending %s packet from "
 				       "interface %s (%s)\n",
 				       s, ifctx->ireq.ifr_name,
@@ -804,7 +805,11 @@
 			auio.uio_td = td;
 			
 			rcvflg = 0;
-			error = soreceive(so, NULL, &auio,
+			if (fromp != NULL) {
+				kfree(fromp, M_SONAME);
+				fromp = NULL;
+			}
+			error = soreceive(so, &fromp, &auio,
 					  NULL, NULL, &rcvflg);
 			gctx->secs = time_uptime - gctx->starttime;
 			for (ifctx = gctx->interfaces;
@@ -820,6 +825,13 @@
 				continue;
 			if (error != 0)
 				goto out;
+			if (fromp == NULL ||
+				((struct sockaddr_in *)fromp)->sin_port !=
+				htons(IPPORT_BOOTPS)) {
+				kprintf("bootpc: reply not from server port %d, ignored\n",
+					IPPORT_BOOTPS);
+				continue;
+			}
 			len = sizeof(gctx->reply) - auio.uio_resid;
 			
 			/* Do we have the required number of bytes ? */
@@ -1045,11 +1057,20 @@
 	sdl = NULL;
 	TAILQ_FOREACH(ifac, &ifctx->ifp->if_addrheads[mycpuid], ifa_link) {
 		struct ifaddr *ifa = ifac->ifa;
+		struct sockaddr_dl *sdl2;
 
-		if (ifa->ifa_addr->sa_family == AF_LINK &&
-		    (sdl = ((struct sockaddr_dl *) ifa->ifa_addr)) != NULL &&
-		    sdl->sdl_type == IFT_ETHER)
+		if (ifa->ifa_addr->sa_family != AF_LINK)
+			continue;
+		sdl2 = (struct sockaddr_dl *)ifa->ifa_addr;
+		/* Only accept an address that fits chaddr[16] (and is
+		 * nonzero): every byte of it is copied into the BOOTP
+		 * query and compared on replies. */
+		if (sdl2->sdl_type == IFT_ETHER &&
+		    sdl2->sdl_alen > 0 &&
+		    sdl2->sdl_alen <= sizeof(ifctx->call.chaddr)) {
+			sdl = sdl2;
 			break;
+		}
 	}
 
 	if (sdl == NULL)
@@ -1285,6 +1306,10 @@
 			return;
 		}
 		len = *j++;
+		if (code == TAG_OVERLOAD && len != 1) {
+			tctx->badopt = 1;
+			return;
+		}
 		if (code == tag) {
 			if (tctx->taglen + len > TAG_MAXLEN) {
 				tctx->badtag = 1;
@@ -1535,7 +1560,7 @@
 
 	gctx = kmalloc(sizeof(*gctx), M_TEMP, M_WAITOK | M_ZERO);
 	
-	gctx->xid = ~0xFFFF;
+	gctx->xid = karc4random();
 	gctx->starttime = time_uptime;
 	
 	ifctx = allocifctx(gctx);