crypto: use-after-free in hash_sock_destruct_common

From: Dmitry Vyukov
Date: Tue Jan 12 2016 - 13:31:31 EST


Hello,

The following program triggers use-after-free in
hash_sock_destruct_common. This is on master of
git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6.git
(cd7e98414462b9db70067ac29896c58210b13b69). I've also seen a similar
crash in skcipher_sock_destruct_common.

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

int fd;

void *thr(void *arg)
{
switch ((long)arg) {
case 0:
break;
case 1:
break;
case 2:
*(uint16_t*)0x20023000 = (uint16_t)0x26;
memcpy((void*)0x20023002,
"\x68\x61\x73\x68\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 14);
*(uint32_t*)0x20023010 = (uint32_t)0x2000;
*(uint32_t*)0x20023014 = (uint32_t)0x84;
memcpy((void*)0x20023018,
"\x74\x67\x72\x31\x36\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
64);
syscall(SYS_bind, fd, 0x20023000ul, 0x58ul, 0, 0, 0);
break;
case 3:
syscall(SYS_accept, fd, 0x0ul, 0x2000affcul, 0, 0, 0);
break;
}
return 0;
}

int main()
{
long i;
pthread_t th[4];

fd = syscall(SYS_socket, 0x26ul, 0x5ul, 0x0ul, 0, 0, 0);
syscall(SYS_mmap, 0x20000000ul, 0x28000ul, 0x3ul, 0x32ul,
0xfffffffffffffffful, 0x0ul);
for (i = 0; i < 4; i++) {
pthread_create(&th[i], 0, thr, (void*)i);
usleep(10000);
}
for (i = 0; i < 4; i++) {
pthread_create(&th[i], 0, thr, (void*)i);
if (i%2==0)
usleep(10000);
}
usleep(100000);
return 0;
}

==================================================================
BUG: KASAN: use-after-free in hash_sock_destruct_common+0x12b/0x160 at
addr ffff880064550490
Read of size 8 by task a.out/6513
=============================================================================
BUG kmalloc-192 (Not tainted): kasan: bad access detected
-----------------------------------------------------------------------------

Disabling lock debugging due to kernel taint
INFO: Allocated in crypto_create_tfm+0x7a/0x210 age=147 cpu=2 pid=6516
[< none >] __slab_alloc+0x535/0x5d0 mm/slub.c:2399
[< inline >] slab_alloc_node mm/slub.c:2467
[< inline >] slab_alloc mm/slub.c:2509
[< none >] __kmalloc+0x2cd/0x370 mm/slub.c:3414
[< inline >] kmalloc include/linux/slab.h:445
[< inline >] kzalloc include/linux/slab.h:593
[< none >] crypto_create_tfm+0x7a/0x210 crypto/api.c:470
[< none >] crypto_alloc_tfm+0x11d/0x330 crypto/api.c:555
[< none >] crypto_alloc_ahash+0x14/0x20 crypto/ahash.c:541
[< none >] hash_bind+0x66/0xe0 crypto/algif_hash.c:357
[< none >] alg_bind+0x179/0x3c0 crypto/af_alg.c:175
[< none >] SYSC_bind+0x1ae/0x210 net/socket.c:1383
[< none >] SyS_bind+0x9/0x10 net/socket.c:1369
[< none >] entry_SYSCALL_64_fastpath+0x16/0x7a
arch/x86/entry/entry_64.S:185
INFO: Freed in kzfree+0x28/0x30 age=121 cpu=3 pid=6520
[< none >] __slab_free+0x1e7/0x310 mm/slub.c:2584
[< inline >] slab_free mm/slub.c:2733
[< none >] kfree+0x29f/0x2c0 mm/slub.c:3514
[< none >] kzfree+0x28/0x30 mm/slab_common.c:1270
[< none >] crypto_destroy_tfm+0xac/0x150 crypto/api.c:596
[< inline >] crypto_free_ahash include/crypto/hash.h:259
[< none >] hash_release+0x2b/0x40 crypto/algif_hash.c:372
[< inline >] alg_do_release crypto/af_alg.c:118
[< none >] alg_bind+0x269/0x3c0 crypto/af_alg.c:196
[< none >] SYSC_bind+0x1ae/0x210 net/socket.c:1383
[< none >] SyS_bind+0x9/0x10 net/socket.c:1369
[< none >] entry_SYSCALL_64_fastpath+0x16/0x7a
arch/x86/entry/entry_64.S:185
INFO: Slab 0xffffea0001915400 objects=16 used=9 fp=0xffff880064550400
flags=0x5fffc0000004080
INFO: Object 0xffff880064550400 @offset=1024 fp=0xffff880064550e00

Bytes b4 ffff8800645503f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 ................
Object ffff880064550400: 00 0e 55 64 00 88 ff ff 00 00 00 00 00 00 00
00 ..Ud............
Object ffff880064550410: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 ................
Object ffff880064550420: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 ................
Object ffff880064550430: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 ................
Object ffff880064550440: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 ................
Object ffff880064550450: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 ................
Object ffff880064550460: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 ................
Object ffff880064550470: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 ................
Object ffff880064550480: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 ................
Object ffff880064550490: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 ................
Object ffff8800645504a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 ................
Object ffff8800645504b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 ................
Redzone ffff8800645504c0: bb bb bb bb bb bb bb bb
........
Padding ffff8800645505f8: 00 00 00 00 00 00 00 00
........
CPU: 1 PID: 6513 Comm: a.out Tainted: G B 4.4.0-rc1+ #3
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
ffff880064550000 ffff8800340a7a88 ffffffff828b0ea7 ffff88003e804a00
ffff8800340a7ab8 ffffffff816fa734 ffff88003e804a00 ffffea0001915400
ffff880064550400 0000000000000000 ffff8800340a7ae0 ffffffff81700c9f
Call Trace:
[< inline >] __dump_stack lib/dump_stack.c:15
[<ffffffff828b0ea7>] dump_stack+0x4b/0x64 lib/dump_stack.c:50
[<ffffffff816fa734>] print_trailer+0xf4/0x150 mm/slub.c:652
[<ffffffff81700c9f>] object_err+0x2f/0x40 mm/slub.c:659
[< inline >] print_address_description mm/kasan/report.c:138
[<ffffffff817034d6>] kasan_report_error+0x206/0x520 mm/kasan/report.c:236
[< inline >] kasan_report mm/kasan/report.c:259
[<ffffffff817038ee>] __asan_report_load8_noabort+0x3e/0x40
mm/kasan/report.c:280
[< inline >] crypto_ahash_digestsize include/crypto/hash.h:291
[<ffffffff827f12ab>] hash_sock_destruct_common+0x12b/0x160
crypto/algif_hash.c:393
[<ffffffff827f1e6d>] hash_sock_destruct_nokey+0xd/0x90 crypto/algif_hash.c:417
[<ffffffff84d122cf>] sk_destruct+0x3f/0x420 net/core/sock.c:1448
[<ffffffff84d126ff>] __sk_free+0x4f/0x1e0 net/core/sock.c:1476
[<ffffffff84d128a3>] sk_free+0x13/0x20 net/core/sock.c:1487
[< inline >] sock_put include/net/sock.h:1623
[<ffffffff827f035f>] af_alg_release+0x3f/0x50 crypto/af_alg.c:125
[<ffffffff84cfdaa3>] sock_release+0x83/0x1a0 net/socket.c:571
[<ffffffff84cfdbcd>] sock_close+0xd/0x20 net/socket.c:1022
[<ffffffff81749d70>] __fput+0x210/0x750 fs/file_table.c:208
[<ffffffff8174a319>] ____fput+0x9/0x10 fs/file_table.c:244
[<ffffffff81388992>] task_work_run+0x132/0x200 kernel/task_work.c:115
[< inline >] exit_task_work include/linux/task_work.h:21
[<ffffffff8133989b>] do_exit+0x7fb/0x2be0 kernel/exit.c:748
[<ffffffff8133bdb4>] do_group_exit+0xf4/0x2f0 kernel/exit.c:878
[< inline >] SYSC_exit_group kernel/exit.c:889
[<ffffffff8133bfc8>] SyS_exit_group+0x18/0x20 kernel/exit.c:887
[<ffffffff85e519f6>] entry_SYSCALL_64_fastpath+0x16/0x7a
arch/x86/entry/entry_64.S:185
Memory state around the buggy address:
ffff880064550380: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
ffff880064550400: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>ffff880064550480: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
^
ffff880064550500: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
ffff880064550580: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
==================================================================
BUG: unable to handle kernel paging request at fffffffffffffff8
IP: [<ffffffff827f1238>] hash_sock_destruct_common+0xb8/0x160
crypto/algif_hash.c:392
PGD 6fa5067 PUD 6fa7067 PMD 0
Oops: 0000 [#1] SMP DEBUG_PAGEALLOC KASAN
Modules linked in:
CPU: 1 PID: 6513 Comm: a.out Tainted: G B 4.4.0-rc1+ #3
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
task: ffff880037bbc380 ti: ffff8800340a0000 task.ti: ffff8800340a0000
RIP: 0010:[<ffffffff827f1238>] [<ffffffff827f1238>]
hash_sock_destruct_common+0xb8/0x160
RSP: 0018:ffff8800340a7ba8 EFLAGS: 00010246
RAX: dffffc0000000000 RBX: ffff8800663740c0 RCX: 0000000000000000
RDX: 1fffffffffffffff RSI: 0000000000000001 RDI: ffff8800663743f0
RBP: ffff8800340a7bc8 R08: 0000000000000001 R09: 0000000000000000
R10: ffffffff861e0380 R11: 0000000000000000 R12: ffff880066373780
R13: 0000000000000000 R14: 0000000000000000 R15: ffff880067e92110
FS: 0000000000000000(0000) GS:ffff88003ed00000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: fffffffffffffff8 CR3: 0000000006fa2000 CR4: 00000000000006e0
Stack:
0000000000000000 ffff880066373780 ffffffff8738c1e0 ffff8800665ff828
ffff8800340a7be0 ffffffff827f1e6d ffff880066373780 ffff8800340a7c08
ffffffff84d122cf ffff880066373780 ffffffff8738c1e0 ffff8800665ff828
Call Trace:
[<ffffffff827f1e6d>] hash_sock_destruct_nokey+0xd/0x90 crypto/algif_hash.c:417
[<ffffffff84d122cf>] sk_destruct+0x3f/0x420 net/core/sock.c:1448
[<ffffffff84d126ff>] __sk_free+0x4f/0x1e0 net/core/sock.c:1476
[<ffffffff84d128a3>] sk_free+0x13/0x20 net/core/sock.c:1487
[< inline >] sock_put include/net/sock.h:1623
[<ffffffff827f035f>] af_alg_release+0x3f/0x50 crypto/af_alg.c:125
[<ffffffff84cfdaa3>] sock_release+0x83/0x1a0 net/socket.c:571
[<ffffffff84cfdbcd>] sock_close+0xd/0x20 net/socket.c:1022
[<ffffffff81749d70>] __fput+0x210/0x750 fs/file_table.c:208
[<ffffffff8174a319>] ____fput+0x9/0x10 fs/file_table.c:244
[<ffffffff81388992>] task_work_run+0x132/0x200 kernel/task_work.c:115
[< inline >] exit_task_work include/linux/task_work.h:21
[<ffffffff8133989b>] do_exit+0x7fb/0x2be0 kernel/exit.c:748
[<ffffffff8133bdb4>] do_group_exit+0xf4/0x2f0 kernel/exit.c:878
[< inline >] SYSC_exit_group kernel/exit.c:889
[<ffffffff8133bfc8>] SyS_exit_group+0x18/0x20 kernel/exit.c:887
[<ffffffff85e519f6>] entry_SYSCALL_64_fastpath+0x16/0x7a
arch/x86/entry/entry_64.S:185
Code: fc ff df 49 8d 7d f8 48 89 fa 48 c1 ea 03 0f b6 04 02 84 c0 74
04 3c 03 7e 78 48 8d bb 30 03 00 00 48 b8 00 00 00 00 00 fc ff df <41>
8b 55 f8 48 89 f9 48 c1 e9 03 80 3c 01 00 75 7b 48 8b b3 30
RIP [<ffffffff827f1238>] hash_sock_destruct_common+0xb8/0x160
crypto/algif_hash.c:392
RSP <ffff8800340a7ba8>
CR2: fffffffffffffff8
---[ end trace 130c2827b1841caa ]---
Fixing recursive fault but reboot is needed!