Index: sys/kern/uipc_socket.c =================================================================== --- sys/kern/uipc_socket.c +++ sys/kern/uipc_socket.c @@ -3741,6 +3741,9 @@ struct sockaddr *addr, struct mbuf *control, struct thread *td) { + m_freem(control); + if ((flags & PRUS_NOTREADY) == 0) + m_freem(m); return EOPNOTSUPP; } Index: sys/netinet/ip_divert.c =================================================================== --- sys/netinet/ip_divert.c +++ sys/netinet/ip_divert.c @@ -676,6 +676,7 @@ if (m->m_len < sizeof (struct ip) && (m = m_pullup(m, sizeof (struct ip))) == NULL) { KMOD_IPSTAT_INC(ips_toosmall); + m_freem(control); m_freem(m); return EINVAL; } Index: sys/netinet/raw_ip.c =================================================================== --- sys/netinet/raw_ip.c +++ sys/netinet/raw_ip.c @@ -1077,13 +1077,16 @@ inp = sotoinpcb(so); KASSERT(inp != NULL, ("rip_send: inp == NULL")); + m_freem(control); + control = NULL; + /* * Note: 'dst' reads below are unlocked. */ if (so->so_state & SS_ISCONNECTED) { if (nam) { - m_freem(m); - return (EISCONN); + error = EISCONN; + goto release; } dst = inp->inp_faddr.s_addr; /* Unlocked read. */ } else { @@ -1094,13 +1097,15 @@ error = EAFNOSUPPORT; else if (nam->sa_len != sizeof(struct sockaddr_in)) error = EINVAL; - if (error != 0) { - m_freem(m); - return (error); - } + if (error != 0) + goto release; dst = ((struct sockaddr_in *)nam)->sin_addr.s_addr; } return (rip_output(m, so, dst)); + +release: + m_freem(m); + return (error); } #endif /* INET */ Index: sys/netinet/tcp_usrreq.c =================================================================== --- sys/netinet/tcp_usrreq.c +++ sys/netinet/tcp_usrreq.c @@ -991,23 +991,32 @@ incflagsav = inp->inp_inc.inc_flags; restoreflags = false; if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) { - if (control) - m_freem(control); + m_freem(control); + /* * In case of PRUS_NOTREADY, tcp_usr_ready() is responsible * for freeing memory. */ - if (m && (flags & PRUS_NOTREADY) == 0) + if ((flags & PRUS_NOTREADY) == 0) m_freem(m); error = ECONNRESET; goto out; } + if (control != NULL) { + /* TCP doesn't do control messages (rights, creds, etc) */ + if (control->m_len) { + m_freem(control); + m_freem(m); + error = EINVAL; + goto out; + } + m_freem(control); /* empty control, just free it */ + control = NULL; + } tp = intotcpcb(inp); if (flags & PRUS_OOB) { if ((error = tcp_pru_options_support(tp, PRUS_OOB)) != 0) { - if (control) - m_freem(control); - if (m && (flags & PRUS_NOTREADY) == 0) + if ((flags & PRUS_NOTREADY) == 0) m_freem(m); goto out; } @@ -1019,33 +1028,28 @@ case AF_INET: sinp = (struct sockaddr_in *)nam; if (sinp->sin_len != sizeof(struct sockaddr_in)) { - if (m) - m_freem(m); + m_freem(m); error = EINVAL; goto out; } if ((inp->inp_vflag & INP_IPV6) != 0) { - if (m) - m_freem(m); + m_freem(m); error = EAFNOSUPPORT; goto out; } if (IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) { - if (m) - m_freem(m); + m_freem(m); error = EAFNOSUPPORT; goto out; } if (ntohl(sinp->sin_addr.s_addr) == INADDR_BROADCAST) { - if (m) - m_freem(m); + m_freem(m); error = EACCES; goto out; } if ((error = prison_remote_ip4(td->td_ucred, &sinp->sin_addr))) { - if (m) - m_freem(m); + m_freem(m); goto out; } #ifdef INET6 @@ -1060,20 +1064,17 @@ sin6 = (struct sockaddr_in6 *)nam; if (sin6->sin6_len != sizeof(*sin6)) { - if (m) - m_freem(m); + m_freem(m); error = EINVAL; goto out; } if ((inp->inp_vflag & INP_IPV6PROTO) == 0) { - if (m != NULL) - m_freem(m); + m_freem(m); error = EAFNOSUPPORT; goto out; } if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { - if (m) - m_freem(m); + m_freem(m); error = EAFNOSUPPORT; goto out; } @@ -1081,14 +1082,12 @@ #ifdef INET if ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0) { error = EINVAL; - if (m) - m_freem(m); + m_freem(m); goto out; } if ((inp->inp_vflag & INP_IPV4) == 0) { error = EAFNOSUPPORT; - if (m) - m_freem(m); + m_freem(m); goto out; } restoreflags = true; @@ -1098,27 +1097,23 @@ if (IN_MULTICAST( ntohl(sinp->sin_addr.s_addr))) { error = EAFNOSUPPORT; - if (m) - m_freem(m); + m_freem(m); goto out; } if ((error = prison_remote_ip4(td->td_ucred, &sinp->sin_addr))) { - if (m) - m_freem(m); + m_freem(m); goto out; } isipv6 = 0; #else /* !INET */ error = EAFNOSUPPORT; - if (m) - m_freem(m); + m_freem(m); goto out; #endif /* INET */ } else { if ((inp->inp_vflag & INP_IPV6) == 0) { - if (m) - m_freem(m); + m_freem(m); error = EAFNOSUPPORT; goto out; } @@ -1127,8 +1122,7 @@ inp->inp_inc.inc_flags |= INC_ISIPV6; if ((error = prison_remote_ip6(td->td_ucred, &sin6->sin6_addr))) { - if (m) - m_freem(m); + m_freem(m); goto out; } isipv6 = 1; @@ -1137,23 +1131,11 @@ } #endif /* INET6 */ default: - if (m) - m_freem(m); + m_freem(m); error = EAFNOSUPPORT; goto out; } } - if (control) { - /* TCP doesn't do control messages (rights, creds, etc) */ - if (control->m_len) { - m_freem(control); - if (m) - m_freem(m); - error = EINVAL; - goto out; - } - m_freem(control); /* empty control, just free it */ - } if (!(flags & PRUS_OOB)) { sbappendstream(&so->so_snd, m, flags); if (nam && tp->t_state < TCPS_SYN_SENT) { Index: sys/netinet/udp_usrreq.c =================================================================== --- sys/netinet/udp_usrreq.c +++ sys/netinet/udp_usrreq.c @@ -1273,6 +1273,7 @@ break; } m_freem(control); + control = NULL; } if (error) goto release; Index: sys/netinet6/raw_ip6.c =================================================================== --- sys/netinet6/raw_ip6.c +++ sys/netinet6/raw_ip6.c @@ -867,7 +867,7 @@ struct inpcb *inp; struct sockaddr_in6 tmp; struct sockaddr_in6 *dst; - int ret; + int error; inp = sotoinpcb(so); KASSERT(inp != NULL, ("rip6_send: inp == NULL")); @@ -876,8 +876,8 @@ /* Unlocked read. */ if (so->so_state & SS_ISCONNECTED) { if (nam) { - m_freem(m); - return (EISCONN); + error = EISCONN; + goto release; } /* XXX */ bzero(&tmp, sizeof(tmp)); @@ -889,18 +889,15 @@ INP_RUNLOCK(inp); dst = &tmp; } else { - if (nam == NULL) { - 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); - } + error = 0; + if (nam == NULL) + error = ENOTCONN; + else if (nam->sa_family != AF_INET6) + error = EAFNOSUPPORT; + else if (nam->sa_len != sizeof(struct sockaddr_in6)) + error = EINVAL; + if (error != 0) + goto release; tmp = *(struct sockaddr_in6 *)nam; dst = &tmp; @@ -914,12 +911,16 @@ "unspec. Assume AF_INET6\n"); dst->sin6_family = AF_INET6; } else if (dst->sin6_family != AF_INET6) { - m_freem(m); - return(EAFNOSUPPORT); + error = EAFNOSUPPORT; + goto release; } } - ret = rip6_output(m, so, dst, control); - return (ret); + return (rip6_output(m, so, dst, control)); + +release: + m_freem(control); + m_freem(m); + return (error); } struct pr_usrreqs rip6_usrreqs = { Index: sys/netinet6/sctp6_usrreq.c =================================================================== --- sys/netinet6/sctp6_usrreq.c +++ sys/netinet6/sctp6_usrreq.c @@ -713,6 +713,8 @@ #ifdef INET case AF_INET: if (addr->sa_len != sizeof(struct sockaddr_in)) { + SCTP_RELEASE_PKT(m); + SCTP_RELEASE_PKT(control); SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL); return (EINVAL); } @@ -721,12 +723,16 @@ #ifdef INET6 case AF_INET6: if (addr->sa_len != sizeof(struct sockaddr_in6)) { + SCTP_RELEASE_PKT(m); + SCTP_RELEASE_PKT(control); SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL); return (EINVAL); } break; #endif default: + SCTP_RELEASE_PKT(m); + SCTP_RELEASE_PKT(control); SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL); return (EINVAL); } @@ -738,10 +744,14 @@ * v4 addr or v4-mapped addr */ if (addr->sa_family == AF_INET) { + SCTP_RELEASE_PKT(m); + SCTP_RELEASE_PKT(control); SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL); return (EINVAL); } if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { + SCTP_RELEASE_PKT(m); + SCTP_RELEASE_PKT(control); SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL); return (EINVAL); } Index: sys/netinet6/send.c =================================================================== --- sys/netinet6/send.c +++ sys/netinet6/send.c @@ -250,8 +250,11 @@ m = NULL; err: + if (control != NULL) + m_freem(control); if (m != NULL) m_freem(m); + return (error); }