[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20230310212547.25491-1-kuniyu@amazon.com>
Date: Fri, 10 Mar 2023 13:25:47 -0800
From: Kuniyuki Iwashima <kuniyu@...zon.com>
To: <pholzing@...hat.com>
CC: <kuba@...nel.org>, <martin.lau@...nel.org>,
<netdev@...r.kernel.org>, <regressions@...ts.linux.dev>,
<stable@...r.kernel.org>, <kuniyu@...zon.com>
Subject: Re: [REGRESSION] v6.1+ bind() does not fail with EADDRINUSE if dual stack is bound
From: Paul Holzinger <pholzing@...hat.com>
Date: Fri, 10 Mar 2023 17:01:31 +0100
> Hi all,
>
> there seems to be a regression which allows you to bind the same port
> twice when the first bind call bound to all ip addresses (i. e. dual stack).
>
> A second bind call for the same port will succeed if you try to bind to
> a specific ipv4 (e. g. 127.0.0.1), binding to 0.0.0.0 or an ipv6 address
> fails correctly with EADDRINUSE.
>
> I included a small c program below to show the issue. Normally the
> second bind call should fail, this was the case before v6.1.
>
>
> I bisected the regression to commit 5456262d2baa ("net: Fix incorrect
> address comparison when searching for a bind2 bucket").
>
> I also checked that the issue is still present in v6.3-rc1.
Thanks for the detailed report.
It seems we should take care of the special case in
inet_bind2_bucket_match_addr_any().
I'll fix it.
Thanks,
Kuniyuki
>
>
> Original report: https://github.com/containers/podman/issues/17719
>
> #regzbot introduced: 5456262d2baa
>
>
> ```
>
> #include <sys/socket.h>
> #include <sys/un.h>
> #include <stdlib.h>
> #include <stdio.h>
> #include <netinet/in.h>
> #include <unistd.h>
>
> int main(int argc, char *argv[])
> {
> int ret, sock1, sock2;
> struct sockaddr_in6 addr;
> struct sockaddr_in addr2;
>
> sock1 = socket(AF_INET6, SOCK_STREAM, 0);
> if (sock1 == -1)
> {
> perror("socket1");
> exit(1);
> }
> sock2 = socket(AF_INET, SOCK_STREAM, 0);
> if (sock2 == -1)
> {
> perror("socket2");
> exit(1);
> }
>
> memset(&addr, 0, sizeof(addr));
> addr.sin6_family = AF_INET6;
> addr.sin6_addr = in6addr_any;
> addr.sin6_port = htons(8080);
>
> memset(&addr2, 0, sizeof(addr2));
> addr2.sin_family = AF_INET;
> addr2.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
> addr2.sin_port = htons(8080);
>
> ret = bind(sock1, (struct sockaddr *)&addr, sizeof(addr));
> if (ret == -1)
> {
> perror("bind1");
> exit(1);
> }
> printf("bind1 ret: %d\n", ret);
>
> if ((listen(sock1, 5)) != 0)
> {
> perror("listen1");
> exit(1);
> }
>
> ret = bind(sock2, (struct sockaddr *)&addr2, sizeof(addr2));
> if (ret == -1)
> {
> perror("bind2");
> exit(1);
> }
> printf("bind2 ret: %d\n", ret);
>
> if ((listen(sock2, 5)) != 0)
> {
> perror("listen2");
> exit(1);
> }
>
> // uncomment pause() to see with ss -tlpn the bound ports
> // pause();
>
> return 0;
> }
>
> ```
>
>
> Best regards,
>
> Paul
Powered by blists - more mailing lists