forked from Minki/linux
nvme: avoid possible double fetch in handling CQE
While handling the completion queue, keep a local copy of the command id from the DMA-accessible completion entry. This silences a time-of-check to time-of-use (TOCTOU) warning from KF/x[1], with respect to a Thunderclap[2] vulnerability analysis. The double-read impact appears benign. There may be a theoretical window for @command_id to be used as an adversary-controlled array-index-value for mounting a speculative execution attack, but that mitigation is saved for a potential follow-on. A man-in-the-middle attack on the data payload is out of scope for this analysis and is hopefully mitigated by filesystem integrity mechanisms. [1] https://github.com/intel/kernel-fuzzer-for-xen-project [2] http://thunderclap.io/thunderclap-paper-ndss2019.pdf Signed-off-by: Lalithambika Krishna Kumar <lalithambika.krishnakumar@intel.com> Signed-off-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
parent
5c11f7d9f8
commit
62df80165d
@ -967,6 +967,7 @@ static inline struct blk_mq_tags *nvme_queue_tagset(struct nvme_queue *nvmeq)
|
||||
static inline void nvme_handle_cqe(struct nvme_queue *nvmeq, u16 idx)
|
||||
{
|
||||
struct nvme_completion *cqe = &nvmeq->cqes[idx];
|
||||
__u16 command_id = READ_ONCE(cqe->command_id);
|
||||
struct request *req;
|
||||
|
||||
/*
|
||||
@ -975,17 +976,17 @@ static inline void nvme_handle_cqe(struct nvme_queue *nvmeq, u16 idx)
|
||||
* aborts. We don't even bother to allocate a struct request
|
||||
* for them but rather special case them here.
|
||||
*/
|
||||
if (unlikely(nvme_is_aen_req(nvmeq->qid, cqe->command_id))) {
|
||||
if (unlikely(nvme_is_aen_req(nvmeq->qid, command_id))) {
|
||||
nvme_complete_async_event(&nvmeq->dev->ctrl,
|
||||
cqe->status, &cqe->result);
|
||||
return;
|
||||
}
|
||||
|
||||
req = blk_mq_tag_to_rq(nvme_queue_tagset(nvmeq), cqe->command_id);
|
||||
req = blk_mq_tag_to_rq(nvme_queue_tagset(nvmeq), command_id);
|
||||
if (unlikely(!req)) {
|
||||
dev_warn(nvmeq->dev->ctrl.device,
|
||||
"invalid id %d completed on queue %d\n",
|
||||
cqe->command_id, le16_to_cpu(cqe->sq_id));
|
||||
command_id, le16_to_cpu(cqe->sq_id));
|
||||
return;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user