mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 20:54:03 +02:00
NFSD: Prevent post-shutdown use-after-free in unlock_filesystem
Writing a filesystem path to /proc/fs/nfsd/unlock_filesystem runs
nfsd4_cancel_copy_by_sb() before nfsd_mutex is held and before the
handler confirms that nn->nfsd_serv is set. Once nfsd has shut down,
nfs4_state_destroy_net() has freed nn->conf_id_hashtbl but left the
pointer intact, so the cancel helper iterates freed slab memory as an
array of struct list_head and then dereferences a bogus nfs4_client
when it takes clp->async_lock. A local administrator holding
CAP_SYS_ADMIN can reach this use-after-free by stopping the server and
then writing to unlock_filesystem; KASAN reports a slab-use-after-free
read in nfsd4_cancel_copy_by_sb().
nfsd4_revoke_states() walks the same state tables and for that reason
already runs only under nfsd_mutex with nn->nfsd_serv confirmed
present. Move the async COPY cancel into that protected section so
every NFSv4 state-table walker on this path observes a running server.
Async copies exist only while the server runs, so gating the cancel on
nn->nfsd_serv loses nothing.
Reported-by: Musaab Khan <musaab.khan@protonmail.com>
Fixes: 3daab3112f ("nfsd: cancel async COPY operations when admin revokes filesystem state")
Cc: stable@vger.kernel.org
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Link: https://patch.msgid.link/20260613-unlock-filesystem-uaf-v1-1-462b9bec8c84@kernel.org
Signed-off-by: Chuck Lever <cel@kernel.org>
This commit is contained in:
parent
5e4627d351
commit
292d915d3b
|
|
@ -296,14 +296,15 @@ static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size)
|
|||
* 2. Is that directory a mount point, or
|
||||
* 3. Is that directory the root of an exported file system?
|
||||
*/
|
||||
nfsd4_cancel_copy_by_sb(netns(file), path.dentry->d_sb);
|
||||
error = nlmsvc_unlock_all_by_sb(path.dentry->d_sb);
|
||||
mutex_lock(&nfsd_mutex);
|
||||
nn = net_generic(netns(file), nfsd_net_id);
|
||||
if (nn->nfsd_serv)
|
||||
if (nn->nfsd_serv) {
|
||||
nfsd4_cancel_copy_by_sb(netns(file), path.dentry->d_sb);
|
||||
nfsd4_revoke_states(nn, path.dentry->d_sb);
|
||||
else
|
||||
} else {
|
||||
error = -EINVAL;
|
||||
}
|
||||
mutex_unlock(&nfsd_mutex);
|
||||
|
||||
path_put(&path);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user