Commit a746ca66 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'nfsd-6.4-2' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux

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
...@@ -690,16 +690,11 @@ static ssize_t __write_ports_addfd(char *buf, struct net *net, const struct cred ...@@ -690,16 +690,11 @@ static ssize_t __write_ports_addfd(char *buf, struct net *net, const struct cred
if (err != 0 || fd < 0) if (err != 0 || fd < 0)
return -EINVAL; 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); err = nfsd_create_serv(net);
if (err != 0) if (err != 0)
return err; 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 && if (err >= 0 &&
!nn->nfsd_serv->sv_nrthreads && !xchg(&nn->keep_active, 1)) !nn->nfsd_serv->sv_nrthreads && !xchg(&nn->keep_active, 1))
......
...@@ -536,7 +536,15 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, ...@@ -536,7 +536,15 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp,
inode_lock(inode); inode_lock(inode);
for (retries = 1;;) { 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--) if (host_err != -EAGAIN || !retries--)
break; break;
if (!nfsd_wait_for_delegreturn(rqstp, inode)) if (!nfsd_wait_for_delegreturn(rqstp, inode))
......
...@@ -61,10 +61,9 @@ int svc_recv(struct svc_rqst *, long); ...@@ -61,10 +61,9 @@ int svc_recv(struct svc_rqst *, long);
void svc_send(struct svc_rqst *rqstp); void svc_send(struct svc_rqst *rqstp);
void svc_drop(struct svc_rqst *); void svc_drop(struct svc_rqst *);
void svc_sock_update_bufs(struct svc_serv *serv); 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, struct net *net,
int svc_addsock(struct svc_serv *serv, const int fd, const int fd, char *name_return, const size_t len,
char *name_return, const size_t len, const struct cred *cred);
const struct cred *cred);
void svc_init_xprt_sock(void); void svc_init_xprt_sock(void);
void svc_cleanup_xprt_sock(void); void svc_cleanup_xprt_sock(void);
struct svc_xprt *svc_sock_create(struct svc_serv *serv, int prot); struct svc_xprt *svc_sock_create(struct svc_serv *serv, int prot);
......
...@@ -1480,25 +1480,10 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv, ...@@ -1480,25 +1480,10 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
return svsk; 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 * svc_addsock - add a listener socket to an RPC service
* @serv: pointer to RPC service to which to add a new listener * @serv: pointer to RPC service to which to add a new listener
* @net: caller's network namespace
* @fd: file descriptor of the new listener * @fd: file descriptor of the new listener
* @name_return: pointer to buffer to fill in with name of listener * @name_return: pointer to buffer to fill in with name of listener
* @len: size of the buffer * @len: size of the buffer
...@@ -1508,8 +1493,8 @@ EXPORT_SYMBOL_GPL(svc_alien_sock); ...@@ -1508,8 +1493,8 @@ EXPORT_SYMBOL_GPL(svc_alien_sock);
* Name is terminated with '\n'. On error, returns a negative errno * Name is terminated with '\n'. On error, returns a negative errno
* value. * value.
*/ */
int svc_addsock(struct svc_serv *serv, const int fd, char *name_return, int svc_addsock(struct svc_serv *serv, struct net *net, const int fd,
const size_t len, const struct cred *cred) char *name_return, const size_t len, const struct cred *cred)
{ {
int err = 0; int err = 0;
struct socket *so = sockfd_lookup(fd, &err); struct socket *so = sockfd_lookup(fd, &err);
...@@ -1520,6 +1505,9 @@ int svc_addsock(struct svc_serv *serv, const int fd, char *name_return, ...@@ -1520,6 +1505,9 @@ int svc_addsock(struct svc_serv *serv, const int fd, char *name_return,
if (!so) if (!so)
return err; return err;
err = -EINVAL;
if (sock_net(so->sk) != net)
goto out;
err = -EAFNOSUPPORT; err = -EAFNOSUPPORT;
if ((so->sk->sk_family != PF_INET) && (so->sk->sk_family != PF_INET6)) if ((so->sk->sk_family != PF_INET) && (so->sk->sk_family != PF_INET6))
goto out; goto out;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment