crypto: slab-out-of-bounds in skcipher_recvmsg

229 views
Skip to first unread message

Dmitry Vyukov

unread,
Jan 15, 2016, 1:22:25 PM1/15/16
to Herbert Xu, David S. Miller, linux-...@vger.kernel.org, LKML, syzkaller, Kostya Serebryany, Alexander Potapenko, Eric Dumazet, Sasha Levin
Hello,

The following program causes slab-out-of-bounds in skcipher_recvmsg:

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

#ifndef SYS_userfaultfd
#define SYS_userfaultfd 323
#endif

long r[72];

void *thr(void *arg)
{
switch ((long)arg) {
case 0:
r[0] = syscall(SYS_mmap, 0x20000000ul, 0x28000ul,
0x3ul, 0x32ul, 0xfffffffffffffffful, 0x0ul);
break;
case 1:
r[1] = syscall(SYS_userfaultfd, 0x80000ul, 0, 0, 0, 0, 0);
break;
case 2:
r[2] = syscall(SYS_socket, 0x26ul, 0x5ul, 0x0ul, 0, 0, 0);
break;
case 3:
*(uint16_t*)0x2000c8ab = (uint16_t)0x26;
memcpy((void*)0x2000c8ad,
"\x73\x6b\x63\x69\x70\x68\x65\x72\x00\x00\x00\x00\x00\x00", 14);
*(uint32_t*)0x2000c8bb = (uint32_t)0x8;
*(uint32_t*)0x2000c8bf = (uint32_t)0xb;
memcpy((void*)0x2000c8c3,
"\x6c\x72\x77\x28\x73\x65\x72\x70\x65\x6e\x74\x29\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);
r[8] = syscall(SYS_bind, r[2], 0x2000c8abul, 0x58ul, 0, 0, 0);
break;
case 4:
memcpy((void*)0x20013fea,
"\xdc\x4f\x77\x67\x54\xf2\x63\xd1\xbe\x5c\x6b\x02\xa6\x65\xeb\xc1\x0f\x74\xbd\xea\x88\x2e",
22);
r[10] = syscall(SYS_setsockopt, r[2], 0x117ul, 0x1ul,
0x20013feaul, 0x16ul, 0);
break;
case 5:
r[11] = syscall(SYS_accept4, r[2], 0x0ul,
0x2001f000ul, 0x80800ul, 0, 0);
break;
case 6:
r[12] = syscall(SYS_dup3, r[11], r[1], 0x80000ul, 0, 0, 0);
break;
case 7:
*(uint32_t*)0x20027fe2 = (uint32_t)0x20;
*(uint32_t*)0x20027fe6 = (uint32_t)0x3;
*(uint64_t*)0x20027fea = (uint64_t)0x0;
*(uint64_t*)0x20027ff2 = (uint64_t)0x9;
*(uint32_t*)0x20027ffa = (uint32_t)0x5;
r[18] = syscall(SYS_write, r[12], 0x20027fe2ul,
0x20ul, 0, 0, 0);
break;
case 8:
r[19] = syscall(SYS_mmap, 0x20028000ul, 0x1000ul,
0x3ul, 0x32ul, 0xfffffffffffffffful, 0x0ul);
break;
case 9:
r[20] = syscall(SYS_mmap, 0x20029000ul, 0x1000ul,
0x3ul, 0x32ul, 0xfffffffffffffffful, 0x0ul);
break;
case 10:
r[21] = syscall(SYS_mmap, 0x20029000ul, 0x1000ul,
0x3ul, 0x32ul, 0xfffffffffffffffful, 0x0ul);
break;
case 11:
r[22] = syscall(SYS_mmap, 0x20029000ul, 0x1000ul,
0x3ul, 0x32ul, 0xfffffffffffffffful, 0x0ul);
break;
case 12:
r[23] = syscall(SYS_mmap, 0x20029000ul, 0x1000ul,
0x3ul, 0x32ul, 0xfffffffffffffffful, 0x0ul);
break;
case 13:
r[24] = syscall(SYS_mmap, 0x20029000ul, 0x1000ul,
0x3ul, 0x32ul, 0xfffffffffffffffful, 0x0ul);
break;
case 14:
r[25] = syscall(SYS_mmap, 0x20029000ul, 0x1000ul,
0x3ul, 0x32ul, 0xfffffffffffffffful, 0x0ul);
break;
case 15:
*(uint64_t*)0x200290fc = (uint64_t)0x20029000;
*(uint32_t*)0x20029104 = (uint32_t)0x80;
*(uint64_t*)0x2002910c = (uint64_t)0x200298fa;
*(uint64_t*)0x20029114 = (uint64_t)0x4;
*(uint64_t*)0x2002911c = (uint64_t)0x20029000;
*(uint64_t*)0x20029124 = (uint64_t)0x14;
*(uint32_t*)0x2002912c = (uint32_t)0x6;
*(uint64_t*)0x200298fa = (uint64_t)0x20029f85;
*(uint64_t*)0x20029902 = (uint64_t)0xd4;
*(uint64_t*)0x2002990a = (uint64_t)0x20029ff4;
*(uint64_t*)0x20029912 = (uint64_t)0x21;
*(uint64_t*)0x2002991a = (uint64_t)0x20029e5e;
*(uint64_t*)0x20029922 = (uint64_t)0xcd;
*(uint64_t*)0x2002992a = (uint64_t)0x20029ff5;
*(uint64_t*)0x20029932 = (uint64_t)0x38;
r[41] = syscall(SYS_recvmsg, r[12], 0x200290fcul,
0x40010102ul, 0, 0, 0);
break;
case 16:
*(uint64_t*)0x20028000 = (uint64_t)0x200116d7;
*(uint32_t*)0x20028008 = (uint32_t)0x1c;
*(uint64_t*)0x20028010 = (uint64_t)0x20028767;
*(uint64_t*)0x20028018 = (uint64_t)0x1;
*(uint64_t*)0x20028020 = (uint64_t)0x20028eba;
*(uint64_t*)0x20028028 = (uint64_t)0x2;
*(uint32_t*)0x20028030 = (uint32_t)0x804;
memcpy((void*)0x200116d7,
"\x0a\x00\xab\x08\xcb\xc6\x9d\xd5\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x9f\x5e\x4b\x81",
28);
*(uint64_t*)0x20028767 = (uint64_t)0x20028f0f;
*(uint64_t*)0x2002876f = (uint64_t)0x89;
memcpy((void*)0x20028f0f,
"\xe2\xce\x66\x53\xea\xa6\x66\x67\x2d\x07\xd0\x6f\xdc\x69\x19\x2f\xd3\x37\x4a\x0a\xcf\xb9\x85\x4b\xcc\x47\x33\x46\x6e\x96\x1b\x3e\x2a\xc3\x8a\x61\xf8\x37\x1c\xcf\x4c\x6e\xdb\x93\xd1\xf6\x93\x38\x9a\x16\xa7\x8b\x3d\x21\x4f\x48\xe0\x8a\x0d\x34\x83\x2a\x17\xe0\xc3\x9f\xa9\xca\x5f\x9b\x9c\xc8\x5b\x33\x8b\x7d\xc8\xf8\xb8\x70\xc5\x01\x18\xe2\xc9\x19\xdd\x38\x22\x50\x09\x00\x2a\x3e\x38\x87\xcb\x48\x4e\x05\x2d\x6f\xc0\x90\xe7\x94\x15\xdf\x0e\xd4\x6d\xeb\x42\x73\x6d\x51\x87\x46\xad\x1c\x95\x4e\x96\x96\x31\x0b\x7f\xdc\x47\x04\xe9\xc3\x84\x01\xeb\x9c\xb8",
137);
*(uint64_t*)0x20028eba = (uint64_t)0x15;
*(uint32_t*)0x20028ec2 = (uint32_t)0xfffffffffffffff9;
*(uint32_t*)0x20028ec6 = (uint32_t)0x13a9fde2;
*(uint8_t*)0x20028eca = (uint8_t)0x3;
*(uint8_t*)0x20028ecb = (uint8_t)0x9;
*(uint8_t*)0x20028ecc = (uint8_t)0x2;
*(uint8_t*)0x20028ecd = (uint8_t)0x2;
*(uint8_t*)0x20028ece = (uint8_t)0xffffffffffffffff;
*(uint64_t*)0x20028ecf = (uint64_t)0x13;
*(uint32_t*)0x20028ed7 = (uint32_t)0x9;
*(uint32_t*)0x20028edb = (uint32_t)0x5;
*(uint8_t*)0x20028edf = (uint8_t)0x1;
*(uint8_t*)0x20028ee0 = (uint8_t)0x1;
*(uint8_t*)0x20028ee1 = (uint8_t)0x69f3;
r[67] = syscall(SYS_sendmsg, r[12], 0x20028000ul,
0x5ul, 0, 0, 0);
break;
case 17:
r[68] = syscall(SYS_fcntl, r[11], 0x2ul, 0x1ul, 0, 0, 0);
break;
case 18:
r[69] = syscall(SYS_mmap, 0x2002a000ul, 0x1000ul,
0x3ul, 0x32ul, 0xfffffffffffffffful, 0x0ul);
break;
case 19:
*(uint32_t*)0x2002affd = (uint32_t)0x5;
r[71] = syscall(SYS_setsockopt, r[11], 0x0ul, 0xaul,
0x2002affdul, 0x4ul, 0);
break;
}
return 0;
}

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

memset(r, -1, sizeof(r));
for (i = 0; i < 20; i++) {
pthread_create(&th[i], 0, thr, (void*)i);
usleep(10000);
}
for (i = 0; i < 20; i++) {
pthread_create(&th[i], 0, thr, (void*)i);
if (i%2==0)
usleep(10000);
}
usleep(100000);
return 0;
}


==================================================================
BUG: KASAN: slab-out-of-bounds in skcipher_recvmsg+0x1894/0x1c00 at
addr ffff8800619033a4
Read of size 4 by task syz-executor/7411
=============================================================================
BUG kmalloc-4096 (Not tainted): kasan: bad access detected
-----------------------------------------------------------------------------

Disabling lock debugging due to kernel taint
INFO: Allocated in sock_kmalloc+0x7f/0xc0 age=21 cpu=2 pid=7411
[< none >] ___slab_alloc+0x486/0x4e0 mm/slub.c:2468
[< none >] __slab_alloc+0x66/0xc0 mm/slub.c:2497
[< inline >] slab_alloc_node mm/slub.c:2560
[< inline >] slab_alloc mm/slub.c:2602
[< none >] __kmalloc+0x2b9/0x350 mm/slub.c:3562
[< inline >] kmalloc include/linux/slab.h:463
[< none >] sock_kmalloc+0x7f/0xc0 net/core/sock.c:1792
[< none >] skcipher_alloc_sgl+0x234/0x2f0 crypto/algif_skcipher.c:143
[< none >] skcipher_sendmsg+0x5ff/0x1040 crypto/algif_skcipher.c:389
[< inline >] sock_sendmsg_nosec net/socket.c:611
[< none >] sock_sendmsg+0xca/0x110 net/socket.c:621
[< none >] sock_write_iter+0x216/0x3a0 net/socket.c:820
[< inline >] new_sync_write fs/read_write.c:517
[< none >] __vfs_write+0x302/0x480 fs/read_write.c:530
[< none >] vfs_write+0x167/0x4a0 fs/read_write.c:577
[< inline >] SYSC_write fs/read_write.c:624
[< none >] SyS_write+0x111/0x220 fs/read_write.c:616
[< none >] entry_SYSCALL_64_fastpath+0x16/0x7a
arch/x86/entry/entry_64.S:185

