DragonFlyBSD Kernel Audit
DF-0600 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/netproto/smb/smb_usr.c b/sys/netproto/smb/smb_usr.c
--- a/sys/netproto/smb/smb_usr.c
+++ b/sys/netproto/smb/smb_usr.c
@@ -74,12 +74,29 @@
 	spec->sap = smb_memdupin(dp->ioc_server, dp->ioc_svlen);
 	if (spec->sap == NULL)
 		return ENOMEM;
+	/*
+	 * dup_sockaddr() (uipc_socket2.c) trusts sa->sa_len unconditionally
+	 * and bcopy()s that many bytes.  smb_memdupin() only allocated
+	 * ioc_svlen bytes, so sa_len > ioc_svlen drives an OOB heap read in
+	 * dup_sockaddr when smb_vc_create() copies the address.  Reject any
+	 * sa_len that does not fit in the buffer we actually allocated.
+	 * (DF-0600)
+	 */
+	if (spec->sap->sa_len < 2 || spec->sap->sa_len > dp->ioc_svlen) {
+		smb_usr_vcspec_free(spec);
+		return EINVAL;
+	}
 	if (dp->ioc_local) {
 		spec->lap = smb_memdupin(dp->ioc_local, dp->ioc_lolen);
 		if (spec->lap == NULL) {
 			smb_usr_vcspec_free(spec);
 			return ENOMEM;
 		}
+		if (spec->lap->sa_len < 2 ||
+		    spec->lap->sa_len > dp->ioc_lolen) {
+			smb_usr_vcspec_free(spec);
+			return EINVAL;
+		}
 	}
 	spec->srvname = dp->ioc_srvname;
 	spec->pass = dp->ioc_password;