public inbox for ntfs3@lists.linux.dev
 help / color / mirror / Atom feed
From: lei lu <llfamsec@gmail.com>
To: almaz.alexandrovich@paragon-software.com, ntfs3@lists.linux.dev
Subject: [PATCH v2] ntfs3: Add bounds checking to enum_rstbl()
Date: Tue,  9 Jul 2024 11:48:23 +0800	[thread overview]
Message-ID: <20240709034823.176357-1-llfamsec@gmail.com> (raw)

Added bounds checking to make sure rsize is not less than the entry
size and make sure the remaining bytes are large enough to hold an
entry before accessing in the caller.

Signed-off-by: lei lu <llfamsec@gmail.com>
---
 fs/ntfs3/fslog.c | 33 +++++++++++++++++++--------------
 1 file changed, 19 insertions(+), 14 deletions(-)

diff --git a/fs/ntfs3/fslog.c b/fs/ntfs3/fslog.c
index 855519713bf7..5bdb31ffab3a 100644
--- a/fs/ntfs3/fslog.c
+++ b/fs/ntfs3/fslog.c
@@ -609,12 +609,15 @@ static inline void add_client(struct CLIENT_REC *ca, u16 index, __le16 *head)
 	*head = cpu_to_le16(index);
 }
 
-static inline void *enum_rstbl(struct RESTART_TABLE *t, void *c)
+static inline void *enum_rstbl(struct RESTART_TABLE *t, void *c, u16 esize)
 {
 	__le32 *e;
 	u32 bprt;
 	u16 rsize = t ? le16_to_cpu(t->size) : 0;
 
+	if (rsize < esize)
+		return NULL;
+
 	if (!c) {
 		if (!t || !t->total)
 			return NULL;
@@ -626,6 +629,8 @@ static inline void *enum_rstbl(struct RESTART_TABLE *t, void *c)
 	/* Loop until we hit the first one allocated, or the end of the list. */
 	for (bprt = bytes_per_rt(t); PtrOffset(t, e) < bprt;
 	     e = Add2Ptr(e, rsize)) {
+		if (PtrOffset(t, Add2Ptr(e, esize)) > bprt)
+			return NULL;
 		if (*e == RESTART_ENTRY_ALLOCATED_LE)
 			return e;
 	}
@@ -641,7 +646,7 @@ static inline struct DIR_PAGE_ENTRY *find_dp(struct RESTART_TABLE *dptbl,
 	__le32 ta = cpu_to_le32(target_attr);
 	struct DIR_PAGE_ENTRY *dp = NULL;
 
-	while ((dp = enum_rstbl(dptbl, dp))) {
+	while ((dp = enum_rstbl(dptbl, dp, sizeof(*dp)))) {
 		u64 dp_vcn = le64_to_cpu(dp->vcn);
 
 		if (dp->target_attr == ta && vcn >= dp_vcn &&
@@ -2950,7 +2955,7 @@ static struct OpenAttr *find_loaded_attr(struct ntfs_log *log,
 {
 	struct OPEN_ATTR_ENRTY *oe = NULL;
 
-	while ((oe = enum_rstbl(log->open_attr_tbl, oe))) {
+	while ((oe = enum_rstbl(log->open_attr_tbl, oe, sizeof(*oe)))) {
 		struct OpenAttr *op_attr;
 
 		if (ino_get(&oe->ref) != rno)
@@ -4182,7 +4187,7 @@ int log_replay(struct ntfs_inode *ni, bool *initialized)
 		goto end_conv_1;
 
 	dp = NULL;
-	while ((dp = enum_rstbl(dptbl, dp))) {
+	while ((dp = enum_rstbl(dptbl, dp, sizeof(struct DIR_PAGE_ENTRY_32)))) {
 		struct DIR_PAGE_ENTRY_32 *dp0 = (struct DIR_PAGE_ENTRY_32 *)dp;
 		// NOTE: Danger. Check for of boundary.
 		memmove(&dp->vcn, &dp0->vcn_low,
@@ -4202,10 +4207,10 @@ int log_replay(struct ntfs_inode *ni, bool *initialized)
 		goto trace_dp_table;
 
 	dp = NULL;
-	while ((dp = enum_rstbl(dptbl, dp))) {
+	while ((dp = enum_rstbl(dptbl, dp, sizeof(*dp)))) {
 		struct DIR_PAGE_ENTRY *next = dp;
 
-		while ((next = enum_rstbl(dptbl, next))) {
+		while ((next = enum_rstbl(dptbl, next, sizeof(*next)))) {
 			if (next->target_attr == dp->target_attr &&
 			    next->vcn == dp->vcn) {
 				if (le64_to_cpu(next->oldest_lsn) <
@@ -4290,7 +4295,7 @@ int log_replay(struct ntfs_inode *ni, bool *initialized)
 
 	/* Clear all of the Attr pointers. */
 	oe = NULL;
-	while ((oe = enum_rstbl(oatbl, oe))) {
+	while ((oe = enum_rstbl(oatbl, oe, sizeof(*oe)))) {
 		if (!rst->major_ver) {
 			struct OPEN_ATTR_ENRTY_32 oe0;
 
@@ -4507,7 +4512,7 @@ int log_replay(struct ntfs_inode *ni, bool *initialized)
 			u64 lcn_e = lcn0 + le64_to_cpu(r->len) - 1;
 
 			dp = NULL;
-			while ((dp = enum_rstbl(dptbl, dp))) {
+			while ((dp = enum_rstbl(dptbl, dp, sizeof(*dp)))) {
 				u32 j;
 
 				t32 = le32_to_cpu(dp->lcns_follow);
@@ -4640,14 +4645,14 @@ int log_replay(struct ntfs_inode *ni, bool *initialized)
 	 * the lowest lsn, and return it as the Redo lsn.
 	 */
 	dp = NULL;
-	while ((dp = enum_rstbl(dptbl, dp))) {
+	while ((dp = enum_rstbl(dptbl, dp, sizeof(*dp)))) {
 		t64 = le64_to_cpu(dp->oldest_lsn);
 		if (t64 && t64 < rlsn)
 			rlsn = t64;
 	}
 
 	tr = NULL;
-	while ((tr = enum_rstbl(trtbl, tr))) {
+	while ((tr = enum_rstbl(trtbl, tr, sizeof(*tr)))) {
 		t64 = le64_to_cpu(tr->first_lsn);
 		if (t64 && t64 < rlsn)
 			rlsn = t64;
@@ -4668,7 +4673,7 @@ int log_replay(struct ntfs_inode *ni, bool *initialized)
 	oe = NULL;
 next_open_attribute:
 
-	oe = enum_rstbl(oatbl, oe);
+	oe = enum_rstbl(oatbl, oe, sizeof(*oe));
 	if (!oe) {
 		err = 0;
 		dp = NULL;
@@ -4770,7 +4775,7 @@ int log_replay(struct ntfs_inode *ni, bool *initialized)
 	 * Mapping that we have, and insert it into the appropriate run.
 	 */
 next_dirty_page:
-	dp = enum_rstbl(dptbl, dp);
+	dp = enum_rstbl(dptbl, dp, sizeof(*dp));
 	if (!dp)
 		goto do_redo_1;
 
@@ -4968,7 +4973,7 @@ int log_replay(struct ntfs_inode *ni, bool *initialized)
 	/* Scan Transaction Table. */
 	tr = NULL;
 transaction_table_next:
-	tr = enum_rstbl(trtbl, tr);
+	tr = enum_rstbl(trtbl, tr, sizeof(*tr));
 	if (!tr)
 		goto undo_action_done;
 
@@ -5142,7 +5147,7 @@ int log_replay(struct ntfs_inode *ni, bool *initialized)
 	 * the open attributes.
 	 */
 	oe = NULL;
-	while ((oe = enum_rstbl(oatbl, oe))) {
+	while ((oe = enum_rstbl(oatbl, oe, sizeof(*oe)))) {
 		rno = ino_get(&oe->ref);
 
 		if (oe->is_attr_name == 1) {
-- 
2.34.1


             reply	other threads:[~2024-07-09  3:48 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-07-09  3:48 lei lu [this message]
  -- strict thread matches above, loose matches on Subject: below --
2024-09-18 17:17 [PATCH v2] ntfs3: Add bounds checking to enum_rstbl() lei lu
2024-09-18 17:43 ` lei lu

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=20240709034823.176357-1-llfamsec@gmail.com \
    --to=llfamsec@gmail.com \
    --cc=almaz.alexandrovich@paragon-software.com \
    --cc=ntfs3@lists.linux.dev \
    /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