lkml.org 
[lkml]   [2022]   [Aug]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.15 376/779] net: allow unbound socket for packets in VRF when tcp_l3mdev_accept set
    Date
    From: Mike Manning <mvrmanning@gmail.com>

    [ Upstream commit 944fd1aeacb627fa617f85f8e5a34f7ae8ea4d8e ]

    The commit 3c82a21f4320 ("net: allow binding socket in a VRF when
    there's an unbound socket") changed the inet socket lookup to avoid
    packets in a VRF from matching an unbound socket. This is to ensure the
    necessary isolation between the default and other VRFs for routing and
    forwarding. VRF-unaware processes running in the default VRF cannot
    access another VRF and have to be run with 'ip vrf exec <vrf>'. This is
    to be expected with tcp_l3mdev_accept disabled, but could be reallowed
    when this sysctl option is enabled. So instead of directly checking dif
    and sdif in inet[6]_match, here call inet_sk_bound_dev_eq(). This
    allows a match on unbound socket for non-zero sdif i.e. for packets in
    a VRF, if tcp_l3mdev_accept is enabled.

    Fixes: 3c82a21f4320 ("net: allow binding socket in a VRF when there's an unbound socket")
    Signed-off-by: Mike Manning <mvrmanning@gmail.com>
    Link: https://lore.kernel.org/netdev/a54c149aed38fded2d3b5fdb1a6c89e36a083b74.camel@lasnet.de/
    Reviewed-by: David Ahern <dsahern@kernel.org>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    include/net/inet6_hashtables.h | 7 +++----
    include/net/inet_hashtables.h | 19 +++----------------
    include/net/inet_sock.h | 11 +++++++++++
    3 files changed, 17 insertions(+), 20 deletions(-)

    diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h
    index f259e1ae14ba..56f1286583d3 100644
    --- a/include/net/inet6_hashtables.h
    +++ b/include/net/inet6_hashtables.h
    @@ -110,8 +110,6 @@ static inline bool inet6_match(struct net *net, const struct sock *sk,
    const __portpair ports,
    const int dif, const int sdif)
    {
    - int bound_dev_if;
    -
    if (!net_eq(sock_net(sk), net) ||
    sk->sk_family != AF_INET6 ||
    sk->sk_portpair != ports ||
    @@ -119,8 +117,9 @@ static inline bool inet6_match(struct net *net, const struct sock *sk,
    !ipv6_addr_equal(&sk->sk_v6_rcv_saddr, daddr))
    return false;

    - bound_dev_if = READ_ONCE(sk->sk_bound_dev_if);
    - return bound_dev_if == dif || bound_dev_if == sdif;
    + /* READ_ONCE() paired with WRITE_ONCE() in sock_bindtoindex_locked() */
    + return inet_sk_bound_dev_eq(net, READ_ONCE(sk->sk_bound_dev_if), dif,
    + sdif);
    }
    #endif /* IS_ENABLED(CONFIG_IPV6) */

    diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
    index 825ad1d06d05..53c22b64e972 100644
    --- a/include/net/inet_hashtables.h
    +++ b/include/net/inet_hashtables.h
    @@ -203,17 +203,6 @@ static inline void inet_ehash_locks_free(struct inet_hashinfo *hashinfo)
    hashinfo->ehash_locks = NULL;
    }

    -static inline bool inet_sk_bound_dev_eq(struct net *net, int bound_dev_if,
    - int dif, int sdif)
    -{
    -#if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV)
    - return inet_bound_dev_eq(!!READ_ONCE(net->ipv4.sysctl_tcp_l3mdev_accept),
    - bound_dev_if, dif, sdif);
    -#else
    - return inet_bound_dev_eq(true, bound_dev_if, dif, sdif);
    -#endif
    -}
    -
    struct inet_bind_bucket *
    inet_bind_bucket_create(struct kmem_cache *cachep, struct net *net,
    struct inet_bind_hashbucket *head,
    @@ -311,16 +300,14 @@ static inline bool INET_MATCH(struct net *net, const struct sock *sk,
    const __addrpair cookie, const __portpair ports,
    int dif, int sdif)
    {
    - int bound_dev_if;
    -
    if (!net_eq(sock_net(sk), net) ||
    sk->sk_portpair != ports ||
    sk->sk_addrpair != cookie)
    return false;

    - /* Paired with WRITE_ONCE() from sock_bindtoindex_locked() */
    - bound_dev_if = READ_ONCE(sk->sk_bound_dev_if);
    - return bound_dev_if == dif || bound_dev_if == sdif;
    + /* READ_ONCE() paired with WRITE_ONCE() in sock_bindtoindex_locked() */
    + return inet_sk_bound_dev_eq(net, READ_ONCE(sk->sk_bound_dev_if), dif,
    + sdif);
    }

    /* Sockets in TCP_CLOSE state are _always_ taken out of the hash, so we need
    diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
    index c307a547d2cb..2c2b41ea7f81 100644
    --- a/include/net/inet_sock.h
    +++ b/include/net/inet_sock.h
    @@ -149,6 +149,17 @@ static inline bool inet_bound_dev_eq(bool l3mdev_accept, int bound_dev_if,
    return bound_dev_if == dif || bound_dev_if == sdif;
    }

    +static inline bool inet_sk_bound_dev_eq(struct net *net, int bound_dev_if,
    + int dif, int sdif)
    +{
    +#if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV)
    + return inet_bound_dev_eq(!!READ_ONCE(net->ipv4.sysctl_tcp_l3mdev_accept),
    + bound_dev_if, dif, sdif);
    +#else
    + return inet_bound_dev_eq(true, bound_dev_if, dif, sdif);
    +#endif
    +}
    +
    struct inet_cork {
    unsigned int flags;
    __be32 addr;
    --
    2.35.1


    \
     
     \ /
      Last update: 2022-08-15 21:05    [W:2.338 / U:0.024 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site