Commit 827bf12236fbafc02bc899aec1b37c342c8cf4e5

Authored by Sridhar Samudrala
Committed by David S. Miller
1 parent ce5325c133

[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>

Showing 3 changed files with 79 additions and 53 deletions Side-by-side Diff

include/net/sctp/sctp.h
... ... @@ -378,11 +378,15 @@
378 378  
379 379 int sctp_v6_init(void);
380 380 void sctp_v6_exit(void);
  381 +int sctp_v6_add_protocol(void);
  382 +void sctp_v6_del_protocol(void);
381 383  
382 384 #else /* #ifdef defined(CONFIG_IPV6) */
383 385  
384 386 static inline int sctp_v6_init(void) { return 0; }
385 387 static inline void sctp_v6_exit(void) { return; }
  388 +static inline int sctp_v6_add_protocol(void) { return 0; }
  389 +static inline void sctp_v6_del_protocol(void) { return; }
386 390  
387 391 #endif /* #if defined(CONFIG_IPV6) */
388 392  
... ... @@ -992,46 +992,53 @@
992 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 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 1007 if (rc)
1001   - goto out;
1002   - /* Register inet6 protocol. */
1003   - rc = -EAGAIN;
1004   - if (inet6_add_protocol(&sctpv6_protocol, IPPROTO_SCTP) < 0)
1005   - goto out_unregister_sctp_proto;
  1008 + return rc;
1006 1009  
1007 1010 /* Add SCTPv6(UDP and TCP style) to inetsw6 linked list. */
1008 1011 inet6_register_protosw(&sctpv6_seqpacket_protosw);
1009 1012 inet6_register_protosw(&sctpv6_stream_protosw);
1010 1013  
1011   - /* Register the SCTP specific PF_INET6 functions. */
1012   - sctp_register_pf(&sctp_pf_inet6_specific, PF_INET6);
  1014 + return 0;
  1015 +}
1013 1016  
1014   - /* Register the SCTP specific AF_INET6 functions. */
1015   - sctp_register_af(&sctp_ipv6_specific);
1016   -
  1017 +/* Register with inet6 layer. */
  1018 +int sctp_v6_add_protocol(void)
  1019 +{
1017 1020 /* Register notifier for inet6 address additions/deletions. */
1018 1021 register_inet6addr_notifier(&sctp_inet6addr_notifier);
1019   - rc = 0;
1020   -out:
1021   - return rc;
1022   -out_unregister_sctp_proto:
1023   - proto_unregister(&sctpv6_prot);
1024   - goto out;
  1022 +
  1023 + if (inet6_add_protocol(&sctpv6_protocol, IPPROTO_SCTP) < 0)
  1024 + return -EAGAIN;
  1025 +
  1026 + return 0;
1025 1027 }
1026 1028  
1027 1029 /* IPv6 specific exit support. */
1028 1030 void sctp_v6_exit(void)
1029 1031 {
1030   - list_del(&sctp_ipv6_specific.list);
1031   - inet6_del_protocol(&sctpv6_protocol, IPPROTO_SCTP);
1032 1032 inet6_unregister_protosw(&sctpv6_seqpacket_protosw);
1033 1033 inet6_unregister_protosw(&sctpv6_stream_protosw);
1034   - unregister_inet6addr_notifier(&sctp_inet6addr_notifier);
1035 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 }
... ... @@ -975,28 +975,14 @@
975 975 if (!sctp_sanity_check())
976 976 goto out;
977 977  
978   - status = proto_register(&sctp_prot, 1);
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. */
  978 + /* Allocate bind_bucket and chunk caches. */
992 979 status = -ENOBUFS;
993 980 sctp_bucket_cachep = kmem_cache_create("sctp_bind_bucket",
994 981 sizeof(struct sctp_bind_bucket),
995 982 0, SLAB_HWCACHE_ALIGN,
996 983 NULL, NULL);
997   -
998 984 if (!sctp_bucket_cachep)
999   - goto err_bucket_cachep;
  985 + goto out;
