Bug 2360236 (CVE-2025-22126)

Summary: CVE-2025-22126 kernel: md: fix mddev uaf while iterating all_mddevs list
Product: [Other] Security Response Reporter: OSIDB Bzimport <bzimport>
Component: vulnerabilityAssignee: Product Security DevOps Team <prodsec-dev>
Status: NEW --- QA Contact:
Severity: medium Docs Contact:
Priority: medium    
Version: unspecifiedCC: dfreiber, drow, jburrell, vkumar
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: ---
Doc Text:
A flaw was discovered in the Linux kernel’s MD (multiple device) subsystem during iteration over the all_mddevs list in functions such as md_notify_reboot() and md_exit(). The code used list_for_each_entry_safe, but released locks before completing reference counting, allowing concurrent deletion and freeing of an mddev entry. This led to a use-after-free when the kernel continued to reference freed mddev structures. A local user with low privileges could trigger this to corrupt memory and cause a denial of service. The issue has been resolved by reworking the iteration logic, introducing proper locking and reference handling (mddev_put_locked()), and switching to list_for_each_entry to avoid unsafe continuation across deletions
Story Points: ---
Clone Of: Environment:
Last Closed: Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description OSIDB Bzimport 2025-04-16 15:03:53 UTC
In the Linux kernel, the following vulnerability has been resolved:

md: fix mddev uaf while iterating all_mddevs list

While iterating all_mddevs list from md_notify_reboot() and md_exit(),
list_for_each_entry_safe is used, and this can race with deletint the
next mddev, causing UAF:

t1:
spin_lock
//list_for_each_entry_safe(mddev, n, ...)
 mddev_get(mddev1)
 // assume mddev2 is the next entry
 spin_unlock
            t2:
            //remove mddev2
            ...
            mddev_free
            spin_lock
            list_del
            spin_unlock
            kfree(mddev2)
 mddev_put(mddev1)
 spin_lock
 //continue dereference mddev2->all_mddevs

The old helper for_each_mddev() actually grab the reference of mddev2
while holding the lock, to prevent from being freed. This problem can be
fixed the same way, however, the code will be complex.

Hence switch to use list_for_each_entry, in this case mddev_put() can free
the mddev1 and it's not safe as well. Refer to md_seq_show(), also factor
out a helper mddev_put_locked() to fix this problem.

Comment 1 Avinash Hanwate 2025-04-17 11:48:22 UTC
Upstream advisory:
https://lore.kernel.org/linux-cve-announce/2025041629-CVE-2025-22126-50e3@gregkh/T

Comment 3 errata-xmlrpc 2025-06-16 08:36:10 UTC
This issue has been addressed in the following products:

  Red Hat Enterprise Linux 9

Via RHSA-2025:9080 https://access.redhat.com/errata/RHSA-2025:9080

Comment 4 errata-xmlrpc 2025-07-08 00:11:33 UTC
This issue has been addressed in the following products:

  Red Hat Enterprise Linux 9.2 Update Services for SAP Solutions

Via RHSA-2025:10536 https://access.redhat.com/errata/RHSA-2025:10536

Comment 5 errata-xmlrpc 2025-07-08 01:06:30 UTC
This issue has been addressed in the following products:

  Red Hat Enterprise Linux 9.2 Update Services for SAP Solutions

Via RHSA-2025:10547 https://access.redhat.com/errata/RHSA-2025:10547

Comment 6 errata-xmlrpc 2025-07-09 12:11:37 UTC
This issue has been addressed in the following products:

  Red Hat Enterprise Linux 9.4 Extended Update Support

Via RHSA-2025:10701 https://access.redhat.com/errata/RHSA-2025:10701