diff options
author | Eric Dumazet <edumazet@google.com> | 2016-10-20 09:39:40 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-10-20 14:45:52 -0400 |
commit | 286c72deabaa240b7eebbd99496ed3324d69f3c0 (patch) | |
tree | 00a0b07bfc20b08a025720c4c1b3c724ed4eaf67 /net/ipv6/raw.c | |
parent | 2399d6143f85b155ae84ccd94237befd36b8f6c7 (diff) | |
download | linux-stable-286c72deabaa240b7eebbd99496ed3324d69f3c0.tar.gz linux-stable-286c72deabaa240b7eebbd99496ed3324d69f3c0.tar.bz2 linux-stable-286c72deabaa240b7eebbd99496ed3324d69f3c0.zip |
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>
Diffstat (limited to 'net/ipv6/raw.c')
-rw-r--r-- | net/ipv6/raw.c | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 54404f08efcc..054a1d84fc5e 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -1241,7 +1241,7 @@ struct proto rawv6_prot = { .close = rawv6_close, .destroy = raw6_destroy, .connect = ip6_datagram_connect_v6_only, - .disconnect = udp_disconnect, + .disconnect = __udp_disconnect, .ioctl = rawv6_ioctl, .init = rawv6_init_sk, .setsockopt = rawv6_setsockopt, |