⬢ DragonFlyBSD Kernel Audit
DF-3203 / fix.diff
← back to finding ↓ download raw
--- a/sys/vfs/nfs/krpc_subr.c
+++ b/sys/vfs/nfs/krpc_subr.c
@@ -363,13 +363,26 @@
 			}
 			if (error)
 				goto out;
-			len -= sio.sb_cc;
+			/*
+			 * sbinit() zeroes sb_cc and soreceive() counts
+			 * the DELIVERED bytes into it, so the residual
+			 * math below could never gate a UDP reply (the
+			 * max datagram is far below 65520).  Use the
+			 * received length.
+			 */
+			len = (int)sio.sb_cc;
 			m = sio.sb_mb;
 
-			/* Does the reply contain at least a header? */
-			if (len < MIN_REPLY_HDR)
+			/*
+			 * rp_status lives at offset 20..23 of the
+			 * 24-byte struct and is read below BEFORE any
+			 * m_pullup(), so require the full header up
+			 * front and pull it into the first mbuf now.
+			 */
+			if (len < (int)sizeof(struct rpc_reply))
 				continue;
-			if (m->m_len < MIN_REPLY_HDR)
+			m = m_pullup(m, sizeof(struct rpc_reply));
+			if (m == NULL)
 				continue;
 			reply = mtod(m, struct rpc_reply *);