Subject: CVE-2024-44952: driver core: Fix uevent_show() vs driver detach race

From: Greg Kroah-Hartman <[email-masked]>

Description
===========

In the Linux kernel, the following vulnerability has been resolved:

driver core: Fix uevent_show() vs driver detach race

uevent_show() wants to de-reference dev->driver->name. There is no clean
way for a device attribute to de-reference dev->driver unless that
attribute is defined via (struct device_driver).dev_groups. Instead, the
anti-pattern of taking the device_lock() in the attribute handler risks
deadlocks with code paths that remove device attributes while holding
the lock.

This deadlock is typically invisible to lockdep given the device_lock()
is marked lockdep_set_novalidate_class(), but some subsystems allocate a
local lockdep key for @dev->mutex to reveal reports of the form:

 ======================================================
 WARNING: possible circular locking dependency detected
 6.10.0-rc7+ #275 Tainted: G           OE    N
 ------------------------------------------------------
 modprobe/2374 is trying to acquire lock:
 ffff8c2270070de0 (kn->active#6){++++}-{0:0}, at: __kernfs_remove+0xde/0x220

 but task is already holding lock:
 ffff8c22016e88f8 (&cxl_root_key){+.+.}-{3:3}, at: device_release_driver_internal+0x39/0x210

 which lock already depends on the new lock.

 the existing dependency chain (in reverse order) is:

 -> #1 (&cxl_root_key){+.+.}-{3:3}:
        __mutex_lock+0x99/0xc30
        uevent_show+0xac/0x130
        dev_attr_show+0x18/0x40
        sysfs_kf_seq_show+0xac/0xf0
        seq_read_iter+0x110/0x450
        vfs_read+0x25b/0x340
        ksys_read+0x67/0xf0
        do_syscall_64+0x75/0x190
        entry_SYSCALL_64_after_hwframe+0x76/0x7e

 -> #0 (kn->active#6){++++}-{0:0}:
        __lock_acquire+0x121a/0x1fa0
        lock_acquire+0xd6/0x2e0
        kernfs_drain+0x1e9/0x200
        __kernfs_remove+0xde/0x220
        kernfs_remove_by_name_ns+0x5e/0xa0
        device_del+0x168/0x410
        device_unregister+0x13/0x60
        devres_release_all+0xb8/0x110
        device_unbind_cleanup+0xe/0x70
        device_release_driver_internal+0x1c7/0x210
        driver_detach+0x47/0x90
        bus_remove_driver+0x6c/0xf0
        cxl_acpi_exit+0xc/0x11 [cxl_acpi]
        __do_sys_delete_module.isra.0+0x181/0x260
        do_syscall_64+0x75/0x190
        entry_SYSCALL_64_after_hwframe+0x76/0x7e

The observation though is that driver objects are typically much longer
lived than device objects. It is reasonable to perform lockless
de-reference of a @driver pointer even if it is racing detach from a
device. Given the infrequency of driver unregistration, use
synchronize_rcu() in module_remove_driver() to close any potential
races.  It is potentially overkill to suffer synchronize_rcu() just to
handle the rare module removal racing uevent_show() event.

Thanks to Tetsuo Handa for the debug analysis of the syzbot report [1].

The Linux kernel CVE team has assigned CVE-2024-44952 to this issue.

Affected and fixed versions
===========================

	Issue introduced in 4.19.317 with commit bb3641a58317 and fixed in 4.19.320 with commit 49ea4e0d8626
	Issue introduced in 5.4.279 with commit 13d25e82b6d0 and fixed in 5.4.282 with commit dd98c9630b7e
	Issue introduced in 5.10.221 with commit 760603e30bf1 and fixed in 5.10.224 with commit f098e8fc7227
	Issue introduced in 5.15.162 with commit ec772ed7cb21 and fixed in 5.15.165 with commit 9c23fc327d6e
	Issue introduced in 6.1.95 with commit 08891eeaa97c and fixed in 6.1.105 with commit 4a7c2a838752
	Issue introduced in 6.6.35 with commit a42b0060d6ff and fixed in 6.6.46 with commit 4d035c743c3e
	Issue introduced in 6.10 with commit c0a40097f0bc and fixed in 6.10.5 with commit cd490a247ddf
	Issue introduced in 6.10 with commit c0a40097f0bc and fixed in 6.11 with commit 15fffc6a5624
	Issue introduced in 6.9.6 with commit 95d03d369ea6

Please see https://www.kernel.org for a full list of currently supported
kernel versions by the kernel community.

Unaffected versions might change over time as fixes are backported to
older supported kernel versions.  The official CVE entry at
	https://cve.org/CVERecord/?id=CVE-2024-44952
will be updated if fixes are backported, please check that for the most
up to date information about this issue.

Affected files
==============

The file(s) affected by this issue are:
	drivers/base/core.c
	drivers/base/module.c

Mitigation
==========

The Linux kernel CVE team recommends that you update to the latest
stable kernel version for this, and many other bugfixes.  Individual
changes are never tested alone, but rather are part of a larger kernel
release.  Cherry-picking individual commits is not recommended or
supported by the Linux kernel community at all.  If however, updating to
the latest release is impossible, the individual changes to resolve this
issue can be found at these commits:
	https://git.kernel.org/stable/c/49ea4e0d862632d51667da5e7a9c88a560e9c5a1
	https://git.kernel.org/stable/c/dd98c9630b7ee273da87e9a244f94ddf947161e2
	https://git.kernel.org/stable/c/f098e8fc7227166206256c18d56ab622039108b1
	https://git.kernel.org/stable/c/9c23fc327d6ec67629b4ad323bd64d3834c0417d
	https://git.kernel.org/stable/c/4a7c2a8387524942171037e70b80e969c3b5c05b
	https://git.kernel.org/stable/c/4d035c743c3e391728a6f81cbf0f7f9ca700cf62
	https://git.kernel.org/stable/c/cd490a247ddf325325fd0de8898659400c9237ef
	https://git.kernel.org/stable/c/15fffc6a5624b13b428bb1c6e9088e32a55eb82c