In the Linux kernel, the following vulnerability has been resolved:
cachefiles: fix slab-use-after-free in fscachewithdrawvolume()
We got the following issue in our fault injection stress test:
================================================================== BUG: KASAN: slab-use-after-free in fscachewithdrawvolume+0x2e1/0x370 Read of size 4 at addr ffff88810680be08 by task ondemand-04-dae/5798
CPU: 0 PID: 5798 Comm: ondemand-04-dae Not tainted 6.8.0-dirty #565 Call Trace: kasancheckrange+0xf6/0x1b0 fscachewithdrawvolume+0x2e1/0x370 cachefileswithdrawvolume+0x31/0x50 cachefileswithdrawcache+0x3ad/0x900 cachefilesputunbindpincount+0x1f6/0x250 cachefilesdaemonrelease+0x13b/0x290 _fput+0x204/0xa00 taskworkrun+0x139/0x230
Allocated by task 5820: _kmalloc+0x1df/0x4b0 fscacheallocvolume+0x70/0x600 _fscacheacquirevolume+0x1c/0x610 erofsfscacheregistervolume+0x96/0x1a0 erofsfscacheregisterfs+0x49a/0x690 erofsfcfillsuper+0x6c0/0xcc0 vfsgetsuper+0xa9/0x140 vfsgettree+0x8e/0x300 donew_mount+0x28c/0x580 [...]
Freed by task 5820: kfree+0xf1/0x2c0 fscacheputvolume.part.0+0x5cb/0x9e0 erofsfscacheunregisterfs+0x157/0x1b0 erofskillsb+0xd9/0x1c0 deactivatelockedsuper+0xa3/0x100 vfsgetsuper+0x105/0x140 vfsgettree+0x8e/0x300 donew_mount+0x28c/0x580
Following is the process that triggers the issue:
deactivatelockedsuper cachefilesdaemonrelease erofskillsb erofsfscacheunregisterfs fscacherelinquishvolume _fscacherelinquishvolume fscacheputvolume(fscachevolume, fscachevolumeputrelinquish) zero = _refcountdecandtest(&fscachevolume->ref, &ref); cachefilesputunbindpincount cachefilesdaemonunbind cachefileswithdrawcache cachefileswithdrawvolumes listdelinit(&volume->cachelink) fscachefreevolume(fscachevolume) cache->ops->freevolume cachefilesfreevolume listdelinit(&cachefilesvolume->cachelink); kfree(fscachevolume) cachefileswithdrawvolume fscachewithdrawvolume fscachevolume->naccesses // fscache_volume UAF !!!
The fscachevolume in cache->volumes must not have been freed yet, but its reference count may be 0. So use the new fscachetrygetvolume() helper function try to get its reference count.
If the reference count of fscachevolume is 0, fscacheput_volume() is freeing it, so wait for it to be removed from cache->volumes.
If its reference count is not 0, call cachefileswithdrawvolume() with reference count protection to avoid the above issue.