INFO: Slab 0xffffea0001864000 objects=7 used=7 fp=0x (null)
flags=0x5fffc0000004080
INFO: Object 0xffff8800619023b0 @offset=9136 fp=0xffff880062e31d88
CPU: 2 PID: 7411 Comm: syz-executor Tainted: G B 4.4.0+ #254
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
00000000ffffffff ffff880033bdf910 ffffffff82925f7d ffff88003e806a00
ffff8800619023b0 ffff880061900000 ffff880033bdf940 ffffffff81741284
ffff88003e806a00 ffffea0001864000 ffff8800619023b0 ffff8800619023b0

Call Trace:
[<ffffffff8174a79e>] __asan_report_load4_noabort+0x3e/0x40
mm/kasan/report.c:294
[< inline >] skcipher_recvmsg_sync crypto/algif_skcipher.c:654
[<ffffffff8286a6c4>] skcipher_recvmsg+0x1894/0x1c00 crypto/algif_skcipher.c:710
[< inline >] sock_recvmsg_nosec net/socket.c:713
[<ffffffff85103560>] sock_recvmsg+0xa0/0xc0 net/socket.c:721
[<ffffffff85106329>] ___sys_recvmsg+0x259/0x540 net/socket.c:2100
[<ffffffff851084fe>] __sys_recvmsg+0xce/0x170 net/socket.c:2146
[< inline >] SYSC_recvmsg net/socket.c:2158
[<ffffffff851085cd>] SyS_recvmsg+0x2d/0x50 net/socket.c:2153
[<ffffffff8626c436>] entry_SYSCALL_64_fastpath+0x16/0x7a
arch/x86/entry/entry_64.S:185

