]> www.infradead.org Git - users/sagi/nvme-cli.git/commitdiff
nvme: PEL need to check gen number for verification of collected log
authorSteven Seungcheol Lee <sc108.lee@samsung.com>
Thu, 26 Aug 2021 03:06:11 +0000 (12:06 +0900)
committerKeith Busch <kbusch@kernel.org>
Thu, 26 Aug 2021 15:04:46 +0000 (09:04 -0600)
+fix bug(unallocated pointer free)

If the Persistent Event Log is not read with a single Get Log Page command,
then host software should read the Generation Number field in the Persistent Event Log header after establishing a reporting context
but before reading the remainder of the log and then re-read the Generation Number field after it has read the entire log.
If the generation numbers do not match, then:
    • the reporting context may have been lost while reading the log;
    • the Persistent Event Log contents read may be invalid; and
    • host software should re-read the log.

Signed-off-by: Steven Seungcheol Lee <sc108.lee@samsung.com>
nvme.c

diff --git a/nvme.c b/nvme.c
index c10932f0576b1e549c68e00609a37e47b554bdf0..8f970bb188aa25a53e3d003a77c2ee3582649753 100644 (file)
--- a/nvme.c
+++ b/nvme.c
@@ -929,7 +929,7 @@ static int get_persistent_event_log(int argc, char **argv,
        const char *log_len = "number of bytes to retrieve";
        const char *raw = "use binary output";
        void *pevent_log_info;
-       struct nvme_persistent_event_log_head *pevent_log_head = NULL;
+       struct nvme_persistent_event_log_head *pevent_log_head, *collected_head;
        enum nvme_print_flags flags;
        int err = -1, fd;
        bool huge;
@@ -985,22 +985,22 @@ static int get_persistent_event_log(int argc, char **argv,
                        sizeof(*pevent_log_head), pevent_log_head);
        if (err < 0) {
                perror("persistent event log");
-               goto close_fd;
+               goto free_head;
        } else if (err) {
                nvme_show_status(err);
-               goto close_fd;
+               goto free_head;
        }
 
        if (cfg.action == NVME_PEVENT_LOG_RELEASE_CTX) {
                printf("Releasing Persistent Event Log Context\n");
-               goto close_fd;
+               goto free_head;
        }
 
        if (!cfg.log_len && cfg.action != NVME_PEVENT_LOG_EST_CTX_AND_READ) {
                cfg.log_len = le64_to_cpu(pevent_log_head->tll);
        } else if (!cfg.log_len && cfg.action == NVME_PEVENT_LOG_EST_CTX_AND_READ) {
                printf("Establishing Persistent Event Log Context\n");
-               goto close_fd;
+               goto free_head;
        }
 
        /*
@@ -1018,22 +1018,39 @@ static int get_persistent_event_log(int argc, char **argv,
                perror("could not alloc buffer for persistent event log page\n");
                errno = ENOMEM;
                err = -1;
-               goto close_fd;
+               goto free_head;
        }
        err = nvme_persistent_event_log(fd, cfg.action,
                cfg.log_len, pevent_log_info);
-       if (!err)
+       if (!err) {
+               err = nvme_persistent_event_log(fd, cfg.action,
+                               sizeof(*pevent_log_head), pevent_log_head);
+               if (err < 0) {
+                       perror("persistent event log");
+                       goto free;
+               } else if (err) {
+                       nvme_show_status(err);
+                       goto free;
+               }
+               collected_head = pevent_log_info;
+               if(collected_head->gen_number != pevent_log_head->gen_number) {
+                       printf("Collected Persistent Event Log may be invalid, "\
+                               "Re-read the log is reiquired\n");
+                       goto free;
+               }
                nvme_show_persistent_event_log(pevent_log_info, cfg.action,
                        cfg.log_len, devicename, flags);
+       }
        else if (err > 0)
                nvme_show_status(err);
        else
                perror("persistent event log");
 
+free:
        nvme_free(pevent_log_info, huge);
-
-close_fd:
+free_head:
        free(pevent_log_head);
+close_fd:
        close(fd);
 ret:
        return nvme_status_to_errno(err, false);