Skip to content

Commit 1071ec9

Browse files
lxindavem330
authored andcommitted
sctp: do not check port in sctp_inet6_cmp_addr
pf->cmp_addr() is called before binding a v6 address to the sock. It should not check ports, like in sctp_inet_cmp_addr. But sctp_inet6_cmp_addr checks the addr by invoking af(6)->cmp_addr, sctp_v6_cmp_addr where it also compares the ports. This would cause that setsockopt(SCTP_SOCKOPT_BINDX_ADD) could bind multiple duplicated IPv6 addresses after Commit 40b4f0f ("sctp: lack the check for ports in sctp_v6_cmp_addr"). This patch is to remove af->cmp_addr called in sctp_inet6_cmp_addr, but do the proper check for both v6 addrs and v4mapped addrs. v1->v2: - define __sctp_v6_cmp_addr to do the common address comparison used for both pf and af v6 cmp_addr. Fixes: 40b4f0f ("sctp: lack the check for ports in sctp_v6_cmp_addr") Reported-by: Jianwen Ji <[email protected]> Signed-off-by: Xin Long <[email protected]> Acked-by: Neil Horman <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 837708a commit 1071ec9

File tree

1 file changed

+30
-30
lines changed

1 file changed

+30
-30
lines changed

net/sctp/ipv6.c

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -556,46 +556,49 @@ static void sctp_v6_to_addr(union sctp_addr *addr, struct in6_addr *saddr,
556556
addr->v6.sin6_scope_id = 0;
557557
}
558558

559-
/* Compare addresses exactly.
560-
* v4-mapped-v6 is also in consideration.
561-
*/
562-
static int sctp_v6_cmp_addr(const union sctp_addr *addr1,
563-
const union sctp_addr *addr2)
559+
static int __sctp_v6_cmp_addr(const union sctp_addr *addr1,
560+
const union sctp_addr *addr2)
564561
{
565562
if (addr1->sa.sa_family != addr2->sa.sa_family) {
566563
if (addr1->sa.sa_family == AF_INET &&
567564
addr2->sa.sa_family == AF_INET6 &&
568-
ipv6_addr_v4mapped(&addr2->v6.sin6_addr)) {
569-
if (addr2->v6.sin6_port == addr1->v4.sin_port &&
570-
addr2->v6.sin6_addr.s6_addr32[3] ==
571-
addr1->v4.sin_addr.s_addr)
572-
return 1;
573-
}
565+
ipv6_addr_v4mapped(&addr2->v6.sin6_addr) &&
566+
addr2->v6.sin6_addr.s6_addr32[3] ==
567+
addr1->v4.sin_addr.s_addr)
568+
return 1;
569+
574570
if (addr2->sa.sa_family == AF_INET &&
575571
addr1->sa.sa_family == AF_INET6 &&
576-
ipv6_addr_v4mapped(&addr1->v6.sin6_addr)) {
577-
if (addr1->v6.sin6_port == addr2->v4.sin_port &&
578-
addr1->v6.sin6_addr.s6_addr32[3] ==
579-
addr2->v4.sin_addr.s_addr)
580-
return 1;
581-
}
572+
ipv6_addr_v4mapped(&addr1->v6.sin6_addr) &&
573+
addr1->v6.sin6_addr.s6_addr32[3] ==
574+
addr2->v4.sin_addr.s_addr)
575+
return 1;
576+
582577
return 0;
583578
}
584-
if (addr1->v6.sin6_port != addr2->v6.sin6_port)
585-
return 0;
579+
586580
if (!ipv6_addr_equal(&addr1->v6.sin6_addr, &addr2->v6.sin6_addr))
587581
return 0;
582+
588583
/* If this is a linklocal address, compare the scope_id. */
589-
if (ipv6_addr_type(&addr1->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL) {
590-
if (addr1->v6.sin6_scope_id && addr2->v6.sin6_scope_id &&
591-
(addr1->v6.sin6_scope_id != addr2->v6.sin6_scope_id)) {
592-
return 0;
593-
}
594-
}
584+
if ((ipv6_addr_type(&addr1->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL) &&
585+
addr1->v6.sin6_scope_id && addr2->v6.sin6_scope_id &&
586+
addr1->v6.sin6_scope_id != addr2->v6.sin6_scope_id)
587+
return 0;
595588

596589
return 1;
597590
}
598591

592+
/* Compare addresses exactly.
593+
* v4-mapped-v6 is also in consideration.
594+
*/
595+
static int sctp_v6_cmp_addr(const union sctp_addr *addr1,
596+
const union sctp_addr *addr2)
597+
{
598+
return __sctp_v6_cmp_addr(addr1, addr2) &&
599+
addr1->v6.sin6_port == addr2->v6.sin6_port;
600+
}
601+
599602
/* Initialize addr struct to INADDR_ANY. */
600603
static void sctp_v6_inaddr_any(union sctp_addr *addr, __be16 port)
601604
{
@@ -875,8 +878,8 @@ static int sctp_inet6_cmp_addr(const union sctp_addr *addr1,
875878
const union sctp_addr *addr2,
876879
struct sctp_sock *opt)
877880
{
878-
struct sctp_af *af1, *af2;
879881
struct sock *sk = sctp_opt2sk(opt);
882+
struct sctp_af *af1, *af2;
880883

881884
af1 = sctp_get_af_specific(addr1->sa.sa_family);
882885
af2 = sctp_get_af_specific(addr2->sa.sa_family);
@@ -892,10 +895,7 @@ static int sctp_inet6_cmp_addr(const union sctp_addr *addr1,
892895
if (sctp_is_any(sk, addr1) || sctp_is_any(sk, addr2))
893896
return 1;
894897

895-
if (addr1->sa.sa_family != addr2->sa.sa_family)
896-
return 0;
897-
898-
return af1->cmp_addr(addr1, addr2);
898+
return __sctp_v6_cmp_addr(addr1, addr2);
899899
}
900900

901901
/* Verify that the provided sockaddr looks bindable. Common verification,

0 commit comments

Comments
 (0)