diff options
-rw-r--r-- | fs/udf/super.c | 45 |
1 files changed, 36 insertions, 9 deletions
diff --git a/fs/udf/super.c b/fs/udf/super.c index 91219385691d..3306b9f69bed 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c | |||
@@ -76,6 +76,9 @@ | |||
76 | 76 | ||
77 | #define UDF_DEFAULT_BLOCKSIZE 2048 | 77 | #define UDF_DEFAULT_BLOCKSIZE 2048 |
78 | 78 | ||
79 | #define VSD_FIRST_SECTOR_OFFSET 32768 | ||
80 | #define VSD_MAX_SECTOR_OFFSET 0x800000 | ||
81 | |||
79 | enum { UDF_MAX_LINKS = 0xffff }; | 82 | enum { UDF_MAX_LINKS = 0xffff }; |
80 | 83 | ||
81 | /* These are the "meat" - everything else is stuffing */ | 84 | /* These are the "meat" - everything else is stuffing */ |
@@ -685,7 +688,7 @@ out_unlock: | |||
685 | static loff_t udf_check_vsd(struct super_block *sb) | 688 | static loff_t udf_check_vsd(struct super_block *sb) |
686 | { | 689 | { |
687 | struct volStructDesc *vsd = NULL; | 690 | struct volStructDesc *vsd = NULL; |
688 | loff_t sector = 32768; | 691 | loff_t sector = VSD_FIRST_SECTOR_OFFSET; |
689 | int sectorsize; | 692 | int sectorsize; |
690 | struct buffer_head *bh = NULL; | 693 | struct buffer_head *bh = NULL; |
691 | int nsr02 = 0; | 694 | int nsr02 = 0; |
@@ -703,8 +706,18 @@ static loff_t udf_check_vsd(struct super_block *sb) | |||
703 | udf_debug("Starting at sector %u (%ld byte sectors)\n", | 706 | udf_debug("Starting at sector %u (%ld byte sectors)\n", |
704 | (unsigned int)(sector >> sb->s_blocksize_bits), | 707 | (unsigned int)(sector >> sb->s_blocksize_bits), |
705 | sb->s_blocksize); | 708 | sb->s_blocksize); |
706 | /* Process the sequence (if applicable) */ | 709 | /* Process the sequence (if applicable). The hard limit on the sector |
707 | for (; !nsr02 && !nsr03; sector += sectorsize) { | 710 | * offset is arbitrary, hopefully large enough so that all valid UDF |
711 | * filesystems will be recognised. There is no mention of an upper | ||
712 | * bound to the size of the volume recognition area in the standard. | ||
713 | * The limit will prevent the code to read all the sectors of a | ||
714 | * specially crafted image (like a bluray disc full of CD001 sectors), | ||
715 | * potentially causing minutes or even hours of uninterruptible I/O | ||
716 | * activity. This actually happened with uninitialised SSD partitions | ||
717 | * (all 0xFF) before the check for the limit and all valid IDs were | ||
718 | * added */ | ||
719 | for (; !nsr02 && !nsr03 && sector < VSD_MAX_SECTOR_OFFSET; | ||
720 | sector += sectorsize) { | ||
708 | /* Read a block */ | 721 | /* Read a block */ |
709 | bh = udf_tread(sb, sector >> sb->s_blocksize_bits); | 722 | bh = udf_tread(sb, sector >> sb->s_blocksize_bits); |
710 | if (!bh) | 723 | if (!bh) |
@@ -714,10 +727,7 @@ static loff_t udf_check_vsd(struct super_block *sb) | |||
714 | vsd = (struct volStructDesc *)(bh->b_data + | 727 | vsd = (struct volStructDesc *)(bh->b_data + |
715 | (sector & (sb->s_blocksize - 1))); | 728 | (sector & (sb->s_blocksize - 1))); |
716 | 729 | ||
717 | if (vsd->stdIdent[0] == 0) { | 730 | if (!strncmp(vsd->stdIdent, VSD_STD_ID_CD001, |
718 | brelse(bh); | ||
719 | break; | ||
720 | } else if (!strncmp(vsd->stdIdent, VSD_STD_ID_CD001, | ||
721 | VSD_STD_ID_LEN)) { | 731 | VSD_STD_ID_LEN)) { |
722 | switch (vsd->structType) { | 732 | switch (vsd->structType) { |
723 | case 0: | 733 | case 0: |
@@ -753,6 +763,17 @@ static loff_t udf_check_vsd(struct super_block *sb) | |||
753 | else if (!strncmp(vsd->stdIdent, VSD_STD_ID_NSR03, | 763 | else if (!strncmp(vsd->stdIdent, VSD_STD_ID_NSR03, |
754 | VSD_STD_ID_LEN)) | 764 | VSD_STD_ID_LEN)) |
755 | nsr03 = sector; | 765 | nsr03 = sector; |
766 | else if (!strncmp(vsd->stdIdent, VSD_STD_ID_BOOT2, | ||
767 | VSD_STD_ID_LEN)) | ||
768 | ; /* nothing */ | ||
769 | else if (!strncmp(vsd->stdIdent, VSD_STD_ID_CDW02, | ||
770 | VSD_STD_ID_LEN)) | ||
771 | ; /* nothing */ | ||
772 | else { | ||
773 | /* invalid id : end of volume recognition area */ | ||
774 | brelse(bh); | ||
775 | break; | ||
776 | } | ||
756 | brelse(bh); | 777 | brelse(bh); |
757 | } | 778 | } |
758 | 779 | ||
@@ -760,7 +781,8 @@ static loff_t udf_check_vsd(struct super_block *sb) | |||
760 | return nsr03; | 781 | return nsr03; |
761 | else if (nsr02) | 782 | else if (nsr02) |
762 | return nsr02; | 783 | return nsr02; |
763 | else if (sector - (sbi->s_session << sb->s_blocksize_bits) == 32768) | 784 | else if (!bh && sector - (sbi->s_session << sb->s_blocksize_bits) == |
785 | VSD_FIRST_SECTOR_OFFSET) | ||
764 | return -1; | 786 | return -1; |
765 | else | 787 | else |
766 | return 0; | 788 | return 0; |
@@ -1270,6 +1292,9 @@ static int udf_load_partdesc(struct super_block *sb, sector_t block) | |||
1270 | * PHYSICAL partitions are already set up | 1292 | * PHYSICAL partitions are already set up |
1271 | */ | 1293 | */ |
1272 | type1_idx = i; | 1294 | type1_idx = i; |
1295 | #ifdef UDFFS_DEBUG | ||
1296 | map = NULL; /* supress 'maybe used uninitialized' warning */ | ||
1297 | #endif | ||
1273 | for (i = 0; i < sbi->s_partitions; i++) { | 1298 | for (i = 0; i < sbi->s_partitions; i++) { |
1274 | map = &sbi->s_partmaps[i]; | 1299 | map = &sbi->s_partmaps[i]; |
1275 | 1300 | ||
@@ -1891,7 +1916,9 @@ static int udf_load_vrs(struct super_block *sb, struct udf_options *uopt, | |||
1891 | return 0; | 1916 | return 0; |
1892 | } | 1917 | } |
1893 | if (nsr_off == -1) | 1918 | if (nsr_off == -1) |
1894 | udf_debug("Failed to read byte 32768. Assuming open disc. Skipping validity check\n"); | 1919 | udf_debug("Failed to read sector at offset %d. " |
1920 | "Assuming open disc. Skipping validity " | ||
1921 | "check\n", VSD_FIRST_SECTOR_OFFSET); | ||
1895 | if (!sbi->s_last_block) | 1922 | if (!sbi->s_last_block) |
1896 | sbi->s_last_block = udf_get_last_block(sb); | 1923 | sbi->s_last_block = udf_get_last_block(sb); |
1897 | } else { | 1924 | } else { |