From: Andrei Vagin <avagin@gmail.com>
To: Martin KaFai Lau <kafai@fb.com>
Cc: netdev@vger.kernel.org, David Miller <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>,
kernel-team@fb.com, Paolo Abeni <pabeni@redhat.com>,
Joanne Koong <joannelkoong@gmail.com>,
Alexander Potapenko <glider@google.com>,
Martin KaFai Lau <martin.lau@kernel.org>
Subject: Re: [PATCH net-next] net: Fix incorrect address comparison when searching for a bind2 bucket
Date: Fri, 8 Sep 2023 14:54:12 -0700 [thread overview]
Message-ID: <ZPuYBOFC8zsK6r9T@google.com> (raw)
In-Reply-To: <20220927002544.3381205-1-kafai@fb.com>
On Mon, Sep 26, 2022 at 05:25:44PM -0700, Martin KaFai Lau wrote:
> From: Martin KaFai Lau <martin.lau@kernel.org>
>
> The v6_rcv_saddr and rcv_saddr are inside a union in the
> 'struct inet_bind2_bucket'. When searching a bucket by following the
> bhash2 hashtable chain, eg. inet_bind2_bucket_match, it is only using
> the sk->sk_family and there is no way to check if the inet_bind2_bucket
> has a v6 or v4 address in the union. This leads to an uninit-value
> KMSAN report in [0] and also potentially incorrect matches.
>
> This patch fixes it by adding a family member to the inet_bind2_bucket
> and then tests 'sk->sk_family != tb->family' before matching
> the sk's address to the tb's address.
It seems this patch doesn't handle v4mapped addresses properly. One of
gVisor test started failing with this change:
socket(AF_INET6, SOCK_STREAM, IPPROTO_IP) = 3
bind(3, {sa_family=AF_INET6, sin6_port=htons(0), sin6_flowinfo=htonl(0), inet_pton(AF_INET6, "::ffff:0.0.0.0", &sin6_addr), sin6_scope_id=0}, 28) = 0
getsockname(3, {sa_family=AF_INET6, sin6_port=htons(33789), sin6_flowinfo=htonl(0), inet_pton(AF_INET6, "::ffff:0.0.0.0", &sin6_addr), sin6_scope_id=0}, [28]) = 0
socket(AF_INET6, SOCK_STREAM, IPPROTO_IP) = 4
bind(4, {sa_family=AF_INET6, sin6_port=htons(33789), sin6_flowinfo=htonl(0), inet_pton(AF_INET6, "::1", &sin6_addr), sin6_scope_id=0}, 28) = 0
socket(AF_INET, SOCK_STREAM, IPPROTO_IP) = 5
bind(5, {sa_family=AF_INET, sin_port=htons(33789), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
The test expects that the second bind returns EADDRINUSE.
Thanks,
Andrei
>
> Cc: Joanne Koong <joannelkoong@gmail.com>
> Cc: Alexander Potapenko <glider@google.com>
> Fixes: 28044fc1d495 ("net: Add a bhash2 table hashed by port and address")
> Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
> ---
> include/net/inet_hashtables.h | 3 +++
> net/ipv4/inet_hashtables.c | 10 ++++++++++
> 2 files changed, 13 insertions(+)
>
> diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
> index 9121ccab1fa1..3af1e927247d 100644
> --- a/include/net/inet_hashtables.h
> +++ b/include/net/inet_hashtables.h
> @@ -95,6 +95,9 @@ struct inet_bind2_bucket {
> possible_net_t ib_net;
> int l3mdev;
> unsigned short port;
> +#if IS_ENABLED(CONFIG_IPV6)
> + unsigned short family;
> +#endif
> union {
> #if IS_ENABLED(CONFIG_IPV6)
> struct in6_addr v6_rcv_saddr;
> diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
> index 74e64aad5114..49db8c597eea 100644
> --- a/net/ipv4/inet_hashtables.c
> +++ b/net/ipv4/inet_hashtables.c
> @@ -109,6 +109,7 @@ static void inet_bind2_bucket_init(struct inet_bind2_bucket *tb,
> tb->l3mdev = l3mdev;
> tb->port = port;
> #if IS_ENABLED(CONFIG_IPV6)
> + tb->family = sk->sk_family;
> if (sk->sk_family == AF_INET6)
> tb->v6_rcv_saddr = sk->sk_v6_rcv_saddr;
> else
> @@ -146,6 +147,9 @@ static bool inet_bind2_bucket_addr_match(const struct inet_bind2_bucket *tb2,
> const struct sock *sk)
> {
> #if IS_ENABLED(CONFIG_IPV6)
> + if (sk->sk_family != tb2->family)
> + return false;
> +
> if (sk->sk_family == AF_INET6)
> return ipv6_addr_equal(&tb2->v6_rcv_saddr,
> &sk->sk_v6_rcv_saddr);
> @@ -791,6 +795,9 @@ static bool inet_bind2_bucket_match(const struct inet_bind2_bucket *tb,
> int l3mdev, const struct sock *sk)
> {
> #if IS_ENABLED(CONFIG_IPV6)
> + if (sk->sk_family != tb->family)
> + return false;
> +
> if (sk->sk_family == AF_INET6)
> return net_eq(ib2_net(tb), net) && tb->port == port &&
> tb->l3mdev == l3mdev &&
> @@ -807,6 +814,9 @@ bool inet_bind2_bucket_match_addr_any(const struct inet_bind2_bucket *tb, const
> #if IS_ENABLED(CONFIG_IPV6)
> struct in6_addr addr_any = {};
>
> + if (sk->sk_family != tb->family)
> + return false;
> +
> if (sk->sk_family == AF_INET6)
> return net_eq(ib2_net(tb), net) && tb->port == port &&
> tb->l3mdev == l3mdev &&
> --
> 2.30.2
>
next prev parent reply other threads:[~2023-09-08 21:54 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-09-27 0:25 [PATCH net-next] net: Fix incorrect address comparison when searching for a bind2 bucket Martin KaFai Lau
2022-09-28 3:49 ` Eric Dumazet
2022-09-28 4:46 ` Martin KaFai Lau
2022-09-28 5:07 ` Eric Dumazet
2022-09-28 11:15 ` Alexander Potapenko
2022-09-29 2:20 ` patchwork-bot+netdevbpf
2023-09-08 21:54 ` Andrei Vagin [this message]
2023-09-09 7:05 ` Kuniyuki Iwashima
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ZPuYBOFC8zsK6r9T@google.com \
--to=avagin@gmail.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=glider@google.com \
--cc=joannelkoong@gmail.com \
--cc=kafai@fb.com \
--cc=kernel-team@fb.com \
--cc=kuba@kernel.org \
--cc=martin.lau@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.