Linux block layer
 help / color / mirror / Atom feed
From: Pengpeng Hou <pengpeng@iscas.ac.cn>
To: jonathan.derrick@linux.dev, axboe@kernel.dk
Cc: Pengpeng Hou <pengpeng@iscas.ac.cn>,
	linux-block@vger.kernel.org, linux-kernel@vger.kernel.org,
	Scott Bauer <scott.bauer@intel.com>
Subject: [PATCH] block: sed-opal: validate response token bounds
Date: Wed, 15 Jul 2026 16:35:04 +0800	[thread overview]
Message-ID: <20260715083504.27022-1-pengpeng@iscas.ac.cn> (raw)

The response parser validates that the complete subpacket fits in the
response buffer, but it does not validate that each token is contained
within the declared subpacket before parsing it. A short atom's numeric
payload can be consumed before the loop subtracts its declared length.
Medium and long atoms can read additional header bytes before there is
proof that those bytes remain in the subpacket. The parser also stores
token metadata in a fixed MAX_TOKS array without a capacity check.

Pass the current subpacket remainder to the variable-width atom parsers
and reject truncated headers and tokens. Reject a response with more
tokens than the parsed response can retain, and validate the declared
subpacket length against the supplied response size.

Fixes: 455a7b238cd6 ("block: Add Sed-opal library")
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
---
 block/sed-opal.c | 49 +++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 40 insertions(+), 9 deletions(-)

diff --git a/block/sed-opal.c b/block/sed-opal.c
index 79b290d9458a..c0afd34f8e2f 100644
--- a/block/sed-opal.c
+++ b/block/sed-opal.c
@@ -936,12 +936,17 @@ static ssize_t response_parse_tiny(struct opal_resp_tok *tok,
 }
 
 static ssize_t response_parse_short(struct opal_resp_tok *tok,
-				    const u8 *pos)
+				    const u8 *pos, size_t remaining)
 {
 	tok->pos = pos;
 	tok->len = (pos[0] & SHORT_ATOM_LEN_MASK) + 1;
 	tok->width = OPAL_WIDTH_SHORT;
 
+	if (tok->len > remaining) {
+		pr_debug("Short atom exceeds response subpacket\n");
+		return -EINVAL;
+	}
+
 	if (pos[0] & SHORT_ATOM_BYTESTRING) {
 		tok->type = OPAL_DTA_TOKENID_BYTESTRING;
 	} else if (pos[0] & SHORT_ATOM_SIGNED) {
@@ -966,12 +971,22 @@ static ssize_t response_parse_short(struct opal_resp_tok *tok,
 }
 
 static ssize_t response_parse_medium(struct opal_resp_tok *tok,
-				     const u8 *pos)
+				     const u8 *pos, size_t remaining)
 {
+	if (remaining < 2) {
+		pr_debug("Truncated medium atom header\n");
+		return -EINVAL;
+	}
+
 	tok->pos = pos;
 	tok->len = (((pos[0] & MEDIUM_ATOM_LEN_MASK) << 8) | pos[1]) + 2;
 	tok->width = OPAL_WIDTH_MEDIUM;
 
+	if (tok->len > remaining) {
+		pr_debug("Medium atom exceeds response subpacket\n");
+		return -EINVAL;
+	}
+
 	if (pos[0] & MEDIUM_ATOM_BYTESTRING)
 		tok->type = OPAL_DTA_TOKENID_BYTESTRING;
 	else if (pos[0] & MEDIUM_ATOM_SIGNED)
@@ -983,12 +998,22 @@ static ssize_t response_parse_medium(struct opal_resp_tok *tok,
 }
 
 static ssize_t response_parse_long(struct opal_resp_tok *tok,
-				   const u8 *pos)
+				   const u8 *pos, size_t remaining)
 {
+	if (remaining < 4) {
+		pr_debug("Truncated long atom header\n");
+		return -EINVAL;
+	}
+
 	tok->pos = pos;
 	tok->len = ((pos[1] << 16) | (pos[2] << 8) | pos[3]) + 4;
 	tok->width = OPAL_WIDTH_LONG;
 
+	if (tok->len > remaining) {
+		pr_debug("Long atom exceeds response subpacket\n");
+		return -EINVAL;
+	}
+
 	if (pos[0] & LONG_ATOM_BYTESTRING)
 		tok->type = OPAL_DTA_TOKENID_BYTESTRING;
 	else if (pos[0] & LONG_ATOM_SIGNED)
@@ -1016,7 +1041,7 @@ static int response_parse(const u8 *buf, size_t length,
 	const struct opal_header *hdr;
 	struct opal_resp_tok *iter;
 	int num_entries = 0;
-	int total;
+	size_t total;
 	ssize_t token_length;
 	const u8 *pos;
 	u32 clen, plen, slen;
@@ -1027,6 +1052,9 @@ static int response_parse(const u8 *buf, size_t length,
 	if (!resp)
 		return -EFAULT;
 
+	if (length < sizeof(*hdr))
+		return -EINVAL;
+
 	hdr = (struct opal_header *)buf;
 	pos = buf;
 	pos += sizeof(*hdr);
@@ -1038,10 +1066,10 @@ static int response_parse(const u8 *buf, size_t length,
 		 clen, plen, slen);
 
 	if (clen == 0 || plen == 0 || slen == 0 ||
-	    slen > IO_BUFFER_LENGTH - sizeof(*hdr)) {
+	    slen > length - sizeof(*hdr)) {
 		pr_debug("Bad header length. cp: %u, pkt: %u, subpkt: %u\n",
 			 clen, plen, slen);
-		print_buffer(pos, sizeof(*hdr));
+		print_buffer(buf, sizeof(*hdr));
 		return -EINVAL;
 	}
 
@@ -1052,14 +1080,17 @@ static int response_parse(const u8 *buf, size_t length,
 	total = slen;
 	print_buffer(pos, total);
 	while (total > 0) {
+		if (iter == resp->toks + MAX_TOKS)
+			return -E2BIG;
+
 		if (pos[0] <= TINY_ATOM_BYTE) /* tiny atom */
 			token_length = response_parse_tiny(iter, pos);
 		else if (pos[0] <= SHORT_ATOM_BYTE) /* short atom */
-			token_length = response_parse_short(iter, pos);
+			token_length = response_parse_short(iter, pos, total);
 		else if (pos[0] <= MEDIUM_ATOM_BYTE) /* medium atom */
-			token_length = response_parse_medium(iter, pos);
+			token_length = response_parse_medium(iter, pos, total);
 		else if (pos[0] <= LONG_ATOM_BYTE) /* long atom */
-			token_length = response_parse_long(iter, pos);
+			token_length = response_parse_long(iter, pos, total);
 		else if (pos[0] == EMPTY_ATOM_BYTE) /* empty atom */
 			token_length = 1;
 		else /* TOKEN */
-- 
2.43.0


                 reply	other threads:[~2026-07-15  8:35 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260715083504.27022-1-pengpeng@iscas.ac.cn \
    --to=pengpeng@iscas.ac.cn \
    --cc=axboe@kernel.dk \
    --cc=jonathan.derrick@linux.dev \
    --cc=linux-block@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=scott.bauer@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox