lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20211229155302.16789-1-dwagner@suse.de>
Date:   Wed, 29 Dec 2021 16:53:02 +0100
From:   Daniel Wagner <dwagner@...e.de>
To:     linux-nvme@...ts.infradead.org
Cc:     linux-kernel@...r.kernel.org, Daniel Wagner <dwagner@...e.de>
Subject: [PATCH] nvmet: add support reading with offset from ANA log

Add support to read with offsets from ANA log buffer.

The controller claims to support extended data for the Get Log Page
command (including extended Number of Dwords and Log Page Offset 2
fields):

lpa     : 0x7
  [2:2] : 0x1   Extended data for Get Log Page Supported
  [1:1] : 0x1   Command Effects Log Page Supported
  [0:0] : 0x1   SMART/Health Log Page per NS Supported

Signed-off-by: Daniel Wagner <dwagner@...e.de>
---
 drivers/nvme/target/admin-cmd.c | 37 +++++++++++++++++++--------------
 1 file changed, 21 insertions(+), 16 deletions(-)

diff --git a/drivers/nvme/target/admin-cmd.c b/drivers/nvme/target/admin-cmd.c
index 6fb24746de06..7c8806f477e2 100644
--- a/drivers/nvme/target/admin-cmd.c
+++ b/drivers/nvme/target/admin-cmd.c
@@ -263,35 +263,40 @@ static u32 nvmet_format_ana_group(struct nvmet_req *req, u32 grpid,
 	desc->nnsids = cpu_to_le32(count);
 	desc->chgcnt = cpu_to_le64(nvmet_ana_chgcnt);
 	desc->state = req->port->ana_state[grpid];
-	memset(desc->rsvd17, 0, sizeof(desc->rsvd17));
 	return struct_size(desc, nsids, count);
 }
 
 static void nvmet_execute_get_log_page_ana(struct nvmet_req *req)
 {
-	struct nvme_ana_rsp_hdr hdr = { 0, };
+	struct nvme_ana_rsp_hdr *hdr;
 	struct nvme_ana_group_desc *desc;
-	size_t offset = sizeof(struct nvme_ana_rsp_hdr); /* start beyond hdr */
+	u64 offset = nvmet_get_log_page_offset(req->cmd);
 	size_t len;
+	void *buffer;
 	u32 grpid;
 	u16 ngrps = 0;
 	u16 status;
 
+	if (offset & 0x3) {
+		req->error_loc =
+			offsetof(struct nvme_get_log_page_command, lpo);
+		status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+		goto out;
+	}
+
 	status = NVME_SC_INTERNAL;
-	desc = kmalloc(struct_size(desc, nsids, NVMET_MAX_NAMESPACES),
-		       GFP_KERNEL);
-	if (!desc)
+	len = sizeof(*hdr) + struct_size(desc, nsids, NVMET_MAX_NAMESPACES);
+	buffer = kzalloc(len, GFP_KERNEL);
+	if (!buffer)
 		goto out;
+	hdr = buffer;
+	desc = buffer + sizeof(*hdr);
 
 	down_read(&nvmet_ana_sem);
 	for (grpid = 1; grpid <= NVMET_MAX_ANAGRPS; grpid++) {
 		if (!nvmet_ana_group_enabled[grpid])
 			continue;
-		len = nvmet_format_ana_group(req, grpid, desc);
-		status = nvmet_copy_to_sgl(req, offset, desc, len);
-		if (status)
-			break;
-		offset += len;
+		nvmet_format_ana_group(req, grpid, desc);
 		ngrps++;
 	}
 	for ( ; grpid <= NVMET_MAX_ANAGRPS; grpid++) {
@@ -299,15 +304,15 @@ static void nvmet_execute_get_log_page_ana(struct nvmet_req *req)
 			ngrps++;
 	}
 
-	hdr.chgcnt = cpu_to_le64(nvmet_ana_chgcnt);
-	hdr.ngrps = cpu_to_le16(ngrps);
+	hdr->chgcnt = cpu_to_le64(nvmet_ana_chgcnt);
+	hdr->ngrps = cpu_to_le16(ngrps);
 	nvmet_clear_aen_bit(req, NVME_AEN_BIT_ANA_CHANGE);
 	up_read(&nvmet_ana_sem);
 
-	kfree(desc);
+	status = nvmet_copy_to_sgl(req, 0, buffer + offset,
+				   nvmet_get_log_page_len(req->cmd));
 
-	/* copy the header last once we know the number of groups */
-	status = nvmet_copy_to_sgl(req, 0, &hdr, sizeof(hdr));
+	kfree(buffer);
 out:
 	nvmet_req_complete(req, status);
 }
-- 
2.29.2

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