KASAN: use-after-free Read in hci_send_acl

Original report of the bug: https://syzkaller.appspot.com/bug?id=2e1943a94647f7732dd6fc60368642d6e8dc91b1

Our system SyzScope detects arbitrary address write in this bug.

Fuzzer tested kernel version: ac3a0c84

Upstream patch : Bluetooth: verify AMP hci_chan before amp_destroy

Primitive 1: Arbitrary address write in skb_queue_tail

Bug Impact Analysis:

The vulnerable object was freed in hci_disconn_loglink_complete_evt


static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,

struct sk_buff *skb)

{

...

hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle));

if (!hchan)

goto unlock;

amp_destroy_logical_link(hchan, ev->reason); //hchan was freed inside

unlock:

hci_dev_unlock(hdev);

}

Then the same freed object was used in hci_queue_acl,

void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags)

{

struct hci_dev *hdev = chan->conn->hdev;


BT_DBG("%s chan %p flags 0x%4.4x", hdev->name, chan, flags);


hci_queue_acl(chan, &chan->data_q, skb, flags); //chan is the freed object, so chan->data_q can take any arbitrary value


queue_work(hdev->workqueue, &hdev->tx_work);

}

In hci_queue_acl, the second argument was passed to skb_queue_tail->__skb_queue_tail->__skb_queue_before->__skb_insert

static void hci_queue_acl(struct hci_chan *chan, struct sk_buff_head *queue, struct sk_buff *skb, __u16 flags)

