forked from Minki/linux
[SCTP]: Re-order SCTP initializations to avoid race with sctp_rcv()
Signed-off-by: Sridhar Samudrala <sri@us.ibm.com> Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
ce5325c133
commit
827bf12236
@ -378,11 +378,15 @@ static inline int sctp_sysctl_jiffies_ms(ctl_table *table, int __user *name, int
|
||||
|
||||
int sctp_v6_init(void);
|
||||
void sctp_v6_exit(void);
|
||||
int sctp_v6_add_protocol(void);
|
||||
void sctp_v6_del_protocol(void);
|
||||
|
||||
#else /* #ifdef defined(CONFIG_IPV6) */
|
||||
|
||||
static inline int sctp_v6_init(void) { return 0; }
|
||||
static inline void sctp_v6_exit(void) { return; }
|
||||
static inline int sctp_v6_add_protocol(void) { return 0; }
|
||||
static inline void sctp_v6_del_protocol(void) { return; }
|
||||
|
||||
#endif /* #if defined(CONFIG_IPV6) */
|
||||
|
||||
|
@ -992,21 +992,10 @@ static struct sctp_pf sctp_pf_inet6_specific = {
|
||||
.af = &sctp_ipv6_specific,
|
||||
};
|
||||
|
||||
/* Initialize IPv6 support and register with inet6 stack. */
|
||||
/* Initialize IPv6 support and register with socket layer. */
|
||||
int sctp_v6_init(void)
|
||||
{
|
||||
int rc = proto_register(&sctpv6_prot, 1);
|
||||
|
||||
if (rc)
|
||||
goto out;
|
||||
/* Register inet6 protocol. */
|
||||
rc = -EAGAIN;
|
||||
if (inet6_add_protocol(&sctpv6_protocol, IPPROTO_SCTP) < 0)
|
||||
goto out_unregister_sctp_proto;
|
||||
|
||||
/* Add SCTPv6(UDP and TCP style) to inetsw6 linked list. */
|
||||
inet6_register_protosw(&sctpv6_seqpacket_protosw);
|
||||
inet6_register_protosw(&sctpv6_stream_protosw);
|
||||
int rc;
|
||||
|
||||
/* Register the SCTP specific PF_INET6 functions. */
|
||||
sctp_register_pf(&sctp_pf_inet6_specific, PF_INET6);
|
||||
@ -1014,23 +1003,41 @@ int sctp_v6_init(void)
|
||||
/* Register the SCTP specific AF_INET6 functions. */
|
||||
sctp_register_af(&sctp_ipv6_specific);
|
||||
|
||||
rc = proto_register(&sctpv6_prot, 1);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* Add SCTPv6(UDP and TCP style) to inetsw6 linked list. */
|
||||
inet6_register_protosw(&sctpv6_seqpacket_protosw);
|
||||
inet6_register_protosw(&sctpv6_stream_protosw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Register with inet6 layer. */
|
||||
int sctp_v6_add_protocol(void)
|
||||
{
|
||||
/* Register notifier for inet6 address additions/deletions. */
|
||||
register_inet6addr_notifier(&sctp_inet6addr_notifier);
|
||||
rc = 0;
|
||||
out:
|
||||
return rc;
|
||||
out_unregister_sctp_proto:
|
||||
proto_unregister(&sctpv6_prot);
|
||||
goto out;
|
||||
|
||||
if (inet6_add_protocol(&sctpv6_protocol, IPPROTO_SCTP) < 0)
|
||||
return -EAGAIN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* IPv6 specific exit support. */
|
||||
void sctp_v6_exit(void)
|
||||
{
|
||||
list_del(&sctp_ipv6_specific.list);
|
||||
inet6_del_protocol(&sctpv6_protocol, IPPROTO_SCTP);
|
||||
inet6_unregister_protosw(&sctpv6_seqpacket_protosw);
|
||||
inet6_unregister_protosw(&sctpv6_stream_protosw);
|
||||
unregister_inet6addr_notifier(&sctp_inet6addr_notifier);
|
||||
proto_unregister(&sctpv6_prot);
|
||||
list_del(&sctp_ipv6_specific.list);
|
||||
}
|
||||
|
||||
/* Unregister with inet6 layer. */
|
||||
void sctp_v6_del_protocol(void)
|
||||
{
|
||||
inet6_del_protocol(&sctpv6_protocol, IPPROTO_SCTP);
|
||||
unregister_inet6addr_notifier(&sctp_inet6addr_notifier);
|
||||
}
|
||||
|
@ -975,28 +975,14 @@ SCTP_STATIC __init int sctp_init(void)
|
||||
if (!sctp_sanity_check())
|
||||
goto out;
|
||||
|
||||
status = proto_register(&sctp_prot, 1);
|
||||
if (status)
|
||||
goto out;
|
||||
|
||||
/* Add SCTP to inet_protos hash table. */
|
||||
status = -EAGAIN;
|
||||
if (inet_add_protocol(&sctp_protocol, IPPROTO_SCTP) < 0)
|
||||
goto err_add_protocol;
|
||||
|
||||
/* Add SCTP(TCP and UDP style) to inetsw linked list. */
|
||||
inet_register_protosw(&sctp_seqpacket_protosw);
|
||||
inet_register_protosw(&sctp_stream_protosw);
|
||||
|
||||
/* Allocate a cache pools. */
|
||||
/* Allocate bind_bucket and chunk caches. */
|
||||
status = -ENOBUFS;
|
||||
sctp_bucket_cachep = kmem_cache_create("sctp_bind_bucket",
|
||||
sizeof(struct sctp_bind_bucket),
|
||||
0, SLAB_HWCACHE_ALIGN,
|
||||
NULL, NULL);
|
||||
|
||||
if (!sctp_bucket_cachep)
|
||||
goto err_bucket_cachep;
|
||||
goto out;
|
||||
|
||||
sctp_chunk_cachep = kmem_cache_create("sctp_chunk",
|
||||
sizeof(struct sctp_chunk),
|
||||
@ -1153,6 +1139,14 @@ SCTP_STATIC __init int sctp_init(void)
|
||||
INIT_LIST_HEAD(&sctp_address_families);
|
||||
sctp_register_af(&sctp_ipv4_specific);
|
||||
|
||||
status = proto_register(&sctp_prot, 1);
|
||||
if (status)
|
||||
goto err_proto_register;
|
||||
|
||||
/* Register SCTP(UDP and TCP style) with socket layer. */
|
||||
inet_register_protosw(&sctp_seqpacket_protosw);
|
||||
inet_register_protosw(&sctp_stream_protosw);
|
||||
|
||||
status = sctp_v6_init();
|
||||
if (status)
|
||||
goto err_v6_init;
|
||||
@ -1166,19 +1160,39 @@ SCTP_STATIC __init int sctp_init(void)
|
||||
|
||||
/* Initialize the local address list. */
|
||||
INIT_LIST_HEAD(&sctp_local_addr_list);
|
||||
|
||||
sctp_get_local_addr_list();
|
||||
|
||||
/* Register notifier for inet address additions/deletions. */
|
||||
register_inetaddr_notifier(&sctp_inetaddr_notifier);
|
||||
|
||||
/* Register SCTP with inet layer. */
|
||||
if (inet_add_protocol(&sctp_protocol, IPPROTO_SCTP) < 0) {
|
||||
status = -EAGAIN;
|
||||
goto err_add_protocol;
|
||||
}
|
||||
|
||||
/* Register SCTP with inet6 layer. */
|
||||
status = sctp_v6_add_protocol();
|
||||
if (status)
|
||||
goto err_v6_add_protocol;
|
||||
|
||||
__unsafe(THIS_MODULE);
|
||||
status = 0;
|
||||
out:
|
||||
return status;
|
||||
err_v6_add_protocol:
|
||||
inet_del_protocol(&sctp_protocol, IPPROTO_SCTP);
|
||||
unregister_inetaddr_notifier(&sctp_inetaddr_notifier);
|
||||
err_add_protocol:
|
||||
sctp_free_local_addr_list();
|
||||
sock_release(sctp_ctl_socket);
|
||||
err_ctl_sock_init:
|
||||
sctp_v6_exit();
|
||||
err_v6_init:
|
||||
inet_unregister_protosw(&sctp_stream_protosw);
|
||||
inet_unregister_protosw(&sctp_seqpacket_protosw);
|
||||
proto_unregister(&sctp_prot);
|
||||
err_proto_register:
|
||||
sctp_sysctl_unregister();
|
||||
list_del(&sctp_ipv4_specific.list);
|
||||
free_pages((unsigned long)sctp_port_hashtable,
|
||||
@ -1192,19 +1206,13 @@ err_ehash_alloc:
|
||||
sizeof(struct sctp_hashbucket)));
|
||||
err_ahash_alloc:
|
||||
sctp_dbg_objcnt_exit();
|
||||
err_init_proc:
|
||||
sctp_proc_exit();
|
||||
err_init_proc:
|
||||
cleanup_sctp_mibs();
|
||||
err_init_mibs:
|
||||
kmem_cache_destroy(sctp_chunk_cachep);
|
||||
err_chunk_cachep:
|
||||
kmem_cache_destroy(sctp_bucket_cachep);
|
||||
err_bucket_cachep:
|
||||
inet_del_protocol(&sctp_protocol, IPPROTO_SCTP);
|
||||
inet_unregister_protosw(&sctp_seqpacket_protosw);
|
||||
inet_unregister_protosw(&sctp_stream_protosw);
|
||||
err_add_protocol:
|
||||
proto_unregister(&sctp_prot);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -1215,8 +1223,9 @@ SCTP_STATIC __exit void sctp_exit(void)
|
||||
* up all the remaining associations and all that memory.
|
||||
*/
|
||||
|
||||
/* Unregister notifier for inet address additions/deletions. */
|
||||
unregister_inetaddr_notifier(&sctp_inetaddr_notifier);
|
||||
/* Unregister with inet6/inet layers. */
|
||||
sctp_v6_del_protocol();
|
||||
inet_del_protocol(&sctp_protocol, IPPROTO_SCTP);
|
||||
|
||||
/* Free the local address list. */
|
||||
sctp_free_local_addr_list();
|
||||
@ -1224,7 +1233,16 @@ SCTP_STATIC __exit void sctp_exit(void)
|
||||
/* Free the control endpoint. */
|
||||
sock_release(sctp_ctl_socket);
|
||||
|
||||
/* Cleanup v6 initializations. */
|
||||
sctp_v6_exit();
|
||||
|
||||
/* Unregister with socket layer. */
|
||||
inet_unregister_protosw(&sctp_stream_protosw);
|
||||
inet_unregister_protosw(&sctp_seqpacket_protosw);
|
||||
|
||||
/* Unregister notifier for inet address additions/deletions. */
|
||||
unregister_inetaddr_notifier(&sctp_inetaddr_notifier);
|
||||
|
||||
sctp_sysctl_unregister();
|
||||
list_del(&sctp_ipv4_specific.list);
|
||||
|
||||
@ -1236,16 +1254,13 @@ SCTP_STATIC __exit void sctp_exit(void)
|
||||
get_order(sctp_port_hashsize *
|
||||
sizeof(struct sctp_bind_hashbucket)));
|
||||
|
||||
kmem_cache_destroy(sctp_chunk_cachep);
|
||||
kmem_cache_destroy(sctp_bucket_cachep);
|
||||
|
||||
sctp_dbg_objcnt_exit();
|
||||
sctp_proc_exit();
|
||||
cleanup_sctp_mibs();
|
||||
|
||||
inet_del_protocol(&sctp_protocol, IPPROTO_SCTP);
|
||||
inet_unregister_protosw(&sctp_seqpacket_protosw);
|
||||
inet_unregister_protosw(&sctp_stream_protosw);
|
||||
kmem_cache_destroy(sctp_chunk_cachep);
|
||||
kmem_cache_destroy(sctp_bucket_cachep);
|
||||
|
||||
proto_unregister(&sctp_prot);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user