The Linux Kernel Mailing List
 help / color / mirror / Atom feed
From: DaeMyung Kang <charsyam@gmail.com>
To: linkinjeon@kernel.org, hyc.lee@gmail.com
Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org,
	DaeMyung Kang <charsyam@gmail.com>
Subject: [PATCH 1/3] ntfs: return view index entry data from lookup
Date: Tue, 12 May 2026 01:06:23 +0900	[thread overview]
Message-ID: <20260511160626.1268612-2-charsyam@gmail.com> (raw)
In-Reply-To: <20260511160626.1268612-1-charsyam@gmail.com>

ntfs_index_lookup() always exposes the matched entry key through
icx->data.  That is correct for file name indexes, where $I30 callers
expect the key to be a struct file_name_attr and update it in place.

NTFS view indexes store a separate value in index_entry.data.vi.  For
example, $Quota/$Q uses the owner_id as the key and stores the
quota_control_entry in the entry value.  Returning the key makes quota code
see only the 4-byte owner_id instead of the quota control entry.

Preserve the existing $FILE_NAME index behavior, but return the entry value
for view indexes.  Use the index root type for that layout decision:
indexes with ir->type == AT_FILE_NAME expose the entry key, while view
indexes have type 0 and expose the entry value through data.vi.  Validate
the value offset and length before exposing the pointer, and clear
icx->data when the key is not found because the context then describes an
insertion point rather than a matched value.  Use unsigned arithmetic for
the minimum data offset check, account for the VCN stored at the end of
INDEX_ENTRY_NODE entries, and clear the returned context pointers before
returning an entry-data validation error.

Move the matched-entry data exposure and validation into a small helper,
ntfs_index_lookup_set_data(), so the done label stays flat and the bounds
check has a single return.

Signed-off-by: DaeMyung Kang <charsyam@gmail.com>
---
 fs/ntfs/index.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
 fs/ntfs/index.h |  3 +-
 2 files changed, 73 insertions(+), 5 deletions(-)

diff --git a/fs/ntfs/index.c b/fs/ntfs/index.c
index a547bdc..30dfcbb 100644
--- a/fs/ntfs/index.c
+++ b/fs/ntfs/index.c
@@ -696,6 +696,53 @@ static int ntfs_icx_parent_dec(struct ntfs_index_context *icx)
 }

 /*
+ * ntfs_index_lookup_set_data - populate icx->data for the matched entry
+ *
+ * For directory $FILE_NAME indexes the caller updates the key in place, so
+ * expose the key.  For view indexes the value lives at data.vi; validate
+ * its offset and length before exposing the pointer.  Return 0 on success,
+ * or -EIO if the entry value is out of bounds.
+ */
+static int ntfs_index_lookup_set_data(struct ntfs_index_context *icx,
+				      struct index_root *ir,
+				      struct index_entry *ie)
+{
+	u16 data_len, data_off, entry_len, found_key_len;
+	unsigned int data_end, min_data_off;
+
+	if (ie->flags & INDEX_ENTRY_END)
+		return -EIO;
+
+	found_key_len = le16_to_cpu(ie->key_length);
+	if (ir->type == AT_FILE_NAME) {
+		icx->data = (u8 *)ie + offsetof(struct index_entry, key);
+		icx->data_len = found_key_len;
+		return 0;
+	}
+
+	entry_len = le16_to_cpu(ie->length);
+	data_off = le16_to_cpu(ie->data.vi.data_offset);
+	data_len = le16_to_cpu(ie->data.vi.data_length);
+	data_end = entry_len;
+	if (ie->flags & INDEX_ENTRY_NODE) {
+		/* The trailing child VCN is not part of the entry value. */
+		if (data_end < sizeof(s64))
+			return -EIO;
+		data_end -= sizeof(s64);
+	}
+
+	min_data_off = offsetof(struct index_entry, key) + found_key_len;
+	if (data_off < min_data_off || data_off > data_end)
+		return -EIO;
+	if (data_len > data_end - data_off)
+		return -EIO;
+
+	icx->data = (u8 *)ie + data_off;
+	icx->data_len = data_len;
+	return 0;
+}
+
+/*
  * ntfs_index_lookup - find a key in an index and return its index entry
  * @key:	key for which to search in the index
  * @key_len:	length of @key in bytes
@@ -710,7 +757,8 @@ static int ntfs_icx_parent_dec(struct ntfs_index_context *icx)
  * If the @key is found in the index, 0 is returned and @icx is setup to
  * describe the index entry containing the matching @key.  @icx->entry is the
  * index entry and @icx->data and @icx->data_len are the index entry data and
- * its length in bytes, respectively.
+ * its length in bytes, respectively.  For file name indexes @icx->data points
+ * to the entry key; for view indexes @icx->data points to the entry value.
  *
  * If the @key is not found in the index, -ENOENT is returned and
  * @icx is setup to describe the index entry whose key collates immediately
@@ -836,11 +884,30 @@ err_out:
 	return err;
 done:
 	icx->entry = ie;
-	icx->data = (u8 *)ie + offsetof(struct index_entry, key);
-	icx->data_len = le16_to_cpu(ie->key_length);
+	if (err) {
+		/* When the key is not found, ie is an insertion point. */
+		icx->data = NULL;
+		icx->data_len = 0;
+		ntfs_debug("Done.\n");
+		return err;
+	}
+	err = ntfs_index_lookup_set_data(icx, ir, ie);
+	if (err) {
+		ntfs_error(sb,
+			   "Index entry data out of bounds in inode 0x%llx.",
+			   (unsigned long long)ni->mft_no);
+		icx->entry = NULL;
+		icx->data = NULL;
+		icx->data_len = 0;
+		if (!icx->is_in_root) {
+			kvfree(ib);
+			ib = NULL;
+			icx->ib = NULL;
+		}
+		goto err_out;
+	}
 	ntfs_debug("Done.\n");
 	return err;
-
 }

 static struct index_block *ntfs_ib_alloc(s64 ib_vcn, u32 ib_size,
diff --git a/fs/ntfs/index.h b/fs/ntfs/index.h
index e68d6fa..4b8c5c8 100644
--- a/fs/ntfs/index.h
+++ b/fs/ntfs/index.h
@@ -58,7 +58,8 @@
  * To obtain a context call ntfs_index_ctx_get().
  *
  * We use this context to allow ntfs_index_lookup() to return the found index
  * @entry and its @data without having to allocate a buffer and copy the @entry
- * and/or its @data into it.
+ * and/or its @data into it.  For file name indexes @data points to the entry
+ * key; for view indexes @data points to the entry value.
  *
  * When finished with the @entry and its @data, call ntfs_index_ctx_put() to
  * free the context and other associated resources.
--
2.43.0

  reply	other threads:[~2026-05-11 16:06 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-11 16:06 [PATCH 0/3] ntfs: fix quota out-of-date marking DaeMyung Kang
2026-05-11 16:06 ` DaeMyung Kang [this message]
2026-05-11 16:06 ` [PATCH 2/3] ntfs: use $Q when marking quotas out of date DaeMyung Kang
2026-05-11 16:06 ` [PATCH 3/3] ntfs: mark quotas out of date on initial rw mount DaeMyung Kang

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=20260511160626.1268612-2-charsyam@gmail.com \
    --to=charsyam@gmail.com \
    --cc=hyc.lee@gmail.com \
    --cc=linkinjeon@kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    /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