
From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> mainline inclusion from mainline-v6.1-rc1 commit 3124d320c22f3f4388d9ac5c8f37eaad0cefd6b1 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/ICYJ1Y CVE: CVE-2022-50374 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=... -------------------------------- syzbot is reporting NULL pointer dereference at hci_uart_tty_close() [1], for rcu_sync_enter() is called without rcu_sync_init() due to hci_uart_tty_open() ignoring percpu_init_rwsem() failure. While we are at it, fix that hci_uart_register_device() ignores percpu_init_rwsem() failure and hci_uart_unregister_device() does not call percpu_free_rwsem(). Link: https://syzkaller.appspot.com/bug?extid=576dfca25381fb6fbc5f [1] Reported-by: syzbot <syzbot+576dfca25381fb6fbc5f@syzkaller.appspotmail.com> Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Fixes: 67d2f8781b9f00d1 ("Bluetooth: hci_ldisc: Allow sleeping while proto locks are held.") Fixes: d73e172816652772 ("Bluetooth: hci_serdev: Init hci_uart proto_lock to avoid oops") Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Conflicts: drivers/bluetooth/hci_serdev.c [Fix the context conflict] Signed-off-by: Luo Gengkun <luogengkun2@huawei.com> --- drivers/bluetooth/hci_ldisc.c | 7 +++++-- drivers/bluetooth/hci_serdev.c | 9 +++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index 73ba2977350a..99b38f70ee26 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -498,6 +498,11 @@ static int hci_uart_tty_open(struct tty_struct *tty) BT_ERR("Can't allocate control structure"); return -ENFILE; } + if (percpu_init_rwsem(&hu->proto_lock)) { + BT_ERR("Can't allocate semaphore structure"); + kfree(hu); + return -ENOMEM; + } tty->disc_data = hu; hu->tty = tty; @@ -510,8 +515,6 @@ static int hci_uart_tty_open(struct tty_struct *tty) INIT_WORK(&hu->init_ready, hci_uart_init_work); INIT_WORK(&hu->write_work, hci_uart_write_work); - percpu_init_rwsem(&hu->proto_lock); - /* Flush any pending characters in the driver */ tty_driver_flush_buffer(tty); diff --git a/drivers/bluetooth/hci_serdev.c b/drivers/bluetooth/hci_serdev.c index 46e20444ba19..a551597eb6b5 100644 --- a/drivers/bluetooth/hci_serdev.c +++ b/drivers/bluetooth/hci_serdev.c @@ -284,9 +284,12 @@ int hci_uart_register_device(struct hci_uart *hu, serdev_device_set_client_ops(hu->serdev, &hci_serdev_client_ops); + if (percpu_init_rwsem(&hu->proto_lock)) + return -ENOMEM; + err = serdev_device_open(hu->serdev); if (err) - return err; + goto err_rwsem; err = p->open(hu); if (err) @@ -310,7 +313,6 @@ int hci_uart_register_device(struct hci_uart *hu, INIT_WORK(&hu->init_ready, hci_uart_init_work); INIT_WORK(&hu->write_work, hci_uart_write_work); - percpu_init_rwsem(&hu->proto_lock); /* Only when vendor specific setup callback is provided, consider * the manufacturer information valid. This avoids filling in the @@ -360,6 +362,8 @@ int hci_uart_register_device(struct hci_uart *hu, p->close(hu); err_open: serdev_device_close(hu->serdev); +err_rwsem: + percpu_free_rwsem(&hu->proto_lock); return err; } EXPORT_SYMBOL_GPL(hci_uart_register_device); @@ -376,5 +380,6 @@ void hci_uart_unregister_device(struct hci_uart *hu) hu->proto->close(hu); serdev_device_close(hu->serdev); + percpu_free_rwsem(&hu->proto_lock); } EXPORT_SYMBOL_GPL(hci_uart_unregister_device); -- 2.34.1