From: Daniel Axtens <[email protected]>
commit 54e200ab40fc14c863bcc80a51e20b7906608fce upstream.
alloc_percpu() may return NULL, which means chan->buf may be set to NULL.
In that case, when we do *per_cpu_ptr(chan->buf, ...), we dereference an
invalid pointer:
BUG: Unable to handle kernel data access at 0x7dae0000
Faulting instruction address: 0xc0000000003f3fec
...
NIP relay_open+0x29c/0x600
LR relay_open+0x270/0x600
Call Trace:
relay_open+0x264/0x600 (unreliable)
__blk_trace_setup+0x254/0x600
blk_trace_setup+0x68/0xa0
sg_ioctl+0x7bc/0x2e80
do_vfs_ioctl+0x13c/0x1300
ksys_ioctl+0x94/0x130
sys_ioctl+0x48/0xb0
system_call+0x5c/0x68
Check if alloc_percpu returns NULL.
This was found by syzkaller both on x86 and powerpc, and the reproducer
it found on powerpc is capable of hitting the issue as an unprivileged
user.
Fixes: 017c59c042d0 ("relay: Use per CPU constructs for the relay channel
buffer pointers")
Reported-by: [email protected]
Reported-by: [email protected]
Reported-by: [email protected]
Reported-by: [email protected]
Signed-off-by: Daniel Axtens <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Reviewed-by: Michael Ellerman <[email protected]>
Reviewed-by: Andrew Donnellan <[email protected]>
Acked-by: David Rientjes <[email protected]>
Cc: Akash Goel <[email protected]>
Cc: Andrew Donnellan <[email protected]>
Cc: Guenter Roeck <[email protected]>
Cc: Salvatore Bonaccorso <[email protected]>
Cc: <[email protected]> [4.10+]
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
kernel/relay.c | 5 +++++
1 file changed, 5 insertions(+)
--- a/kernel/relay.c
+++ b/kernel/relay.c
@@ -578,6 +578,11 @@ struct rchan *relay_open(const char *bas
return NULL;
chan->buf = alloc_percpu(struct rchan_buf *);
+ if (!chan->buf) {
+ kfree(chan);
+ return NULL;
+ }
+
chan->version = RELAYFS_CHANNEL_VERSION;
chan->n_subbufs = n_subbufs;
chan->subbuf_size = subbuf_size;