mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 08:15:07 -04:00
cuse: wait for pending RCU callbacks on module exit
Since commit053fc4f755("fuse: fix UAF in rcu pathwalks"), fuse_conn_put() frees the fuse_conn through call_rcu() rather than synchronously. For cuse, fc->release is cuse_fc_release(), which lives in the cuse module. If the module is removed before the RCU grace period ends, the callback jumps into freed module memory: userspace / module unload | RCU softirq ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ close(/dev/cuse) | cuse_channel_release() | fuse_dev_release() | fuse_conn_put(fch->conn) | call_rcu(delayed_release) ------+---> callback queued | rmmod cuse | cuse_exit() | cuse_channel_destroy() | ... | return | | <module text freed> | | rcu_do_batch() | delayed_release() | fc->release() | -> cuse_fc_release() | ^^^ freed text! The freed module text is unmapped by vfree(), so the jump into the stale callback triggers a page-fault Oops. If the virtual address is subsequently reused, the callback could execute unrelated code (undefined behaviour). Fix this by calling rcu_barrier() in cuse_exit() so that any pending fuse_conn release callback completes before the module is removed. Fixes:053fc4f755("fuse: fix UAF in rcu pathwalks") Signed-off-by: Baokun Li <libaokun@linux.alibaba.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
This commit is contained in:
committed by
Miklos Szeredi
parent
a927f1867e
commit
4deb3edead
@@ -654,6 +654,11 @@ static void __exit cuse_exit(void)
|
||||
{
|
||||
misc_deregister(&cuse_miscdev);
|
||||
class_destroy(cuse_class);
|
||||
/*
|
||||
* Wait for pending call_rcu() callbacks that call back into
|
||||
* this module via fc->release (cuse_fc_release).
|
||||
*/
|
||||
rcu_barrier();
|
||||
}
|
||||
|
||||
module_init(cuse_init);
|
||||
|
||||
Reference in New Issue
Block a user