Skip to content

Commit

Permalink
Merge tag 'nfsd-4.21' of git://linux-nfs.org/~bfields/linux
Browse files Browse the repository at this point in the history
Pull nfsd updates from Bruce Fields:
 "Thanks to Vasily Averin for fixing a use-after-free in the
  containerized NFSv4.2 client, and cleaning up some convoluted
  backchannel server code in the process.

  Otherwise, miscellaneous smaller bugfixes and cleanup"

* tag 'nfsd-4.21' of git://linux-nfs.org/~bfields/linux: (25 commits)
  nfs: fixed broken compilation in nfs_callback_up_net()
  nfs: minor typo in nfs4_callback_up_net()
  sunrpc: fix debug message in svc_create_xprt()
  sunrpc: make visible processing error in bc_svc_process()
  sunrpc: remove unused xpo_prep_reply_hdr callback
  sunrpc: remove svc_rdma_bc_class
  sunrpc: remove svc_tcp_bc_class
  sunrpc: remove unused bc_up operation from rpc_xprt_ops
  sunrpc: replace svc_serv->sv_bc_xprt by boolean flag
  sunrpc: use-after-free in svc_process_common()
  sunrpc: use SVC_NET() in svcauth_gss_* functions
  nfsd: drop useless LIST_HEAD
  lockd: Show pid of lockd for remote locks
  NFSD remove OP_CACHEME from 4.2 op_flags
  nfsd: Return EPERM, not EACCES, in some SETATTR cases
  sunrpc: fix cache_head leak due to queued request
  nfsd: clean up indentation, increase indentation in switch statement
  svcrdma: Optimize the logic that selects the R_key to invalidate
  nfsd: fix a warning in __cld_pipe_upcall()
  nfsd4: fix crash on writing v4_end_grace before nfsd startup
  ...
  • Loading branch information
torvalds committed Jan 3, 2019
2 parents 85f7845 + 0ad30ff commit e45428a
Show file tree
Hide file tree
Showing 31 changed files with 192 additions and 360 deletions.
22 changes: 6 additions & 16 deletions fs/lockd/clnt4xdr.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,24 +128,14 @@ static void encode_netobj(struct xdr_stream *xdr,
static int decode_netobj(struct xdr_stream *xdr,
struct xdr_netobj *obj)
{
u32 length;
__be32 *p;
ssize_t ret;

p = xdr_inline_decode(xdr, 4);
if (unlikely(p == NULL))
goto out_overflow;
length = be32_to_cpup(p++);
if (unlikely(length > XDR_MAX_NETOBJ))
goto out_size;
obj->len = length;
obj->data = (u8 *)p;
ret = xdr_stream_decode_opaque_inline(xdr, (void *)&obj->data,
XDR_MAX_NETOBJ);
if (unlikely(ret < 0))
return -EIO;
obj->len = ret;
return 0;
out_size:
dprintk("NFS: returned netobj was too long: %u\n", length);
return -EIO;
out_overflow:
print_overflow_msg(__func__, xdr);
return -EIO;
}

/*
Expand Down
2 changes: 1 addition & 1 deletion fs/lockd/clntproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@ nlmclnt_test(struct nlm_rqst *req, struct file_lock *fl)
fl->fl_start = req->a_res.lock.fl.fl_start;
fl->fl_end = req->a_res.lock.fl.fl_end;
fl->fl_type = req->a_res.lock.fl.fl_type;
fl->fl_pid = 0;
fl->fl_pid = -req->a_res.lock.fl.fl_pid;
break;
default:
status = nlm_stat_to_errno(req->a_res.status);
Expand Down
22 changes: 6 additions & 16 deletions fs/lockd/clntxdr.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,24 +125,14 @@ static void encode_netobj(struct xdr_stream *xdr,
static int decode_netobj(struct xdr_stream *xdr,
struct xdr_netobj *obj)
{
u32 length;
__be32 *p;
ssize_t ret;

p = xdr_inline_decode(xdr, 4);
if (unlikely(p == NULL))
goto out_overflow;
length = be32_to_cpup(p++);
if (unlikely(length > XDR_MAX_NETOBJ))
goto out_size;
obj->len = length;
obj->data = (u8 *)p;
ret = xdr_stream_decode_opaque_inline(xdr, (void *)&obj->data,
XDR_MAX_NETOBJ);
if (unlikely(ret < 0))
return -EIO;
obj->len = ret;
return 0;
out_size:
dprintk("NFS: returned netobj was too long: %u\n", length);
return -EIO;
out_overflow:
print_overflow_msg(__func__, xdr);
return -EIO;
}

/*
Expand Down
4 changes: 2 additions & 2 deletions fs/lockd/xdr.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ nlm_decode_lock(__be32 *p, struct nlm_lock *lock)

locks_init_lock(fl);
fl->fl_owner = current->files;
fl->fl_pid = (pid_t)lock->svid;
fl->fl_pid = current->tgid;
fl->fl_flags = FL_POSIX;
fl->fl_type = F_RDLCK; /* as good as anything else */
start = ntohl(*p++);
Expand Down Expand Up @@ -269,7 +269,7 @@ nlmsvc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p)
memset(lock, 0, sizeof(*lock));
locks_init_lock(&lock->fl);
lock->svid = ~(u32) 0;
lock->fl.fl_pid = (pid_t)lock->svid;
lock->fl.fl_pid = current->tgid;

