nvmet-auth: expire authentication sessions
authorHannes Reinecke <hare@suse.de>
Mon, 27 Jun 2022 09:52:07 +0000 (11:52 +0200)
committerJens Axboe <axboe@kernel.dk>
Tue, 2 Aug 2022 23:14:50 +0000 (17:14 -0600)
Each authentication step is required to be completed within the
KATO interval (or two minutes if not set). So add a workqueue function
to reset the transaction ID and the expected next protocol step;
this will automatically the next authentication command referring
to the terminated authentication.

Signed-off-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
drivers/nvme/target/auth.c
drivers/nvme/target/fabrics-cmd-auth.c
drivers/nvme/target/nvmet.h

index d5624bd..bf92435 100644 (file)
@@ -218,6 +218,7 @@ out_unlock:
 
 void nvmet_auth_sq_free(struct nvmet_sq *sq)
 {
+       cancel_delayed_work(&sq->auth_expired_work);
        kfree(sq->dhchap_c1);
        sq->dhchap_c1 = NULL;
        kfree(sq->dhchap_c2);
index 5b1be7e..cc56e8c 100644 (file)
 #include <crypto/kpp.h>
 #include "nvmet.h"
 
+static void nvmet_auth_expired_work(struct work_struct *work)
+{
+       struct nvmet_sq *sq = container_of(to_delayed_work(work),
+                       struct nvmet_sq, auth_expired_work);
+
+       pr_debug("%s: ctrl %d qid %d transaction %u expired, resetting\n",
+                __func__, sq->ctrl->cntlid, sq->qid, sq->dhchap_tid);
+       sq->dhchap_step = NVME_AUTH_DHCHAP_MESSAGE_NEGOTIATE;
+       sq->dhchap_tid = -1;
+}
+
 void nvmet_init_auth(struct nvmet_ctrl *ctrl, struct nvmet_req *req)
 {
        u32 result = le32_to_cpu(req->cqe->result.u32);
 
        /* Initialize in-band authentication */
+       INIT_DELAYED_WORK(&req->sq->auth_expired_work,
+                         nvmet_auth_expired_work);
        req->sq->authenticated = false;
        req->sq->dhchap_step = NVME_AUTH_DHCHAP_MESSAGE_NEGOTIATE;
        result |= (u32)NVME_CONNECT_AUTHREQ_ATR << 16;
@@ -333,8 +346,13 @@ done:
        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)
+           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;
+       }
        /* Final states, clear up variables */
        nvmet_auth_sq_free(req->sq);
        if (req->sq->dhchap_step == NVME_AUTH_DHCHAP_MESSAGE_FAILURE2)
index b76b291..6ffeeb0 100644 (file)
@@ -109,6 +109,7 @@ struct nvmet_sq {
        u32                     sqhd;
        bool                    sqhd_disabled;
 #ifdef CONFIG_NVME_TARGET_AUTH
+       struct delayed_work     auth_expired_work;
        bool                    authenticated;
        u16                     dhchap_tid;
        u16                     dhchap_status;