--- 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 *);