BACKPORT: block: add blk_rq_set_block_pc()
With the optimizations around not clearing the full request at alloc time, we are leaving some of the needed init for REQ_TYPE_BLOCK_PC up to the user allocating the request. Add a blk_rq_set_block_pc() that sets the command type to REQ_TYPE_BLOCK_PC, and properly initializes the members associated with this type of request. Update callers to use this function instead of manipulating rq->cmd_type directly. Includes fixes from Christoph Hellwig <hch@lst.de> for my half-assed attempt. Change-Id: Ifc386dfb951c5d6adebf48ff38135dda28e4b1ce Signed-off-by: Jens Axboe <axboe@fb.com> CVE-2017-7187 Signed-off-by: Kevin F. Haggerty <haggertk@lineageos.org>
This commit is contained in:
parent
2f91ba612a
commit
fac436f91c
|
@ -1047,6 +1047,8 @@ struct request *blk_make_request(struct request_queue *q, struct bio *bio,
|
|||
if (unlikely(!rq))
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
blk_rq_set_block_pc(rq);
|
||||
|
||||
for_each_bio(bio) {
|
||||
struct bio *bounce_bio = bio;
|
||||
int ret;
|
||||
|
@ -1063,6 +1065,22 @@ struct request *blk_make_request(struct request_queue *q, struct bio *bio,
|
|||
}
|
||||
EXPORT_SYMBOL(blk_make_request);
|
||||
|
||||
/**
|
||||
* blk_rq_set_block_pc - initialize a requeest to type BLOCK_PC
|
||||
* @rq: request to be initialized
|
||||
*
|
||||
*/
|
||||
void blk_rq_set_block_pc(struct request *rq)
|
||||
{
|
||||
rq->cmd_type = REQ_TYPE_BLOCK_PC;
|
||||
rq->__data_len = 0;
|
||||
rq->__sector = (sector_t) -1;
|
||||
rq->bio = rq->biotail = NULL;
|
||||
memset(rq->__cmd, 0, sizeof(rq->__cmd));
|
||||
rq->cmd = rq->__cmd;
|
||||
}
|
||||
EXPORT_SYMBOL(blk_rq_set_block_pc);
|
||||
|
||||
/**
|
||||
* blk_requeue_request - put a request back on queue
|
||||
* @q: request queue where request should be inserted
|
||||
|
|
|
@ -196,7 +196,6 @@ static int blk_fill_sgv4_hdr_rq(struct request_queue *q, struct request *rq,
|
|||
* fill in request structure
|
||||
*/
|
||||
rq->cmd_len = hdr->request_len;
|
||||
rq->cmd_type = REQ_TYPE_BLOCK_PC;
|
||||
|
||||
rq->timeout = msecs_to_jiffies(hdr->timeout);
|
||||
if (!rq->timeout)
|
||||
|
@ -273,6 +272,8 @@ bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, fmode_t has_write_perm,
|
|||
rq = blk_get_request(q, rw, GFP_KERNEL);
|
||||
if (!rq)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
blk_rq_set_block_pc(rq);
|
||||
|
||||
ret = blk_fill_sgv4_hdr_rq(q, rq, hdr, bd, has_write_perm);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
|
|
@ -232,7 +232,6 @@ static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq,
|
|||
* fill in request structure
|
||||
*/
|
||||
rq->cmd_len = hdr->cmd_len;
|
||||
rq->cmd_type = REQ_TYPE_BLOCK_PC;
|
||||
|
||||
rq->timeout = msecs_to_jiffies(hdr->timeout);
|
||||
if (!rq->timeout)
|
||||
|
@ -313,6 +312,7 @@ static int sg_io(struct request_queue *q, struct gendisk *bd_disk,
|
|||
rq = blk_get_request(q, writing ? WRITE : READ, GFP_KERNEL);
|
||||
if (!rq)
|
||||
return -ENOMEM;
|
||||
blk_rq_set_block_pc(rq);
|
||||
|
||||
if (blk_fill_sghdr_rq(q, rq, hdr, mode)) {
|
||||
blk_put_request(rq);
|
||||
|
@ -511,7 +511,7 @@ int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk, fmode_t mode,
|
|||
memset(sense, 0, sizeof(sense));
|
||||
rq->sense = sense;
|
||||
rq->sense_len = 0;
|
||||
rq->cmd_type = REQ_TYPE_BLOCK_PC;
|
||||
blk_rq_set_block_pc(rq);
|
||||
|
||||
blk_execute_rq(q, disk, rq, 0);
|
||||
|
||||
|
@ -543,7 +543,7 @@ static int __blk_send_generic(struct request_queue *q, struct gendisk *bd_disk,
|
|||
int err;
|
||||
|
||||
rq = blk_get_request(q, WRITE, __GFP_WAIT);
|
||||
rq->cmd_type = REQ_TYPE_BLOCK_PC;
|
||||
blk_rq_set_block_pc(rq);
|
||||
rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
|
||||
rq->cmd[0] = cmd;
|
||||
rq->cmd[4] = data;
|
||||
|
|
|
@ -742,6 +742,7 @@ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command *
|
|||
|
||||
rq = blk_get_request(q, (cgc->data_direction == CGC_DATA_WRITE) ?
|
||||
WRITE : READ, __GFP_WAIT);
|
||||
blk_rq_set_block_pc(rq);
|
||||
|
||||
if (cgc->buflen) {
|
||||
if (blk_rq_map_kern(q, rq, cgc->buffer, cgc->buflen, __GFP_WAIT))
|
||||
|
@ -752,7 +753,6 @@ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command *
|
|||
memcpy(rq->cmd, cgc->cmd, CDROM_PACKET_SIZE);
|
||||
|
||||
rq->timeout = 60*HZ;
|
||||
rq->cmd_type = REQ_TYPE_BLOCK_PC;
|
||||
if (cgc->quiet)
|
||||
rq->cmd_flags |= REQ_QUIET;
|
||||
|
||||
|
|
|
@ -2165,6 +2165,7 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
|
|||
ret = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
blk_rq_set_block_pc(rq);
|
||||
|
||||
ret = blk_rq_map_user(q, rq, NULL, ubuf, len, GFP_KERNEL);
|
||||
if (ret) {
|
||||
|
@ -2184,7 +2185,6 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
|
|||
rq->cmd[9] = 0xf8;
|
||||
|
||||
rq->cmd_len = 12;
|
||||
rq->cmd_type = REQ_TYPE_BLOCK_PC;
|
||||
rq->timeout = 60 * HZ;
|
||||
bio = rq->bio;
|
||||
|
||||
|
|
|
@ -111,6 +111,7 @@ static struct request *get_alua_req(struct scsi_device *sdev,
|
|||
"%s: blk_get_request failed\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
blk_rq_set_block_pc(rq);
|
||||
|
||||
if (buflen && blk_rq_map_kern(q, rq, buffer, buflen, GFP_NOIO)) {
|
||||
blk_put_request(rq);
|
||||
|
@ -119,7 +120,6 @@ static struct request *get_alua_req(struct scsi_device *sdev,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
rq->cmd_type = REQ_TYPE_BLOCK_PC;
|
||||
rq->cmd_flags |= REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
|
||||
REQ_FAILFAST_DRIVER;
|
||||
rq->retries = ALUA_FAILOVER_RETRIES;
|
||||
|
|
|
@ -280,6 +280,7 @@ static struct request *get_req(struct scsi_device *sdev, int cmd,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
blk_rq_set_block_pc(rq);
|
||||
rq->cmd_len = COMMAND_SIZE(cmd);
|
||||
rq->cmd[0] = cmd;
|
||||
|
||||
|
@ -304,7 +305,6 @@ static struct request *get_req(struct scsi_device *sdev, int cmd,
|
|||
break;
|
||||
}
|
||||
|
||||
rq->cmd_type = REQ_TYPE_BLOCK_PC;
|
||||
rq->cmd_flags |= REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
|
||||
REQ_FAILFAST_DRIVER;
|
||||
rq->timeout = CLARIION_TIMEOUT;
|
||||
|
|
|
@ -120,7 +120,7 @@ retry:
|
|||
if (!req)
|
||||
return SCSI_DH_RES_TEMP_UNAVAIL;
|
||||
|
||||
req->cmd_type = REQ_TYPE_BLOCK_PC;
|
||||
blk_rq_set_block_pc(req);
|
||||
req->cmd_flags |= REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
|
||||
REQ_FAILFAST_DRIVER;
|
||||
req->cmd_len = COMMAND_SIZE(TEST_UNIT_READY);
|
||||
|
@ -250,7 +250,7 @@ static int hp_sw_start_stop(struct hp_sw_dh_data *h)
|
|||
if (!req)
|
||||
return SCSI_DH_RES_TEMP_UNAVAIL;
|
||||
|
||||
req->cmd_type = REQ_TYPE_BLOCK_PC;
|
||||
blk_rq_set_block_pc(req);
|
||||
req->cmd_flags |= REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
|
||||
REQ_FAILFAST_DRIVER;
|
||||
req->cmd_len = COMMAND_SIZE(START_STOP);
|
||||
|
|
|
@ -279,6 +279,7 @@ static struct request *get_rdac_req(struct scsi_device *sdev,
|
|||
"get_rdac_req: blk_get_request failed.\n");
|
||||
return NULL;
|
||||
}
|
||||
blk_rq_set_block_pc(rq);
|
||||
|
||||
if (buflen && blk_rq_map_kern(q, rq, buffer, buflen, GFP_NOIO)) {
|
||||
blk_put_request(rq);
|
||||
|
@ -287,7 +288,6 @@ static struct request *get_rdac_req(struct scsi_device *sdev,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
rq->cmd_type = REQ_TYPE_BLOCK_PC;
|
||||
rq->cmd_flags |= REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
|
||||
REQ_FAILFAST_DRIVER;
|
||||
rq->retries = RDAC_RETRIES;
|
||||
|
|
|
@ -1566,6 +1566,7 @@ static struct request *_make_request(struct request_queue *q, bool has_write,
|
|||
if (unlikely(!req))
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
blk_rq_set_block_pc(req);
|
||||
return req;
|
||||
}
|
||||
}
|
||||
|
@ -1586,7 +1587,6 @@ static int _init_blk_request(struct osd_request *or,
|
|||
}
|
||||
|
||||
or->request = req;
|
||||
req->cmd_type = REQ_TYPE_BLOCK_PC;
|
||||
req->cmd_flags |= REQ_QUIET;
|
||||
|
||||
req->timeout = or->timeout;
|
||||
|
@ -1604,7 +1604,7 @@ static int _init_blk_request(struct osd_request *or,
|
|||
ret = PTR_ERR(req);
|
||||
goto out;
|
||||
}
|
||||
req->cmd_type = REQ_TYPE_BLOCK_PC;
|
||||
blk_rq_set_block_pc(req);
|
||||
or->in.req = or->request->next_rq = req;
|
||||
}
|
||||
} else if (has_in)
|
||||
|
|
|
@ -365,7 +365,7 @@ static int osst_execute(struct osst_request *SRpnt, const unsigned char *cmd,
|
|||
if (!req)
|
||||
return DRIVER_ERROR << 24;
|
||||
|
||||
req->cmd_type = REQ_TYPE_BLOCK_PC;
|
||||
blk_rq_set_block_pc(req);
|
||||
req->cmd_flags |= REQ_QUIET;
|
||||
|
||||
SRpnt->bio = NULL;
|
||||
|
|
|
@ -1643,6 +1643,8 @@ static void scsi_eh_lock_door(struct scsi_device *sdev)
|
|||
*/
|
||||
req = blk_get_request(sdev->request_queue, READ, GFP_KERNEL);
|
||||
|
||||
blk_rq_set_block_pc(req);
|
||||
|
||||
req->cmd[0] = ALLOW_MEDIUM_REMOVAL;
|
||||
req->cmd[1] = 0;
|
||||
req->cmd[2] = 0;
|
||||
|
@ -1652,7 +1654,6 @@ static void scsi_eh_lock_door(struct scsi_device *sdev)
|
|||
|
||||
req->cmd_len = COMMAND_SIZE(req->cmd[0]);
|
||||
|
||||
req->cmd_type = REQ_TYPE_BLOCK_PC;
|
||||
req->cmd_flags |= REQ_QUIET;
|
||||
req->timeout = 10 * HZ;
|
||||
req->retries = 5;
|
||||
|
|
|
@ -217,6 +217,7 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
|
|||
req = blk_get_request(sdev->request_queue, write, __GFP_WAIT);
|
||||
if (!req)
|
||||
return ret;
|
||||
blk_rq_set_block_pc(req);
|
||||
|
||||
if (bufflen && blk_rq_map_kern(sdev->request_queue, req,
|
||||
buffer, bufflen, __GFP_WAIT))
|
||||
|
@ -228,7 +229,6 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
|
|||
req->sense_len = 0;
|
||||
req->retries = retries;
|
||||
req->timeout = timeout;
|
||||
req->cmd_type = REQ_TYPE_BLOCK_PC;
|
||||
req->cmd_flags |= flags | REQ_QUIET | REQ_PREEMPT;
|
||||
|
||||
/*
|
||||
|
|
|
@ -1659,10 +1659,9 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd)
|
|||
if (!rq)
|
||||
return -ENOMEM;
|
||||
|
||||
blk_rq_set_block_pc(rq);
|
||||
memcpy(rq->cmd, cmd, hp->cmd_len);
|
||||
|
||||
rq->cmd_len = hp->cmd_len;
|
||||
rq->cmd_type = REQ_TYPE_BLOCK_PC;
|
||||
|
||||
srp->rq = rq;
|
||||
rq->end_io_data = srp;
|
||||
|
|
|
@ -488,7 +488,7 @@ static int st_scsi_execute(struct st_request *SRpnt, const unsigned char *cmd,
|
|||
if (!req)
|
||||
return DRIVER_ERROR << 24;
|
||||
|
||||
req->cmd_type = REQ_TYPE_BLOCK_PC;
|
||||
blk_rq_set_block_pc(req);
|
||||
req->cmd_flags |= REQ_QUIET;
|
||||
|
||||
mdata->null_mapped = 1;
|
||||
|
|
|
@ -1085,6 +1085,8 @@ static int pscsi_do_task(struct se_task *task)
|
|||
TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
blk_rq_set_block_pc(req);
|
||||
} else {
|
||||
BUG_ON(!task->task_size);
|
||||
|
||||
|
@ -1106,7 +1108,6 @@ static int pscsi_do_task(struct se_task *task)
|
|||
}
|
||||
}
|
||||
|
||||
req->cmd_type = REQ_TYPE_BLOCK_PC;
|
||||
req->end_io = pscsi_req_done;
|
||||
req->end_io_data = task;
|
||||
req->cmd_len = scsi_command_size(pt->pscsi_cdb);
|
||||
|
|
|
@ -683,6 +683,7 @@ extern void __blk_put_request(struct request_queue *, struct request *);
|
|||
extern struct request *blk_get_request(struct request_queue *, int, gfp_t);
|
||||
extern struct request *blk_make_request(struct request_queue *, struct bio *,
|
||||
gfp_t);
|
||||
extern void blk_rq_set_block_pc(struct request *);
|
||||
extern void blk_requeue_request(struct request_queue *, struct request *);
|
||||
extern int blk_reinsert_request(struct request_queue *q, struct request *rq);
|
||||
extern bool blk_reinsert_req_sup(struct request_queue *q);
|
||||
|
|
Loading…
Reference in New Issue