oss-sec mailing list archives

CVE-2023-6817: Linux kernel: use-after-free in nf_tables


From: Xingyuan Mo <hdthky0 () gmail com>
Date: Fri, 22 Dec 2023 10:16:24 +0800

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

Attachment: poc.c
Description:


Current thread: