Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date: Fri, 22 Dec 2023 10:16:24 +0800
From: Xingyuan Mo <hdthky0@...il.com>
To: oss-security@...ts.openwall.com
Subject: CVE-2023-6817: Linux kernel: use-after-free in nf_tables

Hello,

I found a use-after-free vulnerability in the implementation of pipapo set
in Linux kernel nf_tables, which can lead to DoS or local privilege
escalation, with CAP_NET_ADMIN capability required. The bug is fixed in
v6.7-rc5 kernel and the patch is:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=317eb9685095678f2c9f5a8189de698c5354316a

=*=*=*=*=*=*=*=*=  Bug Details  =*=*=*=*=*=*=*=*=
According to the design of nf_tables, when calling NFT_MSG_DELSETELEM
command without a set element specified, all elements in the target set
will be deleted. During this process, nft_set_flush() is called, which
calls set->ops->walk() at (0).

static int nft_set_flush(struct nft_ctx *ctx, struct nft_set *set, u8 genmask)
{
	struct nft_set_iter iter = {
		.genmask	= genmask,
		.fn		= nft_setelem_flush,
	};

	set->ops->walk(ctx, set, &iter);   <==== (0)
	if (!iter.err)
		iter.err = nft_set_catchall_flush(ctx, set);

	return iter.err;
}

If the backend is a pipapo set, nft_pipapo_walk() will be called. This
function does not check the activeness of an element before operating on
it, just like similar functions in other set backend such as
nft_rhash_walk(). Thus NFT_MSG_DELSETELEM command can be called
twice in one transaction to deleted every element in that set twice,
resulting in double free.

A POC is attached, which can be compiled with:
gcc -o poc poc.c -lnftnl -lmnl

I tested against v6.7-rc4 kernel and got a KASAN report as follows:
[  286.833955] ==================================================================
[  286.834580] BUG: KASAN: slab-use-after-free in nf_tables_trans_destroy_work+0x43c/0x630
[  286.835253] Read of size 1 at addr ffff88800754ba88 by task kworker/0:0/8

[  286.835931] CPU: 0 PID: 8 Comm: kworker/0:0 Not tainted 6.7.0-rc4 #1
[  286.836440] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1.1 04/01/2014
[  286.837167] Workqueue: events nf_tables_trans_destroy_work
[  286.837619] Call Trace:
[  286.837825]  <TASK>
[  286.838005]  dump_stack_lvl+0x3b/0x50
[  286.838316]  print_report+0xcf/0x620
[  286.838621]  ? __virt_addr_valid+0xf7/0x180
[  286.838974]  ? nf_tables_trans_destroy_work+0x43c/0x630
[  286.839397]  ? kasan_complete_mode_report_info+0x80/0x210
[  286.839839]  ? nf_tables_trans_destroy_work+0x43c/0x630
[  286.840269]  kasan_report+0xbd/0x100
[  286.840573]  ? nf_tables_trans_destroy_work+0x43c/0x630
[  286.841001]  __asan_load1+0x66/0x70
[  286.841297]  nf_tables_trans_destroy_work+0x43c/0x630
[  286.841719]  ? __pfx_nf_tables_trans_destroy_work+0x10/0x10
[  286.842175]  ? read_word_at_a_time+0x12/0x20
[  286.842528]  ? kick_pool+0x39/0x1a0
[  286.842829]  process_one_work+0x2e4/0x5c0
[  286.843167]  worker_thread+0x520/0x790
[  286.843491]  ? __pfx_worker_thread+0x10/0x10
[  286.843849]  kthread+0x16e/0x1b0
[  286.844119]  ? __pfx_kthread+0x10/0x10
[  286.844433]  ret_from_fork+0x3b/0x70
[  286.844750]  ? __pfx_kthread+0x10/0x10
[  286.845069]  ret_from_fork_asm+0x1b/0x30
[  286.845400]  </TASK>

