From: Aristeu Rozanski <arozansk@redhat.com>
To: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Cc: linux-ide@vger.kernel.org
Subject: [PATCH] ide-io: set REQ_FAILED when drive is dead
Date: Thu, 24 Jan 2008 15:37:38 -0500 [thread overview]
Message-ID: <20080124203738.GA2176@redhat.com> (raw)
Currently it's possible to ide-cd to set an incorrect blocksize by
reading garbage if the drive is dead:
ide_cd_probe()
-> cdrom_read_toc()
-> cdrom_read_capacity()
-> cdrom_queue_packet_command()
-> ide_do_drive_cmd()
-> ide_do_request()
-> start_request()
on start_request():
/* bail early if we've exceeded max_failures */
if (drive->max_failures && (drive->failures > drive->max_failures)) {
goto kill_rq;
}
(...)
kill_rq:
ide_kill_rq(drive, rq);
return ide_stopped;
ide_kill_rq() and the next calls won't set REQ_FAILED on rq->cmd_flags and thus
cdrom_queue_packet_command() won't return an error. then:
stat = cdrom_queue_packet_command(drive, &req);
if (stat == 0) {
*capacity = 1 + be32_to_cpu(capbuf.lba);
*sectors_per_frame =
be32_to_cpu(capbuf.blocklen) >> SECTOR_BITS;
}
cdrom_read_capacity() ends believing capbuf is valid but in fact it's just
uninitialized data. back to cdrom_read_toc():
/* Try to get the total cdrom capacity and sector size. */
stat = cdrom_read_capacity(drive, &toc->capacity, §ors_per_frame,
sense);
if (stat)
toc->capacity = 0x1fffff;
set_capacity(info->disk, toc->capacity * sectors_per_frame);
/* Save a private copy of te TOC capacity for error handling */
drive->probed_capacity = toc->capacity * sectors_per_frame;
blk_queue_hardsect_size(drive->queue,
sectors_per_frame << SECTOR_BITS);
that will set drive->queue->hardsect_size to be the random value.
hardsect_size is used to calculate inode->i_blkbits. later on, on a read
path:
void create_empty_buffers(struct page *page,
unsigned long blocksize, unsigned long b_state)
{
struct buffer_head *bh, *head, *tail;
head = alloc_page_buffers(page, blocksize, 1);
bh = head;
do {
bh->b_state |= b_state;
tail = bh;
bh = bh->b_this_page;
} while (bh);
tail->b_this_page = head;
alloc_page_buffers() will return NULL if blocksize > 4096. blocksize is
calculed based on inode->i_blkbits. that will trigger a null
dereference on create_empty_buffers().
Signed-off-by: Aristeu Rozanski <arozansk@redhat.com>
---
drivers/ide/ide-io.c | 1 +
1 file changed, 1 insertion(+)
--- linus-2.6.orig/drivers/ide/ide-io.c 2007-12-18 07:54:59.000000000 -0500
+++ linus-2.6/drivers/ide/ide-io.c 2008-01-24 14:48:29.000000000 -0500
@@ -1003,6 +1003,7 @@ static ide_startstop_t start_request (id
/* bail early if we've exceeded max_failures */
if (drive->max_failures && (drive->failures > drive->max_failures)) {
+ rq->cmd_flags |= REQ_FAILED;
goto kill_rq;
}
next reply other threads:[~2008-01-24 20:41 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-01-24 20:37 Aristeu Rozanski [this message]
2008-01-25 21:06 ` [PATCH] ide-io: set REQ_FAILED when drive is dead Bartlomiej Zolnierkiewicz
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20080124203738.GA2176@redhat.com \
--to=arozansk@redhat.com \
--cc=bzolnier@gmail.com \
--cc=linux-ide@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.