diff options
author | Sridhar Samudrala <sri@us.ibm.com> | 2007-05-04 16:36:30 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2007-05-04 16:36:30 -0400 |
commit | 827bf12236fbafc02bc899aec1b37c342c8cf4e5 (patch) | |
tree | 41101b0d866629b3cc3341712996f11e655f6250 /net | |
parent | ce5325c1338acf965f4300f4976eac2129aeb439 (diff) |
[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>
Diffstat (limited to 'net')
-rw-r--r-- | net/sctp/ipv6.c | 49 | ||||
-rw-r--r-- | net/sctp/protocol.c | 79 |
2 files changed, 75 insertions, 53 deletions
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index ca527a27dd05..84cd53635fe8 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c | |||
@@ -992,45 +992,52 @@ static struct sctp_pf sctp_pf_inet6_specific = { | |||
992 | .af = &sctp_ipv6_specific, | 992 | .af = &sctp_ipv6_specific, |
993 | }; | 993 | }; |
994 | 994 | ||
995 | /* Initialize IPv6 support and register with inet6 stack. */ | 995 | /* Initialize IPv6 support and register with socket layer. */ |
996 | int sctp_v6_init(void) | 996 | int sctp_v6_init(void) |
997 | { | 997 | { |
998 | int rc = proto_register(&sctpv6_prot, 1); | 998 | int rc; |
999 | 999 | ||
1000 | /* Register the SCTP specific PF_INET6 functions. */ | ||
1001 | sctp_register_pf(&sctp_pf_inet6_specific, PF_INET6); | ||
1002 | |||
1003 | /* Register the SCTP specific AF_INET6 functions. */ | ||
1004 | sctp_register_af(&sctp_ipv6_specific); | ||
1005 | |||
1006 | rc = proto_register(&sctpv6_prot, 1); | ||
1000 | if (rc) | 1007 | if (rc) |
1001 | goto out; | 1008 | return rc; |
1002 | /* Register inet6 protocol. */ | ||
1003 | rc = -EAGAIN; | ||
1004 | if (inet6_add_protocol(&sctpv6_protocol, IPPROTO_SCTP) < 0) | ||
1005 | goto out_unregister_sctp_proto; | ||
1006 | 1009 | ||
1007 | /* Add SCTPv6(UDP and TCP style) to inetsw6 linked list. */ | 1010 | /* Add SCTPv6(UDP and TCP style) to inetsw6 linked list. */ |
1008 | inet6_register_protosw(&sctpv6_seqpacket_protosw); | 1011 | inet6_register_protosw(&sctpv6_seqpacket_protosw); |
1009 | inet6_register_protosw(&sctpv6_stream_protosw); | 1012 | inet6_register_protosw(&sctpv6_stream_protosw); |
1010 | 1013 | ||
1011 | /* Register the SCTP specific PF_INET6 functions. */ | 1014 | return 0; |
1012 | sctp_register_pf(&sctp_pf_inet6_specific, PF_INET6); | 1015 | } |
1013 | |||
1014 | /* Register the SCTP specific AF_INET6 functions. */ | ||
1015 | sctp_register_af(&sctp_ipv6_specific); | ||
1016 | 1016 | ||
1017 | /* Register with inet6 layer. */ | ||
1018 | int sctp_v6_add_protocol(void) | ||
1019 | { | ||
1017 | /* Register notifier for inet6 address additions/deletions. */ | 1020 | /* Register notifier for inet6 address additions/deletions. */ |
1018 | register_inet6addr_notifier(&sctp_inet6addr_notifier); | 1021 | register_inet6addr_notifier(&sctp_inet6addr_notifier); |
1019 | rc = 0; | 1022 | |
1020 | out: | 1023 | if (inet6_add_protocol(&sctpv6_protocol, IPPROTO_SCTP) < 0) |
1021 | return rc; | 1024 | return -EAGAIN; |
1022 | out_unregister_sctp_proto: | 1025 | |
1023 | proto_unregister(&sctpv6_prot); | 1026 | return 0; |
1024 | goto out; | ||
1025 | } | 1027 | } |
1026 | 1028 | ||
1027 | /* IPv6 specific exit support. */ | 1029 | /* IPv6 specific exit support. */ |
1028 | void sctp_v6_exit(void) | 1030 | void sctp_v6_exit(void) |
1029 | { | 1031 | { |
1030 | list_del(&sctp_ipv6_specific.list); | ||
1031 | inet6_del_protocol(&sctpv6_protocol, IPPROTO_SCTP); | ||
1032 | inet6_unregister_protosw(&sctpv6_seqpacket_protosw); | 1032 | inet6_unregister_protosw(&sctpv6_seqpacket_protosw); |
1033 | inet6_unregister_protosw(&sctpv6_stream_protosw); | 1033 | inet6_unregister_protosw(&sctpv6_stream_protosw); |
1034 | unregister_inet6addr_notifier(&sctp_inet6addr_notifier); | ||
1035 | proto_unregister(&sctpv6_prot); | 1034 | proto_unregister(&sctpv6_prot); |
1035 | list_del(&sctp_ipv6_specific.list); | ||
1036 | } | ||
1037 | |||
1038 | /* Unregister with inet6 layer. */ | ||
1039 | void sctp_v6_del_protocol(void) | ||
1040 | { | ||
1041 | inet6_del_protocol(&sctpv6_protocol, IPPROTO_SCTP); | ||
1042 | unregister_inet6addr_notifier(&sctp_inet6addr_notifier); | ||
1036 | } | 1043 | } |
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index d4afafc39138..34bab36637ac 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -975,28 +975,14 @@ SCTP_STATIC __init int sctp_init(void) | |||
975 | if (!sctp_sanity_check()) | 975 | if (!sctp_sanity_check()) |
976 | goto out; | 976 | goto out; |
977 | 977 | ||
978 | status = proto_register(&sctp_prot, 1); | 978 | /* Allocate bind_bucket and chunk caches. */ |
979 | if (status) | ||
980 | goto out; | ||
981 | |||
982 | /* Add SCTP to inet_protos hash table. */ | ||
983 | status = -EAGAIN; | ||
984 | if (inet_add_protocol(&sctp_protocol, IPPROTO_SCTP) < 0) | ||
985 | goto err_add_protocol; | ||
986 | |||
987 | /* Add SCTP(TCP and UDP style) to inetsw linked list. */ | ||
988 | inet_register_protosw(&sctp_seqpacket_protosw); | ||
989 | inet_register_protosw(&sctp_stream_protosw); | ||
990 | |||
991 | /* Allocate a cache pools. */ | ||
992 | status = -ENOBUFS; | 979 | status = -ENOBUFS; |
993 | sctp_bucket_cachep = kmem_cache_create("sctp_bind_bucket", | 980 | sctp_bucket_cachep = kmem_cache_create("sctp_bind_bucket", |
994 | sizeof(struct sctp_bind_bucket), | 981 | sizeof(struct sctp_bind_bucket), |
995 | 0, SLAB_HWCACHE_ALIGN, | 982 | 0, SLAB_HWCACHE_ALIGN, |
996 | NULL, NULL); | 983 | NULL, NULL); |
997 | |||
998 | if (!sctp_bucket_cachep) | 984 | if (!sctp_bucket_cachep) |
999 | goto err_bucket_cachep; | 985 | goto out; |
1000 | 986 | ||
1001 | sctp_chunk_cachep = kmem_cache_create("sctp_chunk", | 987 | sctp_chunk_cachep = kmem_cache_create("sctp_chunk", |
1002 | sizeof(struct sctp_chunk), | 988 | sizeof(struct sctp_chunk), |
@@ -1153,6 +1139,14 @@ SCTP_STATIC __init int sctp_init(void) | |||
1153 | INIT_LIST_HEAD(&sctp_address_families); | 1139 | INIT_LIST_HEAD(&sctp_address_families); |
1154 | sctp_register_af(&sctp_ipv4_specific); | 1140 | sctp_register_af(&sctp_ipv4_specific); |
1155 | 1141 | ||
1142 | status = proto_register(&sctp_prot, 1); | ||
1143 | if (status) | ||
1144 | goto err_proto_register; | ||
1145 | |||
1146 | /* Register SCTP(UDP and TCP style) with socket layer. */ | ||
1147 | inet_register_protosw(&sctp_seqpacket_protosw); | ||
1148 | inet_register_protosw(&sctp_stream_protosw); | ||
1149 | |||
1156 | status = sctp_v6_init(); | 1150 | status = sctp_v6_init(); |
1157 | if (status) | 1151 | if (status) |
1158 | goto err_v6_init; | 1152 | goto err_v6_init; |
@@ -1166,19 +1160,39 @@ SCTP_STATIC __init int sctp_init(void) | |||
1166 | 1160 | ||
1167 | /* Initialize the local address list. */ | 1161 | /* Initialize the local address list. */ |
1168 | INIT_LIST_HEAD(&sctp_local_addr_list); | 1162 | INIT_LIST_HEAD(&sctp_local_addr_list); |
1169 | |||
1170 | sctp_get_local_addr_list(); | 1163 | sctp_get_local_addr_list(); |
1171 | 1164 | ||
1172 | /* Register notifier for inet address additions/deletions. */ | 1165 | /* Register notifier for inet address additions/deletions. */ |
1173 | register_inetaddr_notifier(&sctp_inetaddr_notifier); | 1166 | register_inetaddr_notifier(&sctp_inetaddr_notifier); |
1174 | 1167 | ||
1168 | /* Register SCTP with inet layer. */ | ||
1169 | if (inet_add_protocol(&sctp_protocol, IPPROTO_SCTP) < 0) { | ||
1170 | status = -EAGAIN; | ||
1171 | goto err_add_protocol; | ||
1172 | } | ||
1173 | |||
1174 | /* Register SCTP with inet6 layer. */ | ||
1175 | status = sctp_v6_add_protocol(); | ||
1176 | if (status) | ||
1177 | goto err_v6_add_protocol; | ||
1178 | |||
1175 | __unsafe(THIS_MODULE); | 1179 | __unsafe(THIS_MODULE); |
1176 | status = 0; | 1180 | status = 0; |
1177 | out: | 1181 | out: |
1178 | return status; | 1182 | return status; |
1183 | err_v6_add_protocol: | ||
1184 | inet_del_protocol(&sctp_protocol, IPPROTO_SCTP); | ||
1185 | unregister_inetaddr_notifier(&sctp_inetaddr_notifier); | ||
1186 | err_add_protocol: | ||
1187 | sctp_free_local_addr_list(); | ||
1188 | sock_release(sctp_ctl_socket); | ||
1179 | err_ctl_sock_init: | 1189 | err_ctl_sock_init: |
1180 | sctp_v6_exit(); | 1190 | sctp_v6_exit(); |
1181 | err_v6_init: | 1191 | err_v6_init: |
1192 | inet_unregister_protosw(&sctp_stream_protosw); | ||
1193 | inet_unregister_protosw(&sctp_seqpacket_protosw); | ||
1194 | proto_unregister(&sctp_prot); | ||
1195 | err_proto_register: | ||
1182 | sctp_sysctl_unregister(); | 1196 | sctp_sysctl_unregister(); |
1183 | list_del(&sctp_ipv4_specific.list); | 1197 | list_del(&sctp_ipv4_specific.list); |
1184 | free_pages((unsigned long)sctp_port_hashtable, | 1198 | free_pages((unsigned long)sctp_port_hashtable, |
@@ -1192,19 +1206,13 @@ err_ehash_alloc: | |||
1192 | sizeof(struct sctp_hashbucket))); | 1206 | sizeof(struct sctp_hashbucket))); |
1193 | err_ahash_alloc: | 1207 | err_ahash_alloc: |
1194 | sctp_dbg_objcnt_exit(); | 1208 | sctp_dbg_objcnt_exit(); |
1195 | err_init_proc: | ||
1196 | sctp_proc_exit(); | 1209 | sctp_proc_exit(); |
1210 | err_init_proc: | ||
1197 | cleanup_sctp_mibs(); | 1211 | cleanup_sctp_mibs(); |
1198 | err_init_mibs: | 1212 | err_init_mibs: |
1199 | kmem_cache_destroy(sctp_chunk_cachep); | 1213 | kmem_cache_destroy(sctp_chunk_cachep); |
1200 | err_chunk_cachep: | 1214 | err_chunk_cachep: |
1201 | kmem_cache_destroy(sctp_bucket_cachep); | 1215 | kmem_cache_destroy(sctp_bucket_cachep); |
1202 | err_bucket_cachep: | ||
1203 | inet_del_protocol(&sctp_protocol, IPPROTO_SCTP); | ||
1204 | inet_unregister_protosw(&sctp_seqpacket_protosw); | ||
1205 | inet_unregister_protosw(&sctp_stream_protosw); | ||
1206 | err_add_protocol: | ||
1207 | proto_unregister(&sctp_prot); | ||
1208 | goto out; | 1216 | goto out; |
1209 | } | 1217 | } |
1210 | 1218 | ||
@@ -1215,8 +1223,9 @@ SCTP_STATIC __exit void sctp_exit(void) | |||
1215 | * up all the remaining associations and all that memory. | 1223 | * up all the remaining associations and all that memory. |
1216 | */ | 1224 | */ |
1217 | 1225 | ||
1218 | /* Unregister notifier for inet address additions/deletions. */ | 1226 | /* Unregister with inet6/inet layers. */ |
1219 | unregister_inetaddr_notifier(&sctp_inetaddr_notifier); | 1227 | sctp_v6_del_protocol(); |
1228 | inet_del_protocol(&sctp_protocol, IPPROTO_SCTP); | ||
1220 | 1229 | ||
1221 | /* Free the local address list. */ | 1230 | /* Free the local address list. */ |
1222 | sctp_free_local_addr_list(); | 1231 | sctp_free_local_addr_list(); |
@@ -1224,7 +1233,16 @@ SCTP_STATIC __exit void sctp_exit(void) | |||
1224 | /* Free the control endpoint. */ | 1233 | /* Free the control endpoint. */ |
1225 | sock_release(sctp_ctl_socket); | 1234 | sock_release(sctp_ctl_socket); |
1226 | 1235 | ||
1236 | /* Cleanup v6 initializations. */ | ||
1227 | sctp_v6_exit(); | 1237 | sctp_v6_exit(); |
1238 | |||
1239 | /* Unregister with socket layer. */ | ||
1240 | inet_unregister_protosw(&sctp_stream_protosw); | ||
1241 | inet_unregister_protosw(&sctp_seqpacket_protosw); | ||
1242 | |||
1243 | /* Unregister notifier for inet address additions/deletions. */ | ||
1244 | unregister_inetaddr_notifier(&sctp_inetaddr_notifier); | ||
1245 | |||
1228 | sctp_sysctl_unregister(); | 1246 | sctp_sysctl_unregister(); |
1229 | list_del(&sctp_ipv4_specific.list); | 1247 | list_del(&sctp_ipv4_specific.list); |
1230 | 1248 | ||
@@ -1236,16 +1254,13 @@ SCTP_STATIC __exit void sctp_exit(void) | |||
1236 | get_order(sctp_port_hashsize * | 1254 | get_order(sctp_port_hashsize * |
1237 | sizeof(struct sctp_bind_hashbucket))); | 1255 | sizeof(struct sctp_bind_hashbucket))); |
1238 | 1256 | ||
1239 | kmem_cache_destroy(sctp_chunk_cachep); | ||
1240 | kmem_cache_destroy(sctp_bucket_cachep); | ||
1241 | |||
1242 | sctp_dbg_objcnt_exit(); | 1257 | sctp_dbg_objcnt_exit(); |
1243 | sctp_proc_exit(); | 1258 | sctp_proc_exit(); |
1244 | cleanup_sctp_mibs(); | 1259 | cleanup_sctp_mibs(); |
1245 | 1260 | ||
1246 | inet_del_protocol(&sctp_protocol, IPPROTO_SCTP); | 1261 | kmem_cache_destroy(sctp_chunk_cachep); |
1247 | inet_unregister_protosw(&sctp_seqpacket_protosw); | 1262 | kmem_cache_destroy(sctp_bucket_cachep); |
1248 | inet_unregister_protosw(&sctp_stream_protosw); | 1263 | |
1249 | proto_unregister(&sctp_prot); | 1264 | proto_unregister(&sctp_prot); |
1250 | } | 1265 | } |
1251 | 1266 | ||