Fix the handling of IPSec policies in the SCTP stack. At least

make sure they are not leaked...

MFC after: 	1 week
This commit is contained in:
Michael Tuexen 2015-11-21 18:21:16 +00:00
parent e5d23883bf
commit 3bf2363dca
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=291141
2 changed files with 9 additions and 47 deletions

View File

@ -2495,14 +2495,7 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
return (ENOBUFS);
}
#ifdef IPSEC
{
struct inpcbpolicy *pcb_sp = NULL;
error = ipsec_init_policy(so, &pcb_sp);
/* Arrange to share the policy */
inp->ip_inp.inp.inp_sp = pcb_sp;
((struct in6pcb *)(&inp->ip_inp.inp))->in6p_sp = pcb_sp;
}
error = ipsec_init_policy(so, &inp->ip_inp.inp.inp_sp);
if (error != 0) {
crfree(inp->ip_inp.inp.inp_cred);
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp);
@ -2536,6 +2529,9 @@ 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);
#ifdef IPSEC
ipsec_delete_pcbpolicy(&inp->ip_inp.inp);
#endif
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp);
return (EOPNOTSUPP);
}
@ -2556,6 +2552,9 @@ 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);
#ifdef IPSEC
ipsec_delete_pcbpolicy(&inp->ip_inp.inp);
#endif
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp);
return (ENOBUFS);
}
@ -3640,13 +3639,9 @@ 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 (so) {
#ifdef IPSEC
ipsec_delete_pcbpolicy(ip_pcb);
#endif /* IPSEC */
/* Unlocks not needed since the socket is gone now */
}
ipsec_delete_pcbpolicy(ip_pcb);
#endif
if (ip_pcb->inp_options) {
(void)sctp_m_free(ip_pcb->inp_options);
ip_pcb->inp_options = 0;

View File

@ -487,11 +487,6 @@ sctp_attach(struct socket *so, int proto SCTP_UNUSED, struct thread *p SCTP_UNUS
int error;
uint32_t vrf_id = SCTP_DEFAULT_VRFID;
#ifdef IPSEC
uint32_t flags;
#endif
inp = (struct sctp_inpcb *)so->so_pcb;
if (inp != 0) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
@ -513,34 +508,6 @@ sctp_attach(struct socket *so, int proto SCTP_UNUSED, struct thread *p SCTP_UNUS
ip_inp = &inp->ip_inp.inp;
ip_inp->inp_vflag |= INP_IPV4;
ip_inp->inp_ip_ttl = MODULE_GLOBAL(ip_defttl);
#ifdef IPSEC
error = ipsec_init_policy(so, &ip_inp->inp_sp);
#ifdef SCTP_LOG_CLOSING
sctp_log_closing(inp, NULL, 17);
#endif
if (error != 0) {
try_again:
flags = inp->sctp_flags;
if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
(atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
#ifdef SCTP_LOG_CLOSING
sctp_log_closing(inp, NULL, 15);
#endif
SCTP_INP_WUNLOCK(inp);
sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
} else {
flags = inp->sctp_flags;
if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
goto try_again;
} else {
SCTP_INP_WUNLOCK(inp);
}
}
so->so_pcb = NULL;
return (error);
}
#endif
SCTP_INP_WUNLOCK(inp);
return (0);
}