nvme fixes for Linux 6.6

- nvme-rdma queue fix (Maurizio)
  - nvmet-auth double free fix (Maurizio)
  - nvme-tcp use-after-free fix (Sagi)
  - nvme-auth data direction fix (Martin)
  - nvme passthrough metadata sanitization (Keith)
  - nvme bogus identifiers for multi-controller ssd (Keith)
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE3Fbyvv+648XNRdHTPe3zGtjzRgkFAmUwSk0ACgkQPe3zGtjz
 Rgk2Zg//VxDYxuJZGs8r/G3wFiMoQ/XJ+0rcykH/0SRTt8tmgzR9yhFMme/GXVrm
 P7ydvwxyB0NnsmSrB51thLhbPbvGozSqXYg44KlWohfmFXkCOmP/HzHxYFBSADoW
 VbqjXrY7KfsZN85qfY6pnn7kKvG4HDpdrc49QotTr8gI5Krk4DjH8Znm30sZwqug
 EisKfigFmsS+soW3xjKzqAmTMQaEjskvAjKP7tJiwBKPgykX3nSMqBDSJOg7Tal8
 d9bbtzLzBODhXklZD6+gg4AKkJGEhJfYgieddJDUW18ApUtdV5cm+E95jFslOF7z
 v3+wz6MzDxiQ+ObE/5CCZtqQDHD4mnP+FCAqGz8XRFXXKRoSzmPYfgcgBT3qr2AX
 GFWDPt9gbxqP91svbhmF4BWubHUNcmSLUln3OsY0zs2+/ijQA3DnlL1JdlNVeO20
 XNqd4coThSVYuNPL98+ntgSRmwOUGmKns6XDIwgjsDubbR2V9tOPSoTtOD+15Ewn
 48Z8hrA/7/H3fapXP4wF2YlEtkiCe6KADefkcWpnXioK7RmopFYXfPCTmc/9uQ9t
 dAectAsGfWSJ0RpTP1zIyiYdjVNLEEdZfxvDW7EdAW9u7rxk4kWfLy914QZeDBjB
 KwC9KVr8LH8m97qIXVMtfQnN69n67sXYDuQtHVHXwqTRvbMgKnQ=
 =gmU7
 -----END PGP SIGNATURE-----

Merge tag 'nvme-6.6-2023-10-18' of git://git.infradead.org/nvme into block-6.6

Pull NVMe fixes from Keith:

"nvme fixes for Linux 6.6

 - nvme-rdma queue fix (Maurizio)
 - nvmet-auth double free fix (Maurizio)
 - nvme-tcp use-after-free fix (Sagi)
 - nvme-auth data direction fix (Martin)
 - nvme passthrough metadata sanitization (Keith)
 - nvme bogus identifiers for multi-controller ssd (Keith)"

* tag 'nvme-6.6-2023-10-18' of git://git.infradead.org/nvme:
  nvme-pci: add BOGUS_NID for Intel 0a54 device
  nvmet-auth: complete a request only after freeing the dhchap pointers
  nvme: sanitize metadata bounce buffer for reads
  nvme-auth: use chap->s2 to indicate bidirectional authentication
  nvmet-tcp: Fix a possible UAF in queue intialization setup
  nvme-rdma: do not try to stop unallocated queues
This commit is contained in:
Jens Axboe 2023-10-18 15:32:51 -06:00
commit c3414550cb
6 changed files with 22 additions and 14 deletions

View File

