aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp
diff options
context:
space:
mode:
authorSridhar Samudrala <sri@us.ibm.com>2007-05-04 16:36:30 -0400
committerDavid S. Miller <davem@davemloft.net>2007-05-04 16:36:30 -0400
commit827bf12236fbafc02bc899aec1b37c342c8cf4e5 (patch)
tree41101b0d866629b3cc3341712996f11e655f6250 /net/sctp
parentce5325c1338acf965f4300f4976eac2129aeb439 (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/sctp')
-rw-r--r--net/sctp/ipv6.c49
-rw-r--r--net/sctp/protocol.c79
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. */
996int sctp_v6_init(void) 996int 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. */
1018int 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
1020out: 1023 if (inet6_add_protocol(&sctpv6_protocol, IPPROTO_SCTP) < 0)
1021 return rc; 1024 return -EAGAIN;
1022out_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. */
1028void sctp_v6_exit(void) 1030void 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. */
1039void 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;
1177out: 1181out:
1178 return status; 1182 return status;
1183err_v6_add_protocol:
1184 inet_del_protocol(&sctp_protocol, IPPROTO_SCTP);
1185 unregister_inetaddr_notifier(&sctp_inetaddr_notifier);
1186err_add_protocol:
1187 sctp_free_local_addr_list();
1188 sock_release(sctp_ctl_socket);
1179err_ctl_sock_init: 1189err_ctl_sock_init:
1180 sctp_v6_exit(); 1190 sctp_v6_exit();
1181err_v6_init: 1191err_v6_init:
1192 inet_unregister_protosw(&sctp_stream_protosw);
1193 inet_unregister_protosw(&sctp_seqpacket_protosw);
1194 proto_unregister(&sctp_prot);
1195err_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)));
1193err_ahash_alloc: 1207err_ahash_alloc:
1194 sctp_dbg_objcnt_exit(); 1208 sctp_dbg_objcnt_exit();
1195err_init_proc:
1196 sctp_proc_exit(); 1209 sctp_proc_exit();
1210err_init_proc:
1197 cleanup_sctp_mibs(); 1211 cleanup_sctp_mibs();
1198err_init_mibs: 1212err_init_mibs:
1199 kmem_cache_destroy(sctp_chunk_cachep); 1213 kmem_cache_destroy(sctp_chunk_cachep);
1200err_chunk_cachep: 1214err_chunk_cachep:
1201 kmem_cache_destroy(sctp_bucket_cachep); 1215 kmem_cache_destroy(sctp_bucket_cachep);
1202err_bucket_cachep:
1203 inet_del_protocol(&sctp_protocol, IPPROTO_SCTP);
1204 inet_unregister_protosw(&sctp_seqpacket_protosw);
1205 inet_unregister_protosw(&sctp_stream_protosw);
1206err_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