Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
168 changes: 168 additions & 0 deletions SPECS/ntfs-3g/CVE-2026-56135.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
From 82f48346651391e9d8804368ba21b246a176b516 Mon Sep 17 00:00:00 2001
From: Azure Linux Security Servicing Account
<azurelinux-security@microsoft.com>
Date: Thu, 27 Aug 2026 02:28:21 +0000
Subject: [PATCH] Patch CVE-2026-56135 for ntfs-3g (applied via patch -p1)

Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com>
Upstream-reference: https://github.com/user-attachments/files/29755309/ntfs-3g_2022.10.3-cve_2026-04_8.patch
---
include/ntfs-3g/acls.h | 2 +
libntfs-3g/acls.c | 85 +++++++++++++++++++++++++++++++++++++++++-
libntfs-3g/security.c | 24 ++++++++++++
3 files changed, 110 insertions(+), 1 deletion(-)

diff --git a/include/ntfs-3g/acls.h b/include/ntfs-3g/acls.h
index 932791e..4f36389 100644
--- a/include/ntfs-3g/acls.h
+++ b/include/ntfs-3g/acls.h
@@ -168,6 +168,8 @@ char *ntfs_build_descr_posix(struct MAPPING* const mapping[],

#endif /* POSIXACLS */

+int ntfs_inherit_acl_extra_size(const ACL *acl, const SID *usid,
+ const SID *gsid);
int ntfs_inherit_acl(const ACL *oldacl, ACL *newacl,
const SID *usid, const SID *gsid,
BOOL fordir, le16 inherited);
diff --git a/libntfs-3g/acls.c b/libntfs-3g/acls.c
index 4cf534b..0b8c616 100644
--- a/libntfs-3g/acls.c
+++ b/libntfs-3g/acls.c
@@ -560,7 +560,9 @@ static BOOL valid_acl(const ACL *pacl, unsigned int end)
pace = (const ACCESS_ALLOWED_ACE*)
&((const char*)pacl)[offace];
acesz = le16_to_cpu(pace->size);
- switch (pace->type) {
+ if (acesz < sizeof(ACE_HEADER))
+ ok = FALSE;
+ else switch (pace->type) {
case ACCESS_ALLOWED_ACE_TYPE :
case ACCESS_DENIED_ACE_TYPE :
wantsz = ntfs_sid_size(&pace->sid) + 8;
@@ -681,6 +683,87 @@ BOOL ntfs_valid_descr(const char *securattr, unsigned int attrsz)
return (ok);
}

+/**
+ * ntfs_inherit_acl_extra_size: compute creator SID inheritance slack
+ * @acl: ACL to scan
+ * @usid: owner SID to substitute for CREATOR_OWNER
+ * @gsid: group SID to substitute for CREATOR_GROUP
+ *
+ * Walks @acl bounded by acl->size, adding slack for ALLOW and DENY ACEs
+ * whose SID matches either creator placeholder. ntfs_inherit_acl() can
+ * replace those placeholders by @usid or @gsid and, for directories, can
+ * also keep a verbatim copy for child inheritance. Count the worst-case
+ * extra bytes so the inherited descriptor allocation cannot be overrun.
+ *
+ * Return: extra bytes needed, or 0 if @acl is NULL or structurally rejected.
+ */
+
+int ntfs_inherit_acl_extra_size(const ACL *acl,
+ const SID *usid, const SID *gsid)
+{
+ const ACCESS_ALLOWED_ACE *ace;
+ unsigned int off;
+ unsigned int acl_size;
+ unsigned int acesz;
+ unsigned int sidsz;
+ int usidsz;
+ int gsidsz;
+ int ownersidsz;
+ int groupsidsz;
+ int oldcnt;
+ int nace;
+ int extra;
+ BOOL usid_is_group_sid;
+
+ extra = 0;
+ if (!acl || !usid || !gsid)
+ return (0);
+ acl_size = le16_to_cpu(acl->size);
+ if (acl_size < sizeof(ACL))
+ return (0);
+ oldcnt = le16_to_cpu(acl->ace_count);
+ usidsz = ntfs_sid_size(usid);
+ gsidsz = ntfs_sid_size(gsid);
+ ownersidsz = sizeof(ownersidbytes);
+ groupsidsz = sizeof(groupsidbytes);
+ usid_is_group_sid = ntfs_same_sid(usid, groupsid);
+ off = sizeof(ACL);
+ for (nace = 0; nace < oldcnt; nace++) {
+ if (off + 8 > acl_size)
+ break;
+ ace = (const ACCESS_ALLOWED_ACE*)((const char*)acl + off);
+ acesz = le16_to_cpu(ace->size);
+ if (acesz < 8 || acesz > acl_size - off)
+ break;
+ switch (ace->type) {
+ case ACCESS_ALLOWED_ACE_TYPE :
+ case ACCESS_DENIED_ACE_TYPE :
+ if ((acesz >= 8 + sizeof(ownersidbytes))
+ && ntfs_valid_sid(&ace->sid)) {
+ sidsz = ntfs_sid_size(&ace->sid);
+ if (sidsz <= acesz - 8) {
+ if (ntfs_same_sid(&ace->sid, ownersid))
+ {
+ extra += usidsz - ownersidsz +
+ 20;
+ if (usid_is_group_sid)
+ extra += gsidsz -
+ groupsidsz + 20;
+ }
+ if (ntfs_same_sid(&ace->sid, groupsid))
+ extra += gsidsz - groupsidsz +
+ 20;
+ }
+ }
+ break;
+ default :
+ break;
+ }
+ off += acesz;
+ }
+ return extra;
+}
+
/*
* Copy the inheritable parts of an ACL
*
diff --git a/libntfs-3g/security.c b/libntfs-3g/security.c
index acee0a5..d0e030e 100644
--- a/libntfs-3g/security.c
+++ b/libntfs-3g/security.c
@@ -3944,6 +3944,30 @@ static le32 build_inherited_id(struct SECURITY_CONTEXT *scx,
usidsz = ntfs_sid_size(usid);
gsidsz = ntfs_sid_size(gsid);
newattrsz = parentattrsz + 3*usidsz + 3*gsidsz;
+ /*
+ * The +3*usidsz + 3*gsidsz slack above only covers a few creator SID
+ * expansions during ntfs_inherit_acl(). Add worst-case slack for every
+ * ALLOW/DENY creator-owner and creator-group ACE in both the parent
+ * DACL and SACL.
+ */
+ if (pphead->dacl) {
+ offpacl = le32_to_cpu(pphead->dacl);
+ if ((unsigned int)offpacl + sizeof(ACL) <=
+ (unsigned int)parentattrsz) {
+ ppacl = (const ACL*)&parentattr[offpacl];
+ newattrsz += ntfs_inherit_acl_extra_size(ppacl,
+ usid, gsid);
+ }
+ }
+ if (pphead->sacl) {
+ offpacl = le32_to_cpu(pphead->sacl);
+ if ((unsigned int)offpacl + sizeof(ACL) <=
+ (unsigned int)parentattrsz) {
+ ppacl = (const ACL*)&parentattr[offpacl];
+ newattrsz += ntfs_inherit_acl_extra_size(ppacl,
+ usid, gsid);
+ }
+ }
if (fordir)
newattrsz *= 2;
newattr = (char*)ntfs_malloc(newattrsz);
--
2.45.4

147 changes: 147 additions & 0 deletions SPECS/ntfs-3g/CVE-2026-56136.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
From 42e33edc6318efd7882312ffec38c1f4ba6226a1 Mon Sep 17 00:00:00 2001
From: Azure Linux Security Servicing Account
<azurelinux-security@microsoft.com>
Date: Thu, 27 Aug 2026 02:28:51 +0000
Subject: [PATCH] Patch CVE-2026-56136 for ntfs-3g (applied via patch -p1)

Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com>
Upstream-reference: https://github.com/user-attachments/files/29755343/ntfs-3g_2022.10.3-cve_2026-04_9.patch
---
include/ntfs-3g/index.h | 1 +
libntfs-3g/attrib.c | 7 ++++++
libntfs-3g/index.c | 55 ++++++++++++++++++++++++++++++++++++++---
3 files changed, 60 insertions(+), 3 deletions(-)

diff --git a/include/ntfs-3g/index.h b/include/ntfs-3g/index.h
index d001863..1d5845d 100644
--- a/include/ntfs-3g/index.h
+++ b/include/ntfs-3g/index.h
@@ -143,6 +143,7 @@ extern int ntfs_index_block_inconsistent(const INDEX_BLOCK *ib, u32 block_size,
u64 inum, VCN vcn);
extern int ntfs_index_entry_inconsistent(const INDEX_ENTRY *ie,
COLLATION_RULES collation_rule, u64 inum);
+extern int ntfs_ie_stream_inconsistent(const INDEX_HEADER *ih, u64 inum);
extern int ntfs_index_lookup(const void *key, const int key_len,
ntfs_index_context *ictx) __attribute_warn_unused_result__;

diff --git a/libntfs-3g/attrib.c b/libntfs-3g/attrib.c
index efb9194..cfc2446 100644
--- a/libntfs-3g/attrib.c
+++ b/libntfs-3g/attrib.c
@@ -3528,6 +3528,10 @@ int ntfs_attr_inconsistent(const ATTR_RECORD *a, const MFT_REF mref)
if (a->non_resident
|| (le32_to_cpu(a->value_length)
< offsetof(INDEX_ROOT, index.reserved))
+ || (le32_to_cpu(ir->index_block_size)
+ < NTFS_BLOCK_SIZE)
+ || (le32_to_cpu(ir->index_block_size)
+ & (le32_to_cpu(ir->index_block_size) - 1))
|| (le32_to_cpu(ir->index.entries_offset)
< sizeof(INDEX_HEADER))
|| (le32_to_cpu(ir->index.index_length)
@@ -3542,6 +3546,9 @@ int ntfs_attr_inconsistent(const ATTR_RECORD *a, const MFT_REF mref)
(long long)inum);
errno = EIO;
ret = -1;
+ } else if (ntfs_ie_stream_inconsistent(&ir->index, inum)) {
+ errno = EIO;
+ ret = -1;
}
break;
case AT_STANDARD_INFORMATION :
diff --git a/libntfs-3g/index.c b/libntfs-3g/index.c
index e48d6aa..c9651a6 100644
--- a/libntfs-3g/index.c
+++ b/libntfs-3g/index.c
@@ -504,6 +504,8 @@ int ntfs_index_block_inconsistent(const INDEX_BLOCK *ib, u32 block_size,
(unsigned long long)inum);
return -1;
}
+ if (ntfs_ie_stream_inconsistent(&ib->index, inum))
+ return -1;

return (0);
}
@@ -560,7 +562,40 @@ int ntfs_index_entry_inconsistent(const INDEX_ENTRY *ie,
return (ret);
}

