nfsd: better layoutupdate bounds-checking
authorJ. Bruce Fields <bfields@redhat.com>
Fri, 18 Mar 2016 15:31:17 +0000 (11:31 -0400)
committerJ. Bruce Fields <bfields@redhat.com>
Tue, 22 Mar 2016 18:39:35 +0000 (14:39 -0400)
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>
fs/nfsd/blocklayoutxdr.c

index ca1883668810145b279ad54cce08b94ba639ae4e..6c3b316f932e94d993f34a054f88e0e7355ff8fd 100644 (file)
@@ -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;
        }