[PATCH net] sctp: fix slab OOB read from oversized AUTH parameters in COOKIE-ECHO
Henry Martin <[email protected]>
| Newsgroups | org.kernel.vger.netdev,org.kernel.vger.linux-sctp |
|---|---|
| Message-ID | <[email protected]> |
sctp_unpack_cookie() copies the attacker-supplied sctp_cookie into the
new association without validating the length fields of the three
embedded AUTH parameters (auth_random, auth_hmacs, auth_chunks) against
their fixed in-struct capacities (36/12/20 bytes). When cookie
authentication is disabled (net.sctp.cookie_hmac_alg=none), a remote
peer can forge a COOKIE-ECHO with an inflated param_hdr.length.
The polluted length then drives out-of-bounds reads past the
association: n_elt in sctp_auth_asoc_verify_hmac_id() (up to ~64KB of
16-bit probe reads), the key vector memcpy in
sctp_auth_make_key_vector() (up to ~64KB source read copied into the
HMAC key material), and the chunk-id scan in __sctp_auth_cid().
KASAN reports slab-out-of-bounds reads crossing into unrelated slabs.
[ 552.245703] ==================================================================
[ 552.245873] BUG: KASAN: slab-out-of-bounds in sctp_auth_asoc_verify_hmac_id+0x105/0x110
[ 552.246050] Read of size 2 at addr ffff8881012a90f4 by task poc_guest/333
[ 552.246258] CPU: 1 UID: 0 PID: 333 Comm: poc_guest Tainted: G B 7.2.0-rc6-dirtyfrag-00017-g848acc8ffe1b-dirty #65 PREEMPT(lazy)
[ 552.246283] Tainted: [B]=BAD_PAGE
[ 552.246291] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.2-4.tl4 04/01/2014
[ 552.246304] Call Trace:
[ 552.246328] <IRQ>
[ 552.246344] dump_stack_lvl+0x53/0x70
[ 552.246374] print_report+0xce/0x620
[ 552.246395] ? sctp_auth_asoc_verify_hmac_id+0x105/0x110
[ 552.246412] kasan_report+0xce/0x100
[ 552.246430] ? sctp_auth_asoc_verify_hmac_id+0x105/0x110
[ 552.246453] sctp_auth_asoc_verify_hmac_id+0x105/0x110
[ 552.246473] sctp_sf_authenticate+0xd2/0x470
[ 552.246491] ? __pfx__raw_spin_lock+0x10/0x10
[ 552.246508] sctp_auth_chunk_verify+0x25b/0x380
[ 552.246526] ? __pfx_sctp_auth_chunk_verify+0x10/0x10
[ 552.246558] ? sctp_auth_asoc_init_active_key+0x1eb/0x810
[ 552.246576] ? sctp_auth_asoc_init_active_key+0x163/0x810
[ 552.246598] sctp_sf_do_5_1D_ce+0x6cf/0x1b50
[ 552.246619] ? __pfx_sctp_sf_do_5_1D_ce+0x10/0x10
[ 552.246637] ? stack_depot_save_flags+0x485/0x7f0
[ 552.246675] ? __pfx_sctp_sm_lookup_event+0x10/0x10
[ 552.246696] sctp_do_sm+0x111/0x5b90
[ 552.246732] ? ip_local_deliver_finish+0x31c/0x4a0
[ 552.246751] ? ip_rcv+0x2ed/0x360
[ 552.246768] ? process_backlog+0x1ea/0x5f0
[ 552.246785] ? __napi_poll+0xa1/0x530
[ 552.246801] ? net_rx_action+0x944/0xfa0
[ 552.246816] ? handle_softirqs+0x1bd/0x620
[ 552.246831] ? do_softirq+0x43/0x60
[ 552.246844] ? __local_bh_enable_ip+0x6a/0x70
[ 552.246858] ? __dev_queue_xmit+0x9f3/0x3470
[ 552.246874] ? ip_finish_output2+0x724/0x1900
[ 552.246889] ? __pfx_sctp_do_sm+0x10/0x10
[ 552.246903] ? raw_sendmsg+0xe72/0x2710
[ 552.246919] ? __x64_sys_sendto+0xe0/0x1c0
[ 552.246938] ? do_syscall_64+0x102/0x5a0
[ 552.246955] ? entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 552.246991] ? __pfx_sctp_epaddr_lookup_transport+0x10/0x10
[ 552.247013] sctp_endpoint_bh_rcv+0x2c4/0x8e0
[ 552.247038] sctp_rcv+0x1545/0x3980
[ 552.247063] ? sock_queue_rcv_skb_reason+0x39/0x70
[ 552.247081] ? __pfx_sctp_rcv+0x10/0x10
[ 552.247105] ? __pfx_raw_local_deliver+0x10/0x10
[ 552.247121] ? lapic_next_event+0x15/0x20
[ 552.247138] ? clockevents_program_event+0x2bf/0x860
[ 552.247159] ip_protocol_deliver_rcu+0x279/0x2f0
[ 552.247176] ? _raw_spin_lock+0x84/0xe0
[ 552.247192] ip_local_deliver_finish+0x31c/0x4a0
[ 552.247211] ip_local_deliver+0x18b/0x2d0
--
[ 552.247752] ? __pfx___dev_queue_xmit+0x10/0x10
[ 552.247769] ? csum_and_copy_from_iter_full+0x1d9/0x1da0
[ 552.247788] ? kasan_save_track+0x14/0x30
[ 552.247803] ? __kasan_kmalloc+0x8f/0xa0
[ 552.247821] ? __alloc_skb+0x123/0x890
[ 552.247843] ? selinux_ip_postroute+0x3fe/0xb00
[ 552.247863] ip_finish_output2+0x724/0x1900
[ 552.247882] ? __pfx_ip_finish_output2+0x10/0x10
[ 552.247899] ? __ip_append_data+0x16ec/0x4150
[ 552.247925] __ip_finish_output+0x508/0xa30
[ 552.247944] ? __pfx___ip_finish_output+0x10/0x10
[ 552.247961] ? nf_hook_slow+0xaa/0x1c0
[ 552.247981] ip_output+0x17d/0x2f0
[ 552.247999] ? __pfx_ip_output+0x10/0x10
[ 552.248015] ? __ip_make_skb+0xe0f/0x2520
[ 552.248031] ? __pfx_ip_finish_output+0x10/0x10
[ 552.248047] ? ip_append_data+0xcb/0x170
[ 552.248066] ip_push_pending_frames+0x15a/0x1a0
[ 552.248084] raw_sendmsg+0xe72/0x2710
[ 552.248107] ? __pfx_raw_sendmsg+0x10/0x10
[ 552.248122] ? mutex_unlock+0x82/0xd0
[ 552.248137] ? __pfx_mutex_unlock+0x10/0x10
[ 552.248157] ? anon_pipe_write+0xa18/0x1900
[ 552.248193] ? selinux_socket_sendmsg+0x91/0x270
[ 552.248215] __sys_sendto+0x31b/0x390
[ 552.248235] ? __pfx___sys_sendto+0x10/0x10
[ 552.248278] ? ksys_write+0x181/0x1d0
[ 552.248295] ? __pfx_ksys_write+0x10/0x10
[ 552.248334] __x64_sys_sendto+0xe0/0x1c0
[ 552.248354] ? fpregs_assert_state_consistent+0x63/0xf0
[ 552.248379] do_syscall_64+0x102/0x5a0
[ 552.248400] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 552.248420] RIP: 0033:0x7facd02ef0a7
[ 552.248442] Code: c7 c0 ff ff ff ff eb be 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 80 3d a5 ef 0d 00 00 41 89 ca 74 10 b8 2c 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 69 c3 55 48 89 e5 53 48 83 ec 38 44 89 4d d0
[ 552.248461] RSP: 002b:00007ffc9f687208 EFLAGS: 00000202 ORIG_RAX: 000000000000002c
[ 552.248489] RAX: ffffffffffffffda RBX: 0000000000000144 RCX: 00007facd02ef0a7
[ 552.248501] RDX: 0000000000000150 RSI: 00007ffc9f687234 RDI: 0000000000000003
[ 552.248512] RBP: 000000000100007f R08: 00007ffc9f687210 R09: 0000000000000010
[ 552.248523] R10: 0000000000000000 R11: 0000000000000202 R12: 000000000000014e
[ 552.248534] R13: 00007ffc9f688100 R14: 0000000000000144 R15: 0000000000000100
[ 552.248555] </TASK>
[ 552.260224] Allocated by task 1:
[ 552.260304] kasan_save_stack+0x33/0x60
[ 552.260410] kasan_save_track+0x14/0x30
[ 552.260501] __kasan_kmalloc+0x8f/0xa0
[ 552.260588] __kmalloc_cache_noprof+0x1b6/0x420
[ 552.260714] pci_alloc_bus.constprop.0+0x3f/0x300
[ 552.260847] pci_register_host_bridge+0xcf/0x15f0
[ 552.260957] pci_create_root_bus+0x1e5/0x300
[ 552.261076] acpi_pci_root_create+0x42d/0x880
[ 552.261193] pci_acpi_scan_root+0x3df/0x5a0
[ 552.261320] acpi_pci_root_add+0x369/0x8e0
[ 552.261453] acpi_bus_attach+0x4f3/0xa40
[ 552.261574] device_for_each_child+0xf8/0x170
[ 552.261732] acpi_dev_for_each_child+0x7a/0xa0
[ 552.261849] acpi_bus_attach+0x72b/0xa40
[ 552.261983] device_for_each_child+0xf8/0x170
[ 552.262087] acpi_dev_for_each_child+0x7a/0xa0
[ 552.262187] acpi_bus_attach+0x72b/0xa40
[ 552.262281] acpi_bus_scan+0xbd/0x3e0
[ 552.262384] acpi_scan_init+0x1c9/0x580
[ 552.262470] acpi_init+0x2e2/0x6d0
[ 552.262540] do_one_initcall+0xa6/0x370
[ 552.262626] kernel_init_freeable+0x42d/0x760
[ 552.262727] kernel_init+0x1f/0x1e0
[ 552.262867] ret_from_fork+0x3af/0x620
[ 552.262974] ret_from_fork_asm+0x1a/0x30
[ 552.263133] The buggy address belongs to the object at ffff8881012a8800
which belongs to the cache kmalloc-2k of size 2048
[ 552.263468] The buggy address is located 1244 bytes to the right of
allocated 1048-byte region [ffff8881012a8800, ffff8881012a8c18)
[ 552.263836] The buggy address belongs to the physical page:
[ 552.263955] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x1012a8
[ 552.264112] head: order:3 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
[ 552.264255] flags: 0x200000000000040(head|node=0|zone=2)
[ 552.264383] page_type: f5(slab)
[ 552.264460] raw: 0200000000000040 ffff888100043240 ffffea0004044410 ffffea0004057c10
[ 552.264616] raw: 0000000000000000 0000000800050005 00000000f5000000 0000000000000000
[ 552.264850] head: 0200000000000040 ffff888100043240 ffffea0004044410 ffffea0004057c10
[ 552.264998] head: 0000000000000000 0000000800050005 00000000f5000000 0000000000000000
[ 552.265145] head: 0200000000000003 fffffffffffffe01 00000000ffffffff 00000000ffffffff
[ 552.265288] head: 0000000000000000 0000000000000000 00000000ffffffff 0000000000000008
[ 552.265437] page dumped because: kasan: bad access detected
[ 552.265575] Memory state around the buggy address:
[ 552.265660] ffff8881012a8f80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[ 552.265881] ffff8881012a9000: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[ 552.266013] >ffff8881012a9080: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[ 552.266143] ^
[ 552.266272] ffff8881012a9100: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[ 552.266412] ffff8881012a9180: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[ 552.266544] ==================================================================
[ 553.517512] systemd[1]: e2scrub_all.service: Deactivated successfully.
[ 553.545039] systemd[1]: Finished e2scrub_all.service - Online ext4 Metadata Check for All Filesystems.
[ 553.682216] systemd[1]: systemd-journald.service: Main process exited, code=killed, status=6/ABRT
[ 553.688936] systemd[1]: systemd-journald.service: Failed with result 'watchdog'.
[ 553.698303] systemd[1]: systemd-journald.service: Consumed 7min 31.125s CPU time.
[ 553.716114] systemd[1]: systemd-journald.service: Scheduled restart job, restart counter is at 1.
[ 553.849464] systemd[1]: Starting systemd-journald.service - Journal Service...
[ 554.149027] systemd[1]: systemd-update-utmp-runlevel.service: Deactivated successfully.
[ 554.176031] systemd[1]: Finished systemd-update-utmp-runlevel.service - Record Runlevel Change in UTMP.
[ 554.675881] systemd-journald[352]: Collecting audit messages is disabled.
[ 554.722954] systemd-journald[352]: File /var/log/journal/650a0aae2d504220b5076f94e1b000de/system.journal corrupted or uncleanly shut down, renaming and replacing.
[ 555.046104] systemd[1]: fstrim.service: Deactivated successfully.
[ 555.053901] systemd[1]: Finished fstrim.service - Discard unused blocks on filesystems from /etc/fstab.
[ 555.063225] systemd[1]: fstrim.service: Consumed 1.297s CPU time.
[ 555.079769] systemd-journald[352]: /dev/kmsg buffer overrun, some messages lost.
[ 556.021993] systemd[1]: Started systemd-journald.service - Journal Service.
Reject cookies whose embedded AUTH parameter lengths exceed the
struct capacities, the same "malformed" path used for other corrupt
cookie fields.
The issue was found by ZeroHive, a vulnerability hunting agent at
Tencent Yunding Lab.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Henry Martin <[email protected]>
---
net/sctp/sm_make_chunk.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 5a335c980a7a4..0634241fd6649 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -1855,6 +1855,16 @@ struct sctp_association *sctp_unpack_cookie(
/* Populate the association from the cookie. */
memcpy(&retval->c, bear_cookie, sizeof(*bear_cookie));
+ if (ntohs(((__be16 *)retval->c.auth_random)[1]) >
+ sizeof(retval->c.auth_random) ||
+ ntohs(((__be16 *)retval->c.auth_hmacs)[1]) >
+ sizeof(retval->c.auth_hmacs) ||
+ ntohs(((__be16 *)retval->c.auth_chunks)[1]) >
+ sizeof(retval->c.auth_chunks)) {
+ *error = -SCTP_IERROR_MALFORMED;
+ goto fail;
+ }
+
if (sctp_assoc_set_bind_addr_from_cookie(retval, bear_cookie,
GFP_ATOMIC) < 0) {
*error = -SCTP_IERROR_NOMEM;
--
2.43.0