ad8337e
From a45318b5ff8c505afcbf04a1c5fa7dbe426d9588 Mon Sep 17 00:00:00 2001
ad8337e
From: Jan Kara <jack@suse.cz>
ad8337e
Date: Thu, 4 Sep 2014 14:06:55 +0200
ad8337e
Subject: [PATCH] udf: Avoid infinite loop when processing indirect ICBs
ad8337e
ad8337e
We did not implement any bound on number of indirect ICBs we follow when
ad8337e
loading inode. Thus corrupted medium could cause kernel to go into an
ad8337e
infinite loop, possibly causing a stack overflow.
ad8337e
ad8337e
Fix the possible stack overflow by removing recursion from
ad8337e
__udf_read_inode() and limit number of indirect ICBs we follow to avoid
ad8337e
infinite loops.
ad8337e
ad8337e
Bugzilla: 1141810
ad8337e
Upstream-status: 3.17
ad8337e
ad8337e
Signed-off-by: Jan Kara <jack@suse.cz>
ad8337e
---
ad8337e
 fs/udf/inode.c | 35 +++++++++++++++++++++--------------
ad8337e
 1 file changed, 21 insertions(+), 14 deletions(-)
ad8337e
ad8337e
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
ad8337e
index 236cd48184c2..a932f7740b51 100644
ad8337e
--- a/fs/udf/inode.c
ad8337e
+++ b/fs/udf/inode.c
ad8337e
@@ -1271,13 +1271,22 @@ update_time:
ad8337e
 	return 0;
ad8337e
 }
ad8337e
 
ad8337e
+/*
ad8337e
+ * Maximum length of linked list formed by ICB hierarchy. The chosen number is
ad8337e
+ * arbitrary - just that we hopefully don't limit any real use of rewritten
ad8337e
+ * inode on write-once media but avoid looping for too long on corrupted media.
ad8337e
+ */
ad8337e
+#define UDF_MAX_ICB_NESTING 1024
ad8337e
+
ad8337e
 static void __udf_read_inode(struct inode *inode)
ad8337e
 {
ad8337e
 	struct buffer_head *bh = NULL;
ad8337e
 	struct fileEntry *fe;
ad8337e
 	uint16_t ident;
ad8337e
 	struct udf_inode_info *iinfo = UDF_I(inode);
ad8337e
+	unsigned int indirections = 0;
ad8337e
 
ad8337e
+reread:
ad8337e
 	/*
ad8337e
 	 * Set defaults, but the inode is still incomplete!
ad8337e
 	 * Note: get_new_inode() sets the following on a new inode:
ad8337e
@@ -1314,28 +1323,26 @@ static void __udf_read_inode(struct inode *inode)
ad8337e
 		ibh = udf_read_ptagged(inode->i_sb, &iinfo->i_location, 1,
ad8337e
 					&ident);
ad8337e
 		if (ident == TAG_IDENT_IE && ibh) {
ad8337e
-			struct buffer_head *nbh = NULL;
ad8337e
 			struct kernel_lb_addr loc;
ad8337e
 			struct indirectEntry *ie;
ad8337e
 
ad8337e
 			ie = (struct indirectEntry *)ibh->b_data;
ad8337e
 			loc = lelb_to_cpu(ie->indirectICB.extLocation);
ad8337e
 
ad8337e
-			if (ie->indirectICB.extLength &&
ad8337e
-				(nbh = udf_read_ptagged(inode->i_sb, &loc, 0,
ad8337e
-							&ident))) {
ad8337e
-				if (ident == TAG_IDENT_FE ||
ad8337e
-					ident == TAG_IDENT_EFE) {
ad8337e
-					memcpy(&iinfo->i_location,
ad8337e
-						&loc,
ad8337e
-						sizeof(struct kernel_lb_addr));
ad8337e
-					brelse(bh);
ad8337e
-					brelse(ibh);
ad8337e
-					brelse(nbh);
ad8337e
-					__udf_read_inode(inode);
ad8337e
+			if (ie->indirectICB.extLength) {
ad8337e
+				brelse(bh);
ad8337e
+				brelse(ibh);
ad8337e
+				memcpy(&iinfo->i_location, &loc,
ad8337e
+				       sizeof(struct kernel_lb_addr));
ad8337e
+				if (++indirections > UDF_MAX_ICB_NESTING) {
ad8337e
+					udf_err(inode->i_sb,
ad8337e
+						"too many ICBs in ICB hierarchy"
ad8337e
+						" (max %d supported)\n",
ad8337e
+						UDF_MAX_ICB_NESTING);
ad8337e
+					make_bad_inode(inode);
ad8337e
 					return;
ad8337e
 				}
ad8337e
-				brelse(nbh);
ad8337e
+				goto reread;
ad8337e
 			}
ad8337e
 		}
ad8337e
 		brelse(ibh);
ad8337e
-- 
ad8337e
2.1.0
ad8337e