udp: must lock the socket in udp_disconnect()
authorEric Dumazet <edumazet@google.com>
Thu, 20 Oct 2016 16:39:40 +0000 (09:39 -0700)
committerDavid S. Miller <davem@davemloft.net>
Thu, 20 Oct 2016 18:45:52 +0000 (14:45 -0400)
commit286c72deabaa240b7eebbd99496ed3324d69f3c0
tree00a0b07bfc20b08a025720c4c1b3c724ed4eaf67
parent2399d6143f85b155ae84ccd94237befd36b8f6c7
udp: must lock the socket in udp_disconnect()

Baozeng Ding reported KASAN traces showing uses after free in
udp_lib_get_port() and other related UDP functions.

A CONFIG_DEBUG_PAGEALLOC=y kernel would eventually crash.

I could write a reproducer with two threads doing :

static int sock_fd;
static void *thr1(void *arg)
{
for (;;) {
connect(sock_fd, (const struct sockaddr *)arg,
sizeof(struct sockaddr_in));
}
}

static void *thr2(void *arg)
{
struct sockaddr_in unspec;

for (;;) {
memset(&unspec, 0, sizeof(unspec));
        connect(sock_fd, (const struct sockaddr *)&unspec,
sizeof(unspec));
        }
}

Problem is that udp_disconnect() could run without holding socket lock,
and this was causing list corruptions.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reported-by: Baozeng Ding <sploving1@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/udp.h
net/ipv4/ping.c
net/ipv4/raw.c
net/ipv4/udp.c
net/ipv6/ping.c
net/ipv6/raw.c
net/l2tp/l2tp_ip.c
net/l2tp/l2tp_ip6.c