All of lore.kernel.org
 help / color / mirror / Atom feed
From: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
To: <ntfs3@lists.linux.dev>
Cc: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
	<linux-fsdevel@vger.kernel.org>
Subject: [PATCH 6/8] fs/ntfs3: Add more attributes checks in mi_enum_attr()
Date: Mon, 3 Jul 2023 11:27:21 +0400	[thread overview]
Message-ID: <18640b25-5018-ebf2-38d9-e750404cb66f@paragon-software.com> (raw)
In-Reply-To: <e41f6717-7c70-edf2-2d3a-8034840d14c5@paragon-software.com>


Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
---
  fs/ntfs3/record.c | 68 ++++++++++++++++++++++++++++++++++++-----------
  1 file changed, 52 insertions(+), 16 deletions(-)

diff --git a/fs/ntfs3/record.c b/fs/ntfs3/record.c
index cae939cb42cf..53629b1f65e9 100644
--- a/fs/ntfs3/record.c
+++ b/fs/ntfs3/record.c
@@ -199,8 +199,9 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, 
struct ATTRIB *attr)
  {
      const struct MFT_REC *rec = mi->mrec;
      u32 used = le32_to_cpu(rec->used);
-    u32 t32, off, asize;
+    u32 t32, off, asize, prev_type;
      u16 t16;
+    u64 data_size, alloc_size, tot_size;

      if (!attr) {
          u32 total = le32_to_cpu(rec->total);
@@ -219,6 +220,7 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, 
struct ATTRIB *attr)
          if (!is_rec_inuse(rec))
              return NULL;

+        prev_type = 0;
          attr = Add2Ptr(rec, off);
      } else {
          /* Check if input attr inside record. */
@@ -232,11 +234,11 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, 
struct ATTRIB *attr)
              return NULL;
          }

-        if (off + asize < off) {
-            /* Overflow check. */
+        /* Overflow check. */
+        if (off + asize < off)
              return NULL;
-        }

+        prev_type = le32_to_cpu(attr->type);
          attr = Add2Ptr(attr, asize);
          off += asize;
      }
@@ -256,7 +258,11 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, 
struct ATTRIB *attr)

      /* 0x100 is last known attribute for now. */
      t32 = le32_to_cpu(attr->type);
-    if ((t32 & 0xf) || (t32 > 0x100))
+    if (!t32 || (t32 & 0xf) || (t32 > 0x100))
+        return NULL;
+
+    /* attributes in record must be ordered by type */
+    if (t32 < prev_type)
          return NULL;

      /* Check overflow and boundary. */
@@ -265,16 +271,15 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, 
struct ATTRIB *attr)

      /* Check size of attribute. */
      if (!attr->non_res) {
+        /* Check resident fields. */
          if (asize < SIZEOF_RESIDENT)
              return NULL;

          t16 = le16_to_cpu(attr->res.data_off);
-
          if (t16 > asize)
              return NULL;

-        t32 = le32_to_cpu(attr->res.data_size);
-        if (t16 + t32 > asize)
+        if (t16 + le32_to_cpu(attr->res.data_size) > asize)
              return NULL;

          t32 = sizeof(short) * attr->name_len;
@@ -284,21 +289,52 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, 
struct ATTRIB *attr)
          return attr;
      }

-    /* Check some nonresident fields. */
-    if (attr->name_len &&
-        le16_to_cpu(attr->name_off) + sizeof(short) * attr->name_len >
-            le16_to_cpu(attr->nres.run_off)) {
+    /* Check nonresident fields. */
+    if (attr->non_res != 1)
+        return NULL;
+
+    t16 = le16_to_cpu(attr->nres.run_off);
+    if (t16 > asize)
+        return NULL;
+
+    t32 = sizeof(short) * attr->name_len;
+    if (t32 && le16_to_cpu(attr->name_off) + t32 > t16)
+        return NULL;
+
+    /* Check start/end vcn. */
+    if (le64_to_cpu(attr->nres.svcn) > le64_to_cpu(attr->nres.evcn) + 1)
+        return NULL;
+
+    data_size = le64_to_cpu(attr->nres.data_size);
+    if (le64_to_cpu(attr->nres.valid_size) > data_size)
          return NULL;
-    }

-    if (attr->nres.svcn || !is_attr_ext(attr)) {
+    alloc_size = le64_to_cpu(attr->nres.alloc_size);
+    if (data_size > alloc_size)
+        return NULL;
+
+    t32 = mi->sbi->cluster_mask;
+    if (alloc_size & t32)
+        return NULL;
+
+    if (!attr->nres.svcn && is_attr_ext(attr)) {
+        /* First segment of sparse/compressed attribute */
+        if (asize + 8 < SIZEOF_NONRESIDENT_EX)
+            return NULL;
+
+        tot_size = le64_to_cpu(attr->nres.total_size);
+        if (tot_size & t32)
+            return NULL;
+
+        if (tot_size > alloc_size)
+            return NULL;
+    } else {
          if (asize + 8 < SIZEOF_NONRESIDENT)
              return NULL;

          if (attr->nres.c_unit)
              return NULL;
-    } else if (asize + 8 < SIZEOF_NONRESIDENT_EX)
-        return NULL;
+    }

      return attr;
  }
-- 
2.34.1


  parent reply	other threads:[~2023-07-03  7:27 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-07-03  7:23 [PATCH 0/8] fs/ntfs3: Bugfix and refactoring Konstantin Komarov
2023-07-03  7:24 ` [PATCH 1/8] fs/ntfs3: Add ckeck in ni_update_parent() Konstantin Komarov
2023-07-03  7:25 ` [PATCH 2/8] fs/ntfs3: Write immediately updated ntfs state Konstantin Komarov
2023-07-03  7:25 ` [PATCH 3/8] fs/ntfs3: Minor code refactoring and formatting Konstantin Komarov
2023-07-03  7:26 ` [PATCH 4/8] fs/ntfs3: Don't allow to change label if volume is read-only Konstantin Komarov
2023-07-03  7:26 ` [PATCH 5/8] fs/ntfs3: Use kvmalloc instead of kmalloc(... __GFP_NOWARN) Konstantin Komarov
2023-12-23  4:46   ` Matthew Wilcox
2023-12-23 13:33     ` Tetsuo Handa
2023-12-23 16:56       ` Matthew Wilcox
2023-07-03  7:27 ` Konstantin Komarov [this message]
2023-07-03  7:27 ` [PATCH 7/8] fs/ntfs3: fix deadlock in mark_as_free_ex Konstantin Komarov
2023-07-03  7:28 ` [PATCH 8/8] fs/ntfs3: Fix shift-out-of-bounds in ntfs_fill_super Konstantin Komarov
2023-12-23  5:00 ` [PATCH 0/8] fs/ntfs3: Bugfix and refactoring Kent Overstreet

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=18640b25-5018-ebf2-38d9-e750404cb66f@paragon-software.com \
    --to=almaz.alexandrovich@paragon-software.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --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 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.