diff options
author | J. Bruce Fields <bfields@redhat.com> | 2016-03-18 16:31:17 +0100 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2016-03-22 19:39:35 +0100 |
commit | 4b15da44e742871206582f6aa2997b009648f02f (patch) | |
tree | e69e230a2db6740a6bc44fd479df3f692429a0c0 /fs/nfsd | |
parent | nfsd: block and scsi layout drivers need to depend on CONFIG_BLOCK (diff) | |
download | linux-4b15da44e742871206582f6aa2997b009648f02f.tar.xz linux-4b15da44e742871206582f6aa2997b009648f02f.zip |
nfsd: better layoutupdate bounds-checking
You could add any multiple of 2^32/PNFS_SCSI_RANGE_SIZE to nr_iomaps and
still pass this check. You'd probably still fail the following kcalloc,
but best to be paranoid since this is from-the-wire data.
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/blocklayoutxdr.c | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/fs/nfsd/blocklayoutxdr.c b/fs/nfsd/blocklayoutxdr.c index ca1883668810..6c3b316f932e 100644 --- a/fs/nfsd/blocklayoutxdr.c +++ b/fs/nfsd/blocklayoutxdr.c @@ -105,18 +105,22 @@ nfsd4_block_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp, u32 block_size) { struct iomap *iomaps; - u32 nr_iomaps, expected, i; + u32 nr_iomaps, i; if (len < sizeof(u32)) { dprintk("%s: extent array too small: %u\n", __func__, len); return -EINVAL; } + len -= sizeof(u32); + if (len % PNFS_BLOCK_EXTENT_SIZE) { + dprintk("%s: extent array invalid: %u\n", __func__, len); + return -EINVAL; + } nr_iomaps = be32_to_cpup(p++); - expected = sizeof(__be32) + nr_iomaps * PNFS_BLOCK_EXTENT_SIZE; - if (len != expected) { + if (nr_iomaps != len / PNFS_BLOCK_EXTENT_SIZE) { dprintk("%s: extent array size mismatch: %u/%u\n", - __func__, len, expected); + __func__, len, nr_iomaps); return -EINVAL; } |