udf_get_extendedattr() had no boundary checks.
authorStian Skjelstad <stian.skjelstad@gmail.com>
Sun, 22 Aug 2021 09:33:32 +0000 (11:33 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 22 Sep 2021 09:42:59 +0000 (11:42 +0200)
[ Upstream commit 58bc6d1be2f3b0ceecb6027dfa17513ec6aa2abb ]

When parsing the ExtendedAttr data, malicous or corrupt attribute length
could cause kernel hangs and buffer overruns in some special cases.

Link: https://lore.kernel.org/r/20210822093332.25234-1-stian.skjelstad@gmail.com
Signed-off-by: Stian Skjelstad <stian.skjelstad@gmail.com>
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/udf/misc.c

index 71d1c25f360d170286862382cb4cf0e31cf40508..8c7f9ea251e5289b61e54123fc35b891203d25d2 100644 (file)
@@ -175,13 +175,22 @@ struct genericFormat *udf_get_extendedattr(struct inode *inode, uint32_t type,
                else
                        offset = le32_to_cpu(eahd->appAttrLocation);
 
-               while (offset < iinfo->i_lenEAttr) {
+               while (offset + sizeof(*gaf) < iinfo->i_lenEAttr) {
+                       uint32_t attrLength;
+
                        gaf = (struct genericFormat *)&ea[offset];
+                       attrLength = le32_to_cpu(gaf->attrLength);
+
+                       /* Detect undersized elements and buffer overflows */
+                       if ((attrLength < sizeof(*gaf)) ||
+                           (attrLength > (iinfo->i_lenEAttr - offset)))
+                               break;
+
                        if (le32_to_cpu(gaf->attrType) == type &&
                                        gaf->attrSubtype == subtype)
                                return gaf;
                        else
-                               offset += le32_to_cpu(gaf->attrLength);
+                               offset += attrLength;
                }
        }