@ -341,7 +341,7 @@ static int nvme_auth_process_dhchap_success1(struct nvme_ctrl *ctrl,
struct nvmf_auth_dhchap_success1_data *data = chap->buf;
size_t size = sizeof(*data);
if (chap->ctrl_key)
if (chap->s2)
size += chap->hash_len;
if (size > CHAP_BUF_SIZE) {
@ -825,7 +825,7 @@ static void nvme_queue_auth_work(struct work_struct *work)
goto fail2;
}
if (chap->ctrl_key) {
if (chap->s2) {
/* DH-HMAC-CHAP Step 5: send success2 */
dev_dbg(ctrl->device, "%s: qid %d send success2\n",
__func__, chap->qid);

View File

@ -108,9 +108,13 @@ static void *nvme_add_user_metadata(struct request *req, void __user *ubuf,
if (!buf)
goto out;
ret = -EFAULT;
if ((req_op(req) == REQ_OP_DRV_OUT) && copy_from_user(buf, ubuf, len))
goto out_free_meta;
if (req_op(req) == REQ_OP_DRV_OUT) {
ret = -EFAULT;
if (copy_from_user(buf, ubuf, len))
goto out_free_meta;
} else {
memset(buf, 0, len);
}
bip = bio_integrity_alloc(bio, GFP_KERNEL, 1);
if (IS_ERR(bip)) {

View File

@ -3329,7 +3329,8 @@ static const struct pci_device_id nvme_id_table[] = {
{ PCI_VDEVICE(INTEL, 0x0a54), /* Intel P4500/P4600 */
.driver_data = NVME_QUIRK_STRIPE_SIZE |
NVME_QUIRK_DEALLOCATE_ZEROES |
NVME_QUIRK_IGNORE_DEV_SUBNQN, },
NVME_QUIRK_IGNORE_DEV_SUBNQN |
NVME_QUIRK_BOGUS_NID, },
{ PCI_VDEVICE(INTEL, 0x0a55), /* Dell Express Flash P4600 */
.driver_data = NVME_QUIRK_STRIPE_SIZE |
NVME_QUIRK_DEALLOCATE_ZEROES, },

View File

@ -638,6 +638,9 @@ static void __nvme_rdma_stop_queue(struct nvme_rdma_queue *queue)
static void nvme_rdma_stop_queue(struct nvme_rdma_queue *queue)
{
if (!test_bit(NVME_RDMA_Q_ALLOCATED, &queue->flags))
return;
mutex_lock(&queue->queue_lock);
if (test_and_clear_bit(NVME_RDMA_Q_LIVE, &queue->flags))
__nvme_rdma_stop_queue(queue);

View File

@ -333,19 +333,21 @@ done:
__func__, ctrl->cntlid, req->sq->qid,
status, req->error_loc);
req->cqe->result.u64 = 0;
nvmet_req_complete(req, status);
if (req->sq->dhchap_step != NVME_AUTH_DHCHAP_MESSAGE_SUCCESS2 &&
req->sq->dhchap_step != NVME_AUTH_DHCHAP_MESSAGE_FAILURE2) {
unsigned long auth_expire_secs = ctrl->kato ? ctrl->kato : 120;
mod_delayed_work(system_wq, &req->sq->auth_expired_work,
auth_expire_secs * HZ);
return;
goto complete;
}
/* Final states, clear up variables */
nvmet_auth_sq_free(req->sq);
if (req->sq->dhchap_step == NVME_AUTH_DHCHAP_MESSAGE_FAILURE2)
nvmet_ctrl_fatal_error(ctrl);
complete:
nvmet_req_complete(req, status);
}
static int nvmet_auth_challenge(struct nvmet_req *req, void *d, int al)
@ -514,11 +516,12 @@ void nvmet_execute_auth_receive(struct nvmet_req *req)
kfree(d);
done:
req->cqe->result.u64 = 0;
nvmet_req_complete(req, status);
if (req->sq->dhchap_step == NVME_AUTH_DHCHAP_MESSAGE_SUCCESS2)
nvmet_auth_sq_free(req->sq);
else if (req->sq->dhchap_step == NVME_AUTH_DHCHAP_MESSAGE_FAILURE1) {
nvmet_auth_sq_free(req->sq);
nvmet_ctrl_fatal_error(ctrl);
}
nvmet_req_complete(req, status);
}

View File

@ -372,6 +372,7 @@ static void nvmet_tcp_fatal_error(struct nvmet_tcp_queue *queue)
static void nvmet_tcp_socket_error(struct nvmet_tcp_queue *queue, int status)
{
queue->rcv_state = NVMET_TCP_RECV_ERR;
if (status == -EPIPE || status == -ECONNRESET)
kernel_sock_shutdown(queue->sock, SHUT_RDWR);
else
@ -910,15 +911,11 @@ static int nvmet_tcp_handle_icreq(struct nvmet_tcp_queue *queue)
iov.iov_len = sizeof(*icresp);
ret = kernel_sendmsg(queue->sock, &msg, &iov, 1, iov.iov_len);
if (ret < 0)
goto free_crypto;
return ret; /* queue removal will cleanup */
queue->state = NVMET_TCP_Q_LIVE;
nvmet_prepare_receive_pdu(queue);
return 0;
free_crypto:
if (queue->hdr_digest || queue->data_digest)
nvmet_tcp_free_crypto(queue);
return ret;
}
static void nvmet_tcp_handle_req_failure(struct nvmet_tcp_queue *queue,