aboutsummaryrefslogtreecommitdiffstats
path: root/fs/udf
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2018-02-09 09:56:34 -0500
committerJan Kara <jack@suse.cz>2018-02-27 04:25:33 -0500
commit7b78fd02fb19530fd101ae137a1f46aa466d9bb6 (patch)
treec8483c52ffda1f31ca87078dd1b33c8d091bd58e /fs/udf
parent18cf4781c9e5dc1067dd50a8f8f321c70142461f (diff)
udf: Fix handling of Partition Descriptors
Current handling of Partition Descriptors in Volume Descriptor Sequence is buggy in several ways. Firstly, it does not take descriptor sequence numbers into account at all, thus any volume making serious use of them would be unmountable. Secondly, it does not handle Volume Descriptor Pointers or Volume Descriptor Sequence without Terminating Descriptor. Fix these problems by properly remembering all Partition Descriptors in the Volume Descriptor Sequence and their sequence numbers. This is made more complicated by the fact that we don't know number of partitions in advance and sequence numbers have to be tracked on per-partition basis. Reported-by: Pali Rohár <pali.rohar@gmail.com> Acked-by: Pali Rohár <pali.rohar@gmail.com> Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/udf')
-rw-r--r--fs/udf/super.c105
1 files changed, 73 insertions, 32 deletions
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 3e9925acd235..28ee2ac2503d 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -68,9 +68,7 @@ enum {
68 VDS_POS_PRIMARY_VOL_DESC, 68 VDS_POS_PRIMARY_VOL_DESC,
69 VDS_POS_UNALLOC_SPACE_DESC, 69 VDS_POS_UNALLOC_SPACE_DESC,
70 VDS_POS_LOGICAL_VOL_DESC, 70 VDS_POS_LOGICAL_VOL_DESC,
71 VDS_POS_PARTITION_DESC,
72 VDS_POS_IMP_USE_VOL_DESC, 71 VDS_POS_IMP_USE_VOL_DESC,
73 VDS_POS_TERMINATING_DESC,
74 VDS_POS_LENGTH 72 VDS_POS_LENGTH
75}; 73};
76 74
@@ -1593,18 +1591,57 @@ static void udf_load_logicalvolint(struct super_block *sb, struct kernel_extent_
1593 sbi->s_lvid_bh = NULL; 1591 sbi->s_lvid_bh = NULL;
1594} 1592}
1595 1593
1596static struct udf_vds_record *get_volume_descriptor_record( 1594/*
1597 struct udf_vds_record *vds, uint16_t ident) 1595 * Step for reallocation of table of partition descriptor sequence numbers.
1596 * Must be power of 2.
1597 */
1598#define PART_DESC_ALLOC_STEP 32
1599
1600struct desc_seq_scan_data {
1601 struct udf_vds_record vds[VDS_POS_LENGTH];
1602 unsigned int size_part_descs;
1603 struct udf_vds_record *part_descs_loc;
1604};
1605
1606static struct udf_vds_record *handle_partition_descriptor(
1607 struct buffer_head *bh,
1608 struct desc_seq_scan_data *data)
1609{
1610 struct partitionDesc *desc = (struct partitionDesc *)bh->b_data;
1611 int partnum;
1612
1613 partnum = le16_to_cpu(desc->partitionNumber);
1614 if (partnum >= data->size_part_descs) {
1615 struct udf_vds_record *new_loc;
1616 unsigned int new_size = ALIGN(partnum, PART_DESC_ALLOC_STEP);
1617
1618 new_loc = kzalloc(sizeof(*new_loc) * new_size, GFP_KERNEL);
1619 if (!new_loc)
1620 return ERR_PTR(-ENOMEM);
1621 memcpy(new_loc, data->part_descs_loc,
1622 data->size_part_descs * sizeof(*new_loc));
1623 kfree(data->part_descs_loc);
1624 data->part_descs_loc = new_loc;
1625 data->size_part_descs = new_size;
1626 }
1627 return &(data->part_descs_loc[partnum]);
1628}
1629
1630
1631static struct udf_vds_record *get_volume_descriptor_record(uint16_t ident,
1632 struct buffer_head *bh, struct desc_seq_scan_data *data)
1598{ 1633{
1599 switch (ident) { 1634 switch (ident) {
1600 case TAG_IDENT_PVD: /* ISO 13346 3/10.1 */ 1635 case TAG_IDENT_PVD: /* ISO 13346 3/10.1 */
1601 return &vds[VDS_POS_PRIMARY_VOL_DESC]; 1636 return &(data->vds[VDS_POS_PRIMARY_VOL_DESC]);
1602 case TAG_IDENT_IUVD: /* ISO 13346 3/10.4 */ 1637 case TAG_IDENT_IUVD: /* ISO 13346 3/10.4 */
1603 return &vds[VDS_POS_IMP_USE_VOL_DESC]; 1638 return &(data->vds[VDS_POS_IMP_USE_VOL_DESC]);
1604 case TAG_IDENT_LVD: /* ISO 13346 3/10.6 */ 1639 case TAG_IDENT_LVD: /* ISO 13346 3/10.6 */
1605 return &vds[VDS_POS_LOGICAL_VOL_DESC]; 1640 return &(data->vds[VDS_POS_LOGICAL_VOL_DESC]);
1606 case TAG_IDENT_USD: /* ISO 13346 3/10.8 */ 1641 case TAG_IDENT_USD: /* ISO 13346 3/10.8 */
1607 return &vds[VDS_POS_UNALLOC_SPACE_DESC]; 1642 return &(data->vds[VDS_POS_UNALLOC_SPACE_DESC]);
1643 case TAG_IDENT_PD: /* ISO 13346 3/10.5 */
1644 return handle_partition_descriptor(bh, data);
1608 } 1645 }
1609 return NULL; 1646 return NULL;
1610} 1647}
@@ -1624,7 +1661,6 @@ static noinline int udf_process_sequence(
1624 struct kernel_lb_addr *fileset) 1661 struct kernel_lb_addr *fileset)
1625{ 1662{
1626 struct buffer_head *bh = NULL; 1663 struct buffer_head *bh = NULL;
1627 struct udf_vds_record vds[VDS_POS_LENGTH];
1628 struct udf_vds_record *curr; 1664 struct udf_vds_record *curr;
1629 struct generic_desc *gd; 1665 struct generic_desc *gd;
1630 struct volDescPtr *vdp; 1666 struct volDescPtr *vdp;
@@ -1633,8 +1669,15 @@ static noinline int udf_process_sequence(
1633 uint16_t ident; 1669 uint16_t ident;
1634 int ret; 1670 int ret;
1635 unsigned int indirections = 0; 1671 unsigned int indirections = 0;
1636 1672 struct desc_seq_scan_data data;
1637 memset(vds, 0, sizeof(struct udf_vds_record) * VDS_POS_LENGTH); 1673 unsigned int i;
1674
1675 memset(data.vds, 0, sizeof(struct udf_vds_record) * VDS_POS_LENGTH);
1676 data.size_part_descs = PART_DESC_ALLOC_STEP;
1677 data.part_descs_loc = kzalloc(sizeof(*data.part_descs_loc) *
1678 data.size_part_descs, GFP_KERNEL);
1679 if (!data.part_descs_loc)
1680 return -ENOMEM;
1638 1681
1639 /* 1682 /*
1640 * Read the main descriptor sequence and find which descriptors 1683 * Read the main descriptor sequence and find which descriptors
@@ -1672,19 +1715,21 @@ static noinline int udf_process_sequence(
1672 case TAG_IDENT_IUVD: /* ISO 13346 3/10.4 */ 1715 case TAG_IDENT_IUVD: /* ISO 13346 3/10.4 */
1673 case TAG_IDENT_LVD: /* ISO 13346 3/10.6 */ 1716 case TAG_IDENT_LVD: /* ISO 13346 3/10.6 */
1674 case TAG_IDENT_USD: /* ISO 13346 3/10.8 */ 1717 case TAG_IDENT_USD: /* ISO 13346 3/10.8 */
1675 curr = get_volume_descriptor_record(vds, ident); 1718 case TAG_IDENT_PD: /* ISO 13346 3/10.5 */
1719 curr = get_volume_descriptor_record(ident, bh, &data);
1720 if (IS_ERR(curr)) {
1721 brelse(bh);
1722 return PTR_ERR(curr);
1723 }
1724 /* Descriptor we don't care about? */
1725 if (!curr)
1726 break;
1676 if (vdsn >= curr->volDescSeqNum) { 1727 if (vdsn >= curr->volDescSeqNum) {
1677 curr->volDescSeqNum = vdsn; 1728 curr->volDescSeqNum = vdsn;
1678 curr->block = block; 1729 curr->block = block;
1679 } 1730 }
1680 break; 1731 break;
1681 case TAG_IDENT_PD: /* ISO 13346 3/10.5 */
1682 curr = &vds[VDS_POS_PARTITION_DESC];
1683 if (!curr->block)
1684 curr->block = block;
1685 break;
1686 case TAG_IDENT_TD: /* ISO 13346 3/10.9 */ 1732 case TAG_IDENT_TD: /* ISO 13346 3/10.9 */
1687 vds[VDS_POS_TERMINATING_DESC].block = block;
1688 done = true; 1733 done = true;
1689 break; 1734 break;
1690 } 1735 }
@@ -1694,31 +1739,27 @@ static noinline int udf_process_sequence(
1694 * Now read interesting descriptors again and process them 1739 * Now read interesting descriptors again and process them
1695 * in a suitable order 1740 * in a suitable order
1696 */ 1741 */
1697 if (!vds[VDS_POS_PRIMARY_VOL_DESC].block) { 1742 if (!data.vds[VDS_POS_PRIMARY_VOL_DESC].block) {
1698 udf_err(sb, "Primary Volume Descriptor not found!\n"); 1743 udf_err(sb, "Primary Volume Descriptor not found!\n");
1699 return -EAGAIN; 1744 return -EAGAIN;
1700 } 1745 }
1701 ret = udf_load_pvoldesc(sb, vds[VDS_POS_PRIMARY_VOL_DESC].block); 1746 ret = udf_load_pvoldesc(sb, data.vds[VDS_POS_PRIMARY_VOL_DESC].block);
1702 if (ret < 0) 1747 if (ret < 0)
1703 return ret; 1748 return ret;
1704 1749
1705 if (vds[VDS_POS_LOGICAL_VOL_DESC].block) { 1750 if (data.vds[VDS_POS_LOGICAL_VOL_DESC].block) {
1706 ret = udf_load_logicalvol(sb, 1751 ret = udf_load_logicalvol(sb,
1707 vds[VDS_POS_LOGICAL_VOL_DESC].block, 1752 data.vds[VDS_POS_LOGICAL_VOL_DESC].block,
1708 fileset); 1753 fileset);
1709 if (ret < 0) 1754 if (ret < 0)
1710 return ret; 1755 return ret;
1711 } 1756 }
1712 1757
1713 if (vds[VDS_POS_PARTITION_DESC].block) { 1758 /* Now handle prevailing Partition Descriptors */
1714 /* 1759 for (i = 0; i < data.size_part_descs; i++) {
1715 * We rescan the whole descriptor sequence to find 1760 if (data.part_descs_loc[i].block) {
1716 * partition descriptor blocks and process them. 1761 ret = udf_load_partdesc(sb,
1717 */ 1762 data.part_descs_loc[i].block);
1718 for (block = vds[VDS_POS_PARTITION_DESC].block;
1719 block < vds[VDS_POS_TERMINATING_DESC].block;
1720 block++) {
1721 ret = udf_load_partdesc(sb, block);
1722 if (ret < 0) 1763 if (ret < 0)
1723 return ret; 1764 return ret;
1724 } 1765 }