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: 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