forked from rubenslte/android_kernel_samsung_msm8226
net: Fix use after free in the recvmmsg exit path
The syzkaller fuzzer hit the following use-after-free:
Call Trace:
[<ffffffff8175ea0e>] __asan_report_load8_noabort+0x3e/0x40 mm/kasan/report.c:295
[<ffffffff851cc31a>] __sys_recvmmsg+0x6fa/0x7f0 net/socket.c:2261
[< inline >] SYSC_recvmmsg net/socket.c:2281
[<ffffffff851cc57f>] SyS_recvmmsg+0x16f/0x180 net/socket.c:2270
[<ffffffff86332bb6>] entry_SYSCALL_64_fastpath+0x16/0x7a
arch/x86/entry/entry_64.S:185
And, as Dmitry rightly assessed, that is because we can drop the
reference and then touch it when the underlying recvmsg calls return
some packets and then hit an error, which will make recvmmsg to set
sock->sk->sk_err, oops, fix it.
Reported-and-Tested-by: Dmitry Vyukov <dvyukov@google.com>
Cc: Alexander Potapenko <glider@google.com>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Kostya Serebryany <kcc@google.com>
Cc: Sasha Levin <sasha.levin@oracle.com>
Fixes: a2e2725541 ("net: Introduce recvmmsg socket syscall")
http://lkml.kernel.org/r/20160122211644.GC2470@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Change-Id: I447302392f46841f31c374bdb560fe5ee9c2d687
Git-repo: http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git
Git-commit: 34b88a68f26a75e4fded796f1a49c40f82234b7d
Signed-off-by: Dennis Cagle <d-cagle@codeaurora.org>
This commit is contained in:
committed by
Gerrit - the friendly Code Review server
parent
1b0d5da2f4
commit
305ac7bc99
+22
-22
@@ -2307,31 +2307,31 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
|
||||
break;
|
||||
}
|
||||
|
||||
if (err == 0)
|
||||
goto out_put;
|
||||
|
||||
if (datagrams == 0) {
|
||||
datagrams = err;
|
||||
goto out_put;
|
||||
}
|
||||
|
||||
/*
|
||||
* We may return less entries than requested (vlen) if the
|
||||
* sock is non block and there aren't enough datagrams...
|
||||
*/
|
||||
if (err != -EAGAIN) {
|
||||
/*
|
||||
* ... or if recvmsg returns an error after we
|
||||
* received some datagrams, where we record the
|
||||
* error to return on the next call or if the
|
||||
* app asks about it using getsockopt(SO_ERROR).
|
||||
*/
|
||||
sock->sk->sk_err = -err;
|
||||
}
|
||||
out_put:
|
||||
fput_light(sock->file, fput_needed);
|
||||
|
||||
if (err == 0)
|
||||
return datagrams;
|
||||
|
||||
if (datagrams != 0) {
|
||||
/*
|
||||
* We may return less entries than requested (vlen) if the
|
||||
* sock is non block and there aren't enough datagrams...
|
||||
*/
|
||||
if (err != -EAGAIN) {
|
||||
/*
|
||||
* ... or if recvmsg returns an error after we
|
||||
* received some datagrams, where we record the
|
||||
* error to return on the next call or if the
|
||||
* app asks about it using getsockopt(SO_ERROR).
|
||||
*/
|
||||
sock->sk->sk_err = -err;
|
||||
}
|
||||
|
||||
return datagrams;
|
||||
}
|
||||
|
||||
return err;
|
||||
return datagrams;
|
||||
}
|
||||
|
||||
SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
|
||||
|
||||
Reference in New Issue
Block a user