nvmet-trace: avoid dereferencing pointer too early
authorDaniel Wagner <dwagner@suse.de>
Mon, 18 Dec 2023 15:30:51 +0000 (16:30 +0100)
committerKeith Busch <kbusch@kernel.org>
Wed, 3 Jan 2024 16:09:41 +0000 (08:09 -0800)
The first command issued from the host to the target is the fabrics
connect command. At this point, neither the target queue nor the
controller have been allocated. But we already try to trace this command
in nvmet_req_init.

Reported by KASAN.

Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Daniel Wagner <dwagner@suse.de>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Keith Busch <kbusch@kernel.org>
drivers/nvme/target/trace.c
drivers/nvme/target/trace.h

index bff454d46255b42162667b12a193dc8b7205469a..6ee1f3db81d04071e761b39640e573c9770aa32f 100644 (file)
@@ -211,7 +211,7 @@ const char *nvmet_trace_disk_name(struct trace_seq *p, char *name)
        return ret;
 }
 
-const char *nvmet_trace_ctrl_name(struct trace_seq *p, struct nvmet_ctrl *ctrl)
+const char *nvmet_trace_ctrl_id(struct trace_seq *p, u16 ctrl_id)
 {
        const char *ret = trace_seq_buffer_ptr(p);
 
@@ -224,8 +224,8 @@ const char *nvmet_trace_ctrl_name(struct trace_seq *p, struct nvmet_ctrl *ctrl)
         * If we can know the extra data of the connect command in this stage,
         * we can update this print statement later.
         */
-       if (ctrl)
-               trace_seq_printf(p, "%d", ctrl->cntlid);
+       if (ctrl_id)
+               trace_seq_printf(p, "%d", ctrl_id);
        else
                trace_seq_printf(p, "_");
        trace_seq_putc(p, 0);
index 6109b3806b12be7dae3d429c083d1fa49ba92c05..2f15070ddc569fff2cc1281f355b4795c724ed8c 100644 (file)
@@ -32,18 +32,24 @@ const char *nvmet_trace_parse_fabrics_cmd(struct trace_seq *p, u8 fctype,
         nvmet_trace_parse_nvm_cmd(p, opcode, cdw10) :                  \
         nvmet_trace_parse_admin_cmd(p, opcode, cdw10)))
 
-const char *nvmet_trace_ctrl_name(struct trace_seq *p, struct nvmet_ctrl *ctrl);
-#define __print_ctrl_name(ctrl)                                \
-       nvmet_trace_ctrl_name(p, ctrl)
+const char *nvmet_trace_ctrl_id(struct trace_seq *p, u16 ctrl_id);
+#define __print_ctrl_id(ctrl_id)                       \
+       nvmet_trace_ctrl_id(p, ctrl_id)
 
 const char *nvmet_trace_disk_name(struct trace_seq *p, char *name);
 #define __print_disk_name(name)                                \
        nvmet_trace_disk_name(p, name)
 
 #ifndef TRACE_HEADER_MULTI_READ
-static inline struct nvmet_ctrl *nvmet_req_to_ctrl(struct nvmet_req *req)
+static inline u16 nvmet_req_to_ctrl_id(struct nvmet_req *req)
 {
-       return req->sq->ctrl;
+       /*
+        * The queue and controller pointers are not valid until an association
+        * has been established.
+        */
+       if (!req->sq || !req->sq->ctrl)
+               return 0;
+       return req->sq->ctrl->cntlid;
 }
 
 static inline void __assign_req_name(char *name, struct nvmet_req *req)
@@ -63,7 +69,7 @@ TRACE_EVENT(nvmet_req_init,
        TP_ARGS(req, cmd),
        TP_STRUCT__entry(
                __field(struct nvme_command *, cmd)
-               __field(struct nvmet_ctrl *, ctrl)
+               __field(u16, ctrl_id)
                __array(char, disk, DISK_NAME_LEN)
                __field(int, qid)
                __field(u16, cid)
@@ -76,7 +82,7 @@ TRACE_EVENT(nvmet_req_init,
        ),
        TP_fast_assign(
                __entry->cmd = cmd;
-               __entry->ctrl = nvmet_req_to_ctrl(req);
+               __entry->ctrl_id = nvmet_req_to_ctrl_id(req);
                __assign_req_name(__entry->disk, req);
                __entry->qid = req->sq->qid;
                __entry->cid = cmd->common.command_id;
@@ -90,7 +96,7 @@ TRACE_EVENT(nvmet_req_init,
        ),
        TP_printk("nvmet%s: %sqid=%d, cmdid=%u, nsid=%u, flags=%#x, "
                  "meta=%#llx, cmd=(%s, %s)",
-               __print_ctrl_name(__entry->ctrl),
+               __print_ctrl_id(__entry->ctrl_id),
                __print_disk_name(__entry->disk),
                __entry->qid, __entry->cid, __entry->nsid,
                __entry->flags, __entry->metadata,
@@ -104,7 +110,7 @@ TRACE_EVENT(nvmet_req_complete,
        TP_PROTO(struct nvmet_req *req),
        TP_ARGS(req),
        TP_STRUCT__entry(
-               __field(struct nvmet_ctrl *, ctrl)
+               __field(u16, ctrl_id)
                __array(char, disk, DISK_NAME_LEN)
                __field(int, qid)
                __field(int, cid)
@@ -112,7 +118,7 @@ TRACE_EVENT(nvmet_req_complete,
                __field(u16, status)
        ),
        TP_fast_assign(
-               __entry->ctrl = nvmet_req_to_ctrl(req);
+               __entry->ctrl_id = nvmet_req_to_ctrl_id(req);
                __entry->qid = req->cq->qid;
                __entry->cid = req->cqe->command_id;
                __entry->result = le64_to_cpu(req->cqe->result.u64);
@@ -120,7 +126,7 @@ TRACE_EVENT(nvmet_req_complete,
                __assign_req_name(__entry->disk, req);
        ),
        TP_printk("nvmet%s: %sqid=%d, cmdid=%u, res=%#llx, status=%#x",
-               __print_ctrl_name(__entry->ctrl),
+               __print_ctrl_id(__entry->ctrl_id),
                __print_disk_name(__entry->disk),
                __entry->qid, __entry->cid, __entry->result, __entry->status)