Skip to content

Commit c03aa9f

Browse files
committed
udf: Avoid infinite loop when processing indirect ICBs
We did not implement any bound on number of indirect ICBs we follow when loading inode. Thus corrupted medium could cause kernel to go into an infinite loop, possibly causing a stack overflow. Fix the possible stack overflow by removing recursion from __udf_read_inode() and limit number of indirect ICBs we follow to avoid infinite loops. Signed-off-by: Jan Kara <jack@suse.cz>
1 parent bb7720a commit c03aa9f

File tree

1 file changed

+21
-14
lines changed

1 file changed

+21
-14
lines changed

Diff for: fs/udf/inode.c

+21-14
Original file line numberDiff line numberDiff line change
@@ -1270,6 +1270,13 @@ int udf_setsize(struct inode *inode, loff_t newsize)
12701270
return 0;
12711271
}
12721272

1273+
/*
1274+
* Maximum length of linked list formed by ICB hierarchy. The chosen number is
1275+
* arbitrary - just that we hopefully don't limit any real use of rewritten
1276+
* inode on write-once media but avoid looping for too long on corrupted media.
1277+
*/
1278+
#define UDF_MAX_ICB_NESTING 1024
1279+
12731280
static void __udf_read_inode(struct inode *inode)
12741281
{
12751282
struct buffer_head *bh = NULL;
@@ -1279,7 +1286,9 @@ static void __udf_read_inode(struct inode *inode)
12791286
struct udf_inode_info *iinfo = UDF_I(inode);
12801287
struct udf_sb_info *sbi = UDF_SB(inode->i_sb);
12811288
unsigned int link_count;
1289+
unsigned int indirections = 0;
12821290

1291+
reread:
12831292
/*
12841293
* Set defaults, but the inode is still incomplete!
12851294
* Note: get_new_inode() sets the following on a new inode:
@@ -1317,28 +1326,26 @@ static void __udf_read_inode(struct inode *inode)
13171326
ibh = udf_read_ptagged(inode->i_sb, &iinfo->i_location, 1,
13181327
&ident);
13191328
if (ident == TAG_IDENT_IE && ibh) {
1320-
struct buffer_head *nbh = NULL;
13211329
struct kernel_lb_addr loc;
13221330
struct indirectEntry *ie;
13231331

13241332
ie = (struct indirectEntry *)ibh->b_data;
13251333
loc = lelb_to_cpu(ie->indirectICB.extLocation);
13261334

1327-
if (ie->indirectICB.extLength &&
1328-
(nbh = udf_read_ptagged(inode->i_sb, &loc, 0,
1329-
&ident))) {
1330-
if (ident == TAG_IDENT_FE ||
1331-
ident == TAG_IDENT_EFE) {
1332-
memcpy(&iinfo->i_location,
1333-
&loc,
1334-
sizeof(struct kernel_lb_addr));
1335-
brelse(bh);
1336-
brelse(ibh);
1337-
brelse(nbh);
1338-
__udf_read_inode(inode);
1335+
if (ie->indirectICB.extLength) {
1336+
brelse(bh);
1337+
brelse(ibh);
1338+
memcpy(&iinfo->i_location, &loc,
1339+
sizeof(struct kernel_lb_addr));
1340+
if (++indirections > UDF_MAX_ICB_NESTING) {
1341+
udf_err(inode->i_sb,
1342+
"too many ICBs in ICB hierarchy"
1343+
" (max %d supported)\n",
1344+
UDF_MAX_ICB_NESTING);
1345+
make_bad_inode(inode);
13391346
return;
13401347
}
1341-
brelse(nbh);
1348+
goto reread;
13421349
}
13431350
}
13441351
brelse(ibh);

0 commit comments

Comments
 (0)