[  286.845735] Allocated by task 279:
[  286.846028]  kasan_save_stack+0x2a/0x50
[  286.846352]  kasan_set_track+0x29/0x40
[  286.846669]  kasan_save_alloc_info+0x1f/0x30
[  286.847030]  __kasan_kmalloc+0x88/0xa0
[  286.847344]  __kmalloc+0x61/0x140
[  286.847630]  nft_set_elem_init+0x72/0x270
[  286.847971]  nft_add_set_elem+0xf7b/0x1bb0
[  286.848315]  nf_tables_newsetelem+0x3fb/0x4d0
[  286.848699]  nfnetlink_rcv_batch+0xcba/0xe90
[  286.849055]  nfnetlink_rcv+0x1df/0x220
[  286.849375]  netlink_unicast+0x3eb/0x540
[  286.849703]  netlink_sendmsg+0x44d/0x7d0
[  286.850039]  __sys_sendto+0x347/0x360
[  286.850353]  __x64_sys_sendto+0x7f/0xa0
[  286.850681]  do_syscall_64+0x46/0xf0
[  286.850980]  entry_SYSCALL_64_after_hwframe+0x6f/0x77

[  286.851546] Freed by task 8:
[  286.851795]  kasan_save_stack+0x2a/0x50
[  286.852121]  kasan_set_track+0x29/0x40
[  286.852447]  kasan_save_free_info+0x2f/0x50
[  286.852804]  __kasan_slab_free+0x113/0x1a0
[  286.853155]  __kmem_cache_free+0x82/0x1b0
[  286.853496]  kfree+0x78/0x120
[  286.853752]  nf_tables_trans_destroy_work+0x460/0x630
[  286.854177]  process_one_work+0x2e4/0x5c0
[  286.854513]  worker_thread+0x520/0x790
[  286.854840]  kthread+0x16e/0x1b0
[  286.855113]  ret_from_fork+0x3b/0x70
[  286.855424]  ret_from_fork_asm+0x1b/0x30

[  286.855890] Last potentially related work creation:
[  286.856296]  kasan_save_stack+0x2a/0x50
[  286.856630]  __kasan_record_aux_stack+0x92/0xa0
[  286.857028]  kasan_record_aux_stack_noalloc+0xf/0x20
[  286.857449]  kvfree_call_rcu+0x2c/0x470
[  286.857769]  kernfs_unlink_open_file+0x19c/0x1b0
[  286.858155]  kernfs_fop_release+0x6b/0x180
[  286.858500]  __fput+0x132/0x4e0
[  286.858765]  __fput_sync+0x35/0x40
[  286.859065]  __x64_sys_close+0x56/0xa0
[  286.859390]  do_syscall_64+0x46/0xf0
[  286.859695]  entry_SYSCALL_64_after_hwframe+0x6f/0x77

[  286.860259] The buggy address belongs to the object at ffff88800754ba80
                which belongs to the cache kmalloc-96 of size 96
[  286.861228] The buggy address is located 8 bytes inside of
                freed 96-byte region [ffff88800754ba80, ffff88800754bae0)

[  286.862296] The buggy address belongs to the physical page:
[  286.862745] page:00000000f0d84d4e refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x754b
[  286.863468] anon flags: 0x100000000000800(slab|node=0|zone=1)
[  286.863929] page_type: 0xffffffff()
[  286.864219] raw: 0100000000000800 ffff888004c41780 ffffea00001bcb40 dead000000000005
[  286.864849] raw: 0000000000000000 0000000000200020 00000001ffffffff 0000000000000000
[  286.865451] page dumped because: kasan: bad access detected

[  286.866030] Memory state around the buggy address:
[  286.866412]  ffff88800754b980: 00 00 00 00 00 00 00 00 00 00 04 fc fc fc fc fc
[  286.866977]  ffff88800754ba00: 00 00 00 00 00 00 00 00 00 04 fc fc fc fc fc fc
[  286.867577] >ffff88800754ba80: fa fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
[  286.868185]                       ^
[  286.868489]  ffff88800754bb00: fa fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
[  286.869089]  ffff88800754bb80: fa fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
[  286.869690] ==================================================================

=*=*=*=*=*=*=*=*=  Discoverer  =*=*=*=*=*=*=*=*=
Xingyuan Mo of IceSword Lab

Best,
Xingyuan Mo

View attachment "poc.c" of type "text/x-csrc" (7988 bytes)

Powered by blists - more mailing lists

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.