Linux useafterfree via race between modify_ldt() and #br exception Vulnerability / Exploit
/
/
/
Exploits / Vulnerability Discovered : 2019-06-20 |
Type : dos |
Platform : linux
This exploit / vulnerability Linux useafterfree via race between modify_ldt() and #br exception is for educational purposes only and if it is used you will do on your own risk!
[+] Code ...
/*
When a #BR exception is raised because of an MPX bounds violation, Linux parses
the faulting instruction and computes the linear address of its memory operand.
If the userspace instruction is in 32-bit code, this involves looking up the
correct segment descriptor and adding the segment offset to the address.
(Another codepath that computes the linear address of an instruction is UMIP,
but I think that requires processors >= Cannon Lake, and my PC isn't that new.)
get_desc() locks the mm context, computes the pointer to the LDT entry, but then
drops the lock again and returns the pointer. This means that when the caller
actually accesses the pointer, the pointer may have been freed already.
This bug was introduced in
<https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=670f928ba09b>
("x86/insn-eval: Add utility function to get segment descriptor", first in 4.15).
To make this easier to hit, I patched a sleep into my kernel:
[ 3129.003669] The buggy address belongs to the object at ffff8883775da000
which belongs to the cache kmalloc-32 of size 32
[ 3129.003674] The buggy address is located 2 bytes inside of
32-byte region [ffff8883775da000, ffff8883775da020)
[ 3129.003677] The buggy address belongs to the page:
[ 3129.003683] page:ffffea000ddd7680 refcount:1 mapcount:0 mapping:ffff8883d0c00180 index:0xffff8883775dafc1
[ 3129.003686] flags: 0x17fffc000000200(slab)
[ 3129.003692] raw: 017fffc000000200 ffffea000f0692c8 ffffea000d4bb988 ffff8883d0c00180
[ 3129.003696] raw: ffff8883775dafc1 ffff8883775da000 000000010000003f 0000000000000000
[ 3129.003698] page dumped because: kasan: bad access detected
[ 3129.003701] Memory state around the buggy address:
[ 3129.003706] ffff8883775d9f00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[ 3129.003711] ffff8883775d9f80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[ 3129.003715] >ffff8883775da000: fb fb fb fb fc fc fc fc fb fb fb fb fc fc fc fc
[ 3129.003718] ^
[ 3129.003723] ffff8883775da080: fb fb fb fb fc fc fc fc fb fb fb fb fc fc fc fc
[ 3129.003727] ffff8883775da100: fb fb fb fb fc fc fc fc fb fb fb fb fc fc fc fc
[ 3129.003730] ==================================================================
[ 3129.003733] Disabling lock debugging due to kernel taint
===============
I'll send a suggested patch ("[PATCH] x86/insn-eval: Fix use-after-free access to LDT entry") in a minute.
*/
Linux useafterfree via race between modify_ldt() and #br exception