Memory state around the buggy address:
ffff880061903280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
ffff880061903300: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>ffff880061903380: 00 00 fc fc fc fc fc fc fc fc fc fc fc fc fc fc
^
ffff880061903400: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
ffff880061903480: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
==================================================================


On commit 67990608c8b95d2b8ccc29932376ae73d5818727 (Jan 12) + a bunch
of unmerged patches form Herbert:
https://gist.githubusercontent.com/dvyukov/7d4eca91f086d7042379/raw/a69956bc779ed112aab671e4e6375fd5595c0548/gistfile1.txt

Herbert Xu

unread,
Jan 18, 2016, 5:46:23 AM1/18/16
to Dmitry Vyukov, David S. Miller, linux-...@vger.kernel.org, LKML, syzkaller, Kostya Serebryany, Alexander Potapenko, Eric Dumazet, Sasha Levin
On Fri, Jan 15, 2016 at 07:22:04PM +0100, Dmitry Vyukov wrote:
> Hello,
>
> The following program causes slab-out-of-bounds in skcipher_recvmsg:

Thanks for the report. This patch should fix it.

---8<---
Subject: crypto: algif_skcipher - Load TX SG list after waiting

We need to load the TX SG list in sendmsg(2) after waiting for
incoming data, not before.

Cc: sta...@vger.kernel.org
Reported-by: Dmitry Vyukov <dvy...@google.com>
Signed-off-by: Herbert Xu <her...@gondor.apana.org.au>

diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
index dfff8b0..df86fb4 100644
--- a/crypto/algif_skcipher.c
+++ b/crypto/algif_skcipher.c
@@ -647,13 +647,6 @@ static int skcipher_recvmsg_sync(struct socket *sock, struct msghdr *msg,

lock_sock(sk);
while (msg_data_left(msg)) {
- sgl = list_first_entry(&ctx->tsgl,
- struct skcipher_sg_list, list);
- sg = sgl->sg;
-
- while (!sg->length)
- sg++;
-
if (!ctx->used) {
err = skcipher_wait_for_data(sk, flags);
if (err)
@@ -674,6 +667,13 @@ static int skcipher_recvmsg_sync(struct socket *sock, struct msghdr *msg,
if (!used)
goto free;

+ sgl = list_first_entry(&ctx->tsgl,
+ struct skcipher_sg_list, list);
+ sg = sgl->sg;
+
+ while (!sg->length)
+ sg++;
+
skcipher_request_set_crypt(&ctx->req, sg, ctx->rsgl.sg, used,
ctx->iv);

--
Email: Herbert Xu <her...@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

Dmitry Vyukov

unread,
Jan 18, 2016, 10:06:59 AM1/18/16
to Herbert Xu, David S. Miller, linux-...@vger.kernel.org, LKML, syzkaller, Kostya Serebryany, Alexander Potapenko, Eric Dumazet, Sasha Levin
On Mon, Jan 18, 2016 at 11:46 AM, Herbert Xu
<her...@gondor.apana.org.au> wrote:
> On Fri, Jan 15, 2016 at 07:22:04PM +0100, Dmitry Vyukov wrote:
>> Hello,
>>
>> The following program causes slab-out-of-bounds in skcipher_recvmsg:
>
> Thanks for the report. This patch should fix it.


Fixes the issue for me. Thanks!

Tested-by: Dmitry Vyukov <dvy...@google.com>
Reply all
Reply to author
Forward
0 new messages