Index: sys/dev/hyperv/hvsock/hv_sock.c =================================================================== --- sys/dev/hyperv/hvsock/hv_sock.c +++ sys/dev/hyperv/hvsock/hv_sock.c @@ -300,6 +300,7 @@ { memset(addr, 0, sizeof(*addr)); addr->sa_family = AF_HYPERV; + addr->sa_len = sizeof(*addr); addr->hvs_port = port; } @@ -430,6 +431,12 @@ __func__, sa->sa_family); return (EAFNOSUPPORT); } + if (sa->sa_len != sizeof(*sa)) { + HVSOCK_DBG(HVSOCK_DBG_ERR, + "%s: Not supported, sa_len is %u\n", + __func__, sa->sa_len); + return (EINVAL); + } HVSOCK_DBG(HVSOCK_DBG_VERBOSE, "%s: binding port = 0x%x\n", __func__, sa->hvs_port); @@ -521,6 +528,8 @@ return (EINVAL); if (raddr->sa_family != AF_HYPERV) return (EAFNOSUPPORT); + if (raddr->sa_len != sizeof(*raddr)) + return (EINVAL); mtx_lock(&hvs_trans_socks_mtx); if (so->so_state & Index: sys/netgraph/ng_socket.c =================================================================== --- sys/netgraph/ng_socket.c +++ sys/netgraph/ng_socket.c @@ -240,6 +240,11 @@ goto release; } + if (sap->sg_len > NG_NODESIZ + 2) { + error = EINVAL; + goto release; + } + /* * Allocate an expendable buffer for the path, chop off * the sockaddr header, and make sure it's NUL terminated. @@ -422,10 +427,15 @@ goto release; } - if (sap == NULL) + if (sap == NULL) { len = 0; /* Make compiler happy. */ - else + } else { + if (sap->sg_len > NG_NODESIZ + 2) { + error = EINVAL; + goto release; + } len = sap->sg_len - 2; + } /* * If the user used any of these ways to not specify an address Index: sys/netinet/in_pcb.c =================================================================== --- sys/netinet/in_pcb.c +++ sys/netinet/in_pcb.c @@ -654,6 +654,10 @@ { int anonport, error; + KASSERT(nam == NULL || nam->sa_family == AF_INET, + ("%s: invalid address family for %p", __func__, nam)); + KASSERT(nam == NULL || nam->sa_len == sizeof(struct sockaddr_in), + ("%s: invalid address length for %p", __func__, nam)); INP_WLOCK_ASSERT(inp); INP_HASH_WLOCK_ASSERT(inp->inp_pcbinfo); @@ -940,16 +944,11 @@ return (error); } else { sin = (struct sockaddr_in *)nam; - if (nam->sa_len != sizeof (*sin)) - return (EINVAL); -#ifdef notdef - /* - * We should check the family, but old programs - * incorrectly fail to initialize it. - */ - if (sin->sin_family != AF_INET) - return (EAFNOSUPPORT); -#endif + KASSERT(sin->sin_family == AF_INET, + ("%s: invalid family for address %p", __func__, sin)); + KASSERT(sin->sin_len == sizeof(*sin), + ("%s: invalid length for address %p", __func__, sin)); + error = prison_local_ip4(cred, &sin->sin_addr); if (error) return (error); @@ -1372,6 +1371,11 @@ u_short lport, fport; int error; + KASSERT(sin->sin_family == AF_INET, + ("%s: invalid address family for %p", __func__, sin)); + KASSERT(sin->sin_len == sizeof(*sin), + ("%s: invalid address length for %p", __func__, sin)); + /* * Because a global state change doesn't actually occur here, a read * lock is sufficient. @@ -1382,10 +1386,6 @@ if (oinpp != NULL) *oinpp = NULL; - if (nam->sa_len != sizeof (*sin)) - return (EINVAL); - if (sin->sin_family != AF_INET) - return (EAFNOSUPPORT); if (sin->sin_port == 0) return (EADDRNOTAVAIL); laddr.s_addr = *laddrp; Index: sys/netinet/ip_divert.c =================================================================== --- sys/netinet/ip_divert.c +++ sys/netinet/ip_divert.c @@ -327,6 +327,13 @@ struct ipfw_rule_ref *dt; int error, family; + if (sin != NULL) { + if (sin->sin_family != AF_INET) + return (EAFNOSUPPORT); + if (sin->sin_len != sizeof(*sin)) + return (EINVAL); + } + /* * An mbuf may hasn't come from userland, but we pretend * that it has. @@ -628,6 +635,8 @@ */ if (nam->sa_family != AF_INET) return EAFNOSUPPORT; + if (nam->sa_len != sizeof(struct sockaddr_in)) + return EINVAL; ((struct sockaddr_in *)nam)->sin_addr.s_addr = INADDR_ANY; INP_INFO_WLOCK(&V_divcbinfo); INP_WLOCK(inp); Index: sys/netinet/raw_ip.c =================================================================== --- sys/netinet/raw_ip.c +++ sys/netinet/raw_ip.c @@ -996,6 +996,8 @@ struct inpcb *inp; int error; + if (nam->sa_family != AF_INET) + return (EAFNOSUPPORT); if (nam->sa_len != sizeof(*addr)) return (EINVAL); @@ -1070,6 +1072,7 @@ { struct inpcb *inp; u_long dst; + int error; inp = sotoinpcb(so); KASSERT(inp != NULL, ("rip_send: inp == NULL")); @@ -1084,9 +1087,16 @@ } dst = inp->inp_faddr.s_addr; /* Unlocked read. */ } else { - if (nam == NULL) { + error = 0; + if (nam == NULL) + error = ENOTCONN; + else if (nam->sa_family != AF_INET) + error = EAFNOSUPPORT; + else if (nam->sa_len != sizeof(struct sockaddr_in)) + error = EINVAL; + if (error != 0) { m_freem(m); - return (ENOTCONN); + return (error); } dst = ((struct sockaddr_in *)nam)->sin_addr.s_addr; } Index: sys/netinet/sctp_usrreq.c =================================================================== --- sys/netinet/sctp_usrreq.c +++ sys/netinet/sctp_usrreq.c @@ -598,29 +598,27 @@ ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) || (inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE))) { goto connected_type; - } else if (addr == NULL) { + } + + error = 0; + if (addr == NULL) { SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EDESTADDRREQ); error = EDESTADDRREQ; - sctp_m_freem(m); - if (control) { - sctp_m_freem(control); - control = NULL; - } - return (error); + } else if (addr->sa_family != AF_INET) { + SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT); + error = EAFNOSUPPORT; + } else if (addr->sa_len != sizeof(struct sockaddr_in)) { + SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + error = EINVAL; } -#ifdef INET6 - if (addr->sa_family != AF_INET) { - /* must be a v4 address! */ - SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EDESTADDRREQ); + if (error != 0) { sctp_m_freem(m); if (control) { sctp_m_freem(control); control = NULL; } - error = EDESTADDRREQ; return (error); } -#endif /* INET6 */ connected_type: /* now what about control */ if (control) { Index: sys/netinet/tcp_usrreq.c =================================================================== --- sys/netinet/tcp_usrreq.c +++ sys/netinet/tcp_usrreq.c @@ -321,14 +321,16 @@ struct sockaddr_in *sinp; sinp = (struct sockaddr_in *)nam; - if (nam->sa_len != sizeof (*sinp)) + if (nam->sa_family != AF_INET) + return (EAFNOSUPPORT); + if (nam->sa_len != sizeof(*sinp)) return (EINVAL); + /* * Must check for multicast addresses and disallow binding * to them. */ - if (sinp->sin_family == AF_INET && - IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) + if (IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) return (EAFNOSUPPORT); TCPDEBUG0; @@ -364,14 +366,16 @@ u_char vflagsav; sin6 = (struct sockaddr_in6 *)nam; - if (nam->sa_len != sizeof (*sin6)) + if (nam->sa_family != AF_INET6) + return (EAFNOSUPPORT); + if (nam->sa_len != sizeof(*sin6)) return (EINVAL); + /* * Must check for multicast addresses and disallow binding * to them. */ - if (sin6->sin6_family == AF_INET6 && - IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) + if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) return (EAFNOSUPPORT); TCPDEBUG0; @@ -542,16 +546,17 @@ struct sockaddr_in *sinp; sinp = (struct sockaddr_in *)nam; + if (nam->sa_family != AF_INET) + return (EAFNOSUPPORT); if (nam->sa_len != sizeof (*sinp)) return (EINVAL); + /* * Must disallow TCP ``connections'' to multicast addresses. */ - if (sinp->sin_family == AF_INET - && IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) + if (IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) return (EAFNOSUPPORT); - if ((sinp->sin_family == AF_INET) && - (ntohl(sinp->sin_addr.s_addr) == INADDR_BROADCAST)) + if (ntohl(sinp->sin_addr.s_addr) == INADDR_BROADCAST) return (EACCES); if ((error = prison_remote_ip4(td->td_ucred, &sinp->sin_addr)) != 0) return (error); @@ -606,13 +611,15 @@ TCPDEBUG0; sin6 = (struct sockaddr_in6 *)nam; + if (nam->sa_family != AF_INET6) + return (EAFNOSUPPORT); if (nam->sa_len != sizeof (*sin6)) return (EINVAL); + /* * Must disallow TCP ``connections'' to multicast addresses. */ - if (sin6->sin6_family == AF_INET6 - && IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) + if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) return (EAFNOSUPPORT); inp = sotoinpcb(so); Index: sys/netinet/udp_usrreq.c =================================================================== --- sys/netinet/udp_usrreq.c +++ sys/netinet/udp_usrreq.c @@ -1626,6 +1626,12 @@ pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol); inp = sotoinpcb(so); KASSERT(inp != NULL, ("udp_bind: inp == NULL")); + + if (nam->sa_family != AF_INET) + return (EAFNOSUPPORT); + if (nam->sa_len != sizeof(struct sockaddr_in)) + return (EINVAL); + INP_WLOCK(inp); INP_HASH_WLOCK(pcbinfo); error = in_pcbbind(inp, nam, td->td_ucred); @@ -1666,12 +1672,18 @@ pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol); inp = sotoinpcb(so); KASSERT(inp != NULL, ("udp_connect: inp == NULL")); + + sin = (struct sockaddr_in *)nam; + if (sin->sin_family != AF_INET) + return (EAFNOSUPPORT); + if (sin->sin_len != sizeof(*sin)) + return (EINVAL); + INP_WLOCK(inp); if (inp->inp_faddr.s_addr != INADDR_ANY) { INP_WUNLOCK(inp); return (EISCONN); } - sin = (struct sockaddr_in *)nam; error = prison_remote_ip4(td->td_ucred, &sin->sin_addr); if (error != 0) { INP_WUNLOCK(inp); @@ -1741,9 +1753,23 @@ struct mbuf *control, struct thread *td) { struct inpcb *inp; + int error; inp = sotoinpcb(so); KASSERT(inp != NULL, ("udp_send: inp == NULL")); + + if (addr != NULL) { + error = 0; + if (addr->sa_family != AF_INET) + error = EAFNOSUPPORT; + else if (addr->sa_len != sizeof(struct sockaddr_in)) + error = EINVAL; + if (__predict_false(error != 0)) { + m_freem(control); + m_freem(m); + return (error); + } + } return (udp_output(inp, m, addr, control, td, flags)); } #endif /* INET */ Index: sys/netinet6/in6_pcb.c =================================================================== --- sys/netinet6/in6_pcb.c +++ sys/netinet6/in6_pcb.c @@ -146,13 +146,10 @@ return (error); } else { sin6 = (struct sockaddr_in6 *)nam; - if (nam->sa_len != sizeof(*sin6)) - return (EINVAL); - /* - * family check. - */ - if (nam->sa_family != AF_INET6) - return (EAFNOSUPPORT); + KASSERT(sin6->sin6_family == AF_INET6, + ("%s: invalid address family for %p", __func__, sin6)); + KASSERT(sin6->sin6_len == sizeof(*sin6), + ("%s: invalid address length for %p", __func__, sin6)); if ((error = sa6_embedscope(sin6, V_ip6_use_defzone)) != 0) return(error); @@ -345,10 +342,9 @@ * have forced minor changes in every protocol). */ static int -in6_pcbladdr(struct inpcb *inp, struct sockaddr *nam, +in6_pcbladdr(struct inpcb *inp, struct sockaddr_in6 *sin6, struct in6_addr *plocal_addr6) { - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam; int error = 0; int scope_ambiguous = 0; struct in6_addr in6a; @@ -357,10 +353,6 @@ INP_WLOCK_ASSERT(inp); INP_HASH_WLOCK_ASSERT(inp->inp_pcbinfo); /* XXXRW: why? */ - if (nam->sa_len != sizeof (*sin6)) - return (EINVAL); - if (sin6->sin6_family != AF_INET6) - return (EAFNOSUPPORT); if (sin6->sin6_port == 0) return (EADDRNOTAVAIL); @@ -421,6 +413,11 @@ struct sockaddr_in6 laddr6; int error; + KASSERT(sin6->sin6_family == AF_INET6, + ("%s: invalid address family for %p", __func__, sin6)); + KASSERT(sin6->sin6_len == sizeof(*sin6), + ("%s: invalid address length for %p", __func__, sin6)); + bzero(&laddr6, sizeof(laddr6)); laddr6.sin6_family = AF_INET6; @@ -442,7 +439,7 @@ * Call inner routine, to assign local interface address. * in6_pcbladdr() may automatically fill in sin6_scope_id. */ - if ((error = in6_pcbladdr(inp, nam, &laddr6.sin6_addr)) != 0) + if ((error = in6_pcbladdr(inp, sin6, &laddr6.sin6_addr)) != 0) return (error); if (in6_pcblookup_hash_locked(pcbinfo, &sin6->sin6_addr, Index: sys/netinet6/raw_ip6.c =================================================================== --- sys/netinet6/raw_ip6.c +++ sys/netinet6/raw_ip6.c @@ -760,6 +760,8 @@ inp = sotoinpcb(so); KASSERT(inp != NULL, ("rip6_bind: inp == NULL")); + if (nam->sa_family != AF_INET6) + return (EAFNOSUPPORT); if (nam->sa_len != sizeof(*addr)) return (EINVAL); if ((error = prison_check_ip6(td->td_ucred, &addr->sin6_addr)) != 0) @@ -891,6 +893,10 @@ m_freem(m); return (ENOTCONN); } + if (nam->sa_family != AF_INET6) { + m_freem(m); + return (EAFNOSUPPORT); + } if (nam->sa_len != sizeof(struct sockaddr_in6)) { m_freem(m); return (EINVAL); Index: sys/netinet6/sctp6_usrreq.c =================================================================== --- sys/netinet6/sctp6_usrreq.c +++ sys/netinet6/sctp6_usrreq.c @@ -709,6 +709,27 @@ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EDESTADDRREQ); return (EDESTADDRREQ); } + switch (addr->sa_family) { +#ifdef INET + case AF_INET: + if (addr->sa_len != sizeof(struct sockaddr_in)) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL); + return (EINVAL); + } + break; +#endif +#ifdef INET6 + case AF_INET6: + if (addr->sa_len != sizeof(struct sockaddr_in6)) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL); + return (EINVAL); + } + break; +#endif + default: + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL); + return (EINVAL); + } #ifdef INET sin6 = (struct sockaddr_in6 *)addr; if (SCTP_IPV6_V6ONLY(inp)) { Index: sys/netinet6/send.c =================================================================== --- sys/netinet6/send.c +++ sys/netinet6/send.c @@ -231,6 +231,14 @@ __func__, so, V_send_so)); sendsrc = (struct sockaddr_send *)nam; + if (sendsrc->send_family != AF_INET6) { + error = EAFNOSUPPORT; + goto err; + } + if (sendsrc->send_len != sizeof(*sendsrc)) { + error = EINVAL; + goto err; + } ifp = ifnet_byindex_ref(sendsrc->send_ifidx); if (ifp == NULL) { error = ENETUNREACH; Index: sys/netinet6/udp6_usrreq.c =================================================================== --- sys/netinet6/udp6_usrreq.c +++ sys/netinet6/udp6_usrreq.c @@ -1091,6 +1091,11 @@ inp = sotoinpcb(so); KASSERT(inp != NULL, ("udp6_bind: inp == NULL")); + if (nam->sa_family != AF_INET6) + return (EAFNOSUPPORT); + if (nam->sa_len != sizeof(struct sockaddr_in6)) + return (EINVAL); + INP_WLOCK(inp); INP_HASH_WLOCK(pcbinfo); vflagsav = inp->inp_vflag; @@ -1176,9 +1181,14 @@ pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol); inp = sotoinpcb(so); - sin6 = (struct sockaddr_in6 *)nam; KASSERT(inp != NULL, ("udp6_connect: inp == NULL")); + sin6 = (struct sockaddr_in6 *)nam; + if (sin6->sin6_family != AF_INET6) + return (EAFNOSUPPORT); + if (sin6->sin6_len != sizeof(*sin6)) + return (EINVAL); + /* * XXXRW: Need to clarify locking of v4/v6 flags. */ Index: sys/netipsec/keysock.c =================================================================== --- sys/netipsec/keysock.c +++ sys/netipsec/keysock.c @@ -322,7 +322,7 @@ static int key_bind(struct socket *so, struct sockaddr *nam, struct thread *td) { - return EINVAL; + return EINVAL; } /* Index: sys/ofed/drivers/infiniband/ulp/sdp/sdp_main.c =================================================================== --- sys/ofed/drivers/infiniband/ulp/sdp/sdp_main.c +++ sys/ofed/drivers/infiniband/ulp/sdp/sdp_main.c @@ -519,9 +519,9 @@ struct sockaddr_in *sin; sin = (struct sockaddr_in *)nam; - if (nam->sa_len != sizeof (*sin)) - return (EINVAL); if (sin->sin_family != AF_INET) + return (EAFNOSUPPORT); + if (nam->sa_len != sizeof(*sin)) return (EINVAL); if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) return (EAFNOSUPPORT); @@ -932,6 +932,17 @@ int error; int cnt; + if (nam != NULL) { + if (nam->sa_family != AF_INET) { + m_freem(m); + return (EAFNOSUPPORT); + } + if (nam->sa_len != sizeof(struct sockaddr_in)) { + m_freem(m); + return (EINVAL); + } + } + error = 0; ssk = sdp_sk(so); KASSERT(m->m_flags & M_PKTHDR,