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>
This commit is contained in:
J. Bruce Fields 2016-03-18 11:31:17 -04:00
parent 10c4de10b2
commit 4b15da44e7

View File

@ -105,18 +105,22 @@ nfsd4_block_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp,
u32 block_size) u32 block_size)
{ {
struct iomap *iomaps; struct iomap *iomaps;
u32 nr_iomaps, expected, i; u32 nr_iomaps, i;
if (len < sizeof(u32)) { if (len < sizeof(u32)) {
dprintk("%s: extent array too small: %u\n", __func__, len); dprintk("%s: extent array too small: %u\n", __func__, len);
return -EINVAL; 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++); nr_iomaps = be32_to_cpup(p++);
expected = sizeof(__be32) + nr_iomaps * PNFS_BLOCK_EXTENT_SIZE; if (nr_iomaps != len / PNFS_BLOCK_EXTENT_SIZE) {
if (len != expected) {
dprintk("%s: extent array size mismatch: %u/%u\n", dprintk("%s: extent array size mismatch: %u/%u\n",
__func__, len, expected); __func__, len, nr_iomaps);
return -EINVAL; return -EINVAL;
} }