Re: [PATCH] NFSD: Guard admin state-revocation walks with NFSD_NET_UP
Jeff Layton <[email protected]>
| Newsgroups | gmane.linux.nfs |
|---|---|
| Message-ID | <[email protected]> |
On Sun, 2026-06-21 at 12:25 -0400, Chuck Lever wrote:
> diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
> index 11bbc7e8210c..29d68abfa5c8 100644
> --- a/fs/nfsd/nfsctl.c
> +++ b/fs/nfsd/nfsctl.c
> @@ -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);
Can nn->nfsd_serv be non-NULL while the NFSv4 state tables are still
NULL? Looking at nfsd_create_serv() in nfssvc.c, it sets nn->nfsd_serv
when a listener is added via portlist or netlink, and that path does not
run nfsd_startup_net().
nfsd_startup_net() is what calls nfs4_state_start_net() which allocates
nn->conf_id_hashtbl in nfs4_state_create_net(). Until threads are started,
nn->nfsd_net_up stays false and the hashtables stay NULL.
In that startup window, write_unlock_fs() would pass the nn->nfsd_serv
check and then call nfsd4_cancel_copy_by_sb():
fs/nfsd/nfs4proc.c:nfsd4_cancel_copy_by_sb() {
...
spin_lock(&nn->client_lock);
for (idhashval = 0; idhashval < CLIENT_HASH_SIZE; idhashval++) {
struct list_head *head = &nn->conf_id_hashtbl[idhashval];
...
Would this dereference a NULL conf_id_hashtbl and trigger the null-ptr-deref
reported in the thread? The KASAN trace shows RIP in nfsd4_cancel_copy_by_sb
at offset 0x184 with RAX 0, which matches the head pointer load.
The same pattern applies to nfsd4_revoke_states() which walks the same
table, and to nfsd_nl_unlock_filesystem_doit() in the netlink path.
Would checking nn->nfsd_net_up instead of nn->nfsd_serv be more accurate
here, since nfsd_net_up is set at the tail of nfsd_startup_net() exactly
when the state tables become valid?
--
Jeff Layton <[email protected]>