Original report of the bug: https://syzkaller.appspot.com/bug?id=abc732dae53fe376a33611bcfd6bfa83f7e8cb09
We found a UAF write primitive in kernel context.
Fuzzer tested kernel version: 5ee96fa9
A fw_priv was somehow freed by another thread but the global list pending_fw_head is still having it. Then a UAF read happens inside function list_add.
static int fw_load_sysfs_fallback(struct fw_sysfs *fw_sysfs, long timeout)
{
...
mutex_lock(&fw_lock);
list_add(&fw_priv->pending_list, &pending_fw_head); // The original UAF read happened inside, fw_priv was somehow freed by another thread but it hasn't been removed from the global list pending_fw_head. Kasan caught the UAF read inside and report as "KASAN: use-after-free Read in fw_load_sysfs_fallback"
mutex_unlock(&fw_lock);
...
}
static inline void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next); // "head->next" points to the UAF memory
}
The UAF object next enters __list_add_valid and dereference a data pointer prev, Kasan caught this read operation and reported it.
static inline void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next)
{
if (!__list_add_valid(new, prev, next)) // "next" enters "__list_add_valid"
return;
next->prev = new; // Assign "new" to the UAF memory, this is a UAF write
new->next = next;
new->prev = prev;
WRITE_ONCE(prev->next, new);
}
bool __list_add_valid(struct list_head *new, struct list_head *prev,
struct list_head *next)
{
if (CHECK_DATA_CORRUPTION(next->prev != prev, // "next" dereferenced a data pointer "prev" and triggered the UAF read
"list_add corruption. next->prev should be prev (%px), but was %px. (next=%px).\n",
prev, next->prev, next) ||
...
}
|__list_add_valid lib/list_debug.c:23(Triggered the UAF read bug)
|firmware_fallback_sysfs ./include/linux/list.h:86
|firmware_fallback_sysfs ./include/linux/list.h:70(Triggered a new impact: UAF write)
0xffffffff82d51dbe
__list_add_valid lib/list_debug.c:23(Triggered the UAF read bug)
--------------------------------------
0xffffffff82d51dc8
__list_add_valid lib/list_debug.c:26
--------------------------------------
0xffffffff82d51dd0
__list_add_valid lib/list_debug.c:26
--------------------------------------
0xffffffff82d51dd9
__list_add_valid lib/list_debug.c:29
--------------------------------------
0xffffffff82d51dde
__list_add_valid lib/list_debug.c:29
--------------------------------------
0xffffffff82d51de3
__list_add_valid lib/list_debug.c:29
--------------------------------------
0xffffffff832def51
firmware_fallback_sysfs ./include/linux/list.h:86
--------------------------------------
0xffffffff832def5d
firmware_fallback_sysfs ./include/linux/list.h:86
--------------------------------------
0xffffffff832def65
firmware_fallback_sysfs ./include/linux/list.h:70
--------------------------------------
0xffffffff832def6a
firmware_fallback_sysfs ./include/linux/list.h:70
--------------------------------------
0xffffffff832def77
firmware_fallback_sysfs ./include/linux/list.h:70(Triggered a new impact: UAF write)
--------------------------------------
Total 17 basic block