aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/sctp/associola.c14
-rw-r--r--net/sctp/bind_addr.c68
-rw-r--r--net/sctp/endpointola.c27
-rw-r--r--net/sctp/ipv6.c12
-rw-r--r--net/sctp/protocol.c25
-rw-r--r--net/sctp/sm_make_chunk.c18
-rw-r--r--net/sctp/socket.c98
7 files changed, 103 insertions, 159 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 2ad1caf1ea42..9bad8ba0feda 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -99,7 +99,6 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
99 99
100 /* Initialize the bind addr area. */ 100 /* Initialize the bind addr area. */
101 sctp_bind_addr_init(&asoc->base.bind_addr, ep->base.bind_addr.port); 101 sctp_bind_addr_init(&asoc->base.bind_addr, ep->base.bind_addr.port);
102 rwlock_init(&asoc->base.addr_lock);
103 102
104 asoc->state = SCTP_STATE_CLOSED; 103 asoc->state = SCTP_STATE_CLOSED;
105 104
@@ -937,8 +936,6 @@ struct sctp_transport *sctp_assoc_is_match(struct sctp_association *asoc,
937{ 936{
938 struct sctp_transport *transport; 937 struct sctp_transport *transport;
939 938
940 sctp_read_lock(&asoc->base.addr_lock);
941
942 if ((htons(asoc->base.bind_addr.port) == laddr->v4.sin_port) && 939 if ((htons(asoc->base.bind_addr.port) == laddr->v4.sin_port) &&
943 (htons(asoc->peer.port) == paddr->v4.sin_port)) { 940 (htons(asoc->peer.port) == paddr->v4.sin_port)) {
944 transport = sctp_assoc_lookup_paddr(asoc, paddr); 941 transport = sctp_assoc_lookup_paddr(asoc, paddr);
@@ -952,7 +949,6 @@ struct sctp_transport *sctp_assoc_is_match(struct sctp_association *asoc,
952 transport = NULL; 949 transport = NULL;
953 950
954out: 951out:
955 sctp_read_unlock(&asoc->base.addr_lock);
956 return transport; 952 return transport;
957} 953}
958 954
@@ -1376,19 +1372,13 @@ int sctp_assoc_set_bind_addr_from_cookie(struct sctp_association *asoc,
1376int sctp_assoc_lookup_laddr(struct sctp_association *asoc, 1372int sctp_assoc_lookup_laddr(struct sctp_association *asoc,
1377 const union sctp_addr *laddr) 1373 const union sctp_addr *laddr)
1378{ 1374{
1379 int found; 1375 int found = 0;
1380 1376
1381 sctp_read_lock(&asoc->base.addr_lock);
1382 if ((asoc->base.bind_addr.port == ntohs(laddr->v4.sin_port)) && 1377 if ((asoc->base.bind_addr.port == ntohs(laddr->v4.sin_port)) &&
1383 sctp_bind_addr_match(&asoc->base.bind_addr, laddr, 1378 sctp_bind_addr_match(&asoc->base.bind_addr, laddr,
1384 sctp_sk(asoc->base.sk))) { 1379 sctp_sk(asoc->base.sk)))
1385 found = 1; 1380 found = 1;
1386 goto out;
1387 }
1388 1381
1389 found = 0;
1390out:
1391 sctp_read_unlock(&asoc->base.addr_lock);
1392 return found; 1382 return found;
1393} 1383}
1394 1384
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c
index 7fc369f9035d..d35cbf5aae33 100644
--- a/net/sctp/bind_addr.c
+++ b/net/sctp/bind_addr.c
@@ -167,7 +167,11 @@ int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new,
167 167
168 INIT_LIST_HEAD(&addr->list); 168 INIT_LIST_HEAD(&addr->list);
169 INIT_RCU_HEAD(&addr->rcu); 169 INIT_RCU_HEAD(&addr->rcu);
170 list_add_tail(&addr->list, &bp->address_list); 170
171 /* We always hold a socket lock when calling this function,
172 * and that acts as a writer synchronizing lock.
173 */
174 list_add_tail_rcu(&addr->list, &bp->address_list);
171 SCTP_DBG_OBJCNT_INC(addr); 175 SCTP_DBG_OBJCNT_INC(addr);
172 176
173 return 0; 177 return 0;
@@ -176,23 +180,35 @@ int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new,
176/* Delete an address from the bind address list in the SCTP_bind_addr 180/* Delete an address from the bind address list in the SCTP_bind_addr
177 * structure. 181 * structure.
178 */ 182 */
179int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr) 183int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr,
184 void (*rcu_call)(struct rcu_head *head,
185 void (*func)(struct rcu_head *head)))
180{ 186{
181 struct list_head *pos, *temp; 187 struct sctp_sockaddr_entry *addr, *temp;
182 struct sctp_sockaddr_entry *addr;
183 188
184 list_for_each_safe(pos, temp, &bp->address_list) { 189 /* We hold the socket lock when calling this function,
185 addr = list_entry(pos, struct sctp_sockaddr_entry, list); 190 * and that acts as a writer synchronizing lock.
191 */
192 list_for_each_entry_safe(addr, temp, &bp->address_list, list) {
186 if (sctp_cmp_addr_exact(&addr->a, del_addr)) { 193 if (sctp_cmp_addr_exact(&addr->a, del_addr)) {
187 /* Found the exact match. */ 194 /* Found the exact match. */
188 list_del(pos); 195 addr->valid = 0;
189 kfree(addr); 196 list_del_rcu(&addr->list);
190 SCTP_DBG_OBJCNT_DEC(addr); 197 break;
191
192 return 0;
193 } 198 }
194 } 199 }
195 200
201 /* Call the rcu callback provided in the args. This function is
202 * called by both BH packet processing and user side socket option
203 * processing, but it works on different lists in those 2 contexts.
204 * Each context provides it's own callback, whether call_rcu_bh()
205 * or call_rcu(), to make sure that we wait for an appropriate time.
206 */
207 if (addr && !addr->valid) {
208 rcu_call(&addr->rcu, sctp_local_addr_free);
209 SCTP_DBG_OBJCNT_DEC(addr);
210 }
211
196 return -EINVAL; 212 return -EINVAL;
197} 213}
198 214
@@ -302,15 +318,20 @@ int sctp_bind_addr_match(struct sctp_bind_addr *bp,
302 struct sctp_sock *opt) 318 struct sctp_sock *opt)
303{ 319{
304 struct sctp_sockaddr_entry *laddr; 320 struct sctp_sockaddr_entry *laddr;
305 struct list_head *pos; 321 int match = 0;
306 322
307 list_for_each(pos, &bp->address_list) { 323 rcu_read_lock();
308 laddr = list_entry(pos, struct sctp_sockaddr_entry, list); 324 list_for_each_entry_rcu(laddr, &bp->address_list, list) {
309 if (opt->pf->cmp_addr(&laddr->a, addr, opt)) 325 if (!laddr->valid)
310 return 1; 326 continue;
327 if (opt->pf->cmp_addr(&laddr->a, addr, opt)) {
328 match = 1;
329 break;
330 }
311 } 331 }
332 rcu_read_unlock();
312 333
313 return 0; 334 return match;
314} 335}
315 336
316/* Find the first address in the bind address list that is not present in 337/* Find the first address in the bind address list that is not present in
@@ -325,18 +346,19 @@ union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr *bp,
325 union sctp_addr *addr; 346 union sctp_addr *addr;
326 void *addr_buf; 347 void *addr_buf;
327 struct sctp_af *af; 348 struct sctp_af *af;
328 struct list_head *pos;
329 int i; 349 int i;
330 350
331 list_for_each(pos, &bp->address_list) { 351 /* This is only called sctp_send_asconf_del_ip() and we hold
332 laddr = list_entry(pos, struct sctp_sockaddr_entry, list); 352 * the socket lock in that code patch, so that address list
333 353 * can't change.
354 */
355 list_for_each_entry(laddr, &bp->address_list, list) {
334 addr_buf = (union sctp_addr *)addrs; 356 addr_buf = (union sctp_addr *)addrs;
335 for (i = 0; i < addrcnt; i++) { 357 for (i = 0; i < addrcnt; i++) {
336 addr = (union sctp_addr *)addr_buf; 358 addr = (union sctp_addr *)addr_buf;
337 af = sctp_get_af_specific(addr->v4.sin_family); 359 af = sctp_get_af_specific(addr->v4.sin_family);
338 if (!af) 360 if (!af)
339 return NULL; 361 break;
340 362
341 if (opt->pf->cmp_addr(&laddr->a, addr, opt)) 363 if (opt->pf->cmp_addr(&laddr->a, addr, opt))
342 break; 364 break;
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index 1404a9e2e78f..8f485a0d14bd 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -92,7 +92,6 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
92 92
93 /* Initialize the bind addr area */ 93 /* Initialize the bind addr area */
94 sctp_bind_addr_init(&ep->base.bind_addr, 0); 94 sctp_bind_addr_init(&ep->base.bind_addr, 0);
95 rwlock_init(&ep->base.addr_lock);
96 95
97 /* Remember who we are attached to. */ 96 /* Remember who we are attached to. */
98 ep->base.sk = sk; 97 ep->base.sk = sk;
@@ -225,21 +224,14 @@ void sctp_endpoint_put(struct sctp_endpoint *ep)
225struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *ep, 224struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *ep,
226 const union sctp_addr *laddr) 225 const union sctp_addr *laddr)
227{ 226{
228 struct sctp_endpoint *retval; 227 struct sctp_endpoint *retval = NULL;
229 228
230 sctp_read_lock(&ep->base.addr_lock);
231 if (htons(ep->base.bind_addr.port) == laddr->v4.sin_port) { 229 if (htons(ep->base.bind_addr.port) == laddr->v4.sin_port) {
232 if (sctp_bind_addr_match(&ep->base.bind_addr, laddr, 230 if (sctp_bind_addr_match(&ep->base.bind_addr, laddr,
233 sctp_sk(ep->base.sk))) { 231 sctp_sk(ep->base.sk)))
234 retval = ep; 232 retval = ep;
235 goto out;
236 }
237 } 233 }
238 234
239 retval = NULL;
240
241out:
242 sctp_read_unlock(&ep->base.addr_lock);
243 return retval; 235 return retval;
244} 236}
245 237
@@ -261,9 +253,7 @@ static struct sctp_association *__sctp_endpoint_lookup_assoc(
261 list_for_each(pos, &ep->asocs) { 253 list_for_each(pos, &ep->asocs) {
262 asoc = list_entry(pos, struct sctp_association, asocs); 254 asoc = list_entry(pos, struct sctp_association, asocs);
263 if (rport == asoc->peer.port) { 255 if (rport == asoc->peer.port) {
264 sctp_read_lock(&asoc->base.addr_lock);
265 *transport = sctp_assoc_lookup_paddr(asoc, paddr); 256 *transport = sctp_assoc_lookup_paddr(asoc, paddr);
266 sctp_read_unlock(&asoc->base.addr_lock);
267 257
268 if (*transport) 258 if (*transport)
269 return asoc; 259 return asoc;
@@ -295,20 +285,17 @@ struct sctp_association *sctp_endpoint_lookup_assoc(
295int sctp_endpoint_is_peeled_off(struct sctp_endpoint *ep, 285int sctp_endpoint_is_peeled_off(struct sctp_endpoint *ep,
296 const union sctp_addr *paddr) 286 const union sctp_addr *paddr)
297{ 287{
298 struct list_head *pos;
299 struct sctp_sockaddr_entry *addr; 288 struct sctp_sockaddr_entry *addr;
300 struct sctp_bind_addr *bp; 289 struct sctp_bind_addr *bp;
301 290
302 sctp_read_lock(&ep->base.addr_lock);
303 bp = &ep->base.bind_addr; 291 bp = &ep->base.bind_addr;
304 list_for_each(pos, &bp->address_list) { 292 /* This function is called with the socket lock held,
305 addr = list_entry(pos, struct sctp_sockaddr_entry, list); 293 * so the address_list can not change.
306 if (sctp_has_association(&addr->a, paddr)) { 294 */
307 sctp_read_unlock(&ep->base.addr_lock); 295 list_for_each_entry(addr, &bp->address_list, list) {
296 if (sctp_has_association(&addr->a, paddr))
308 return 1; 297 return 1;
309 }
310 } 298 }
311 sctp_read_unlock(&ep->base.addr_lock);
312 299
313 return 0; 300 return 0;
314} 301}
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index e12fa0a91da4..670fd2740b89 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -302,9 +302,7 @@ static void sctp_v6_get_saddr(struct sctp_association *asoc,
302 union sctp_addr *saddr) 302 union sctp_addr *saddr)
303{ 303{
304 struct sctp_bind_addr *bp; 304 struct sctp_bind_addr *bp;
305 rwlock_t *addr_lock;
306 struct sctp_sockaddr_entry *laddr; 305 struct sctp_sockaddr_entry *laddr;
307 struct list_head *pos;
308 sctp_scope_t scope; 306 sctp_scope_t scope;
309 union sctp_addr *baddr = NULL; 307 union sctp_addr *baddr = NULL;
310 __u8 matchlen = 0; 308 __u8 matchlen = 0;
@@ -324,14 +322,14 @@ static void sctp_v6_get_saddr(struct sctp_association *asoc,
324 scope = sctp_scope(daddr); 322 scope = sctp_scope(daddr);
325 323
326 bp = &asoc->base.bind_addr; 324 bp = &asoc->base.bind_addr;
327 addr_lock = &asoc->base.addr_lock;
328 325
329 /* Go through the bind address list and find the best source address 326 /* Go through the bind address list and find the best source address
330 * that matches the scope of the destination address. 327 * that matches the scope of the destination address.
331 */ 328 */
332 sctp_read_lock(addr_lock); 329 rcu_read_lock();
333 list_for_each(pos, &bp->address_list) { 330 list_for_each_entry_rcu(laddr, &bp->address_list, list) {
334 laddr = list_entry(pos, struct sctp_sockaddr_entry, list); 331 if (!laddr->valid)
332 continue;
335 if ((laddr->use_as_src) && 333 if ((laddr->use_as_src) &&
336 (laddr->a.sa.sa_family == AF_INET6) && 334 (laddr->a.sa.sa_family == AF_INET6) &&
337 (scope <= sctp_scope(&laddr->a))) { 335 (scope <= sctp_scope(&laddr->a))) {
@@ -353,7 +351,7 @@ static void sctp_v6_get_saddr(struct sctp_association *asoc,
353 __FUNCTION__, asoc, NIP6(daddr->v6.sin6_addr)); 351 __FUNCTION__, asoc, NIP6(daddr->v6.sin6_addr));
354 } 352 }
355 353
356 sctp_read_unlock(addr_lock); 354 rcu_read_unlock();
357} 355}
358 356
359/* Make a copy of all potential local addresses. */ 357/* Make a copy of all potential local addresses. */
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 7ee120e85913..3d036cdfae41 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -224,7 +224,7 @@ int sctp_copy_local_addr_list(struct sctp_bind_addr *bp, sctp_scope_t scope,
224 (copy_flags & SCTP_ADDR6_ALLOWED) && 224 (copy_flags & SCTP_ADDR6_ALLOWED) &&
225 (copy_flags & SCTP_ADDR6_PEERSUPP)))) { 225 (copy_flags & SCTP_ADDR6_PEERSUPP)))) {
226 error = sctp_add_bind_addr(bp, &addr->a, 1, 226 error = sctp_add_bind_addr(bp, &addr->a, 1,
227 GFP_ATOMIC); 227 GFP_ATOMIC);
228 if (error) 228 if (error)
229 goto end_copy; 229 goto end_copy;
230 } 230 }
@@ -428,9 +428,7 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc,
428 struct rtable *rt; 428 struct rtable *rt;
429 struct flowi fl; 429 struct flowi fl;
430 struct sctp_bind_addr *bp; 430 struct sctp_bind_addr *bp;
431 rwlock_t *addr_lock;
432 struct sctp_sockaddr_entry *laddr; 431 struct sctp_sockaddr_entry *laddr;
433 struct list_head *pos;
434 struct dst_entry *dst = NULL; 432 struct dst_entry *dst = NULL;
435 union sctp_addr dst_saddr; 433 union sctp_addr dst_saddr;
436 434
@@ -459,23 +457,20 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc,
459 goto out; 457 goto out;
460 458
461 bp = &asoc->base.bind_addr; 459 bp = &asoc->base.bind_addr;
462 addr_lock = &asoc->base.addr_lock;
463 460
464 if (dst) { 461 if (dst) {
465 /* Walk through the bind address list and look for a bind 462 /* Walk through the bind address list and look for a bind
466 * address that matches the source address of the returned dst. 463 * address that matches the source address of the returned dst.
467 */ 464 */
468 sctp_read_lock(addr_lock); 465 rcu_read_lock();
469 list_for_each(pos, &bp->address_list) { 466 list_for_each_entry_rcu(laddr, &bp->address_list, list) {
470 laddr = list_entry(pos, struct sctp_sockaddr_entry, 467 if (!laddr->valid || !laddr->use_as_src)
471 list);
472 if (!laddr->use_as_src)
473 continue; 468 continue;
474 sctp_v4_dst_saddr(&dst_saddr, dst, htons(bp->port)); 469 sctp_v4_dst_saddr(&dst_saddr, dst, htons(bp->port));
475 if (sctp_v4_cmp_addr(&dst_saddr, &laddr->a)) 470 if (sctp_v4_cmp_addr(&dst_saddr, &laddr->a))
476 goto out_unlock; 471 goto out_unlock;
477 } 472 }
478 sctp_read_unlock(addr_lock); 473 rcu_read_unlock();
479 474
480 /* None of the bound addresses match the source address of the 475 /* None of the bound addresses match the source address of the
481 * dst. So release it. 476 * dst. So release it.
@@ -487,10 +482,10 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc,
487 /* Walk through the bind address list and try to get a dst that 482 /* Walk through the bind address list and try to get a dst that
488 * matches a bind address as the source address. 483 * matches a bind address as the source address.
489 */ 484 */
490 sctp_read_lock(addr_lock); 485 rcu_read_lock();
491 list_for_each(pos, &bp->address_list) { 486 list_for_each_entry_rcu(laddr, &bp->address_list, list) {
492 laddr = list_entry(pos, struct sctp_sockaddr_entry, list); 487 if (!laddr->valid)
493 488 continue;
494 if ((laddr->use_as_src) && 489 if ((laddr->use_as_src) &&
495 (AF_INET == laddr->a.sa.sa_family)) { 490 (AF_INET == laddr->a.sa.sa_family)) {
496 fl.fl4_src = laddr->a.v4.sin_addr.s_addr; 491 fl.fl4_src = laddr->a.v4.sin_addr.s_addr;
@@ -502,7 +497,7 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc,
502 } 497 }
503 498
504out_unlock: 499out_unlock:
505 sctp_read_unlock(addr_lock); 500 rcu_read_unlock();
506out: 501out:
507 if (dst) 502 if (dst)
508 SCTP_DEBUG_PRINTK("rt_dst:%u.%u.%u.%u, rt_src:%u.%u.%u.%u\n", 503 SCTP_DEBUG_PRINTK("rt_dst:%u.%u.%u.%u, rt_src:%u.%u.%u.%u\n",
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 79856c924525..2e34220d94cd 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -1531,7 +1531,7 @@ no_hmac:
1531 /* Also, add the destination address. */ 1531 /* Also, add the destination address. */
1532 if (list_empty(&retval->base.bind_addr.address_list)) { 1532 if (list_empty(&retval->base.bind_addr.address_list)) {
1533 sctp_add_bind_addr(&retval->base.bind_addr, &chunk->dest, 1, 1533 sctp_add_bind_addr(&retval->base.bind_addr, &chunk->dest, 1,
1534 GFP_ATOMIC); 1534 GFP_ATOMIC);
1535 } 1535 }
1536 1536
1537 retval->next_tsn = retval->c.initial_tsn; 1537 retval->next_tsn = retval->c.initial_tsn;
@@ -2613,22 +2613,16 @@ static int sctp_asconf_param_success(struct sctp_association *asoc,
2613 2613
2614 switch (asconf_param->param_hdr.type) { 2614 switch (asconf_param->param_hdr.type) {
2615 case SCTP_PARAM_ADD_IP: 2615 case SCTP_PARAM_ADD_IP:
2616 sctp_local_bh_disable(); 2616 /* This is always done in BH context with a socket lock
2617 sctp_write_lock(&asoc->base.addr_lock); 2617 * held, so the list can not change.
2618 list_for_each(pos, &bp->address_list) { 2618 */
2619 saddr = list_entry(pos, struct sctp_sockaddr_entry, list); 2619 list_for_each_entry(saddr, &bp->address_list, list) {
2620 if (sctp_cmp_addr_exact(&saddr->a, &addr)) 2620 if (sctp_cmp_addr_exact(&saddr->a, &addr))
2621 saddr->use_as_src = 1; 2621 saddr->use_as_src = 1;
2622 } 2622 }
2623 sctp_write_unlock(&asoc->base.addr_lock);
2624 sctp_local_bh_enable();
2625 break; 2623 break;
2626 case SCTP_PARAM_DEL_IP: 2624 case SCTP_PARAM_DEL_IP:
2627 sctp_local_bh_disable(); 2625 retval = sctp_del_bind_addr(bp, &addr, call_rcu_bh);
2628 sctp_write_lock(&asoc->base.addr_lock);
2629 retval = sctp_del_bind_addr(bp, &addr);
2630 sctp_write_unlock(&asoc->base.addr_lock);
2631 sctp_local_bh_enable();
2632 list_for_each(pos, &asoc->peer.transport_addr_list) { 2626 list_for_each(pos, &asoc->peer.transport_addr_list) {
2633 transport = list_entry(pos, struct sctp_transport, 2627 transport = list_entry(pos, struct sctp_transport,
2634 transports); 2628 transports);
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index a3acf78d06ba..772fbfb4bfda 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -367,14 +367,10 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
367 if (!bp->port) 367 if (!bp->port)
368 bp->port = inet_sk(sk)->num; 368 bp->port = inet_sk(sk)->num;
369 369
370 /* Add the address to the bind address list. */ 370 /* Add the address to the bind address list.
371 sctp_local_bh_disable(); 371 * Use GFP_ATOMIC since BHs will be disabled.
372 sctp_write_lock(&ep->base.addr_lock); 372 */
373
374 /* Use GFP_ATOMIC since BHs are disabled. */
375 ret = sctp_add_bind_addr(bp, addr, 1, GFP_ATOMIC); 373 ret = sctp_add_bind_addr(bp, addr, 1, GFP_ATOMIC);
376 sctp_write_unlock(&ep->base.addr_lock);
377 sctp_local_bh_enable();
378 374
379 /* Copy back into socket for getsockname() use. */ 375 /* Copy back into socket for getsockname() use. */
380 if (!ret) { 376 if (!ret) {
@@ -544,15 +540,12 @@ static int sctp_send_asconf_add_ip(struct sock *sk,
544 if (i < addrcnt) 540 if (i < addrcnt)
545 continue; 541 continue;
546 542
547 /* Use the first address in bind addr list of association as 543 /* Use the first valid address in bind addr list of
548 * Address Parameter of ASCONF CHUNK. 544 * association as Address Parameter of ASCONF CHUNK.
549 */ 545 */
550 sctp_read_lock(&asoc->base.addr_lock);
551 bp = &asoc->base.bind_addr; 546 bp = &asoc->base.bind_addr;
552 p = bp->address_list.next; 547 p = bp->address_list.next;
553 laddr = list_entry(p, struct sctp_sockaddr_entry, list); 548 laddr = list_entry(p, struct sctp_sockaddr_entry, list);
554 sctp_read_unlock(&asoc->base.addr_lock);
555
556 chunk = sctp_make_asconf_update_ip(asoc, &laddr->a, addrs, 549 chunk = sctp_make_asconf_update_ip(asoc, &laddr->a, addrs,
557 addrcnt, SCTP_PARAM_ADD_IP); 550 addrcnt, SCTP_PARAM_ADD_IP);
558 if (!chunk) { 551 if (!chunk) {
@@ -567,8 +560,6 @@ static int sctp_send_asconf_add_ip(struct sock *sk,
567 /* Add the new addresses to the bind address list with 560 /* Add the new addresses to the bind address list with
568 * use_as_src set to 0. 561 * use_as_src set to 0.
569 */ 562 */
570 sctp_local_bh_disable();
571 sctp_write_lock(&asoc->base.addr_lock);
572 addr_buf = addrs; 563 addr_buf = addrs;
573 for (i = 0; i < addrcnt; i++) { 564 for (i = 0; i < addrcnt; i++) {
574 addr = (union sctp_addr *)addr_buf; 565 addr = (union sctp_addr *)addr_buf;
@@ -578,8 +569,6 @@ static int sctp_send_asconf_add_ip(struct sock *sk,
578 GFP_ATOMIC); 569 GFP_ATOMIC);
579 addr_buf += af->sockaddr_len; 570 addr_buf += af->sockaddr_len;
580 } 571 }
581 sctp_write_unlock(&asoc->base.addr_lock);
582 sctp_local_bh_enable();
583 } 572 }
584 573
585out: 574out:
@@ -651,13 +640,7 @@ static int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt)
651 * socket routing and failover schemes. Refer to comments in 640 * socket routing and failover schemes. Refer to comments in
652 * sctp_do_bind(). -daisy 641 * sctp_do_bind(). -daisy
653 */ 642 */
654 sctp_local_bh_disable(); 643 retval = sctp_del_bind_addr(bp, sa_addr, call_rcu);
655 sctp_write_lock(&ep->base.addr_lock);
656
657 retval = sctp_del_bind_addr(bp, sa_addr);
658
659 sctp_write_unlock(&ep->base.addr_lock);
660 sctp_local_bh_enable();
661 644
662 addr_buf += af->sockaddr_len; 645 addr_buf += af->sockaddr_len;
663err_bindx_rem: 646err_bindx_rem:
@@ -748,14 +731,16 @@ static int sctp_send_asconf_del_ip(struct sock *sk,
748 * make sure that we do not delete all the addresses in the 731 * make sure that we do not delete all the addresses in the
749 * association. 732 * association.
750 */ 733 */
751 sctp_read_lock(&asoc->base.addr_lock);
752 bp = &asoc->base.bind_addr; 734 bp = &asoc->base.bind_addr;
753 laddr = sctp_find_unmatch_addr(bp, (union sctp_addr *)addrs, 735 laddr = sctp_find_unmatch_addr(bp, (union sctp_addr *)addrs,
754 addrcnt, sp); 736 addrcnt, sp);
755 sctp_read_unlock(&asoc->base.addr_lock);
756 if (!laddr) 737 if (!laddr)
757 continue; 738 continue;
758 739
740 /* We do not need RCU protection throughout this loop
741 * because this is done under a socket lock from the
742 * setsockopt call.
743 */
759 chunk = sctp_make_asconf_update_ip(asoc, laddr, addrs, addrcnt, 744 chunk = sctp_make_asconf_update_ip(asoc, laddr, addrs, addrcnt,
760 SCTP_PARAM_DEL_IP); 745 SCTP_PARAM_DEL_IP);
761 if (!chunk) { 746 if (!chunk) {
@@ -766,23 +751,16 @@ static int sctp_send_asconf_del_ip(struct sock *sk,
766 /* Reset use_as_src flag for the addresses in the bind address 751 /* Reset use_as_src flag for the addresses in the bind address
767 * list that are to be deleted. 752 * list that are to be deleted.
768 */ 753 */
769 sctp_local_bh_disable();
770 sctp_write_lock(&asoc->base.addr_lock);
771 addr_buf = addrs; 754 addr_buf = addrs;
772 for (i = 0; i < addrcnt; i++) { 755 for (i = 0; i < addrcnt; i++) {
773 laddr = (union sctp_addr *)addr_buf; 756 laddr = (union sctp_addr *)addr_buf;
774 af = sctp_get_af_specific(laddr->v4.sin_family); 757 af = sctp_get_af_specific(laddr->v4.sin_family);
775 list_for_each(pos1, &bp->address_list) { 758 list_for_each_entry(saddr, &bp->address_list, list) {
776 saddr = list_entry(pos1,
777 struct sctp_sockaddr_entry,
778 list);
779 if (sctp_cmp_addr_exact(&saddr->a, laddr)) 759 if (sctp_cmp_addr_exact(&saddr->a, laddr))
780 saddr->use_as_src = 0; 760 saddr->use_as_src = 0;
781 } 761 }
782 addr_buf += af->sockaddr_len; 762 addr_buf += af->sockaddr_len;
783 } 763 }
784 sctp_write_unlock(&asoc->base.addr_lock);
785 sctp_local_bh_enable();
786 764
787 /* Update the route and saddr entries for all the transports 765 /* Update the route and saddr entries for all the transports
788 * as some of the addresses in the bind address list are 766 * as some of the addresses in the bind address list are
@@ -4057,11 +4035,9 @@ static int sctp_getsockopt_local_addrs_num_old(struct sock *sk, int len,
4057 int __user *optlen) 4035 int __user *optlen)
4058{ 4036{
4059 sctp_assoc_t id; 4037 sctp_assoc_t id;
4060 struct list_head *pos;
4061 struct sctp_bind_addr *bp; 4038 struct sctp_bind_addr *bp;
4062 struct sctp_association *asoc; 4039 struct sctp_association *asoc;
4063 struct sctp_sockaddr_entry *addr; 4040 struct sctp_sockaddr_entry *addr;
4064 rwlock_t *addr_lock;
4065 int cnt = 0; 4041 int cnt = 0;
4066 4042
4067 if (len < sizeof(sctp_assoc_t)) 4043 if (len < sizeof(sctp_assoc_t))
@@ -4078,17 +4054,13 @@ static int sctp_getsockopt_local_addrs_num_old(struct sock *sk, int len,
4078 */ 4054 */
4079 if (0 == id) { 4055 if (0 == id) {
4080 bp = &sctp_sk(sk)->ep->base.bind_addr; 4056 bp = &sctp_sk(sk)->ep->base.bind_addr;
4081 addr_lock = &sctp_sk(sk)->ep->base.addr_lock;
4082 } else { 4057 } else {
4083 asoc = sctp_id2assoc(sk, id); 4058 asoc = sctp_id2assoc(sk, id);
4084 if (!asoc) 4059 if (!asoc)
4085 return -EINVAL; 4060 return -EINVAL;
4086 bp = &asoc->base.bind_addr; 4061 bp = &asoc->base.bind_addr;
4087 addr_lock = &asoc->base.addr_lock;
4088 } 4062 }
4089 4063
4090 sctp_read_lock(addr_lock);
4091
4092 /* If the endpoint is bound to 0.0.0.0 or ::0, count the valid 4064 /* If the endpoint is bound to 0.0.0.0 or ::0, count the valid
4093 * addresses from the global local address list. 4065 * addresses from the global local address list.
4094 */ 4066 */
@@ -4115,12 +4087,14 @@ static int sctp_getsockopt_local_addrs_num_old(struct sock *sk, int len,
4115 goto done; 4087 goto done;
4116 } 4088 }
4117 4089
4118 list_for_each(pos, &bp->address_list) { 4090 /* Protection on the bound address list is not needed,
4091 * since in the socket option context we hold the socket lock,
4092 * so there is no way that the bound address list can change.
4093 */
4094 list_for_each_entry(addr, &bp->address_list, list) {
4119 cnt ++; 4095 cnt ++;
4120 } 4096 }
4121
4122done: 4097done:
4123 sctp_read_unlock(addr_lock);
4124 return cnt; 4098 return cnt;
4125} 4099}
4126 4100
@@ -4204,7 +4178,6 @@ static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len,
4204{ 4178{
4205 struct sctp_bind_addr *bp; 4179 struct sctp_bind_addr *bp;
4206 struct sctp_association *asoc; 4180 struct sctp_association *asoc;
4207 struct list_head *pos;
4208 int cnt = 0; 4181 int cnt = 0;
4209 struct sctp_getaddrs_old getaddrs; 4182 struct sctp_getaddrs_old getaddrs;
4210 struct sctp_sockaddr_entry *addr; 4183 struct sctp_sockaddr_entry *addr;
@@ -4212,7 +4185,6 @@ static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len,
4212 union sctp_addr temp; 4185 union sctp_addr temp;
4213 struct sctp_sock *sp = sctp_sk(sk); 4186 struct sctp_sock *sp = sctp_sk(sk);
4214 int addrlen; 4187 int addrlen;
4215 rwlock_t *addr_lock;
4216 int err = 0; 4188 int err = 0;
4217 void *addrs; 4189 void *addrs;
4218 void *buf; 4190 void *buf;
@@ -4234,13 +4206,11 @@ static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len,
4234 */ 4206 */
4235 if (0 == getaddrs.assoc_id) { 4207 if (0 == getaddrs.assoc_id) {
4236 bp = &sctp_sk(sk)->ep->base.bind_addr; 4208 bp = &sctp_sk(sk)->ep->base.bind_addr;
4237 addr_lock = &sctp_sk(sk)->ep->base.addr_lock;
4238 } else { 4209 } else {
4239 asoc = sctp_id2assoc(sk, getaddrs.assoc_id); 4210 asoc = sctp_id2assoc(sk, getaddrs.assoc_id);
4240 if (!asoc) 4211 if (!asoc)
4241 return -EINVAL; 4212 return -EINVAL;
4242 bp = &asoc->base.bind_addr; 4213 bp = &asoc->base.bind_addr;
4243 addr_lock = &asoc->base.addr_lock;
4244 } 4214 }
4245 4215
4246 to = getaddrs.addrs; 4216 to = getaddrs.addrs;
@@ -4254,8 +4224,6 @@ static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len,
4254 if (!addrs) 4224 if (!addrs)
4255 return -ENOMEM; 4225 return -ENOMEM;
4256 4226
4257 sctp_read_lock(addr_lock);
4258
4259 /* If the endpoint is bound to 0.0.0.0 or ::0, get the valid 4227 /* If the endpoint is bound to 0.0.0.0 or ::0, get the valid
4260 * addresses from the global local address list. 4228 * addresses from the global local address list.
4261 */ 4229 */
@@ -4271,8 +4239,11 @@ static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len,
4271 } 4239 }
4272 4240
4273 buf = addrs; 4241 buf = addrs;
4274 list_for_each(pos, &bp->address_list) { 4242 /* Protection on the bound address list is not needed since
4275 addr = list_entry(pos, struct sctp_sockaddr_entry, list); 4243 * in the socket option context we hold a socket lock and
4244 * thus the bound address list can't change.
4245 */
4246 list_for_each_entry(addr, &bp->address_list, list) {
4276 memcpy(&temp, &addr->a, sizeof(temp)); 4247 memcpy(&temp, &addr->a, sizeof(temp));
4277 sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); 4248 sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp);
4278 addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; 4249 addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
@@ -4284,8 +4255,6 @@ static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len,
4284 } 4255 }
4285 4256
4286copy_getaddrs: 4257copy_getaddrs:
4287 sctp_read_unlock(addr_lock);
4288
4289 /* copy the entire address list into the user provided space */ 4258 /* copy the entire address list into the user provided space */
4290 if (copy_to_user(to, addrs, bytes_copied)) { 4259 if (copy_to_user(to, addrs, bytes_copied)) {
4291 err = -EFAULT; 4260 err = -EFAULT;
@@ -4307,7 +4276,6 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
4307{ 4276{
4308 struct sctp_bind_addr *bp; 4277 struct sctp_bind_addr *bp;
4309 struct sctp_association *asoc; 4278 struct sctp_association *asoc;
4310 struct list_head *pos;
4311 int cnt = 0; 4279 int cnt = 0;
4312 struct sctp_getaddrs getaddrs; 4280 struct sctp_getaddrs getaddrs;
4313 struct sctp_sockaddr_entry *addr; 4281 struct sctp_sockaddr_entry *addr;
@@ -4315,7 +4283,6 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
4315 union sctp_addr temp; 4283 union sctp_addr temp;
4316 struct sctp_sock *sp = sctp_sk(sk); 4284 struct sctp_sock *sp = sctp_sk(sk);
4317 int addrlen; 4285 int addrlen;
4318 rwlock_t *addr_lock;
4319 int err = 0; 4286 int err = 0;
4320 size_t space_left; 4287 size_t space_left;
4321 int bytes_copied = 0; 4288 int bytes_copied = 0;
@@ -4336,13 +4303,11 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
4336 */ 4303 */
4337 if (0 == getaddrs.assoc_id) { 4304 if (0 == getaddrs.assoc_id) {
4338 bp = &sctp_sk(sk)->ep->base.bind_addr; 4305 bp = &sctp_sk(sk)->ep->base.bind_addr;
4339 addr_lock = &sctp_sk(sk)->ep->base.addr_lock;
4340 } else { 4306 } else {
4341 asoc = sctp_id2assoc(sk, getaddrs.assoc_id); 4307 asoc = sctp_id2assoc(sk, getaddrs.assoc_id);
4342 if (!asoc) 4308 if (!asoc)
4343 return -EINVAL; 4309 return -EINVAL;
4344 bp = &asoc->base.bind_addr; 4310 bp = &asoc->base.bind_addr;
4345 addr_lock = &asoc->base.addr_lock;
4346 } 4311 }
4347 4312
4348 to = optval + offsetof(struct sctp_getaddrs,addrs); 4313 to = optval + offsetof(struct sctp_getaddrs,addrs);
@@ -4352,8 +4317,6 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
4352 if (!addrs) 4317 if (!addrs)
4353 return -ENOMEM; 4318 return -ENOMEM;
4354 4319
4355 sctp_read_lock(addr_lock);
4356
4357 /* If the endpoint is bound to 0.0.0.0 or ::0, get the valid 4320 /* If the endpoint is bound to 0.0.0.0 or ::0, get the valid
4358 * addresses from the global local address list. 4321 * addresses from the global local address list.
4359 */ 4322 */
@@ -4365,21 +4328,24 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
4365 space_left, &bytes_copied); 4328 space_left, &bytes_copied);
4366 if (cnt < 0) { 4329 if (cnt < 0) {
4367 err = cnt; 4330 err = cnt;
4368 goto error_lock; 4331 goto out;
4369 } 4332 }
4370 goto copy_getaddrs; 4333 goto copy_getaddrs;
4371 } 4334 }
4372 } 4335 }
4373 4336
4374 buf = addrs; 4337 buf = addrs;
4375 list_for_each(pos, &bp->address_list) { 4338 /* Protection on the bound address list is not needed since
4376 addr = list_entry(pos, struct sctp_sockaddr_entry, list); 4339 * in the socket option context we hold a socket lock and
4340 * thus the bound address list can't change.
4341 */
4342 list_for_each_entry(addr, &bp->address_list, list) {
4377 memcpy(&temp, &addr->a, sizeof(temp)); 4343 memcpy(&temp, &addr->a, sizeof(temp));
4378 sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); 4344 sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp);
4379 addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; 4345 addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
4380 if (space_left < addrlen) { 4346 if (space_left < addrlen) {
4381 err = -ENOMEM; /*fixme: right error?*/ 4347 err = -ENOMEM; /*fixme: right error?*/
4382 goto error_lock; 4348 goto out;
4383 } 4349 }
4384 memcpy(buf, &temp, addrlen); 4350 memcpy(buf, &temp, addrlen);
4385 buf += addrlen; 4351 buf += addrlen;
@@ -4389,8 +4355,6 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
4389 } 4355 }
4390 4356
4391copy_getaddrs: 4357copy_getaddrs:
4392 sctp_read_unlock(addr_lock);
4393
4394 if (copy_to_user(to, addrs, bytes_copied)) { 4358 if (copy_to_user(to, addrs, bytes_copied)) {
4395 err = -EFAULT; 4359 err = -EFAULT;
4396 goto out; 4360 goto out;
@@ -4401,12 +4365,6 @@ copy_getaddrs:
4401 } 4365 }
4402 if (put_user(bytes_copied, optlen)) 4366 if (put_user(bytes_copied, optlen))
4403 err = -EFAULT; 4367 err = -EFAULT;
4404
4405 goto out;
4406
4407error_lock:
4408 sctp_read_unlock(addr_lock);
4409
4410out: 4368out:
4411 kfree(addrs); 4369 kfree(addrs);
4412 return err; 4370 return err;