From 4df493a260d4c1844437b28009013d5dc408d0df Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 9 Apr 2019 12:13:37 -0400 Subject: SUNRPC: Cache the process user cred in the RPC server listener In order to be able to interpret uids and gids correctly in knfsd, we should cache the user namespace of the process that created the RPC server's listener. To do so, we refcount the credential of that process. Signed-off-by: Trond Myklebust Signed-off-by: J. Bruce Fields --- fs/lockd/svc.c | 3 ++- fs/nfs/callback.c | 7 +++++-- fs/nfsd/nfsctl.c | 16 ++++++++-------- fs/nfsd/nfsd.h | 2 +- fs/nfsd/nfssvc.c | 14 +++++++------- 5 files changed, 23 insertions(+), 19 deletions(-) (limited to 'fs') diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index 96bb74c919f9..82aa0f35e43d 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -190,12 +190,13 @@ static int create_lockd_listener(struct svc_serv *serv, const char *name, struct net *net, const int family, const unsigned short port) { + const struct cred *cred = current_cred(); struct svc_xprt *xprt; xprt = svc_find_xprt(serv, name, net, family, 0); if (xprt == NULL) return svc_create_xprt(serv, name, net, family, port, - SVC_SOCK_DEFAULTS); + SVC_SOCK_DEFAULTS, cred); svc_xprt_put(xprt); return 0; } diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index 15c9575e0e7a..7817ad94a6ba 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c @@ -41,11 +41,13 @@ static struct svc_program nfs4_callback_program; static int nfs4_callback_up_net(struct svc_serv *serv, struct net *net) { + const struct cred *cred = current_cred(); int ret; struct nfs_net *nn = net_generic(net, nfs_net_id); ret = svc_create_xprt(serv, "tcp", net, PF_INET, - nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); + nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS, + cred); if (ret <= 0) goto out_err; nn->nfs_callback_tcpport = ret; @@ -53,7 +55,8 @@ static int nfs4_callback_up_net(struct svc_serv *serv, struct net *net) nn->nfs_callback_tcpport, PF_INET, net->ns.inum); ret = svc_create_xprt(serv, "tcp", net, PF_INET6, - nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); + nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS, + cred); if (ret > 0) { nn->nfs_callback_tcpport6 = ret; dprintk("NFS: Callback listener port = %u (af %u, net %x)\n", diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 630d629090be..90972e1fd785 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -439,7 +439,7 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size) return rv; if (newthreads < 0) return -EINVAL; - rv = nfsd_svc(newthreads, net); + rv = nfsd_svc(newthreads, net, file->f_cred); if (rv < 0) return rv; } else @@ -717,7 +717,7 @@ static ssize_t __write_ports_names(char *buf, struct net *net) * a socket of a supported family/protocol, and we use it as an * nfsd listener. */ -static ssize_t __write_ports_addfd(char *buf, struct net *net) +static ssize_t __write_ports_addfd(char *buf, struct net *net, const struct cred *cred) { char *mesg = buf; int fd, err; @@ -736,7 +736,7 @@ static ssize_t __write_ports_addfd(char *buf, struct net *net) if (err != 0) return err; - err = svc_addsock(nn->nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT); + err = svc_addsock(nn->nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT, cred); if (err < 0) { nfsd_destroy(net); return err; @@ -751,7 +751,7 @@ static ssize_t __write_ports_addfd(char *buf, struct net *net) * A transport listener is added by writing it's transport name and * a port number. */ -static ssize_t __write_ports_addxprt(char *buf, struct net *net) +static ssize_t __write_ports_addxprt(char *buf, struct net *net, const struct cred *cred) { char transport[16]; struct svc_xprt *xprt; @@ -769,12 +769,12 @@ static ssize_t __write_ports_addxprt(char *buf, struct net *net) return err; err = svc_create_xprt(nn->nfsd_serv, transport, net, - PF_INET, port, SVC_SOCK_ANONYMOUS); + PF_INET, port, SVC_SOCK_ANONYMOUS, cred); if (err < 0) goto out_err; err = svc_create_xprt(nn->nfsd_serv, transport, net, - PF_INET6, port, SVC_SOCK_ANONYMOUS); + PF_INET6, port, SVC_SOCK_ANONYMOUS, cred); if (err < 0 && err != -EAFNOSUPPORT) goto out_close; @@ -799,10 +799,10 @@ static ssize_t __write_ports(struct file *file, char *buf, size_t size, return __write_ports_names(buf, net); if (isdigit(buf[0])) - return __write_ports_addfd(buf, net); + return __write_ports_addfd(buf, net, file->f_cred); if (isalpha(buf[0])) - return __write_ports_addxprt(buf, net); + return __write_ports_addxprt(buf, net, file->f_cred); return -EINVAL; } diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h index 6bae2554b2b2..d200c8680259 100644 --- a/fs/nfsd/nfsd.h +++ b/fs/nfsd/nfsd.h @@ -73,7 +73,7 @@ extern const struct seq_operations nfs_exports_op; /* * Function prototypes. */ -int nfsd_svc(int nrservs, struct net *net); +int nfsd_svc(int nrservs, struct net *net, const struct cred *cred); int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp); int nfsd_nrthreads(struct net *); diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 520757774614..32e4d8a334e3 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -283,7 +283,7 @@ int nfsd_nrthreads(struct net *net) return rv; } -static int nfsd_init_socks(struct net *net) +static int nfsd_init_socks(struct net *net, const struct cred *cred) { int error; struct nfsd_net *nn = net_generic(net, nfsd_net_id); @@ -292,12 +292,12 @@ static int nfsd_init_socks(struct net *net) return 0; error = svc_create_xprt(nn->nfsd_serv, "udp", net, PF_INET, NFS_PORT, - SVC_SOCK_DEFAULTS); + SVC_SOCK_DEFAULTS, cred); if (error < 0) return error; error = svc_create_xprt(nn->nfsd_serv, "tcp", net, PF_INET, NFS_PORT, - SVC_SOCK_DEFAULTS); + SVC_SOCK_DEFAULTS, cred); if (error < 0) return error; @@ -348,7 +348,7 @@ static bool nfsd_needs_lockd(struct nfsd_net *nn) return nfsd_vers(nn, 2, NFSD_TEST) || nfsd_vers(nn, 3, NFSD_TEST); } -static int nfsd_startup_net(int nrservs, struct net *net) +static int nfsd_startup_net(int nrservs, struct net *net, const struct cred *cred) { struct nfsd_net *nn = net_generic(net, nfsd_net_id); int ret; @@ -359,7 +359,7 @@ static int nfsd_startup_net(int nrservs, struct net *net) ret = nfsd_startup_generic(nrservs); if (ret) return ret; - ret = nfsd_init_socks(net); + ret = nfsd_init_socks(net, cred); if (ret) goto out_socks; @@ -697,7 +697,7 @@ int nfsd_set_nrthreads(int n, int *nthreads, struct net *net) * this is the first time nrservs is nonzero. */ int -nfsd_svc(int nrservs, struct net *net) +nfsd_svc(int nrservs, struct net *net, const struct cred *cred) { int error; bool nfsd_up_before; @@ -719,7 +719,7 @@ nfsd_svc(int nrservs, struct net *net) nfsd_up_before = nn->nfsd_net_up; - error = nfsd_startup_net(nrservs, net); + error = nfsd_startup_net(nrservs, net, cred); if (error) goto out_destroy; error = nn->nfsd_serv->sv_ops->svo_setup(nn->nfsd_serv, -- cgit v1.2.3-59-g8ed1b