Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Boaz Harrosh and committed by
Jens Axboe
c1c20120 5955c7a2

+10 -7
+10 -7
block/bsg.c
··· 244 244 * map sg_io_v4 to a request. 245 245 */ 246 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 250 struct request_queue *q = bd->queue; 250 251 struct request *rq, *next_rq = NULL; ··· 307 306 if (ret) 308 307 goto out; 309 308 } 309 + 310 + rq->sense = sense; 311 + rq->sense_len = 0; 312 + 310 313 return rq; 311 314 out: 312 315 if (rq->cmd != rq->__cmd) ··· 353 348 static void bsg_add_command(struct bsg_device *bd, struct request_queue *q, 354 349 struct bsg_command *bc, struct request *rq) 355 350 { 356 - rq->sense = bc->sense; 357 - rq->sense_len = 0; 358 - 359 351 /* 360 352 * add bc command to busy queue and submit rq for io 361 353 */ ··· 421 419 { 422 420 int ret = 0; 423 421 424 - dprintk("rq %p bio %p %u\n", rq, bio, rq->errors); 422 + dprintk("rq %p bio %p 0x%x\n", rq, bio, rq->errors); 425 423 /* 426 424 * fill in all the output members 427 425 */ ··· 637 635 /* 638 636 * get a request, fill in the blanks, and add to request queue 639 637 */ 640 - rq = bsg_map_hdr(bd, &bc->hdr, has_write_perm); 638 + rq = bsg_map_hdr(bd, &bc->hdr, has_write_perm, bc->sense); 641 639 if (IS_ERR(rq)) { 642 640 ret = PTR_ERR(rq); 643 641 rq = NULL; ··· 924 922 struct request *rq; 925 923 struct bio *bio, *bidi_bio = NULL; 926 924 struct sg_io_v4 hdr; 925 + u8 sense[SCSI_SENSE_BUFFERSIZE]; 927 926 928 927 if (copy_from_user(&hdr, uarg, sizeof(hdr))) 929 928 return -EFAULT; 930 929 931 - rq = bsg_map_hdr(bd, &hdr, file->f_mode & FMODE_WRITE); 930 + rq = bsg_map_hdr(bd, &hdr, file->f_mode & FMODE_WRITE, sense); 932 931 if (IS_ERR(rq)) 933 932 return PTR_ERR(rq); 934 933