From: Bryam Vargas <[email protected]>

For a v1.2+ index, __nd_label_validate() computes the label size as
1 << (7 + nsindex[i]->labelsize), where labelsize is a u8 read from
the label storage medium.  A value of 25 or more makes the shift count
reach or exceed the width of int -- undefined behavior -- and 24 already
shifts into the sign bit.  Only 0 (128-byte) and 1 (256-byte) are valid.

Reject a labelsize above 1 before the shift.  The result was rejected by
the following size comparison anyway, so this only removes the undefined
shift on a crafted or corrupted medium; conforming labels are unaffected.

Fixes: 564e871aa66f ("libnvdimm, label: add v1.2 nvdimm label definitions")
Signed-off-by: Bryam Vargas <[email protected]>
---
 drivers/nvdimm/label.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c
index ec12ce72cfe2..dea2eee86d13 100644
--- a/drivers/nvdimm/label.c
+++ b/drivers/nvdimm/label.c
@@ -145,10 +145,21 @@ static int __nd_label_validate(struct nvdimm_drvdata *ndd)
                /* label sizes larger than 128 arrived with v1.2 */
                version = __le16_to_cpu(nsindex[i]->major) * 100
                        + __le16_to_cpu(nsindex[i]->minor);
-               if (version >= 102)
+               if (version >= 102) {
+                       /*
+                        * labelsize feeds the shift below; only 0 (128-byte)
+                        * and 1 (256-byte) are valid -- a larger value would
+                        * overflow or exceed the width of int.
+                        */
+                       if (nsindex[i]->labelsize > 1) {
+                               dev_dbg(dev, "nsindex%d labelsize: %d 
invalid\n",
+                                       i, nsindex[i]->labelsize);
+                               continue;
+                       }
                        labelsize = 1 << (7 + nsindex[i]->labelsize);
-               else
+               } else {
                        labelsize = 128;
+               }
 
                if (labelsize != sizeof_namespace_label(ndd)) {
                        dev_dbg(dev, "nsindex%d labelsize %d invalid\n",

-- 
2.43.0



Reply via email to