Remove IPsec related PCB code from SCTP.
The inpcb structure has inp_sp pointer that is initialized by ipsec_init_pcbpolicy() function. This pointer keeps strorage for IPsec security policies associated with a specific socket. An application can use IP_IPSEC_POLICY and IPV6_IPSEC_POLICY socket options to configure these security policies. Then ip[6]_output() uses inpcb pointer to specify that an outgoing packet is associated with some socket. And IPSEC_OUTPUT() method can use a security policy stored in the inp_sp. For inbound packet the protocol-specific input routine uses IPSEC_CHECK_POLICY() method to check that a packet conforms to inbound security policy configured in the inpcb. SCTP protocol doesn't specify inpcb for ip[6]_output() when it sends packets. Thus IPSEC_OUTPUT() method does not consider such packets as associated with some socket and can not apply security policies from inpcb, even if they are configured. Since IPSEC_CHECK_POLICY() method is called from protocol-specific input routine, it can specify inpcb pointer and associated with socket inbound policy will be checked. But there are two problems: 1. Such check is asymmetric, becasue we can not apply security policy from inpcb for outgoing packet. 2. IPSEC_CHECK_POLICY() expects that caller holds INPCB lock and access to inp_sp is protected. But for SCTP this is not correct, becasue SCTP uses own locks to protect inpcb. To fix these problems remove IPsec related PCB code from SCTP. This imply that IP_IPSEC_POLICY and IPV6_IPSEC_POLICY socket options will be not applicable to SCTP sockets. To be able correctly check inbound security policies for SCTP, mark its protocol header with the PR_LASTHDR flag. Reported by: tuexen Reviewed by: tuexen Differential Revision: https://reviews.freebsd.org/D9538
This commit is contained in:
parent
0dac2c5955
commit
5a443cfa6c
@ -148,7 +148,7 @@ struct protosw inetsw[] = {
|
||||
.pr_type = SOCK_SEQPACKET,
|
||||
.pr_domain = &inetdomain,
|
||||
.pr_protocol = IPPROTO_SCTP,
|
||||
.pr_flags = PR_WANTRCVD,
|
||||
.pr_flags = PR_WANTRCVD|PR_LASTHDR,
|
||||
.pr_input = sctp_input,
|
||||
.pr_ctlinput = sctp_ctlinput,
|
||||
.pr_ctloutput = sctp_ctloutput,
|
||||
@ -160,7 +160,7 @@ struct protosw inetsw[] = {
|
||||
.pr_type = SOCK_STREAM,
|
||||
.pr_domain = &inetdomain,
|
||||
.pr_protocol = IPPROTO_SCTP,
|
||||
.pr_flags = PR_CONNREQUIRED|PR_WANTRCVD,
|
||||
.pr_flags = PR_CONNREQUIRED|PR_WANTRCVD|PR_LASTHDR,
|
||||
.pr_input = sctp_input,
|
||||
.pr_ctlinput = sctp_ctlinput,
|
||||
.pr_ctloutput = sctp_ctloutput,
|
||||
|
@ -5790,40 +5790,6 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
|
||||
} else if (stcb == NULL) {
|
||||
inp_decr = inp;
|
||||
}
|
||||
#if defined(IPSEC) || defined(IPSEC_SUPPORT)
|
||||
/*-
|
||||
* I very much doubt any of the IPSEC stuff will work but I have no
|
||||
* idea, so I will leave it in place.
|
||||
*/
|
||||
if (inp != NULL) {
|
||||
switch (dst->sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
if (IPSEC_ENABLED(ipv4)) {
|
||||
if (IPSEC_CHECK_POLICY(ipv4, m,
|
||||
&inp->ip_inp.inp) != 0) {
|
||||
SCTP_STAT_INCR(sctps_hdrops);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
if (IPSEC_ENABLED(ipv6)) {
|
||||
if (IPSEC_CHECK_POLICY(ipv6, m,
|
||||
&inp->ip_inp.inp) != 0) {
|
||||
SCTP_STAT_INCR(sctps_hdrops);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* IPSEC */
|
||||
SCTPDBG(SCTP_DEBUG_INPUT1, "Ok, Common input processing called, m:%p iphlen:%d offset:%d length:%d stcb:%p\n",
|
||||
(void *)m, iphlen, offset, length, (void *)stcb);
|
||||
if (stcb) {
|
||||
|
@ -38,7 +38,6 @@ __FBSDID("$FreeBSD$");
|
||||
/*
|
||||
* includes
|
||||
*/
|
||||
#include "opt_ipsec.h"
|
||||
#include "opt_compat.h"
|
||||
#include "opt_inet6.h"
|
||||
#include "opt_inet.h"
|
||||
@ -82,8 +81,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <netinet/icmp_var.h>
|
||||
|
||||
#include <netipsec/ipsec_support.h>
|
||||
|
||||
#ifdef INET6
|
||||
#include <sys/domain.h>
|
||||
#include <netinet/ip6.h>
|
||||
@ -94,7 +91,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <netinet6/scope6_var.h>
|
||||
#endif /* INET6 */
|
||||
|
||||
|
||||
#include <netinet/ip_options.h>
|
||||
|
||||
#include <crypto/sha1.h>
|
||||
|
@ -2469,15 +2469,6 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
|
||||
SCTP_INP_INFO_WUNLOCK();
|
||||
return (ENOBUFS);
|
||||
}
|
||||
#if defined(IPSEC) || defined(IPSEC_SUPPORT)
|
||||
error = ipsec_init_pcbpolicy(&inp->ip_inp.inp);
|
||||
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;
|
||||
}
|
||||
#endif /* IPSEC */
|
||||
SCTP_INCR_EP_COUNT();
|
||||
inp->ip_inp.inp.inp_ip_ttl = MODULE_GLOBAL(ip_defttl);
|
||||
SCTP_INP_INFO_WUNLOCK();
|
||||
@ -2504,9 +2495,6 @@ 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);
|
||||
#if defined(IPSEC) || defined(IPSEC_SUPPORT)
|
||||
ipsec_delete_pcbpolicy(&inp->ip_inp.inp);
|
||||
#endif
|
||||
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp);
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
@ -2527,9 +2515,6 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOBUFS);
|
||||
so->so_pcb = NULL;
|
||||
crfree(inp->ip_inp.inp.inp_cred);
|
||||
#if defined(IPSEC) || defined(IPSEC_SUPPORT)
|
||||
ipsec_delete_pcbpolicy(&inp->ip_inp.inp);
|
||||
#endif
|
||||
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp);
|
||||
return (ENOBUFS);
|
||||
}
|
||||
@ -3641,9 +3626,6 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
|
||||
* macro here since le_next will get freed as part of the
|
||||
* sctp_free_assoc() call.
|
||||
*/
|
||||
#if defined(IPSEC) || defined(IPSEC_SUPPORT)
|
||||
ipsec_delete_pcbpolicy(ip_pcb);
|
||||
#endif
|
||||
if (ip_pcb->inp_options) {
|
||||
(void)sctp_m_free(ip_pcb->inp_options);
|
||||
ip_pcb->inp_options = 0;
|
||||
|
@ -185,7 +185,7 @@ struct protosw inet6sw[] = {
|
||||
.pr_type = SOCK_SEQPACKET,
|
||||
.pr_domain = &inet6domain,
|
||||
.pr_protocol = IPPROTO_SCTP,
|
||||
.pr_flags = PR_WANTRCVD,
|
||||
.pr_flags = PR_WANTRCVD|PR_LASTHDR,
|
||||
.pr_input = sctp6_input,
|
||||
.pr_ctlinput = sctp6_ctlinput,
|
||||
.pr_ctloutput = sctp_ctloutput,
|
||||
@ -199,7 +199,7 @@ struct protosw inet6sw[] = {
|
||||
.pr_type = SOCK_STREAM,
|
||||
.pr_domain = &inet6domain,
|
||||
.pr_protocol = IPPROTO_SCTP,
|
||||
.pr_flags = PR_CONNREQUIRED|PR_WANTRCVD,
|
||||
.pr_flags = PR_CONNREQUIRED|PR_WANTRCVD|PR_LASTHDR,
|
||||
.pr_input = sctp6_input,
|
||||
.pr_ctlinput = sctp6_ctlinput,
|
||||
.pr_ctloutput = sctp_ctloutput,
|
||||
|
@ -551,10 +551,6 @@ sctp6_attach(struct socket *so, int proto SCTP_UNUSED, struct thread *p SCTP_UNU
|
||||
*/
|
||||
inp6->inp_ip_ttl = MODULE_GLOBAL(ip_defttl);
|
||||
#endif
|
||||
/*
|
||||
* Hmm what about the IPSEC stuff that is missing here but in
|
||||
* sctp_attach()?
|
||||
*/
|
||||
SCTP_INP_WUNLOCK(inp);
|
||||
return (0);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user