-/**
+int ntfs_ie_stream_inconsistent(const INDEX_HEADER *ih, u64 inum)
+{
+ const u8 *ies_start = (const u8 *)ih + le32_to_cpu(ih->entries_offset);
+ const u8 *ies_end = (const u8 *)ih + le32_to_cpu(ih->index_length);
+ const u8 *ie;
+
+ ntfs_log_trace("Entering\n");
+
+ for (ie = ies_start; ie < ies_end; ) {
+ u32 len;
+ const INDEX_ENTRY *ent = (const INDEX_ENTRY *)ie;
+
+ if ((size_t)(ies_end - ie) < sizeof(INDEX_ENTRY_HEADER))
+ goto err;
+ len = le16_to_cpu(ent->length);
+ if (len < sizeof(INDEX_ENTRY_HEADER) || (len & 7))
+ goto err;
+ if ((size_t)(ies_end - ie) < len)
+ goto err;
+ if (ent->ie_flags & INDEX_ENTRY_END) {
+ /* END must terminate the stream exactly. */
+ if (ie + len != ies_end)
+ goto err;
+ return 0;
+ }
+ ie += len;
+ }
+err:
+ ntfs_log_error("Corrupt index entry stream in inode %lld\n",
+ (long long)inum);
+ return -1;
+}
+
+/**
* Find a key in the index block.
*
* Return values:
@@ -1091,14 +1126,16 @@ out:

static INDEX_BLOCK *ntfs_ir_to_ib(INDEX_ROOT *ir, VCN ib_vcn)
{
+ u32 ib_size;
INDEX_BLOCK *ib;
INDEX_ENTRY *ie_last;
char *ies_start, *ies_end;
int i;

ntfs_log_trace("Entering\n");
-
- ib = ntfs_ib_alloc(ib_vcn, le32_to_cpu(ir->index_block_size), LEAF_NODE);
+
+ ib_size = le32_to_cpu(ir->index_block_size);
+ ib = ntfs_ib_alloc(ib_vcn, ib_size, LEAF_NODE);
if (!ib)
return NULL;

@@ -1110,6 +1147,18 @@ static INDEX_BLOCK *ntfs_ir_to_ib(INDEX_ROOT *ir, VCN ib_vcn)
* as well, which can never have any data.
*/
i = (char *)ie_last - ies_start + le16_to_cpu(ie_last->length);
+
+ if (offsetof(INDEX_BLOCK, index) + le32_to_cpu(ib->index.entries_offset)
+ + i > ib_size)
+ {
+ ntfs_log_error("Last entry in index root overflows the index "
+ "block size: %d (index block size: %lu)\n",
+ i, (unsigned long)ib_size);
+ free(ib);
+ errno = EIO;
+ return NULL;
+ }
+
memcpy(ntfs_ie_get_first(&ib->index), ies_start, i);

