diff options
author | 2015-04-03 17:19:41 -0400 | |
---|---|---|
committer | 2015-04-21 16:16:01 -0400 | |
commit | 6e4891dc289cd191d46ab7ba1dcb29646644f9ca (patch) | |
tree | 9b99fa6fa8fd1ab4dcc571ad4125c7be2fece33a /fs/nfsd/nfs4xdr.c | |
parent | nfsd4: disallow SEEK with special stateids (diff) | |
download | linux-6e4891dc289cd191d46ab7ba1dcb29646644f9ca.tar.gz linux-6e4891dc289cd191d46ab7ba1dcb29646644f9ca.tar.bz2 linux-6e4891dc289cd191d46ab7ba1dcb29646644f9ca.zip |
nfsd4: fix READ permission checking
In the case we already have a struct file (derived from a stateid), we
still need to do permission-checking; otherwise an unauthorized user
could gain access to a file by sniffing or guessing somebody else's
stateid.
Cc: stable@vger.kernel.org
Fixes: dc97618ddda9 "nfsd4: separate splice and readv cases"
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd/nfs4xdr.c')
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index cea6c529434f..a45032ce7b80 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -3422,6 +3422,7 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr, unsigned long maxcount; struct xdr_stream *xdr = &resp->xdr; struct file *file = read->rd_filp; + struct svc_fh *fhp = read->rd_fhp; int starting_len = xdr->buf->len; struct raparms *ra; __be32 *p; @@ -3445,12 +3446,15 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr, maxcount = min_t(unsigned long, maxcount, (xdr->buf->buflen - xdr->buf->len)); maxcount = min_t(unsigned long, maxcount, read->rd_length); - if (!read->rd_filp) { + if (read->rd_filp) + err = nfsd_permission(resp->rqstp, fhp->fh_export, + fhp->fh_dentry, + NFSD_MAY_READ|NFSD_MAY_OWNER_OVERRIDE); + else err = nfsd_get_tmp_read_open(resp->rqstp, read->rd_fhp, &file, &ra); - if (err) - goto err_truncate; - } + if (err) + goto err_truncate; if (file->f_op->splice_read && test_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags)) err = nfsd4_encode_splice_read(resp, read, file, maxcount); |