From owner-svn-src-all@FreeBSD.ORG Mon Jun 23 07:54:14 2014 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 130F6295; Mon, 23 Jun 2014 07:54:14 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id F2E5F28DE; Mon, 23 Jun 2014 07:54:13 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s5N7sDwq075932; Mon, 23 Jun 2014 07:54:13 GMT (envelope-from tuexen@svn.freebsd.org) Received: (from tuexen@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s5N7sCgp075926; Mon, 23 Jun 2014 07:54:12 GMT (envelope-from tuexen@svn.freebsd.org) Message-Id: <201406230754.s5N7sCgp075926@svn.freebsd.org> From: Michael Tuexen Date: Mon, 23 Jun 2014 07:54:12 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r267769 - stable/10/sys/netinet X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 23 Jun 2014 07:54:14 -0000 Author: tuexen Date: Mon Jun 23 07:54:12 2014 New Revision: 267769 URL: http://svnweb.freebsd.org/changeset/base/267769 Log: MFC r267674: Honor jails for unbound SCTP sockets when selecting source addresses, reporting IP-addresses to the peer during the handshake, adding addresses to the host, reporting the addresses via the sysctl interface (used by netstat, for example) and reporting the addresses to the application via socket options. This issue was reported by Bernd Walter. Modified: stable/10/sys/netinet/sctp_asconf.c stable/10/sys/netinet/sctp_output.c stable/10/sys/netinet/sctp_pcb.c stable/10/sys/netinet/sctp_sysctl.c stable/10/sys/netinet/sctp_usrreq.c stable/10/sys/netinet/sctputil.c Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/netinet/sctp_asconf.c ============================================================================== --- stable/10/sys/netinet/sctp_asconf.c Mon Jun 23 07:45:44 2014 (r267768) +++ stable/10/sys/netinet/sctp_asconf.c Mon Jun 23 07:54:12 2014 (r267769) @@ -1889,14 +1889,22 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb * * this is boundall or subset bound w/ASCONF allowed */ - /* first, make sure it's a good address family */ + /* first, make sure that the address is IPv4 or IPv6 and not jailed */ switch (ifa->address.sa.sa_family) { #ifdef INET6 case AF_INET6: + if (prison_check_ip6(inp->ip_inp.inp.inp_cred, + &ifa->address.sin6.sin6_addr) != 0) { + return; + } break; #endif #ifdef INET case AF_INET: + if (prison_check_ip4(inp->ip_inp.inp.inp_cred, + &ifa->address.sin.sin_addr) != 0) { + return; + } break; #endif default: @@ -2122,6 +2130,10 @@ sctp_asconf_iterator_stcb(struct sctp_in /* we skip unspecifed addresses */ continue; } + if (prison_check_ip6(inp->ip_inp.inp.inp_cred, + &sin6->sin6_addr) != 0) { + continue; + } if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { if (stcb->asoc.scope.local_scope == 0) { continue; @@ -2152,6 +2164,10 @@ sctp_asconf_iterator_stcb(struct sctp_in /* we skip unspecifed addresses */ continue; } + if (prison_check_ip4(inp->ip_inp.inp.inp_cred, + &sin->sin_addr) != 0) { + continue; + } if (stcb->asoc.scope.ipv4_local_scope == 0 && IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) { continue; @@ -2465,6 +2481,10 @@ sctp_find_valid_localaddr(struct sctp_tc /* skip unspecifed addresses */ continue; } + if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred, + &sin->sin_addr) != 0) { + continue; + } if (stcb->asoc.scope.ipv4_local_scope == 0 && IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) continue; @@ -2498,6 +2518,10 @@ sctp_find_valid_localaddr(struct sctp_tc */ continue; } + if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred, + &sin6->sin6_addr) != 0) { + continue; + } if (stcb->asoc.scope.local_scope == 0 && IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) continue; @@ -3112,6 +3136,10 @@ sctp_check_address_list_all(struct sctp_ #ifdef INET case AF_INET: sin = (struct sockaddr_in *)&sctp_ifa->address.sin; + if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred, + &sin->sin_addr) != 0) { + continue; + } if ((ipv4_scope == 0) && (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) { /* private address not in scope */ @@ -3122,6 +3150,10 @@ sctp_check_address_list_all(struct sctp_ #ifdef INET6 case AF_INET6: sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sin6; + if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred, + &sin6->sin6_addr) != 0) { + continue; + } if ((local_scope == 0) && (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))) { continue; @@ -3407,6 +3439,10 @@ sctp_asconf_send_nat_state_update(struct #ifdef INET case AF_INET: to = &sctp_ifap->address.sin; + if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred, + &to->sin_addr) != 0) { + continue; + } if (IN4_ISPRIVATE_ADDRESS(&to->sin_addr)) { continue; } @@ -3418,6 +3454,10 @@ sctp_asconf_send_nat_state_update(struct #ifdef INET6 case AF_INET6: to6 = &sctp_ifap->address.sin6; + if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred, + &to6->sin6_addr) != 0) { + continue; + } if (IN6_IS_ADDR_LOOPBACK(&to6->sin6_addr)) { continue; } Modified: stable/10/sys/netinet/sctp_output.c ============================================================================== --- stable/10/sys/netinet/sctp_output.c Mon Jun 23 07:45:44 2014 (r267768) +++ stable/10/sys/netinet/sctp_output.c Mon Jun 23 07:54:12 2014 (r267769) @@ -2060,6 +2060,20 @@ sctp_add_addresses_to_i_ia(struct sctp_i continue; } LIST_FOREACH(sctp_ifap, &sctp_ifnp->ifalist, next_ifa) { +#ifdef INET + if ((sctp_ifap->address.sa.sa_family == AF_INET) && + (prison_check_ip4(inp->ip_inp.inp.inp_cred, + &sctp_ifap->address.sin.sin_addr) != 0)) { + continue; + } +#endif +#ifdef INET6 + if ((sctp_ifap->address.sa.sa_family == AF_INET6) && + (prison_check_ip6(inp->ip_inp.inp.inp_cred, + &sctp_ifap->address.sin6.sin6_addr) != 0)) { + continue; + } +#endif if (sctp_is_addr_restricted(stcb, sctp_ifap)) { continue; } @@ -2089,6 +2103,20 @@ skip_count: continue; } LIST_FOREACH(sctp_ifap, &sctp_ifnp->ifalist, next_ifa) { +#ifdef INET + if ((sctp_ifap->address.sa.sa_family == AF_INET) && + (prison_check_ip4(inp->ip_inp.inp.inp_cred, + &sctp_ifap->address.sin.sin_addr) != 0)) { + continue; + } +#endif +#ifdef INET6 + if ((sctp_ifap->address.sa.sa_family == AF_INET6) && + (prison_check_ip6(inp->ip_inp.inp.inp_cred, + &sctp_ifap->address.sin6.sin6_addr) != 0)) { + continue; + } +#endif if (sctp_is_addr_restricted(stcb, sctp_ifap)) { continue; } @@ -2453,6 +2481,20 @@ sctp_choose_boundspecific_inp(struct sct if (sctp_ifn) { /* is a preferred one on the interface we route out? */ LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) { +#ifdef INET + if ((sctp_ifa->address.sa.sa_family == AF_INET) && + (prison_check_ip4(inp->ip_inp.inp.inp_cred, + &sctp_ifa->address.sin.sin_addr) != 0)) { + continue; + } +#endif +#ifdef INET6 + if ((sctp_ifa->address.sa.sa_family == AF_INET6) && + (prison_check_ip6(inp->ip_inp.inp.inp_cred, + &sctp_ifa->address.sin6.sin6_addr) != 0)) { + continue; + } +#endif if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0)) continue; @@ -2576,6 +2618,20 @@ sctp_choose_boundspecific_stcb(struct sc if (sctp_ifn) { /* first try for a preferred address on the ep */ LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) { +#ifdef INET + if ((sctp_ifa->address.sa.sa_family == AF_INET) && + (prison_check_ip4(inp->ip_inp.inp.inp_cred, + &sctp_ifa->address.sin.sin_addr) != 0)) { + continue; + } +#endif +#ifdef INET6 + if ((sctp_ifa->address.sa.sa_family == AF_INET6) && + (prison_check_ip6(inp->ip_inp.inp.inp_cred, + &sctp_ifa->address.sin6.sin6_addr) != 0)) { + continue; + } +#endif if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0)) continue; if (sctp_is_addr_in_ep(inp, sctp_ifa)) { @@ -2596,6 +2652,20 @@ sctp_choose_boundspecific_stcb(struct sc } /* next try for an acceptable address on the ep */ LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) { +#ifdef INET + if ((sctp_ifa->address.sa.sa_family == AF_INET) && + (prison_check_ip4(inp->ip_inp.inp.inp_cred, + &sctp_ifa->address.sin.sin_addr) != 0)) { + continue; + } +#endif +#ifdef INET6 + if ((sctp_ifa->address.sa.sa_family == AF_INET6) && + (prison_check_ip6(inp->ip_inp.inp.inp_cred, + &sctp_ifa->address.sin6.sin6_addr) != 0)) { + continue; + } +#endif if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0)) continue; if (sctp_is_addr_in_ep(inp, sctp_ifa)) { @@ -2700,6 +2770,7 @@ sctp_from_the_top2: static struct sctp_ifa * sctp_select_nth_preferred_addr_from_ifn_boundall(struct sctp_ifn *ifn, + struct sctp_inpcb *inp, struct sctp_tcb *stcb, int non_asoc_addr_ok, uint8_t dest_is_loop, @@ -2721,6 +2792,20 @@ sctp_select_nth_preferred_addr_from_ifn_ } #endif /* INET6 */ LIST_FOREACH(ifa, &ifn->ifalist, next_ifa) { +#ifdef INET + if ((ifa->address.sa.sa_family == AF_INET) && + (prison_check_ip4(inp->ip_inp.inp.inp_cred, + &ifa->address.sin.sin_addr) != 0)) { + continue; + } +#endif +#ifdef INET6 + if ((ifa->address.sa.sa_family == AF_INET6) && + (prison_check_ip6(inp->ip_inp.inp.inp_cred, + &ifa->address.sin6.sin6_addr) != 0)) { + continue; + } +#endif if ((ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0)) continue; @@ -2806,6 +2891,7 @@ sctp_select_nth_preferred_addr_from_ifn_ static int sctp_count_num_preferred_boundall(struct sctp_ifn *ifn, + struct sctp_inpcb *inp, struct sctp_tcb *stcb, int non_asoc_addr_ok, uint8_t dest_is_loop, @@ -2816,6 +2902,21 @@ sctp_count_num_preferred_boundall(struct int num_eligible_addr = 0; LIST_FOREACH(ifa, &ifn->ifalist, next_ifa) { +#ifdef INET + if ((ifa->address.sa.sa_family == AF_INET) && + (prison_check_ip4(inp->ip_inp.inp.inp_cred, + &ifa->address.sin.sin_addr) != 0)) { + continue; + } +#endif +#ifdef INET6 + if ((ifa->address.sa.sa_family == AF_INET6) && + (stcb != NULL) && + (prison_check_ip6(inp->ip_inp.inp.inp_cred, + &ifa->address.sin6.sin6_addr) != 0)) { + continue; + } +#endif if ((ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0)) { continue; @@ -2847,7 +2948,8 @@ sctp_count_num_preferred_boundall(struct } static struct sctp_ifa * -sctp_choose_boundall(struct sctp_tcb *stcb, +sctp_choose_boundall(struct sctp_inpcb *inp, + struct sctp_tcb *stcb, struct sctp_nets *net, sctp_route_t * ro, uint32_t vrf_id, @@ -2902,7 +3004,7 @@ sctp_choose_boundall(struct sctp_tcb *st cur_addr_num = net->indx_of_eligible_next_to_use; } num_preferred = sctp_count_num_preferred_boundall(sctp_ifn, - stcb, + inp, stcb, non_asoc_addr_ok, dest_is_loop, dest_is_priv, fam); @@ -2929,7 +3031,7 @@ sctp_choose_boundall(struct sctp_tcb *st */ SCTPDBG(SCTP_DEBUG_OUTPUT2, "cur_addr_num:%d\n", cur_addr_num); - sctp_ifa = sctp_select_nth_preferred_addr_from_ifn_boundall(sctp_ifn, stcb, non_asoc_addr_ok, dest_is_loop, + sctp_ifa = sctp_select_nth_preferred_addr_from_ifn_boundall(sctp_ifn, inp, stcb, non_asoc_addr_ok, dest_is_loop, dest_is_priv, cur_addr_num, fam, ro); /* if sctp_ifa is NULL something changed??, fall to plan b. */ @@ -2960,7 +3062,7 @@ bound_all_plan_b: SCTPDBG(SCTP_DEBUG_OUTPUT2, "already seen\n"); continue; } - num_preferred = sctp_count_num_preferred_boundall(sctp_ifn, stcb, non_asoc_addr_ok, + num_preferred = sctp_count_num_preferred_boundall(sctp_ifn, inp, stcb, non_asoc_addr_ok, dest_is_loop, dest_is_priv, fam); SCTPDBG(SCTP_DEBUG_OUTPUT2, "Found ifn:%p %d preferred source addresses\n", @@ -2982,7 +3084,7 @@ bound_all_plan_b: if (cur_addr_num >= num_preferred) { cur_addr_num = 0; } - sifa = sctp_select_nth_preferred_addr_from_ifn_boundall(sctp_ifn, stcb, non_asoc_addr_ok, dest_is_loop, + sifa = sctp_select_nth_preferred_addr_from_ifn_boundall(sctp_ifn, inp, stcb, non_asoc_addr_ok, dest_is_loop, dest_is_priv, cur_addr_num, fam, ro); if (sifa == NULL) continue; @@ -3010,6 +3112,22 @@ again_with_private_addresses_allowed: } LIST_FOREACH(sctp_ifa, &emit_ifn->ifalist, next_ifa) { SCTPDBG(SCTP_DEBUG_OUTPUT2, "ifa:%p\n", (void *)sctp_ifa); +#ifdef INET + if ((sctp_ifa->address.sa.sa_family == AF_INET) && + (prison_check_ip4(inp->ip_inp.inp.inp_cred, + &sctp_ifa->address.sin.sin_addr) != 0)) { + SCTPDBG(SCTP_DEBUG_OUTPUT2, "Jailed\n"); + continue; + } +#endif +#ifdef INET6 + if ((sctp_ifa->address.sa.sa_family == AF_INET6) && + (prison_check_ip6(inp->ip_inp.inp.inp_cred, + &sctp_ifa->address.sin6.sin6_addr) != 0)) { + SCTPDBG(SCTP_DEBUG_OUTPUT2, "Jailed\n"); + continue; + } +#endif if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0)) { SCTPDBG(SCTP_DEBUG_OUTPUT2, "Defer\n"); @@ -3060,6 +3178,20 @@ plan_d: continue; } LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) { +#ifdef INET + if ((sctp_ifa->address.sa.sa_family == AF_INET) && + (prison_check_ip4(inp->ip_inp.inp.inp_cred, + &sctp_ifa->address.sin.sin_addr) != 0)) { + continue; + } +#endif +#ifdef INET6 + if ((sctp_ifa->address.sa.sa_family == AF_INET6) && + (prison_check_ip6(inp->ip_inp.inp.inp_cred, + &sctp_ifa->address.sin6.sin6_addr) != 0)) { + continue; + } +#endif if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0)) continue; @@ -3110,6 +3242,20 @@ out: LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) { struct sctp_ifa *tmp_sifa; +#ifdef INET + if ((sctp_ifa->address.sa.sa_family == AF_INET) && + (prison_check_ip4(inp->ip_inp.inp.inp_cred, + &sctp_ifa->address.sin.sin_addr) != 0)) { + continue; + } +#endif +#ifdef INET6 + if ((sctp_ifa->address.sa.sa_family == AF_INET6) && + (prison_check_ip6(inp->ip_inp.inp.inp_cred, + &sctp_ifa->address.sin6.sin6_addr) != 0)) { + continue; + } +#endif if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0)) continue; @@ -3295,7 +3441,7 @@ sctp_source_address_selection(struct sct /* * Bound all case */ - answer = sctp_choose_boundall(stcb, net, ro, vrf_id, + answer = sctp_choose_boundall(inp, stcb, net, ro, vrf_id, dest_is_priv, dest_is_loop, non_asoc_addr_ok, fam); SCTP_IPI_ADDR_RUNLOCK(); Modified: stable/10/sys/netinet/sctp_pcb.c ============================================================================== --- stable/10/sys/netinet/sctp_pcb.c Mon Jun 23 07:45:44 2014 (r267768) +++ stable/10/sys/netinet/sctp_pcb.c Mon Jun 23 07:54:12 2014 (r267769) @@ -898,6 +898,10 @@ sctp_does_stcb_own_this_addr(struct sctp IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) { continue; } + if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred, + &sin->sin_addr) != 0) { + continue; + } if (sin->sin_addr.s_addr == rsin->sin_addr.s_addr) { SCTP_IPI_ADDR_RUNLOCK(); return (1); @@ -913,6 +917,10 @@ sctp_does_stcb_own_this_addr(struct sctp sin6 = &sctp_ifa->address.sin6; rsin6 = (struct sockaddr_in6 *)to; + if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred, + &sin6->sin6_addr) != 0) { + continue; + } if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { if (local_scope == 0) continue; @@ -1060,6 +1068,39 @@ sctp_tcb_special_locate(struct sctp_inpc SCTP_INP_RUNLOCK(inp); continue; } + switch (to->sa_family) { +#ifdef INET + case AF_INET: + { + struct sockaddr_in *sin; + + sin = (struct sockaddr_in *)to; + if (prison_check_ip4(inp->ip_inp.inp.inp_cred, + &sin->sin_addr) != 0) { + SCTP_INP_RUNLOCK(inp); + continue; + } + break; + } +#endif +#ifdef INET6 + case AF_INET6: + { + struct sockaddr_in6 *sin6; + + sin6 = (struct sockaddr_in6 *)to; + if (prison_check_ip6(inp->ip_inp.inp.inp_cred, + &sin6->sin6_addr) != 0) { + SCTP_INP_RUNLOCK(inp); + continue; + } + break; + } +#endif + default: + SCTP_INP_RUNLOCK(inp); + continue; + } if (inp->def_vrf_id != vrf_id) { SCTP_INP_RUNLOCK(inp); continue; @@ -1628,23 +1669,45 @@ sctp_endpoint_probe(struct sockaddr *nam if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) && (inp->sctp_lport == lport)) { /* got it */ + switch (nam->sa_family) { #ifdef INET - if ((nam->sa_family == AF_INET) && - (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && - SCTP_IPV6_V6ONLY(inp)) { - /* IPv4 on a IPv6 socket with ONLY IPv6 set */ - SCTP_INP_RUNLOCK(inp); - continue; - } + case AF_INET: + if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && + SCTP_IPV6_V6ONLY(inp)) { + /* + * IPv4 on a IPv6 socket with ONLY + * IPv6 set + */ + SCTP_INP_RUNLOCK(inp); + continue; + } + if (prison_check_ip4(inp->ip_inp.inp.inp_cred, + &sin->sin_addr) != 0) { + SCTP_INP_RUNLOCK(inp); + continue; + } + break; #endif #ifdef INET6 - /* A V6 address and the endpoint is NOT bound V6 */ - if (nam->sa_family == AF_INET6 && - (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) { - SCTP_INP_RUNLOCK(inp); - continue; - } + case AF_INET6: + /* + * A V6 address and the endpoint is NOT + * bound V6 + */ + if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) { + SCTP_INP_RUNLOCK(inp); + continue; + } + if (prison_check_ip6(inp->ip_inp.inp.inp_cred, + &sin6->sin6_addr) != 0) { + SCTP_INP_RUNLOCK(inp); + continue; + } + break; #endif + default: + break; + } /* does a VRF id match? */ fnd = 0; if (inp->def_vrf_id == vrf_id) @@ -2403,6 +2466,7 @@ sctp_inpcb_alloc(struct socket *so, uint /* setup socket pointers */ inp->sctp_socket = so; inp->ip_inp.inp.inp_socket = so; + inp->ip_inp.inp.inp_cred = crhold(so->so_cred); #ifdef INET6 if (INP_SOCKAF(so) == AF_INET6) { if (MODULE_GLOBAL(ip6_auto_flowlabel)) { @@ -2421,6 +2485,7 @@ sctp_inpcb_alloc(struct socket *so, uint /* init the small hash table we use to track asocid <-> tcb */ inp->sctp_asocidhash = SCTP_HASH_INIT(SCTP_STACK_VTAG_HASH_SIZE, &inp->hashasocidmark); if (inp->sctp_asocidhash == NULL) { + crfree(inp->ip_inp.inp.inp_cred); SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp); SCTP_INP_INFO_WUNLOCK(); return (ENOBUFS); @@ -2435,6 +2500,7 @@ sctp_inpcb_alloc(struct socket *so, uint ((struct in6pcb *)(&inp->ip_inp.inp))->in6p_sp = pcb_sp; } if (error != 0) { + crfree(inp->ip_inp.inp.inp_cred); SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp); SCTP_INP_INFO_WUNLOCK(); return error; @@ -2465,6 +2531,7 @@ sctp_inpcb_alloc(struct socket *so, uint */ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EOPNOTSUPP); so->so_pcb = NULL; + crfree(inp->ip_inp.inp.inp_cred); SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp); return (EOPNOTSUPP); } @@ -2484,6 +2551,7 @@ sctp_inpcb_alloc(struct socket *so, uint SCTP_PRINTF("Out of SCTP-INPCB->hashinit - no resources\n"); SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOBUFS); so->so_pcb = NULL; + crfree(inp->ip_inp.inp.inp_cred); SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp); return (ENOBUFS); } @@ -3630,6 +3698,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, inp->sctp_tcbhash = NULL; } /* Now we must put the ep memory back into the zone pool */ + crfree(inp->ip_inp.inp.inp_cred); INP_LOCK_DESTROY(&inp->ip_inp.inp); SCTP_INP_LOCK_DESTROY(inp); SCTP_INP_READ_DESTROY(inp); Modified: stable/10/sys/netinet/sctp_sysctl.c ============================================================================== --- stable/10/sys/netinet/sctp_sysctl.c Mon Jun 23 07:45:44 2014 (r267768) +++ stable/10/sys/netinet/sctp_sysctl.c Mon Jun 23 07:54:12 2014 (r267769) @@ -252,6 +252,10 @@ copy_out_local_addresses(struct sctp_inp sin = (struct sockaddr_in *)&sctp_ifa->address.sa; if (sin->sin_addr.s_addr == 0) continue; + if (prison_check_ip4(inp->ip_inp.inp.inp_cred, + &sin->sin_addr) != 0) { + continue; + } if ((ipv4_local_scope == 0) && (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) continue; } else { @@ -267,6 +271,10 @@ copy_out_local_addresses(struct sctp_inp sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa; if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) continue; + if (prison_check_ip6(inp->ip_inp.inp.inp_cred, + &sin6->sin6_addr) != 0) { + continue; + } if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { if (local_scope == 0) continue; Modified: stable/10/sys/netinet/sctp_usrreq.c ============================================================================== --- stable/10/sys/netinet/sctp_usrreq.c Mon Jun 23 07:45:44 2014 (r267768) +++ stable/10/sys/netinet/sctp_usrreq.c Mon Jun 23 07:54:12 2014 (r267769) @@ -1197,6 +1197,10 @@ sctp_fill_up_addresses_vrf(struct sctp_i */ continue; } + if (prison_check_ip4(inp->ip_inp.inp.inp_cred, + &sin->sin_addr) != 0) { + continue; + } if ((ipv4_local_scope == 0) && (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) { continue; @@ -1238,6 +1242,10 @@ sctp_fill_up_addresses_vrf(struct sctp_i */ continue; } + if (prison_check_ip6(inp->ip_inp.inp.inp_cred, + &sin6->sin6_addr) != 0) { + continue; + } if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { if (local_scope == 0) continue; @@ -5239,6 +5247,43 @@ sctp_setopt(struct socket *so, int optna error = EINVAL; goto out_of_it; } + } else { + switch (sspp->sspp_addr.ss_family) { +#ifdef INET + case AF_INET: + { + struct sockaddr_in *sin; + + sin = (struct sockaddr_in *)&sspp->sspp_addr; + if (prison_check_ip4(inp->ip_inp.inp.inp_cred, + &sin->sin_addr) != 0) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + error = EINVAL; + goto out_of_it; + } + break; + } +#endif +#ifdef INET6 + case AF_INET6: + { + struct sockaddr_in6 *sin6; + + sin6 = (struct sockaddr_in6 *)&sspp->sspp_addr; + if (prison_check_ip6(inp->ip_inp.inp.inp_cred, + &sin6->sin6_addr) != 0) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + error = EINVAL; + goto out_of_it; + } + break; + } +#endif + default: + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + error = EINVAL; + goto out_of_it; + } } if (sctp_set_primary_ip_address_sa(stcb, (struct sockaddr *)&sspp->sspp_addr) != 0) { Modified: stable/10/sys/netinet/sctputil.c ============================================================================== --- stable/10/sys/netinet/sctputil.c Mon Jun 23 07:45:44 2014 (r267768) +++ stable/10/sys/netinet/sctputil.c Mon Jun 23 07:54:12 2014 (r267769) @@ -6693,6 +6693,10 @@ sctp_local_addr_count(struct sctp_tcb *s */ continue; } + if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred, + &sin->sin_addr) != 0) { + continue; + } if ((ipv4_local_scope == 0) && (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) { continue; @@ -6713,6 +6717,10 @@ sctp_local_addr_count(struct sctp_tcb *s if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { continue; } + if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred, + &sin6->sin6_addr) != 0) { + continue; + } if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { if (local_scope == 0) continue;