lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:   Wed, 27 Sep 2017 14:15:39 +0200
From:   Alexander Potapenko <glider@...gle.com>
To:     David Miller <davem@...emloft.net>, ying.xue@...driver.com,
        jon.maloy@...csson.com
Cc:     Networking <netdev@...r.kernel.org>,
        syzkaller <syzkaller@...glegroups.com>
Subject: [bug][tipc] Too short struct tipc_subscr passed to tipc_subscrb_rcv_cb()

Hi all,

I've spotted the following bug in TIPC server code while fuzzing it
with KMSAN and syzkaller:

==================================================================
BUG: KMSAN: use of uninitialized memory in tipc_subscrb_rcv_cb+0x14a/0xc20
CPU: 2 PID: 29 Comm: kworker/u8:1 Not tainted 4.13.0+ #3150
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
Workqueue: tipc_rcv tipc_recv_work
Call Trace:
 __dump_stack lib/dump_stack.c:16
 dump_stack+0x172/0x1c0 lib/dump_stack.c:52
 kmsan_report+0x145/0x3d0 mm/kmsan/kmsan.c:943
 __msan_warning_32+0x66/0xb0 mm/kmsan/kmsan_instr.c:477
 htohl net/tipc/subscr.c:66
 tipc_subscrb_rcv_cb+0x14a/0xc20 net/tipc/subscr.c:333
 tipc_receive_from_sock+0x369/0x540 net/tipc/server.c:273
 tipc_recv_work+0xbe/0x1c0 net/tipc/server.c:546
 process_one_work+0xf9e/0x1ad0 kernel/workqueue.c:2097
 worker_thread+0xefd/0x2090 kernel/workqueue.c:2231
 kthread+0x499/0x620 kernel/kthread.c:232
 ret_from_fork+0x22/0x30 arch/x86/entry/entry_64.S:425
origin:
 save_stack_trace+0x16/0x20 arch/x86/kernel/stacktrace.c:59
 kmsan_save_stack_with_flags mm/kmsan/kmsan.c:302
 kmsan_internal_poison_shadow+0xb3/0x1b0 mm/kmsan/kmsan.c:198
 kmsan_kmalloc+0x80/0xe0 mm/kmsan/kmsan.c:337
 kmem_cache_alloc+0x1e2/0x220 mm/slub.c:2756
 tipc_receive_from_sock+0xff/0x540 net/tipc/server.c:257
 tipc_recv_work+0xbe/0x1c0 net/tipc/server.c:546
 process_one_work+0xf9e/0x1ad0 kernel/workqueue.c:2097
 worker_thread+0xefd/0x2090 kernel/workqueue.c:2231
 kthread+0x499/0x620 kernel/kthread.c:232
 ret_from_fork+0x22/0x30 arch/x86/entry/entry_64.S:425
==================================================================
(see the reproducer attached).

Here the user sends 16 bytes via sendmsg(), which the kernel attempts
to treat as a struct tipc_subscr. Because the actual size of a struct
is bigger, we end up touching uninitialized fields.

What is the best way to fix this?

I think it's too late to check for |len| in tipc_subscrb_rcv_cb()
(http://elixir.free-electrons.com/linux/latest/source/net/tipc/subscr.c#L320),
because we'll probably need to call tipc_subscrp_cancel(s, subscriber)
in order to cancel the subscription, which is a bad idea since |s| is
invalid.
We could check that ret >= sizeof(struct tipc_subscr) in
tipc_receive_from_sock()
(http://elixir.free-electrons.com/linux/v4.8/source/net/tipc/server.c#L273),
but this function is agnostic to the type of the data received by the
callback, so we'd better not hardcode the size there.
Shall we add an integer field (or yet another callback) to tipc_server, maybe?

On a related note, something is wrong with the
tipc_receive_from_sock()'s return value.
First, the user appears to receive a positive value (16 in our case)
regardless of what tipc_receive_from_sock() returns.
Second, the branch at
http://elixir.free-electrons.com/linux/v4.8/source/net/tipc/server.c#L288
is never taken.

WBR,

Alexander Potapenko
Software Engineer

Google Germany GmbH
Erika-Mann-Straße, 33
80636 München

Geschäftsführer: Paul Manicle, Halimah DeLaine Prado
Registergericht und -nummer: Hamburg, HRB 86891
Sitz der Gesellschaft: Hamburg

View attachment "tipc_subscrb_rcv_cb-kmsan.c" of type "text/x-csrc" (733 bytes)

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