On Thu, 10 Sep 2026, Jeff Layton wrote:

> --- a/fs/nfsd/nfsctl.c
> +++ b/fs/nfsd/nfsctl.c
> @@ -2111,15 +2112,25 @@ int nfsd_nl_listener_set_doit(struct sk_buff *skb, 
> struct genl_info *info)
> +     userspace_rpcbind = 
> nla_get_flag(info->attrs[NFSD_A_SERVER_SOCK_USERSPACE_RPCBIND]);
> +
>       mutex_lock(&nfsd_mutex);
>  
> -     err = nfsd_create_serv(net);
> +     nn = net_generic(net, nfsd_net_id);
> +
> +     if (nn->nfsd_serv && nn->nfsd_serv->sv_no_rpcbind != userspace_rpcbind) 
> {
> +             NL_SET_ERR_MSG(info->extack,
> +                            "cannot change rpcbind ownership while a server 
> exists");
> +             mutex_unlock(&nfsd_mutex);
> +             return -EBUSY;
> +     }
> +
> +     err = nfsd_create_serv(net, userspace_rpcbind);

This ownership check lives only in the netlink path, so it is
enforced in one direction. Consider: the serv is created here with
userspace-rpcbind, then an old rpc.nfsd writes a socket fd to
/proc/fs/nfsd/portlist. __write_ports_addfd() calls
nfsd_create_serv(net, false), which returns 0 at the existing
"if (nn->nfsd_serv) return 0;" without looking at the flag.
svc_addsock() then goes through svc_setup_socket() with pmap_register
set, and svc_register() returns 0 early because sv_no_rpcbind is set.
The write succeeds, and the new listener is neither registered by the
kernel nor reported to the userspace owner. The reverse order gets
-EBUSY from the check above.

Moving the mismatch test into nfsd_create_serv(), where every creator
already funnels, would make both paths agree. The extack message would
need a different home, but the errno is the important part.


-- 
Chuck Lever (Come to NFS bake-a-thon! https://nfsv4bat.org)

Reply via email to