{

...

list = skb_shinfo(skb)->frag_list;

if (!list) {

/* Non fragmented */

BT_DBG("%s nonfrag skb %p len %d", hdev->name, skb, skb->len);


skb_queue_tail(queue, skb); //queue came from the freed object

...

}


static inline void __skb_queue_tail(struct sk_buff_head *list,

struct sk_buff *newsk)

{

__skb_queue_before(list, (struct sk_buff *)list, newsk); //list came from the freed object

}


static inline void __skb_queue_before(struct sk_buff_head *list,

struct sk_buff *next,

struct sk_buff *newsk)

{

__skb_insert(newsk, next->prev, next, list); //next and list came from the freed object

}


static inline void __skb_insert(struct sk_buff *newsk,

struct sk_buff *prev, struct sk_buff *next,

struct sk_buff_head *list)

{

WRITE_ONCE(newsk->next, next);

WRITE_ONCE(newsk->prev, prev);

WRITE_ONCE(next->prev, newsk); //next->prev can point to arbitrary memory address

WRITE_ONCE(prev->next, newsk); //prev->next can point to arbitrary memory address

list->qlen++;

}

In __skb_insert, both next and prev came from freed object, therefore next->prev and prev->next can point to an arbitrary memory address. These are arbitrary address writes.


Trace in high level:

|__asan_load8 mm/kasan/generic.c:186

|hci_send_acl net/bluetooth/hci_core.c:3991 (Triggered the original UAF read)

|skb_queue_tail net/bluetooth/hci_core.c:3956

|skb_queue_tail ./include/linux/skbuff.h:1895 (Triggered a new impact: Arbitrary address write)


Trace in detail:

0xffffffff84e1ee57

hci_send_acl net/bluetooth/hci_core.c:3991 (Triggered the original UAF read)

--------------------------------------

0xffffffff84e1ee6b

hci_send_acl net/bluetooth/hci_core.c:3991

--------------------------------------

0xffffffff84e1ee86

hci_send_acl ./include/linux/skbuff.h:2097

--------------------------------------

0xffffffff84e1ee95

hci_send_acl ./include/linux/skbuff.h:2097

--------------------------------------

0xffffffff84e1eeb2

hci_send_acl net/bluetooth/hci_core.c:3937

--------------------------------------

0xffffffff84e1eec4

hci_send_acl net/bluetooth/hci_core.c:3939

--------------------------------------

0xffffffff84e1eedb

hci_send_acl net/bluetooth/hci_core.c:3939

--------------------------------------

0xffffffff84e1eee0

hci_send_acl net/bluetooth/hci_core.c:3939

--------------------------------------

0xffffffff84e1f22b

hci_send_acl net/bluetooth/hci_core.c:3944

--------------------------------------

0xffffffff84e1f230

hci_send_acl net/bluetooth/hci_core.c:3944

--------------------------------------

0xffffffff84e1f239

hci_send_acl net/bluetooth/hci_core.c:3944

--------------------------------------

0xffffffff84e1ef60

hci_send_acl net/bluetooth/hci_core.c:3920

--------------------------------------

0xffffffff84508b10

skb_push net/core/skbuff.c:1881

--------------------------------------

0xffffffff84508b25

skb_push net/core/skbuff.c:1881

--------------------------------------

0xffffffff84508b32

skb_push net/core/skbuff.c:1881

--------------------------------------

0xffffffff84508b52

skb_push net/core/skbuff.c:1882

--------------------------------------

0xffffffff84508b64

skb_push net/core/skbuff.c:1883

--------------------------------------

0xffffffff84508b72

skb_push net/core/skbuff.c:1885

--------------------------------------

0xffffffff84508b77

skb_push net/core/skbuff.c:1885

--------------------------------------

0xffffffff84e1ef71

hci_send_acl ./include/linux/skbuff.h:2490

--------------------------------------

0xffffffff84e1ef7e

hci_send_acl ./include/linux/skbuff.h:2490

--------------------------------------

0xffffffff84e1ef9e

hci_send_acl ./include/linux/skbuff.h:2490

--------------------------------------

0xffffffff84e1efbe

hci_send_acl ./include/linux/skbuff.h:2490

--------------------------------------

0xffffffff84e1efeb

hci_send_acl net/bluetooth/hci_core.c:3923

--------------------------------------

0xffffffff84e1f011

hci_send_acl net/bluetooth/hci_core.c:3924

--------------------------------------

0xffffffff84e1f01f

hci_send_acl net/bluetooth/hci_core.c:3924

--------------------------------------

0xffffffff84e1f030

hci_send_acl ./include/linux/skbuff.h:1391

--------------------------------------

0xffffffff84e1f045

hci_send_acl ./include/linux/skbuff.h:1391

--------------------------------------

0xffffffff84e1f059

hci_send_acl ./include/linux/skbuff.h:1391

--------------------------------------

0xffffffff84e1f243

hci_send_acl net/bluetooth/hci_core.c:3956

--------------------------------------

0xffffffff84e1f248

hci_send_acl net/bluetooth/hci_core.c:3956

--------------------------------------

0xffffffff845080d0

skb_queue_tail ./include/linux/spinlock.h:328

--------------------------------------

0xffffffff845080e8

skb_queue_tail ./include/linux/spinlock.h:328

--------------------------------------

0xffffffff85675490

_raw_spin_lock_irqsave ./arch/x86/include/asm/paravirt.h:787

--------------------------------------

0xffffffff856754a7

_raw_spin_lock_irqsave ./arch/x86/include/asm/paravirt.h:787

--------------------------------------

0xffffffff856754b1

_raw_spin_lock_irqsave ./arch/x86/include/asm/paravirt.h:765

--------------------------------------

0xffffffff811afa40

native_save_fl arch/x86/kernel/irqflags.S:11

--------------------------------------

0xffffffff856754b8

_raw_spin_lock_irqsave ./arch/x86/include/asm/paravirt.h:765

--------------------------------------

0xffffffff856754c7

_raw_spin_lock_irqsave ./arch/x86/include/asm/paravirt.h:788

--------------------------------------

0xffffffff856754d1

_raw_spin_lock_irqsave ./arch/x86/include/asm/paravirt.h:775

--------------------------------------

0xffffffff8120b8d0

native_irq_disable ./arch/x86/include/asm/irqflags.h:49

--------------------------------------

0xffffffff8120b8d1

native_irq_disable ./arch/x86/include/asm/irqflags.h:49

--------------------------------------

0xffffffff856754d8

_raw_spin_lock_irqsave ./include/linux/spinlock_api_smp.h:108

--------------------------------------

0xffffffff81533930

trace_hardirqs_off kernel/trace/trace_preemptirq.c:76

--------------------------------------

0xffffffff81533942

trace_hardirqs_off kernel/trace/trace_preemptirq.c:76

--------------------------------------

0xffffffff85656b30

lockdep_hardirqs_off ./arch/x86/include/asm/current.h:15

--------------------------------------

0xffffffff85656b93

lockdep_hardirqs_off kernel/locking/lockdep.c:3757

--------------------------------------

0xffffffff8153394b

trace_hardirqs_off kernel/trace/trace_preemptirq.c:78

--------------------------------------

0xffffffff8153395b

trace_hardirqs_off kernel/trace/trace_preemptirq.c:78

--------------------------------------

0xffffffff8153395f

trace_hardirqs_off kernel/trace/trace_preemptirq.c:79

--------------------------------------

0xffffffff81533964

trace_hardirqs_off kernel/trace/trace_preemptirq.c:79

--------------------------------------

0xffffffff81533985

trace_hardirqs_off ./arch/x86/include/asm/preempt.h:26

--------------------------------------

0xffffffff81533999

trace_hardirqs_off kernel/trace/trace_preemptirq.c:82

--------------------------------------

0xffffffff8153399e

trace_hardirqs_off kernel/trace/trace_preemptirq.c:82

--------------------------------------

0xffffffff815339b4

trace_hardirqs_off ./arch/x86/include/asm/jump_label.h:34

--------------------------------------

0xffffffff81533989

trace_hardirqs_off ./arch/x86/include/asm/preempt.h:26

--------------------------------------

0xffffffff8153398e

trace_hardirqs_off ./arch/x86/include/asm/preempt.h:26

--------------------------------------

0xffffffff856754dd

_raw_spin_lock_irqsave ./include/linux/spinlock_api_smp.h:109

--------------------------------------

0xffffffff81382eb0

preempt_count_add kernel/sched/core.c:3870

--------------------------------------

0xffffffff81382ec5

preempt_count_add ./arch/x86/include/asm/preempt.h:79

--------------------------------------

0xffffffff81382ed6

preempt_count_add ./arch/x86/include/asm/preempt.h:26

--------------------------------------

0xffffffff81382ee7

preempt_count_add ./arch/x86/include/asm/preempt.h:26

--------------------------------------

0xffffffff81382efc

preempt_count_add ./include/linux/ftrace.h:816

--------------------------------------

0xffffffff813e4c20

in_lock_functions kernel/locking/spinlock.c:396

--------------------------------------

0xffffffff813e4c2b

in_lock_functions kernel/locking/spinlock.c:396

--------------------------------------

0xffffffff81382f08

preempt_count_add ./include/linux/ftrace.h:818

--------------------------------------

0xffffffff81382f2f

preempt_count_add ./include/linux/ftrace.h:820

--------------------------------------

0xffffffff813e4c20

in_lock_functions kernel/locking/spinlock.c:396

--------------------------------------

0xffffffff813e4c37

in_lock_functions kernel/locking/spinlock.c:396

--------------------------------------

0xffffffff81382f3f

preempt_count_add ./include/linux/ftrace.h:821

--------------------------------------

0xffffffff81382f0c

preempt_count_add ./arch/x86/include/asm/current.h:15

--------------------------------------

0xffffffff81382f22

preempt_count_add ./arch/x86/include/asm/current.h:15

--------------------------------------

0xffffffff856754e7

_raw_spin_lock_irqsave ./include/linux/spinlock_api_smp.h:110

--------------------------------------

0xffffffff813dfae0

lock_acquire kernel/locking/lockdep.c:4931

--------------------------------------

0xffffffff85675503

_raw_spin_lock_irqsave ./include/linux/spinlock_api_smp.h:117

--------------------------------------

0xffffffff813e85c0

do_raw_spin_lock kernel/locking/spinlock_debug.c:111

--------------------------------------

0xffffffff813e8630

do_raw_spin_lock kernel/locking/spinlock_debug.c:112

--------------------------------------

0xffffffff813e8640

do_raw_spin_lock kernel/locking/spinlock_debug.c:84

--------------------------------------

0xffffffff813e864d

do_raw_spin_lock kernel/locking/spinlock_debug.c:84

--------------------------------------

0xffffffff813e8664

do_raw_spin_lock kernel/locking/spinlock_debug.c:85

--------------------------------------

0xffffffff813e8671

do_raw_spin_lock kernel/locking/spinlock_debug.c:85

--------------------------------------

0xffffffff813e8685

do_raw_spin_lock ./include/asm-generic/qspinlock.h:76

--------------------------------------

0xffffffff813e869a

do_raw_spin_lock ./include/linux/instrumented.h:71

--------------------------------------

0xffffffff813e86a8

do_raw_spin_lock ./arch/x86/include/asm/atomic.h:204

--------------------------------------

0xffffffff813e86bd

do_raw_spin_lock kernel/locking/spinlock_debug.c:115

--------------------------------------

0xffffffff813e86cd

do_raw_spin_lock kernel/locking/spinlock_debug.c:91

--------------------------------------

0xffffffff813e86da

do_raw_spin_lock ./arch/x86/include/asm/current.h:15

--------------------------------------

0xffffffff813e870d

do_raw_spin_lock kernel/locking/spinlock_debug.c:92

--------------------------------------

0xffffffff8567550b

_raw_spin_lock_irqsave ./include/linux/spinlock_api_smp.h:121

--------------------------------------

0xffffffff845080f4

skb_queue_tail ./include/linux/spinlock.h:328

--------------------------------------

0xffffffff84508100

skb_queue_tail ./include/linux/skbuff.h:2034

--------------------------------------

0xffffffff8450810c

skb_queue_tail ./include/linux/skbuff.h:1892

--------------------------------------

0xffffffff8450811a

skb_queue_tail ./include/linux/skbuff.h:1893

--------------------------------------

0xffffffff8450812b

skb_queue_tail ./include/linux/skbuff.h:1895(Triggered a new bug: Arbitrary address write)

--------------------------------------

Total 142 basic block