From 270637abff0cdf848b910b9f96ad342e1da61c66 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Thu, 20 Mar 2008 15:17:14 -0700 Subject: [SCTP]: Fix a race between module load and protosw access There is a race is SCTP between the loading of the module and the access by the socket layer to the protocol functions. In particular, a list of addresss that SCTP maintains is not initialized prior to the registration with the protosw. Thus it is possible for a user application to gain access to SCTP functions before everything has been initialized. The problem shows up as odd crashes during connection initializtion when we try to access the SCTP address list. The solution is to refactor how we do registration and initialize the lists prior to registering with the protosw. Care must be taken since the address list initialization depends on some other pieces of SCTP initialization. Also the clean-up in case of failure now also needs to be refactored. Signed-off-by: Vlad Yasevich Acked-by: Sridhar Samudrala Signed-off-by: David S. Miller --- net/sctp/ipv6.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) (limited to 'net/sctp/ipv6.c') diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 9aa0733aee8..b1e05d719f9 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -1014,15 +1014,24 @@ static struct sctp_pf sctp_pf_inet6 = { }; /* Initialize IPv6 support and register with socket layer. */ -int sctp_v6_init(void) +void sctp_v6_pf_init(void) { - int rc; - /* Register the SCTP specific PF_INET6 functions. */ sctp_register_pf(&sctp_pf_inet6, PF_INET6); /* Register the SCTP specific AF_INET6 functions. */ sctp_register_af(&sctp_af_inet6); +} + +void sctp_v6_pf_exit(void) +{ + list_del(&sctp_af_inet6.list); +} + +/* Initialize IPv6 support and register with socket layer. */ +int sctp_v6_protosw_init(void) +{ + int rc; rc = proto_register(&sctpv6_prot, 1); if (rc) @@ -1035,6 +1044,14 @@ int sctp_v6_init(void) return 0; } +void sctp_v6_protosw_exit(void) +{ + inet6_unregister_protosw(&sctpv6_seqpacket_protosw); + inet6_unregister_protosw(&sctpv6_stream_protosw); + proto_unregister(&sctpv6_prot); +} + + /* Register with inet6 layer. */ int sctp_v6_add_protocol(void) { @@ -1047,15 +1064,6 @@ int sctp_v6_add_protocol(void) return 0; } -/* IPv6 specific exit support. */ -void sctp_v6_exit(void) -{ - inet6_unregister_protosw(&sctpv6_seqpacket_protosw); - inet6_unregister_protosw(&sctpv6_stream_protosw); - proto_unregister(&sctpv6_prot); - list_del(&sctp_af_inet6.list); -} - /* Unregister with inet6 layer. */ void sctp_v6_del_protocol(void) { -- cgit v1.2.3