diff options
Diffstat (limited to 'fs/udf/super.c')
-rw-r--r-- | fs/udf/super.c | 67 |
1 files changed, 43 insertions, 24 deletions
diff --git a/fs/udf/super.c b/fs/udf/super.c index 36661acaf33b..5e2c8c814e1b 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c | |||
@@ -78,6 +78,15 @@ | |||
78 | #define VSD_FIRST_SECTOR_OFFSET 32768 | 78 | #define VSD_FIRST_SECTOR_OFFSET 32768 |
79 | #define VSD_MAX_SECTOR_OFFSET 0x800000 | 79 | #define VSD_MAX_SECTOR_OFFSET 0x800000 |
80 | 80 | ||
81 | /* | ||
82 | * Maximum number of Terminating Descriptor / Logical Volume Integrity | ||
83 | * Descriptor redirections. The chosen numbers are arbitrary - just that we | ||
84 | * hopefully don't limit any real use of rewritten inode on write-once media | ||
85 | * but avoid looping for too long on corrupted media. | ||
86 | */ | ||
87 | #define UDF_MAX_TD_NESTING 64 | ||
88 | #define UDF_MAX_LVID_NESTING 1000 | ||
89 | |||
81 | enum { UDF_MAX_LINKS = 0xffff }; | 90 | enum { UDF_MAX_LINKS = 0xffff }; |
82 | 91 | ||
83 | /* These are the "meat" - everything else is stuffing */ | 92 | /* These are the "meat" - everything else is stuffing */ |
@@ -1541,42 +1550,52 @@ out_bh: | |||
1541 | } | 1550 | } |
1542 | 1551 | ||
1543 | /* | 1552 | /* |
1544 | * udf_load_logicalvolint | 1553 | * Find the prevailing Logical Volume Integrity Descriptor. |
1545 | * | ||
1546 | */ | 1554 | */ |
1547 | static void udf_load_logicalvolint(struct super_block *sb, struct kernel_extent_ad loc) | 1555 | static void udf_load_logicalvolint(struct super_block *sb, struct kernel_extent_ad loc) |
1548 | { | 1556 | { |
1549 | struct buffer_head *bh = NULL; | 1557 | struct buffer_head *bh, *final_bh; |
1550 | uint16_t ident; | 1558 | uint16_t ident; |
1551 | struct udf_sb_info *sbi = UDF_SB(sb); | 1559 | struct udf_sb_info *sbi = UDF_SB(sb); |
1552 | struct logicalVolIntegrityDesc *lvid; | 1560 | struct logicalVolIntegrityDesc *lvid; |
1561 | int indirections = 0; | ||
1562 | |||
1563 | while (++indirections <= UDF_MAX_LVID_NESTING) { | ||
1564 | final_bh = NULL; | ||
1565 | while (loc.extLength > 0 && | ||
1566 | (bh = udf_read_tagged(sb, loc.extLocation, | ||
1567 | loc.extLocation, &ident))) { | ||
1568 | if (ident != TAG_IDENT_LVID) { | ||
1569 | brelse(bh); | ||
1570 | break; | ||
1571 | } | ||
1572 | |||
1573 | brelse(final_bh); | ||
1574 | final_bh = bh; | ||
1553 | 1575 | ||
1554 | while (loc.extLength > 0 && | 1576 | loc.extLength -= sb->s_blocksize; |
1555 | (bh = udf_read_tagged(sb, loc.extLocation, | 1577 | loc.extLocation++; |
1556 | loc.extLocation, &ident)) && | 1578 | } |
1557 | ident == TAG_IDENT_LVID) { | ||
1558 | sbi->s_lvid_bh = bh; | ||
1559 | lvid = (struct logicalVolIntegrityDesc *)bh->b_data; | ||
1560 | 1579 | ||
1561 | if (lvid->nextIntegrityExt.extLength) | 1580 | if (!final_bh) |
1562 | udf_load_logicalvolint(sb, | 1581 | return; |
1563 | leea_to_cpu(lvid->nextIntegrityExt)); | ||
1564 | 1582 | ||
1565 | if (sbi->s_lvid_bh != bh) | 1583 | brelse(sbi->s_lvid_bh); |
1566 | brelse(bh); | 1584 | sbi->s_lvid_bh = final_bh; |
1567 | loc.extLength -= sb->s_blocksize; | 1585 | |
1568 | loc.extLocation++; | 1586 | lvid = (struct logicalVolIntegrityDesc *)final_bh->b_data; |
1587 | if (lvid->nextIntegrityExt.extLength == 0) | ||
1588 | return; | ||
1589 | |||
1590 | loc = leea_to_cpu(lvid->nextIntegrityExt); | ||
1569 | } | 1591 | } |
1570 | if (sbi->s_lvid_bh != bh) | 1592 | |
1571 | brelse(bh); | 1593 | udf_warn(sb, "Too many LVID indirections (max %u), ignoring.\n", |
1594 | UDF_MAX_LVID_NESTING); | ||
1595 | brelse(sbi->s_lvid_bh); | ||
1596 | sbi->s_lvid_bh = NULL; | ||
1572 | } | 1597 | } |
1573 | 1598 | ||
1574 | /* | ||
1575 | * Maximum number of Terminating Descriptor redirections. The chosen number is | ||
1576 | * arbitrary - just that we hopefully don't limit any real use of rewritten | ||
1577 | * inode on write-once media but avoid looping for too long on corrupted media. | ||
1578 | */ | ||
1579 | #define UDF_MAX_TD_NESTING 64 | ||
1580 | 1599 | ||
1581 | /* | 1600 | /* |
1582 | * Process a main/reserve volume descriptor sequence. | 1601 | * Process a main/reserve volume descriptor sequence. |