In the Linux kernel, the following vulnerability has been resolved:
md: fix mddev uaf while iterating all_mddevs list
While iterating allmddevs list from mdnotifyreboot() and mdexit(), listforeachentrysafe is used, and this can race with deletint the next mddev, causing UAF:
t1: spinlock //listforeachentrysafe(mddev, n, ...) mddevget(mddev1) // assume mddev2 is the next entry spinunlock t2: //remove mddev2 ... mddevfree spinlock listdel spinunlock kfree(mddev2) mddevput(mddev1) spinlock //continue dereference mddev2->allmddevs
The old helper foreachmddev() 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 listforeachentry, in this case mddevput() can free the mddev1 and it's not safe as well. Refer to mdseqshow(), also factor out a helper mddevputlocked() to fix this problem.