Commit 08d6c4b1 authored by Willem de Bruijn's avatar Willem de Bruijn Committed by Stefan Bader

ipv4: remove warning in ip_recv_error

BugLink: https://bugs.launchpad.net/bugs/1777063

[ Upstream commit 730c54d5 ]

A precondition check in ip_recv_error triggered on an otherwise benign
race. Remove the warning.

The warning triggers when passing an ipv6 socket to this ipv4 error
handling function. RaceFuzzer was able to trigger it due to a race
in setsockopt IPV6_ADDRFORM.

  ---
  CPU0
    do_ipv6_setsockopt
      sk->sk_socket->ops = &inet_dgram_ops;

  ---
  CPU1
    sk->sk_prot->recvmsg
      udp_recvmsg
        ip_recv_error
          WARN_ON_ONCE(sk->sk_family == AF_INET6);

  ---
  CPU0
    do_ipv6_setsockopt
      sk->sk_family = PF_INET;

This socket option converts a v6 socket that is connected to a v4 peer
to an v4 socket. It updates the socket on the fly, changing fields in
sk as well as other structs. This is inherently non-atomic. It races
with the lockless udp_recvmsg path.

No other code makes an assumption that these fields are updated
atomically. It is benign here, too, as ip_recv_error cares only about
the protocol of the skbs enqueued on the error queue, for which
sk_family is not a precise predictor (thanks to another isue with
IPV6_ADDRFORM).

Link: http://lkml.kernel.org/r/20180518120826.GA19515@dragonet.kaist.ac.kr
Fixes: 7ce875e5 ("ipv4: warn once on passing AF_INET6 socket to ip_recv_error")
Reported-by: default avatarDaeRyong Jeong <threeearcat@gmail.com>
Suggested-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarWillem de Bruijn <willemb@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarJuerg Haefliger <juergh@canonical.com>
Signed-off-by: default avatarKhalid Elmously <khalid.elmously@canonical.com>
parent d50bf1ee
...@@ -493,8 +493,6 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) ...@@ -493,8 +493,6 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
int err; int err;
int copied; int copied;
WARN_ON_ONCE(sk->sk_family == AF_INET6);
err = -EAGAIN; err = -EAGAIN;
skb = sock_dequeue_err_skb(sk); skb = sock_dequeue_err_skb(sk);
if (!skb) if (!skb)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment