An open debugfs file retains its file_operations pointer in the debugfs proxy state. However, force_suspend_fops, force_wakeup_fops, aosp_capable_fops, and force_devcoredump_fops have no .owner set to THIS_MODULE. As a result, full_proxy_open_regular() calls fops_get() which succeeds without taking a reference to the hci_vhci module. When userspace opens any of these debugfs files and later closes the /dev/vhci file descriptor (triggering vhci_release() and debugfs file removal), the open debugfs file descriptor remains valid in userspace. Because the module refcount was not incremented, the hci_vhci module can be unloaded via delete_module (rmmod hci_vhci). When the userspace process subsequently closes the debugfs file descriptor, full_proxy_release() accesses the already unmapped file_operations structure, resulting in a kernel page fault / oops: BUG: unable to handle page fault for address: fffffbfff846f18b #PF: supervisor read access in kernel mode #PF: error_code(0x0000) - not-present page Oops: Oops: 0000 [#1] SMP KASAN NOPTI RIP: 0010:full_proxy_release+0x8e/0x140 Call Trace: __fput+0x39f/0xa60 fput_close_sync+0xff/0x200 __x64_sys_close+0x8c/0xf0 do_syscall_64+0xc3/0x590 entry_SYSCALL_64_after_hwframe+0x76/0x7e Modules linked in: ... [last unloaded: hci_vhci(E)] The issue was discovered via manual code audit of drivers/bluetooth/hci_vhci.c and verified on a Linux 7.3-rc6 test VM with CONFIG_BT_VHCI=m by keeping a debugfs file open across controller teardown and module unload. Set .owner = THIS_MODULE on all four file_operations structures so that debugfs pins the module until all file descriptors are closed. Fixes: 28010791193a ("Bluetooth: vhci: Prevent use-after-free by removing debugfs files early") Cc: stable@vger.kernel.org Signed-off-by: Bui Viet Dung --- drivers/bluetooth/hci_vhci.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c index eddb32b30539..8f7db0102b25 100644 --- a/drivers/bluetooth/hci_vhci.c +++ b/drivers/bluetooth/hci_vhci.c @@ -155,6 +155,7 @@ static ssize_t force_suspend_write(struct file *file, } static const struct file_operations force_suspend_fops = { + .owner = THIS_MODULE, .open = simple_open, .read = force_suspend_read, .write = force_suspend_write, @@ -194,6 +195,7 @@ static ssize_t force_wakeup_write(struct file *file, } static const struct file_operations force_wakeup_fops = { + .owner = THIS_MODULE, .open = simple_open, .read = force_wakeup_read, .write = force_wakeup_write, @@ -263,6 +265,7 @@ static ssize_t aosp_capable_write(struct file *file, } static const struct file_operations aosp_capable_fops = { + .owner = THIS_MODULE, .open = simple_open, .read = aosp_capable_read, .write = aosp_capable_write, @@ -386,6 +389,7 @@ static ssize_t force_devcd_write(struct file *file, const char __user *user_buf, } static const struct file_operations force_devcoredump_fops = { + .owner = THIS_MODULE, .open = simple_open, .write = force_devcd_write, }; -- 2.43.0