diff options
| author | Boaz Harrosh <bharrosh@panasas.com> | 2009-02-03 01:47:29 -0500 |
|---|---|---|
| committer | Jens Axboe <jens.axboe@oracle.com> | 2009-02-18 04:32:00 -0500 |
| commit | c1c201200a359cf3b6e2e36a4236cdca77a3cd8e (patch) | |
| tree | e214a2773f20b814cb8cc8c5509066cd9ec98a1a | |
| parent | 5955c7a2cfb6a35429adea5dc480002b15ca8cfc (diff) | |
bsg: Fix sense buffer bug in SG_IO
When submitting requests via SG_IO, which does a sync io, a
bsg_command is not allocated. So an in-Kernel sense_buffer was not
set. However when calling blk_execute_rq() with no sense buffer
one is provided from the stack. Now bsg at blk_complete_sgv4_hdr_rq()
would check if rq->sense_len and a sense was requested by sg_io_v4
the rq->sense was copy_user() back, but by now it is already mangled
stack memory.
I have fixed that by forcing a sense_buffer when calling bsg_map_hdr().
The bsg_command->sense is provided in the write/read path like before,
and on-the-stack buffer is provided when doing SG_IO.
I have also fixed a dprintk message to print rq->errors in hex because
of the scsi bit-field use of this member. For other block devices it
does not matter anyway.
Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Acked-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
| -rw-r--r-- | block/bsg.c | 17 |
1 files changed, 10 insertions, 7 deletions
diff --git a/block/bsg.c b/block/bsg.c index d414bb5607e8..0ce8806dd0c1 100644 --- a/block/bsg.c +++ b/block/bsg.c | |||
| @@ -244,7 +244,8 @@ bsg_validate_sgv4_hdr(struct request_queue *q, struct sg_io_v4 *hdr, int *rw) | |||
| 244 | * map sg_io_v4 to a request. | 244 | * map sg_io_v4 to a request. |
| 245 | */ | 245 | */ |
| 246 | static struct request * | 246 | static struct request * |
| 247 | bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, fmode_t has_write_perm) | 247 | bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, fmode_t has_write_perm, |
| 248 | u8 *sense) | ||
| 248 | { | 249 | { |
| 249 | struct request_queue *q = bd->queue; | 250 | struct request_queue *q = bd->queue; |
| 250 | struct request *rq, *next_rq = NULL; | 251 | struct request *rq, *next_rq = NULL; |
| @@ -306,6 +307,10 @@ bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, fmode_t has_write_perm) | |||
| 306 | if (ret) | 307 | if (ret) |
| 307 | goto out; | 308 | goto out; |
| 308 | } | 309 | } |
| 310 | |||
| 311 | rq->sense = sense; | ||
| 312 | rq->sense_len = 0; | ||
| 313 | |||
| 309 | return rq; | 314 | return rq; |
| 310 | out: | 315 | out: |
| 311 | if (rq->cmd != rq->__cmd) | 316 | if (rq->cmd != rq->__cmd) |
| @@ -348,9 +353,6 @@ static void bsg_rq_end_io(struct request *rq, int uptodate) | |||
| 348 | static void bsg_add_command(struct bsg_device *bd, struct request_queue *q, | 353 | static void bsg_add_command(struct bsg_device *bd, struct request_queue *q, |
| 349 | struct bsg_command *bc, struct request *rq) | 354 | struct bsg_command *bc, struct request *rq) |
| 350 | { | 355 | { |
| 351 | rq->sense = bc->sense; | ||
| 352 | rq->sense_len = 0; | ||
| 353 | |||
| 354 | /* | 356 | /* |
| 355 | * add bc command to busy queue and submit rq for io | 357 | * add bc command to busy queue and submit rq for io |
| 356 | */ | 358 | */ |
| @@ -419,7 +421,7 @@ static int blk_complete_sgv4_hdr_rq(struct request *rq, struct sg_io_v4 *hdr, | |||
| 419 | { | 421 | { |
| 420 | int ret = 0; | 422 | int ret = 0; |
| 421 | 423 | ||
| 422 | dprintk("rq %p bio %p %u\n", rq, bio, rq->errors); | 424 | dprintk("rq %p bio %p 0x%x\n", rq, bio, rq->errors); |
| 423 | /* | 425 | /* |
| 424 | * fill in all the output members | 426 | * fill in all the output members |
| 425 | */ | 427 | */ |
| @@ -635,7 +637,7 @@ static int __bsg_write(struct bsg_device *bd, const char __user *buf, | |||
| 635 | /* | 637 | /* |
| 636 | * get a request, fill in the blanks, and add to request queue | 638 | * get a request, fill in the blanks, and add to request queue |
| 637 | */ | 639 | */ |
| 638 | rq = bsg_map_hdr(bd, &bc->hdr, has_write_perm); | 640 | rq = bsg_map_hdr(bd, &bc->hdr, has_write_perm, bc->sense); |
| 639 | if (IS_ERR(rq)) { | 641 | if (IS_ERR(rq)) { |
| 640 | ret = PTR_ERR(rq); | 642 | ret = PTR_ERR(rq); |
| 641 | rq = NULL; | 643 | rq = NULL; |
| @@ -922,11 +924,12 @@ static long bsg_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
| 922 | struct request *rq; | 924 | struct request *rq; |
| 923 | struct bio *bio, *bidi_bio = NULL; | 925 | struct bio *bio, *bidi_bio = NULL; |
| 924 | struct sg_io_v4 hdr; | 926 | struct sg_io_v4 hdr; |
| 927 | u8 sense[SCSI_SENSE_BUFFERSIZE]; | ||
| 925 | 928 | ||
| 926 | if (copy_from_user(&hdr, uarg, sizeof(hdr))) | 929 | if (copy_from_user(&hdr, uarg, sizeof(hdr))) |
| 927 | return -EFAULT; | 930 | return -EFAULT; |
| 928 | 931 | ||
| 929 | rq = bsg_map_hdr(bd, &hdr, file->f_mode & FMODE_WRITE); | 932 | rq = bsg_map_hdr(bd, &hdr, file->f_mode & FMODE_WRITE, sense); |
| 930 | if (IS_ERR(rq)) | 933 | if (IS_ERR(rq)) |
| 931 | return PTR_ERR(rq); | 934 | return PTR_ERR(rq); |
| 932 | 935 | ||
