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
next prev parent reply other threads:[~2026-05-11 16:06 UTC|newest]
Thread overview: 11+ 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-13 2:14 ` [PATCH 1/3] ntfs: return view index entry data from lookup Hyunchul Lee
2026-05-11 16:06 ` [PATCH 2/3] ntfs: use $Q when marking quotas out of date DaeMyung Kang
2026-05-13 14:53 ` Namjae Jeon
2026-05-11 16:06 ` [PATCH 3/3] ntfs: mark quotas out of date on initial rw mount DaeMyung Kang
2026-05-13 23:46 ` Hyunchul Lee
2026-05-14 13:25 ` CharSyam
2026-05-14 23:50 ` Hyunchul Lee
2026-05-15 0:35 ` CharSyam
2026-05-15 1:13 ` Hyunchul Lee
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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.