[PATCH 3/3] nvme: code command_id with a genctr for use-after-free validation

Sagi Grimberg sagi at grimberg.me
Mon May 17 13:23:08 PDT 2021


>> +static inline struct request *nvme_find_rq(struct blk_mq_tags *tags,
>> +		u16 command_id)
>> +{
>> +	u8 genctr = nvme_genctr_from_cid(command_id);
>> +	u16 tag = nvme_tag_from_cid(command_id);
>> +	struct request *rq;
>> +
>> +	rq = blk_mq_tag_to_rq(tags, tag);
>> +	if (unlikely(!rq)) {
>> +		pr_err("could not locate request for tag %#x\n",
>> +			tag);
>> +		return NULL;
>> +	}
>> +	if (unlikely(nvme_genctr_mask(nvme_req(rq)->genctr) != genctr)) {
>> +		dev_err(nvme_req(rq)->ctrl->device,
>> +			"request %#x genctr mismatch (got %#x expected %#x)\n",
>> +			tag, genctr, nvme_req(rq)->genctr);
>> +		return NULL;
>> +	}
> 
> Should we also check for blk_mq_request_started(rq) here? It doesn't look
> like the genctr is sufficient to detect a double completion of the same
> command_id if the driver hasn't had a chance to advance the genctr for a
> new request.

We could, maybe incrementing the counter again on the completion would
be better?



More information about the Linux-nvme mailing list