Commit 4df493a2 authored by Trond Myklebust's avatar Trond Myklebust Committed by J. Bruce Fields
Browse files

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: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
parent e333f3bb
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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;
}
+5 −2
Original line number Diff line number Diff line
@@ -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",
+8 −8
Original line number Diff line number Diff line
@@ -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;
}
+1 −1
Original line number Diff line number Diff line
@@ -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 *);
+7 −7
Original line number Diff line number Diff line
@@ -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,
Loading