1000 986  
1001 987 sctp_chunk_cachep = kmem_cache_create("sctp_chunk",
1002 988 sizeof(struct sctp_chunk),
... ... @@ -1153,6 +1139,14 @@
1153 1139 INIT_LIST_HEAD(&sctp_address_families);
1154 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 1150 status = sctp_v6_init();
1157 1151 if (status)
1158 1152 goto err_v6_init;
1159 1153  
1160 1154  
1161 1155  
... ... @@ -1166,19 +1160,39 @@
1166 1160  
1167 1161 /* Initialize the local address list. */
1168 1162 INIT_LIST_HEAD(&sctp_local_addr_list);
1169   -
1170 1163 sctp_get_local_addr_list();
1171 1164  
1172 1165 /* Register notifier for inet address additions/deletions. */
1173 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 1179 __unsafe(THIS_MODULE);
1176 1180 status = 0;
1177 1181 out:
1178 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 1189 err_ctl_sock_init:
1180 1190 sctp_v6_exit();
1181 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 1196 sctp_sysctl_unregister();
1183 1197 list_del(&sctp_ipv4_specific.list);
1184 1198 free_pages((unsigned long)sctp_port_hashtable,
1185 1199  
1186 1200  
... ... @@ -1192,19 +1206,13 @@
1192 1206 sizeof(struct sctp_hashbucket)));
1193 1207 err_ahash_alloc:
1194 1208 sctp_dbg_objcnt_exit();
1195   -err_init_proc:
1196 1209 sctp_proc_exit();
  1210 +err_init_proc:
1197 1211 cleanup_sctp_mibs();
1198 1212 err_init_mibs:
1199 1213 kmem_cache_destroy(sctp_chunk_cachep);
1200 1214 err_chunk_cachep:
1201 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 1216 goto out;
1209 1217 }
1210 1218  
... ... @@ -1215,8 +1223,9 @@
1215 1223 * up all the remaining associations and all that memory.
1216 1224 */
1217 1225  
1218   - /* Unregister notifier for inet address additions/deletions. */
1219   - unregister_inetaddr_notifier(&sctp_inetaddr_notifier);
  1226 + /* Unregister with inet6/inet layers. */
  1227 + sctp_v6_del_protocol();
  1228 + inet_del_protocol(&sctp_protocol, IPPROTO_SCTP);
1220 1229  
1221 1230 /* Free the local address list. */
1222 1231 sctp_free_local_addr_list();
1223 1232  
... ... @@ -1224,7 +1233,16 @@
1224 1233 /* Free the control endpoint. */
1225 1234 sock_release(sctp_ctl_socket);
1226 1235  
  1236 + /* Cleanup v6 initializations. */
1227 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 1246 sctp_sysctl_unregister();
1229 1247 list_del(&sctp_ipv4_specific.list);
1230 1248  
1231 1249  
... ... @@ -1236,16 +1254,13 @@
1236 1254 get_order(sctp_port_hashsize *
1237 1255 sizeof(struct sctp_bind_hashbucket)));
1238 1256  
1239   - kmem_cache_destroy(sctp_chunk_cachep);
1240   - kmem_cache_destroy(sctp_bucket_cachep);
1241   -
1242 1257 sctp_dbg_objcnt_exit();
1243 1258 sctp_proc_exit();
1244 1259 cleanup_sctp_mibs();
1245 1260  
1246   - inet_del_protocol(&sctp_protocol, IPPROTO_SCTP);
1247   - inet_unregister_protosw(&sctp_seqpacket_protosw);
1248   - inet_unregister_protosw(&sctp_stream_protosw);
  1261 + kmem_cache_destroy(sctp_chunk_cachep);
  1262 + kmem_cache_destroy(sctp_bucket_cachep);
  1263 +
1249 1264 proto_unregister(&sctp_prot);
1250 1265 }
1251 1266