diff --git a/sys/netinet/sctp_asconf.c b/sys/netinet/sctp_asconf.c index a2daf1800d2f..ed88b3c91f11 100644 --- a/sys/netinet/sctp_asconf.c +++ b/sys/netinet/sctp_asconf.c @@ -1889,14 +1889,22 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, * 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_inpcb *inp, struct sctp_tcb *stcb, /* 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_inpcb *inp, struct sctp_tcb *stcb, /* 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_tcb *stcb, int addr_locked) /* 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_tcb *stcb, int addr_locked) */ 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_tcb *stcb, struct mbuf *m, int offset, #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_tcb *stcb, struct mbuf *m, int offset, #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 sctp_tcb *stcb, #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 sctp_tcb *stcb, #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; } diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index 269ec498be4a..b2a24e753ebd 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -2060,6 +2060,20 @@ sctp_add_addresses_to_i_ia(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 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 @@ sctp_add_addresses_to_i_ia(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 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 sctp_inpcb *inp, 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 sctp_inpcb *inp, 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 sctp_inpcb *inp, } /* 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_choose_boundspecific_stcb(struct sctp_inpcb *inp, 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_boundall(struct sctp_ifn *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_boundall(struct sctp_ifn *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 sctp_ifn *ifn, 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 sctp_ifn *ifn, } 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 *stcb, 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 *stcb, */ 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 @@ sctp_choose_boundall(struct sctp_tcb *stcb, 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 @@ sctp_choose_boundall(struct sctp_tcb *stcb, 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 @@ sctp_choose_boundall(struct sctp_tcb *stcb, } 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 @@ sctp_choose_boundall(struct sctp_tcb *stcb, 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 @@ sctp_choose_boundall(struct sctp_tcb *stcb, 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 sctp_inpcb *inp, /* * 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(); diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c index 861455c40b8d..3cee79e32630 100644 --- a/sys/netinet/sctp_pcb.c +++ b/sys/netinet/sctp_pcb.c @@ -898,6 +898,10 @@ sctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to) 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_tcb *stcb, struct sockaddr *to) 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_inpcb **inp_p, struct sockaddr *from, 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, struct sctppcbhead *head, 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, uint32_t vrf_id) /* 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, uint32_t vrf_id) /* 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, uint32_t vrf_id) ((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, uint32_t vrf_id) */ 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, uint32_t vrf_id) 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, int immediate, int from) 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); diff --git a/sys/netinet/sctp_sysctl.c b/sys/netinet/sctp_sysctl.c index 5836dcb1d77f..6d18b6318cd1 100644 --- a/sys/netinet/sctp_sysctl.c +++ b/sys/netinet/sctp_sysctl.c @@ -252,6 +252,10 @@ copy_out_local_addresses(struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct s 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_inpcb *inp, struct sctp_tcb *stcb, struct s 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; diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c index 83bb0adf342a..e8b42234fe01 100644 --- a/sys/netinet/sctp_usrreq.c +++ b/sys/netinet/sctp_usrreq.c @@ -1197,6 +1197,10 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp, */ 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_inpcb *inp, */ 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 optname, void *optval, size_t optsize, 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) { diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c index 92ee88fd7818..53e58695e20d 100644 --- a/sys/netinet/sctputil.c +++ b/sys/netinet/sctputil.c @@ -6693,6 +6693,10 @@ sctp_local_addr_count(struct sctp_tcb *stcb) */ 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 *stcb) 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;