Commit a746ca66 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull nfsd fixes from Chuck Lever:

 - Two minor bug fixes

* tag 'nfsd-6.4-2' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux:
  nfsd: fix double fget() bug in __write_ports_addfd()
  nfsd: make a copy of struct iattr before calling notify_change
parents 2b749773 c034203b
Loading
Loading
Loading
Loading
+1 −6
Original line number Diff line number Diff line
@@ -690,16 +690,11 @@ static ssize_t __write_ports_addfd(char *buf, struct net *net, const struct cred
	if (err != 0 || fd < 0)
		return -EINVAL;

	if (svc_alien_sock(net, fd)) {
		printk(KERN_ERR "%s: socket net is different to NFSd's one\n", __func__);
		return -EINVAL;
	}

	err = nfsd_create_serv(net);
	if (err != 0)
		return err;

	err = svc_addsock(nn->nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT, cred);
	err = svc_addsock(nn->nfsd_serv, net, fd, buf, SIMPLE_TRANSACTION_LIMIT, cred);

	if (err >= 0 &&
	    !nn->nfsd_serv->sv_nrthreads && !xchg(&nn->keep_active, 1))
+9 −1
Original line number Diff line number Diff line
@@ -536,7 +536,15 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp,

	inode_lock(inode);
	for (retries = 1;;) {
		host_err = __nfsd_setattr(dentry, iap);
		struct iattr attrs;

		/*
		 * notify_change() can alter its iattr argument, making
		 * @iap unsuitable for submission multiple times. Make a
		 * copy for every loop iteration.
		 */
		attrs = *iap;
		host_err = __nfsd_setattr(dentry, &attrs);
		if (host_err != -EAGAIN || !retries--)
			break;
		if (!nfsd_wait_for_delegreturn(rqstp, inode))
+3 −4
Original line number Diff line number Diff line
@@ -61,9 +61,8 @@ int svc_recv(struct svc_rqst *, long);
void		svc_send(struct svc_rqst *rqstp);
void		svc_drop(struct svc_rqst *);
void		svc_sock_update_bufs(struct svc_serv *serv);
bool		svc_alien_sock(struct net *net, int fd);
int		svc_addsock(struct svc_serv *serv, const int fd,
					char *name_return, const size_t len,
int		svc_addsock(struct svc_serv *serv, struct net *net,
			    const int fd, char *name_return, const size_t len,
			    const struct cred *cred);
void		svc_init_xprt_sock(void);
void		svc_cleanup_xprt_sock(void);
+6 −18
Original line number Diff line number Diff line
@@ -1480,25 +1480,10 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
	return svsk;
}

bool svc_alien_sock(struct net *net, int fd)
{
	int err;
	struct socket *sock = sockfd_lookup(fd, &err);
	bool ret = false;

	if (!sock)
		goto out;
	if (sock_net(sock->sk) != net)
		ret = true;
	sockfd_put(sock);
out:
	return ret;
}
EXPORT_SYMBOL_GPL(svc_alien_sock);

/**
 * svc_addsock - add a listener socket to an RPC service
 * @serv: pointer to RPC service to which to add a new listener
 * @net: caller's network namespace
 * @fd: file descriptor of the new listener
 * @name_return: pointer to buffer to fill in with name of listener
 * @len: size of the buffer
@@ -1508,8 +1493,8 @@ EXPORT_SYMBOL_GPL(svc_alien_sock);
 * Name is terminated with '\n'.  On error, returns a negative errno
 * value.
 */
int svc_addsock(struct svc_serv *serv, const int fd, char *name_return,
		const size_t len, const struct cred *cred)
int svc_addsock(struct svc_serv *serv, struct net *net, const int fd,
		char *name_return, const size_t len, const struct cred *cred)
{
	int err = 0;
	struct socket *so = sockfd_lookup(fd, &err);
@@ -1520,6 +1505,9 @@ int svc_addsock(struct svc_serv *serv, const int fd, char *name_return,

	if (!so)
		return err;
	err = -EINVAL;
	if (sock_net(so->sk) != net)
		goto out;
	err = -EAFNOSUPPORT;
	if ((so->sk->sk_family != PF_INET) && (so->sk->sk_family != PF_INET6))
		goto out;