ib->index.ih_flags = ir->index.ih_flags;
--
2.45.4

7 changes: 6 additions & 1 deletion SPECS/ntfs-3g/ntfs-3g.spec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Summary: Linux NTFS userspace driver
Name: ntfs-3g
Version: 2022.10.3
Release: 3%{?dist}
Release: 4%{?dist}
License: GPLv2
Vendor: Microsoft Corporation
Distribution: Azure Linux
Expand All @@ -10,6 +10,8 @@ Source0: https://tuxera.com/opensource/%{name}_ntfsprogs-%{version}.tgz
Patch0: ntfs-3g_ntfsprogs-2011.10.9-RC-ntfsck-unsupported-return-0.patch
Patch1: CVE-2023-52890.patch
Patch2: CVE-2026-40706.patch
Patch3: CVE-2026-56135.patch
Patch4: CVE-2026-56136.patch

BuildRequires: fuse-devel
BuildRequires: gnutls-devel
Expand Down Expand Up @@ -172,6 +174,9 @@ rm -rf %{buildroot}%{_defaultdocdir}/%{name}/README
%exclude %{_mandir}/man8/ntfs-3g*

%changelog
* Thu Aug 27 2026 Azure Linux Security Servicing Account <azurelinux-security@microsoft.com> - 2022.10.3-4
- Patch for CVE-2026-56136, CVE-2026-56135

* Fri Apr 17 2026 Kanishk Bansal <kanbansal@microsoft.com> - 2022.10.3-3
- Patch CVE-2026-40706

Expand Down
Loading