Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

sctp: Allow only 1 listening socket with SO_REUSEADDR

When multiple socket bind to the same port with SO_REUSEADDR,
only 1 can be listining.

Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Vlad Yasevich and committed by
David S. Miller
4e54064e 23b29ed8

+16 -9
+16 -9
net/sctp/socket.c
··· 377 377 if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE)) 378 378 return -EACCES; 379 379 380 + /* See if the address matches any of the addresses we may have 381 + * already bound before checking against other endpoints. 382 + */ 383 + if (sctp_bind_addr_match(bp, addr, sp)) 384 + return -EINVAL; 385 + 380 386 /* Make sure we are allowed to bind here. 381 387 * The function sctp_get_port_local() does duplicate address 382 388 * detection. 383 389 */ 384 390 addr->v4.sin_port = htons(snum); 385 391 if ((ret = sctp_get_port_local(sk, addr))) { 386 - if (ret == (long) sk) { 387 - /* This endpoint has a conflicting address. */ 388 - return -EINVAL; 389 - } else { 390 - return -EADDRINUSE; 391 - } 392 + return -EADDRINUSE; 392 393 } 393 394 394 395 /* Refresh ephemeral port. */ ··· 5585 5584 struct sctp_endpoint *ep2; 5586 5585 ep2 = sctp_sk(sk2)->ep; 5587 5586 5588 - if (reuse && sk2->sk_reuse && 5589 - sk2->sk_state != SCTP_SS_LISTENING) 5587 + if (sk == sk2 || 5588 + (reuse && sk2->sk_reuse && 5589 + sk2->sk_state != SCTP_SS_LISTENING)) 5590 5590 continue; 5591 5591 5592 5592 if (sctp_bind_addr_conflict(&ep2->base.bind_addr, addr, ··· 5704 5702 if (!ep->base.bind_addr.port) { 5705 5703 if (sctp_autobind(sk)) 5706 5704 return -EAGAIN; 5707 - } else 5705 + } else { 5706 + if (sctp_get_port(sk, inet_sk(sk)->num)) { 5707 + sk->sk_state = SCTP_SS_CLOSED; 5708 + return -EADDRINUSE; 5709 + } 5708 5710 sctp_sk(sk)->bind_hash->fastreuse = 0; 5711 + } 5709 5712 5710 5713 sctp_hash_endpoint(ep); 5711 5714 return 0;