if (!(p = nlm_decode_cookie(p, &argp->cookie))
|| !(p = xdr_decode_string_inplace(p, &lock->caller,
Expand Down
4 changes: 2 additions & 2 deletions fs/lockd/xdr4.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ nlm4_decode_lock(__be32 *p, struct nlm_lock *lock)

locks_init_lock(fl);
fl->fl_owner = current->files;
fl->fl_pid = (pid_t)lock->svid;
fl->fl_pid = current->tgid;
fl->fl_flags = FL_POSIX;
fl->fl_type = F_RDLCK; /* as good as anything else */
p = xdr_decode_hyper(p, &start);
Expand Down Expand Up @@ -266,7 +266,7 @@ nlm4svc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p)
memset(lock, 0, sizeof(*lock));
locks_init_lock(&lock->fl);
lock->svid = ~(u32) 0;
lock->fl.fl_pid = (pid_t)lock->svid;
lock->fl.fl_pid = current->tgid;

if (!(p = nlm4_decode_cookie(p, &argp->cookie))
|| !(p = xdr_decode_string_inplace(p, &lock->caller,
Expand Down
10 changes: 6 additions & 4 deletions fs/nfs/callback.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ static int nfs4_callback_up_net(struct svc_serv *serv, struct net *net)
nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS);
if (ret > 0) {
nn->nfs_callback_tcpport6 = ret;
dprintk("NFS: Callback listener port = %u (af %u, net %x\n",
dprintk("NFS: Callback listener port = %u (af %u, net %x)\n",
nn->nfs_callback_tcpport6, PF_INET6, net->ns.inum);
} else if (ret != -EAFNOSUPPORT)
goto out_err;
Expand Down Expand Up @@ -206,11 +206,13 @@ static int nfs_callback_up_net(int minorversion, struct svc_serv *serv,
goto err_bind;
}

ret = -EPROTONOSUPPORT;
ret = 0;
if (!IS_ENABLED(CONFIG_NFS_V4_1) || minorversion == 0)
ret = nfs4_callback_up_net(serv, net);
else if (xprt->ops->bc_up)
ret = xprt->ops->bc_up(serv, net);
else if (xprt->ops->bc_setup)
set_bc_enabled(serv);
else
ret = -EPROTONOSUPPORT;

if (ret < 0) {
printk(KERN_ERR "NFS: callback service start failed\n");
Expand Down
1 change: 0 additions & 1 deletion fs/nfsd/nfs4layouts.c
Original file line number Diff line number Diff line change
Expand Up @@ -656,7 +656,6 @@ nfsd4_cb_layout_done(struct nfsd4_callback *cb, struct rpc_task *task)
struct nfsd_net *nn;
ktime_t now, cutoff;
const struct nfsd4_layout_ops *ops;
LIST_HEAD(reaplist);


switch (task->tk_status) {
Expand Down
15 changes: 6 additions & 9 deletions fs/nfsd/nfs4proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -863,8 +863,7 @@ nfsd4_rename(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
struct nfsd4_rename *rename = &u->rename;
__be32 status;

if (opens_in_grace(SVC_NET(rqstp)) &&
!(cstate->save_fh.fh_export->ex_flags & NFSEXP_NOSUBTREECHECK))
if (opens_in_grace(SVC_NET(rqstp)))
return nfserr_grace;
status = nfsd_rename(rqstp, &cstate->save_fh, rename->rn_sname,
rename->rn_snamelen, &cstate->current_fh,
Expand Down Expand Up @@ -1016,8 +1015,6 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,

nvecs = svc_fill_write_vector(rqstp, write->wr_pagelist,
&write->wr_head, write->wr_buflen);
if (!nvecs)
return nfserr_io;
WARN_ON_ONCE(nvecs > ARRAY_SIZE(rqstp->rq_vec));

status = nfsd_vfs_write(rqstp, &cstate->current_fh, filp,
Expand Down Expand Up @@ -1348,7 +1345,7 @@ static __be32
nfsd4_fallocate(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
struct nfsd4_fallocate *fallocate, int flags)
{
__be32 status = nfserr_notsupp;
__be32 status;
struct file *file;

status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
Expand Down Expand Up @@ -2682,25 +2679,25 @@ static const struct nfsd4_operation nfsd4_ops[] = {
/* NFSv4.2 operations */
[OP_ALLOCATE] = {
.op_func = nfsd4_allocate,
.op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
.op_flags = OP_MODIFIES_SOMETHING,
.op_name = "OP_ALLOCATE",
.op_rsize_bop = nfsd4_only_status_rsize,
},
[OP_DEALLOCATE] = {
.op_func = nfsd4_deallocate,
.op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
.op_flags = OP_MODIFIES_SOMETHING,
.op_name = "OP_DEALLOCATE",
.op_rsize_bop = nfsd4_only_status_rsize,
},
[OP_CLONE] = {
.op_func = nfsd4_clone,
.op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
.op_flags = OP_MODIFIES_SOMETHING,
.op_name = "OP_CLONE",
.op_rsize_bop = nfsd4_only_status_rsize,
},
[OP_COPY] = {
.op_func = nfsd4_copy,
.op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
.op_flags = OP_MODIFIES_SOMETHING,
.op_name = "OP_COPY",
.op_rsize_bop = nfsd4_copy_rsize,
},
Expand Down
17 changes: 6 additions & 11 deletions fs/nfsd/nfs4recover.c
Original file line number Diff line number Diff line change
Expand Up @@ -662,7 +662,7 @@ struct cld_net {
struct cld_upcall {
struct list_head cu_list;
struct cld_net *cu_net;
struct task_struct *cu_task;
struct completion cu_done;
struct cld_msg cu_msg;
};

Expand All @@ -671,23 +671,18 @@ __cld_pipe_upcall(struct rpc_pipe *pipe, struct cld_msg *cmsg)
{
int ret;
struct rpc_pipe_msg msg;
struct cld_upcall *cup = container_of(cmsg, struct cld_upcall, cu_msg);

memset(&msg, 0, sizeof(msg));
msg.data = cmsg;
msg.len = sizeof(*cmsg);

/*
* Set task state before we queue the upcall. That prevents
* wake_up_process in the downcall from racing with schedule.
*/
set_current_state(TASK_UNINTERRUPTIBLE);
ret = rpc_queue_upcall(pipe, &msg);
if (ret < 0) {
set_current_state(TASK_RUNNING);
goto out;
}

schedule();
wait_for_completion(&cup->cu_done);

if (msg.errno < 0)
ret = msg.errno;
Expand Down Expand Up @@ -754,7 +749,7 @@ cld_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
if (copy_from_user(&cup->cu_msg, src, mlen) != 0)
return -EFAULT;

wake_up_process(cup->cu_task);
complete(&cup->cu_done);
return mlen;
}

Expand All @@ -769,7 +764,7 @@ cld_pipe_destroy_msg(struct rpc_pipe_msg *msg)
if (msg->errno >= 0)
return;

wake_up_process(cup->cu_task);
complete(&cup->cu_done);
}

static const struct rpc_pipe_ops cld_upcall_ops = {
Expand Down Expand Up @@ -900,7 +895,7 @@ alloc_cld_upcall(struct cld_net *cn)
goto restart_search;
}
}
new->cu_task = current;
init_completion(&new->cu_done);
new->cu_msg.cm_vers = CLD_UPCALL_VERSION;
put_unaligned(cn->cn_xid++, &new->cu_msg.cm_xid);
new->cu_net = cn;
Expand Down
10 changes: 5 additions & 5 deletions fs/nfsd/nfs4state.c
Original file line number Diff line number Diff line change
Expand Up @@ -5112,7 +5112,7 @@ nfs4_find_file(struct nfs4_stid *s, int flags)
}

static __be32
nfs4_check_olstateid(struct svc_fh *fhp, struct nfs4_ol_stateid *ols, int flags)
nfs4_check_olstateid(struct nfs4_ol_stateid *ols, int flags)
{
__be32 status;

Expand Down Expand Up @@ -5195,7 +5195,7 @@ nfs4_preprocess_stateid_op(struct svc_rqst *rqstp,
break;
case NFS4_OPEN_STID:
case NFS4_LOCK_STID:
status = nfs4_check_olstateid(fhp, openlockstateid(s), flags);
status = nfs4_check_olstateid(openlockstateid(s), flags);
break;
default:
status = nfserr_bad_stateid;
Expand Down Expand Up @@ -6230,15 +6230,15 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
case NFS4_READ_LT:
case NFS4_READW_LT:
file_lock->fl_type = F_RDLCK;
break;
break;
case NFS4_WRITE_LT:
case NFS4_WRITEW_LT:
file_lock->fl_type = F_WRLCK;
break;
break;
default:
dprintk("NFSD: nfs4_lockt: bad lock type!\n");
status = nfserr_inval;
goto out;
goto out;
}

lo = find_lockowner_str(cstate->clp, &lockt->lt_owner);
Expand Down
2 changes: 2 additions & 0 deletions fs/nfsd/nfsctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1126,6 +1126,8 @@ static ssize_t write_v4_end_grace(struct file *file, char *buf, size_t size)
case 'Y':
case 'y':
case '1':
if (nn->nfsd_serv)
return -EBUSY;
nfsd4_end_grace(nn);
break;
default:
Expand Down
17 changes: 15 additions & 2 deletions fs/nfsd/vfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -396,10 +396,23 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
bool get_write_count;
bool size_change = (iap->ia_valid & ATTR_SIZE);

if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE))
if (iap->ia_valid & ATTR_SIZE) {
accmode |= NFSD_MAY_WRITE|NFSD_MAY_OWNER_OVERRIDE;
if (iap->ia_valid & ATTR_SIZE)
ftype = S_IFREG;
}

/*
* If utimes(2) and friends are called with times not NULL, we should
* not set NFSD_MAY_WRITE bit. Otherwise fh_verify->nfsd_permission
* will return EACCESS, when the caller's effective UID does not match
* the owner of the file, and the caller is not privileged. In this
* situation, we should return EPERM(notify_change will return this).
*/
if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME)) {
accmode |= NFSD_MAY_OWNER_OVERRIDE;
if (!(iap->ia_valid & (ATTR_ATIME_SET | ATTR_MTIME_SET)))
accmode |= NFSD_MAY_WRITE;
}

/* Callers that do fh_verify should do the fh_want_write: */
get_write_count = !fhp->fh_dentry;
Expand Down
19 changes: 13 additions & 6 deletions include/linux/sunrpc/bc_xprt.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,14 @@ void xprt_free_bc_rqst(struct rpc_rqst *req);
/*
* Determine if a shared backchannel is in use
*/
static inline int svc_is_backchannel(const struct svc_rqst *rqstp)
static inline bool svc_is_backchannel(const struct svc_rqst *rqstp)
{
if (rqstp->rq_server->sv_bc_xprt)
return 1;
return 0;
return rqstp->rq_server->sv_bc_enabled;
}

static inline void set_bc_enabled(struct svc_serv *serv)
{
serv->sv_bc_enabled = true;
}
#else /* CONFIG_SUNRPC_BACKCHANNEL */
static inline int xprt_setup_backchannel(struct rpc_xprt *xprt,
Expand All @@ -60,9 +63,13 @@ static inline int xprt_setup_backchannel(struct rpc_xprt *xprt,
return 0;
}

static inline int svc_is_backchannel(const struct svc_rqst *rqstp)
static inline bool svc_is_backchannel(const struct svc_rqst *rqstp)
{
return false;
}

static inline void set_bc_enabled(struct svc_serv *serv)
{
return 0;
}

static inline void xprt_free_bc_request(struct rpc_rqst *req)
Expand Down
7 changes: 5 additions & 2 deletions include/linux/sunrpc/svc.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ struct svc_serv {
spinlock_t sv_cb_lock; /* protects the svc_cb_list */
wait_queue_head_t sv_cb_waitq; /* sleep here if there are no
* entries in the svc_cb_list */
struct svc_xprt *sv_bc_xprt; /* callback on fore channel */
bool sv_bc_enabled; /* service uses backchannel */
#endif /* CONFIG_SUNRPC_BACKCHANNEL */
};

Expand Down Expand Up @@ -295,9 +295,12 @@ struct svc_rqst {
struct svc_cacherep * rq_cacherep; /* cache info */
struct task_struct *rq_task; /* service thread */
spinlock_t rq_lock; /* per-request lock */
struct net *rq_bc_net; /* pointer to backchannel's
* net namespace
*/
};

#define SVC_NET(svc_rqst) (svc_rqst->rq_xprt->xpt_net)
#define SVC_NET(rqst) (rqst->rq_xprt ? rqst->rq_xprt->xpt_net : rqst->rq_bc_net)

/*
* Rigorous type checking on sockaddr type conversions
Expand Down
Loading

0 comments on commit e45428a

Please sign in to comment.