diff options
author | Jens Axboe <jens.axboe@oracle.com> | 2008-07-24 16:53:35 -0400 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-07-24 16:53:35 -0400 |
commit | e8e7b9eb11c34ee18bde8b7011af41938d1ad667 (patch) | |
tree | 07e97088cee787f02e9e8de1105829775bc41b5c /drivers/ide/ide-cd.c | |
parent | 96cc112c09b3c6674da01ef8b377f7a916883ea2 (diff) |
ide-cd: fix oops when using growisofs
cdrom_read_capacity() will blindly return the capacity from the device
without sanity-checking it. This later causes code in fs/buffer.c to
oops.
Fix this by checking that the device is telling us sensible things.
From: Jens Axboe <jens.axboe@oracle.com>
Cc: Michael Buesch <mb@bu3sch.de>
Cc: Jan Kara <jack@suse.cz>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: <stable@kernel.org>
Cc: Borislav Petkov <petkovbb@googlemail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
[bart: print device name instead of driver name]
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
[harvey: blocklen is a big-endian value]
Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide/ide-cd.c')
-rw-r--r-- | drivers/ide/ide-cd.c | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 8f253e5f26a8..e617cf08aef6 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c | |||
@@ -1311,13 +1311,30 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity, | |||
1311 | 1311 | ||
1312 | stat = ide_cd_queue_pc(drive, cmd, 0, &capbuf, &len, sense, 0, | 1312 | stat = ide_cd_queue_pc(drive, cmd, 0, &capbuf, &len, sense, 0, |
1313 | REQ_QUIET); | 1313 | REQ_QUIET); |
1314 | if (stat == 0) { | 1314 | if (stat) |
1315 | *capacity = 1 + be32_to_cpu(capbuf.lba); | 1315 | return stat; |
1316 | *sectors_per_frame = | 1316 | |
1317 | be32_to_cpu(capbuf.blocklen) >> SECTOR_BITS; | 1317 | /* |
1318 | * Sanity check the given block size | ||
1319 | */ | ||
1320 | switch (capbuf.blocklen) { | ||
1321 | case __constant_cpu_to_be32(512): | ||
1322 | case __constant_cpu_to_be32(1024): | ||
1323 | case __constant_cpu_to_be32(2048): | ||
1324 | case __constant_cpu_to_be32(4096): | ||
1325 | break; | ||
1326 | default: | ||
1327 | printk(KERN_ERR "%s: weird block size %u\n", | ||
1328 | drive->name, capbuf.blocklen); | ||
1329 | printk(KERN_ERR "%s: default to 2kb block size\n", | ||
1330 | drive->name); | ||
1331 | capbuf.blocklen = __constant_cpu_to_be32(2048); | ||
1332 | break; | ||
1318 | } | 1333 | } |
1319 | 1334 | ||
1320 | return stat; | 1335 | *capacity = 1 + be32_to_cpu(capbuf.lba); |
1336 | *sectors_per_frame = be32_to_cpu(capbuf.blocklen) >> SECTOR_BITS; | ||
1337 | return 0; | ||
1321 | } | 1338 | } |
1322 | 1339 | ||
1323 | static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag, | 1340 | static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag, |