aboutsummaryrefslogtreecommitdiffstats
path: root/fs/udf/super.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/udf/super.c')
-rw-r--r--fs/udf/super.c67
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
81enum { UDF_MAX_LINKS = 0xffff }; 90enum { 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 */
1547static void udf_load_logicalvolint(struct super_block *sb, struct kernel_extent_ad loc) 1555static 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.