summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Pitt <martin.pitt@ubuntu.com>2010-10-05 17:56:19 +0200
committerMartin Pitt <martin.pitt@ubuntu.com>2010-10-05 17:56:19 +0200
commit1ebd2a5620c93ef4698485d392c19ded675412d2 (patch)
treeeebf138873734e92a3ce008f1b1fabbfbf0674b7
parent678df8a461c7573bf423a39be383bc7b70d943df (diff)
cdrom_id: Don't read beyond "last track" in TOC
Read the first and last track from the TOC header, and do not go beyond that stated number of tracks when reading the TOC. Otherwise we interpret random data which leads to bogus tracks. (Reported on an IronKey, which reported 1 data track, and 4 audio tracks which weren't actually present.)
-rw-r--r--extras/cdrom_id/cdrom_id.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/extras/cdrom_id/cdrom_id.c b/extras/cdrom_id/cdrom_id.c
index e7a3e40a85..1b43fe43ae 100644
--- a/extras/cdrom_id/cdrom_id.c
+++ b/extras/cdrom_id/cdrom_id.c
@@ -712,7 +712,7 @@ static int cd_media_toc(struct udev *udev, int fd)
struct scsi_cmd sc;
unsigned char header[12];
unsigned char toc[2048];
- unsigned int len, i;
+ unsigned int len, i, num_tracks;
unsigned char *p;
int err;
@@ -728,11 +728,13 @@ static int cd_media_toc(struct udev *udev, int fd)
}
len = (header[0] << 8 | header[1]) + 2;
- info(udev, "READ TOC: len: %d\n", len);
+ info(udev, "READ TOC: len: %d, start track: %d, end track: %d\n", len, header[2], header[3]);
if (len > sizeof(toc))
return -1;
if (len < 2)
return -1;
+ /* 2: first track, 3: last track */
+ num_tracks = header[3] - header[2] + 1;
/* empty media has no tracks */
if (len < 8)
@@ -750,7 +752,10 @@ static int cd_media_toc(struct udev *udev, int fd)
return -1;
}
- for (p = toc+4, i = 4; i < len-8; i += 8, p += 8) {
+ /* Take care to not iterate beyond the last valid track as specified in
+ * the TOC, but also avoid going beyond the TOC length, just in case
+ * the last track number is invalidly large */
+ for (p = toc+4, i = 4; i < len-8 && num_tracks > 0; i += 8, p += 8, --num_tracks) {
unsigned int block;
unsigned int is_data_track;