From: Daniel Axtens <dja@xxxxxxxxxx> Subject: kernel/relay.c: handle alloc_percpu returning NULL in relay_open 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 [c0000000003f3fec] relay_open+0x29c/0x600 LR [c0000000003f3fc0] relay_open+0x270/0x600 Call Trace: [c000000054353a70] [c0000000003f3fb4] relay_open+0x264/0x600 (unreliable) [c000000054353b00] [c000000000451764] __blk_trace_setup+0x254/0x600 [c000000054353bb0] [c000000000451b78] blk_trace_setup+0x68/0xa0 [c000000054353c10] [c0000000010da77c] sg_ioctl+0x7bc/0x2e80 [c000000054353cd0] [c000000000758cbc] do_vfs_ioctl+0x13c/0x1300 [c000000054353d90] [c000000000759f14] ksys_ioctl+0x94/0x130 [c000000054353de0] [c000000000759ff8] sys_ioctl+0x48/0xb0 [c000000054353e20] [c00000000000bcd0] 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. Link: http://lkml.kernel.org/r/20191219121256.26480-1-dja@xxxxxxxxxx Fixes: 017c59c042d0 ("relay: Use per CPU constructs for the relay channel buffer pointers") Signed-off-by: Daniel Axtens <dja@xxxxxxxxxx> Reviewed-by: Michael Ellerman <mpe@xxxxxxxxxxxxxx> Reviewed-by: Andrew Donnellan <ajd@xxxxxxxxxxxxx> Acked-by: David Rientjes <rientjes@xxxxxxxxxx> Reported-by: syzbot+1e925b4b836afe85a1c6@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Reported-by: syzbot+587b2421926808309d21@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Reported-by: syzbot+58320b7171734bf79d26@xxxxxxxxxxxxxxxxxxxxxxxxx Reported-by: syzbot+d6074fb08bdb2e010520@xxxxxxxxxxxxxxxxxxxxxxxxx Cc: Akash Goel <akash.goel@xxxxxxxxx> Cc: Andrew Donnellan <ajd@xxxxxxxxxxxxx> Cc: Guenter Roeck <linux@xxxxxxxxxxxx> Cc: Salvatore Bonaccorso <carnil@xxxxxxxxxx> Cc: <stable@xxxxxxxxxxxxxxx> [4.10+] Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- kernel/relay.c | 5 +++++ 1 file changed, 5 insertions(+) --- a/kernel/relay.c~relay-handle-alloc_percpu-returning-null-in-relay_open +++ a/kernel/relay.c @@ -581,6 +581,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; _