summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/netinet/sctp_asconf.c42
-rw-r--r--sys/netinet/sctp_output.c158
-rw-r--r--sys/netinet/sctp_pcb.c95
-rw-r--r--sys/netinet/sctp_sysctl.c8
-rw-r--r--sys/netinet/sctp_usrreq.c45
-rw-r--r--sys/netinet/sctputil.c8
6 files changed, 336 insertions, 20 deletions
diff --git a/sys/netinet/sctp_asconf.c b/sys/netinet/sctp_asconf.c
index a2daf18..ed88b3c 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 269ec49..b2a24e7 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 @@ 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 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_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_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 @@ 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 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 861455c..3cee79e 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 5836dcb..6d18b63 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 83bb0ad..e8b4223 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 92ee88f..53e5869 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;
OpenPOWER on IntegriCloud