aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@redhat.com>2016-03-18 11:31:17 -0400
committerJ. Bruce Fields <bfields@redhat.com>2016-03-22 14:39:35 -0400
commit4b15da44e742871206582f6aa2997b009648f02f (patch)
treee69e230a2db6740a6bc44fd479df3f692429a0c0
parent10c4de10b2624ab9d83bd8e708d39a1867302a6a (diff)
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>
-rw-r--r--fs/nfsd/blocklayoutxdr.c12
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,
105 u32 block_size) 105 u32 block_size)
106{ 106{
107 struct iomap *iomaps; 107 struct iomap *iomaps;
108 u32 nr_iomaps, expected, i; 108 u32 nr_iomaps, i;
109 109
110 if (len < sizeof(u32)) { 110 if (len < sizeof(u32)) {
111 dprintk("%s: extent array too small: %u\n", __func__, len); 111 dprintk("%s: extent array too small: %u\n", __func__, len);
112 return -EINVAL; 112 return -EINVAL;
113 } 113 }
114 len -= sizeof(u32);
115 if (len % PNFS_BLOCK_EXTENT_SIZE) {
116 dprintk("%s: extent array invalid: %u\n", __func__, len);
117 return -EINVAL;
118 }
114 119
115 nr_iomaps = be32_to_cpup(p++); 120 nr_iomaps = be32_to_cpup(p++);
116 expected = sizeof(__be32) + nr_iomaps * PNFS_BLOCK_EXTENT_SIZE; 121 if (nr_iomaps != len / PNFS_BLOCK_EXTENT_SIZE) {
117 if (len != expected) {
118 dprintk("%s: extent array size mismatch: %u/%u\n", 122 dprintk("%s: extent array size mismatch: %u/%u\n",
119 __func__, len, expected); 123 __func__, len, nr_iomaps);
120 return -EINVAL; 124 return -EINVAL;
121 } 125 }
122 126