scsi: NULL deref in sg_start_req

From: Dmitry Vyukov
Date: Thu Jan 28 2016 - 05:11:38 EST


Hello,

The following program causes NULL deref in sg_start_req:

// autogenerated by syzkaller (http://github.com/google/syzkaller)
#include <pthread.h>
#include <stdint.h>
#include <string.h>
#include <sys/syscall.h>
#include <unistd.h>

#ifndef SYS_memfd_create
#define SYS_memfd_create 319
#endif

int main()
{
long r[26];

syscall(SYS_mmap, 0x20000000ul, 0xdee000ul, 0x3ul, 0x32ul,
0xfffffffffffffffful, 0x0ul);
r[2] = syscall(SYS_memfd_create,
"\x73\x65\x63\x75\x72\x69\x76\x69\x00", 0x3ul, 0, 0, 0, 0);
memcpy((void*)0x20dea2be, "\x2f\x64\x65\x76\x2f\x73\x67\x23", 8);
r[4] = syscall(SYS_open, "/dev/sg0", 0x2ul, 0, 0, 0);
*(uint64_t*)0x20000ffe = (uint64_t)0x20000000;
*(uint64_t*)0x20001006 = (uint64_t)0x4f;
*(uint64_t*)0x2000100e = (uint64_t)0x20000f7c;
*(uint64_t*)0x20001016 = (uint64_t)0x84;
*(uint64_t*)0x2000101e = (uint64_t)0x20003f9e;
*(uint64_t*)0x20001026 = (uint64_t)0xe0;
*(uint64_t*)0x2000102e = (uint64_t)0x20decf72;
*(uint64_t*)0x20001036 = (uint64_t)0xc6;
syscall(SYS_pwritev, r[2], 0x20000ffeul, 0x4ul, 0x0ul, 0, 0);
*(uint32_t*)0x208b1fea = (uint32_t)0x20;
*(uint32_t*)0x208b1fee = (uint32_t)0xffff;
*(uint64_t*)0x208b1ff2 = (uint64_t)0x0;
*(uint64_t*)0x208b1ffa = (uint64_t)0x0;
*(uint32_t*)0x208b2002 = (uint32_t)0x1;
syscall(SYS_write, r[2], 0x208b1feaul, 0x20ul, 0, 0, 0);
*(uint64_t*)0x20deb20e = (uint64_t)0x0;
syscall(SYS_sendfile, r[4], r[2], 0x20deb20eul, 0x19cbul, 0, 0);
return 0;
}


