diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2015-08-25 18:16:13 +0300 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2015-08-25 21:40:10 +0300 |
commit | 540d9864e1c5f8d3ca2ecc919e7d8a47e713ec3f (patch) | |
tree | 5b542b75b920672a01d8b289dbee0d071dc83810 /fs/nfs | |
parent | 82714bd1424a88e4bb43813c8a78fbe8f6c5feab (diff) | |
download | linux-540d9864e1c5f8d3ca2ecc919e7d8a47e713ec3f.tar.xz |
NFSv4.1/pnfs: Add sanity check for the layout range returned by the server
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/pnfs.c | 25 |
1 files changed, 24 insertions, 1 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 3530bb703214..68cc4b169769 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -1561,6 +1561,26 @@ out_unlock: } EXPORT_SYMBOL_GPL(pnfs_update_layout); +static bool +pnfs_sanity_check_layout_range(struct pnfs_layout_range *range) +{ + switch (range->iomode) { + case IOMODE_READ: + case IOMODE_RW: + break; + default: + return false; + } + if (range->offset == NFS4_MAX_UINT64) + return false; + if (range->length == 0) + return false; + if (range->length != NFS4_MAX_UINT64 && + range->length > NFS4_MAX_UINT64 - range->offset) + return false; + return true; +} + struct pnfs_layout_segment * pnfs_layout_process(struct nfs4_layoutget *lgp) { @@ -1569,7 +1589,10 @@ pnfs_layout_process(struct nfs4_layoutget *lgp) struct pnfs_layout_segment *lseg; struct inode *ino = lo->plh_inode; LIST_HEAD(free_me); - int status = 0; + int status = -EINVAL; + + if (!pnfs_sanity_check_layout_range(&res->range)) + goto out; /* Inject layout blob into I/O device driver */ lseg = NFS_SERVER(ino)->pnfs_curr_ld->alloc_lseg(lo, res, lgp->gfp_flags); |