summaryrefslogtreecommitdiffstats
path: root/libblkid
diff options
context:
space:
mode:
authorPali Rohár2017-11-13 21:45:34 +0100
committerPali Rohár2017-11-13 21:45:34 +0100
commite44eb3e6e568a1dfa85d2ae76273578c7a55fbf4 (patch)
tree6210f52c74dcbc7bb292d33eb74baa05aa27ddd4 /libblkid
parentcal: simplify leap year rule (diff)
downloadkernel-qcow2-util-linux-e44eb3e6e568a1dfa85d2ae76273578c7a55fbf4.tar.gz
kernel-qcow2-util-linux-e44eb3e6e568a1dfa85d2ae76273578c7a55fbf4.tar.xz
kernel-qcow2-util-linux-e44eb3e6e568a1dfa85d2ae76273578c7a55fbf4.zip
libblkid: udf: Fix reading Logical Volume Integrity Descriptor Implementation Use (LVIDIU)
LVIDIU is stored at the end of Logical Volume Integrity Descriptor (LVID), after two variable length array of partitions. And number of partitions is stored in LVID, not in Logical Volume Descriptor (LVD). Length of LVIDIU is also stored in LVID, so add check that LVIDIU has enough size. Fixes commit db316767434c2c451ec1732861256d5729143e89.
Diffstat (limited to 'libblkid')
-rw-r--r--libblkid/src/superblocks/udf.c25
1 files changed, 17 insertions, 8 deletions
diff --git a/libblkid/src/superblocks/udf.c b/libblkid/src/superblocks/udf.c
index 73bf9a8af..ee5b26990 100644
--- a/libblkid/src/superblocks/udf.c
+++ b/libblkid/src/superblocks/udf.c
@@ -77,6 +77,16 @@ struct volume_descriptor {
uint32_t lvid_length;
uint32_t lvid_location;
} __attribute__((packed)) logical;
+
+ struct logical_vol_integ_descriptor {
+ uint8_t recording_date[12];
+ uint32_t type;
+ uint32_t next_lvid_length;
+ uint32_t next_lvid_location;
+ uint8_t logical_contents_use[32];
+ uint32_t num_partitions;
+ uint32_t imp_use_length;
+ } __attribute__((packed)) logical_vol_integ;
} __attribute__((packed)) type;
} __attribute__((packed));
@@ -104,7 +114,8 @@ struct logical_vol_integ_descriptor_imp_use
uint16_t max_udf_write_rev;
} __attribute__ ((packed));
-#define UDF_LVIDIU_OFFSET(num_partition_maps) (80 + 2 * 4 * num_partition_maps)
+#define UDF_LVIDIU_OFFSET(vd) (sizeof((vd).tag) + sizeof((vd).type.logical_vol_integ) + 2 * 4 * le32_to_cpu((vd).type.logical_vol_integ.num_partitions))
+#define UDF_LVIDIU_LENGTH(vd) (le32_to_cpu((vd).type.logical_vol_integ.imp_use_length))
static inline int gen_uuid_from_volset_id(unsigned char uuid[17], struct dstring128 *volset_id)
{
@@ -163,7 +174,6 @@ static int probe_udf(blkid_probe pr,
struct volume_descriptor *vd;
struct volume_structure_descriptor *vsd;
struct logical_vol_integ_descriptor_imp_use *lvidiu;
- uint32_t num_partition_maps = 0;
uint32_t lvid_count = 0;
uint32_t lvid_loc = 0;
uint32_t bs;
@@ -339,8 +349,7 @@ real_blksz:
vd->type.primary.volset_id.c, clen, enc);
}
} else if (type == TAG_ID_LVD) {
- if (!num_partition_maps || !lvid_count || !lvid_loc) {
- num_partition_maps = le32_to_cpu(vd->type.logical.num_partition_maps);
+ if (!lvid_count || !lvid_loc) {
lvid_count = le32_to_cpu(vd->type.logical.lvid_length) / bs;
lvid_loc = le32_to_cpu(vd->type.logical.lvid_location);
}
@@ -387,12 +396,12 @@ real_blksz:
}
}
}
- if (have_volid && have_uuid && have_volsetid && have_logvolid && have_label && num_partition_maps && lvid_count && lvid_loc)
+ if (have_volid && have_uuid && have_volsetid && have_logvolid && have_label && lvid_count && lvid_loc)
break;
}
/* pick the logical volume integrity descriptor from the list and read UDF revision */
- if (lvid_count && lvid_loc && num_partition_maps) {
+ if (lvid_count && lvid_loc) {
for (b = 0; b < lvid_count; b++) {
vd = (struct volume_descriptor *)
blkid_probe_get_buffer(pr,
@@ -405,11 +414,11 @@ real_blksz:
break;
if (le32_to_cpu(vd->tag.location) != lvid_loc + b)
break;
- if (type == TAG_ID_LVID) {
+ if (type == TAG_ID_LVID && UDF_LVIDIU_LENGTH(*vd) >= sizeof(*lvidiu)) {
uint16_t udf_rev;
lvidiu = (struct logical_vol_integ_descriptor_imp_use *)
blkid_probe_get_buffer(pr,
- (uint64_t) (lvid_loc + b) * bs + UDF_LVIDIU_OFFSET(num_partition_maps),
+ (uint64_t) (lvid_loc + b) * bs + UDF_LVIDIU_OFFSET(*vd),
sizeof(*lvidiu));
if (!lvidiu)
return errno ? -errno : 1;