sg_write: data in/out 65499/591 bytes for SCSI command 0x0-- guessing data in;
program a.out not setting count and/or reply_len properly
BUG: unable to handle kernel NULL pointer dereference at (null)
IP: [<ffffffff81323fd2>] __memcpy+0x12/0x20 arch/x86/lib/memcpy_64.S:35
PGD 7ce53067 PUD 7cef8067 PMD 0
Oops: 0000 [#1] SMP
Modules linked in:
CPU: 2 PID: 2650 Comm: a.out Not tainted 4.4.0+ #59
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
task: ffff88007fa25cc0 ti: ffff88007ccf0000 task.ti: ffff88007ccf0000
RIP: 0010:[<ffffffff81323fd2>] [<ffffffff81323fd2>] __memcpy+0x12/0x20
RSP: 0018:ffff88007ccf3800 EFLAGS: 00010246
RAX: ffff88007cc20000 RBX: ffff88007ccf38e0 RCX: 0000000000000200
RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff88007cc20000
RBP: ffff88007ccf3840 R08: ffff88007ccf39c0 R09: 0000000002080020
R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000001000
R13: 0000000000001000 R14: 0000000000001000 R15: 0000000000000000
FS: 00000000012df880(0063) GS:ffff88007fc00000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000000 CR3: 000000007fab8000 CR4: 00000000000006e0
Stack:
ffffffff81328682 ffff88007ccf39c0 ffff88007cc21000 ffff88007ccf38e0
ffff88007fa25cc0 ffff88007cd69a40 ffff88007ccf3a68 ffff88007ccf3a68
ffff88007ccf38a0 ffffffff8132a1a4 000000000000ffdb ffff88007ccf38a0
Call Trace:
[<ffffffff8132a1a4>] copy_page_from_iter+0x274/0x370 lib/iov_iter.c:467
[< inline >] bio_copy_from_iter block/bio.c:1023
[<ffffffff812f1356>] bio_copy_user_iov+0x2e6/0x380 block/bio.c:1221
[<ffffffff812fd214>] blk_rq_map_user_iov+0x1e4/0x270 block/blk-map.c:111
[<ffffffff812fd2ed>] blk_rq_map_user+0x4d/0x60 block/blk-map.c:154
[< inline >] sg_start_req drivers/scsi/sg.c:1766
[<ffffffff8152a277>] sg_common_write.isra.17+0x327/0x540 drivers/scsi/sg.c:782
[<ffffffff8152b4af>] sg_write+0x1af/0x330 drivers/scsi/sg.c:685
[<ffffffff81170143>] __vfs_write+0x23/0xe0 fs/read_write.c:528
[<ffffffff8117024f>] __kernel_write+0x4f/0xf0 fs/read_write.c:550
[<ffffffff8119c9ce>] write_pipe_buf+0x5e/0x70 fs/splice.c:1068
[< inline >] splice_from_pipe_feed fs/splice.c:770
[<ffffffff8119c579>] __splice_from_pipe+0xf9/0x170 fs/splice.c:895
[<ffffffff8119ddec>] splice_from_pipe+0x4c/0x70 fs/splice.c:930
[<ffffffff8119de44>] default_file_splice_write+0x14/0x20 fs/splice.c:1080
[< inline >] do_splice_from fs/splice.c:1122
[<ffffffff8119c011>] direct_splice_actor+0x31/0x40 fs/splice.c:1288
[<ffffffff8119c770>] splice_direct_to_actor+0x90/0x1f0 fs/splice.c:1241
[<ffffffff8119c947>] do_splice_direct+0x77/0xa0 fs/splice.c:1331
[<ffffffff811713e8>] do_sendfile+0x198/0x380 fs/read_write.c:1266
[< inline >] SYSC_sendfile64 fs/read_write.c:1321
[<ffffffff811720fa>] SyS_sendfile64+0x4a/0x90 fs/read_write.c:1313
[<ffffffff8189f86e>] entry_SYSCALL_64_fastpath+0x12/0x71
arch/x86/entry/entry_64.S:185
Code: 60 48 2b 43 50 88 43 4e 5b 5d c3 e8 b9 fc ff ff eb eb 90 90 90
90 90 90 90 0f 1f 44 00 00 48 89 f8 48 89 d1 48 c1 e9 03 83 e2 07 <f3>
48 a5 89 d1 f3 a4 c3 66 0f 1f 44 00 00 48 89 f8 48 89 d1 f3
RIP [<ffffffff81323fd2>] __memcpy+0x12/0x20 arch/x86/lib/memcpy_64.S:35
RSP <ffff88007ccf3800>
CR2: 0000000000000000
---[ end trace 581bd080ffa39d79 ]---


note: a.out[7919] exited with preempt_count 1

BUG: sleeping function called from invalid context at include/linux/sched.h:2805
in_atomic(): 1, irqs_disabled(): 0, pid: 7919, name: a.out
INFO: lockdep is turned off.
CPU: 3 PID: 7919 Comm: a.out Tainted: G D 4.5.0-rc1+ #300
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
00000000ffffffff ffff880061656a90 ffffffff82be118d ffff88006146c740
0000000000001eef 0000000000000000 ffff880061656ab8 ffffffff813cb8cb
ffff88006146c740 ffffffff867387a0 0000000000000af5 ffff880061656af8
Call Trace:
[< inline >] __dump_stack lib/dump_stack.c:15
[<ffffffff82be118d>] dump_stack+0x6f/0xa2 lib/dump_stack.c:50
[<ffffffff813cb8cb>] ___might_sleep+0x27b/0x3a0 kernel/sched/core.c:7703
[<ffffffff813cba80>] __might_sleep+0x90/0x1a0 kernel/sched/core.c:7665
[< inline >] threadgroup_change_begin include/linux/sched.h:2805
[<ffffffff813830d1>] exit_signals+0x81/0x430 kernel/signal.c:2392
[<ffffffff8135c3dc>] do_exit+0x23c/0x2cb0 kernel/exit.c:701
[<ffffffff811aa28f>] oops_end+0x9f/0xd0 arch/x86/kernel/dumpstack.c:250
[<ffffffff811aa686>] die+0x46/0x60 arch/x86/kernel/dumpstack.c:316
[<ffffffff811a4725>] do_general_protection+0x235/0x3e0
arch/x86/kernel/traps.c:463
[<ffffffff866554e8>] general_protection+0x28/0x30 arch/x86/entry/entry_64.S:982
[< inline >] check_memory_region mm/kasan/kasan.c:264
[<ffffffff81763d64>] __asan_loadN+0x124/0x1a0 mm/kasan/kasan.c:512
[<ffffffff817642ed>] memcpy+0x1d/0x40 mm/kasan/kasan.c:297
[<ffffffff82c1ff41>] copy_from_iter+0x581/0x960 lib/iov_iter.c:416
[<ffffffff82c25400>] copy_page_from_iter+0x510/0xa50 lib/iov_iter.c:467
[< inline >] bio_copy_from_iter block/bio.c:1023
[<ffffffff82b37e98>] bio_copy_user_iov+0xac8/0xe10 block/bio.c:1221
[<ffffffff82b69720>] blk_rq_map_user_iov+0x4b0/0x8e0 block/blk-map.c:111
[<ffffffff82b69c50>] blk_rq_map_user+0x100/0x170 block/blk-map.c:154
[< inline >] sg_start_req drivers/scsi/sg.c:1766
[<ffffffff839f5392>] sg_common_write.isra.19+0x1042/0x16d0
drivers/scsi/sg.c:782
[<ffffffff839f90ff>] sg_write+0x60f/0xa20 drivers/scsi/sg.c:685
[<ffffffff817b9093>] __vfs_write+0x113/0x480 fs/read_write.c:528
[<ffffffff817b94e7>] __kernel_write+0xe7/0x320 fs/read_write.c:550
[<ffffffff8185bcb9>] write_pipe_buf+0x159/0x1e0 fs/splice.c:1068
[< inline >] splice_from_pipe_feed fs/splice.c:770
[<ffffffff8185cb17>] __splice_from_pipe+0x257/0x710 fs/splice.c:895
[<ffffffff81860547>] splice_from_pipe+0xf7/0x140 fs/splice.c:930
[<ffffffff81860620>] default_file_splice_write+0x40/0x90 fs/splice.c:1080
[< inline >] do_splice_from fs/splice.c:1122
[<ffffffff8185a0a5>] direct_splice_actor+0x125/0x180 fs/splice.c:1288
[<ffffffff8185b3b9>] splice_direct_to_actor+0x2c9/0x820 fs/splice.c:1241
[<ffffffff8185bab0>] do_splice_direct+0x1a0/0x250 fs/splice.c:1331
[<ffffffff817bcac3>] do_sendfile+0x673/0x1000 fs/read_write.c:1266
[< inline >] SYSC_sendfile64 fs/read_write.c:1321
[<ffffffff817bf4e7>] SyS_sendfile64+0xb7/0x140 fs/read_write.c:1313
[<ffffffff86653236>] entry_SYSCALL_64_fastpath+0x

On commit 4e5448a31d73d0e944b7adb9049438a09bc332cb.