* FAILED: patch "[PATCH] udf: validate the device specification EA before using it" failed to apply to 6.1-stable tree
@ 2026-11-07 10:40 Sasha Levin
2026-11-10 12:02 ` [PATCH 6.1.y] udf: validate the device specification EA before using it Sasha Levin
0 siblings, 1 reply; 2+ messages in thread
From: Sasha Levin @ 2026-11-07 10:40 UTC (permalink / raw)
To: shionthanatos, gmwgg05, npczmd, jupmouse, jack; +Cc: stable
The patch below does not apply to the 6.1-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.1.y
git checkout FETCH_HEAD
git cherry-pick -x 9a2390959685ac35a58c80c8016120849a2babf6
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '20261107054058-failed-6.1-9a2390959685@kernel.org' --subject-prefix 'PATCH 6.1.y' 'HEAD^..'
Thanks,
Sasha
------------------ original commit in Linus's tree ------------------
From 9a2390959685ac35a58c80c8016120849a2babf6 Mon Sep 17 00:00:00 2001
From: Yunpeng Tian <shionthanatos@gmail.com>
Date: Mon, 31 Aug 2026 17:31:16 +0200
Subject: [PATCH] udf: validate the device specification EA before using it
udf_get_extendedattr() bounds an extended attribute only against
struct genericFormat, which is 12 bytes. A type-12 device
specification is struct deviceSpec, which is 24 bytes plus a flexible
impUse array. Thus a corrupted filesystem can contain extended attribute
that is accepted by udf_get_extendedattr() but udf_write_inode() or
udf_read_inode() may access beyond the end of provided buffer.
Provide a udf_device_spec_valid() check to validate correctness of
extended attribute that is a deviceSpec. While here, check the result of
udf_add_extendedattr() before dereferencing it as it can return NULL in
case of error.
[JK: Removed duplicated validity checks]
Reported-by: Yunpeng Tian <shionthanatos@gmail.com>
Reported-by: Gongming Wang <gmwgg05@gmail.com>
Reported-by: Mingda Zhang <npczmd@qq.com>
Reported-by: Qinrun Dai <jupmouse@gmail.com>
Cc: stable@vger.kernel.org
Signed-off-by: Yunpeng Tian <shionthanatos@gmail.com>
Signed-off-by: Jan Kara <jack@suse.cz>
---
fs/udf/inode.c | 43 ++++++++++++++++++++++++++++++++++++++-----
1 file changed, 38 insertions(+), 5 deletions(-)
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index e45e546a739a9..baf9845ac06b0 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -1336,6 +1336,26 @@ int udf_setsize(struct inode *inode, loff_t newsize)
return err;
}
+/*
+ * Verify validity of struct deviceSpec on disk. udf_get_extendedattr() has
+ * already verified the generic header and made sure attribute fits in the
+ * inode so we just have to make sure attribute space is large enough for
+ * deviceSpec struct and required impUse information.
+ */
+static bool udf_device_spec_valid(struct deviceSpec *dsea)
+{
+ u32 attr_length, imp_use_length;
+
+ attr_length = le32_to_cpu(dsea->attrLength);
+ imp_use_length = le32_to_cpu(dsea->impUseLength);
+ if (attr_length < sizeof(struct deviceSpec) ||
+ imp_use_length < sizeof(struct regid) ||
+ imp_use_length > attr_length - sizeof(struct deviceSpec))
+ return false;
+
+ return true;
+}
+
/*
* Maximum length of linked list formed by ICB hierarchy. The chosen number is
* arbitrary - just that we hopefully don't limit any real use of rewritten
@@ -1654,13 +1674,12 @@ static int udf_read_inode(struct inode *inode, bool hidden_inode)
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
struct deviceSpec *dsea =
(struct deviceSpec *)udf_get_extendedattr(inode, 12, 1);
- if (dsea) {
- init_special_inode(inode, inode->i_mode,
+
+ if (!dsea || !udf_device_spec_valid(dsea))
+ goto out;
+ init_special_inode(inode, inode->i_mode,
MKDEV(le32_to_cpu(dsea->majorDeviceIdent),
le32_to_cpu(dsea->minorDeviceIdent)));
- /* Developer ID ??? */
- } else
- goto out;
}
ret = 0;
out:
@@ -1757,6 +1776,7 @@ int udf_write_inode(struct inode *inode, struct writeback_control *wbc)
struct udf_sb_info *sbi = UDF_SB(inode->i_sb);
unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits;
struct udf_inode_info *iinfo = UDF_I(inode);
+ int err;
bh = sb_getblk(inode->i_sb,
udf_get_lb_pblock(inode->i_sb, &iinfo->i_location, 0));
@@ -1821,6 +1841,10 @@ int udf_write_inode(struct inode *inode, struct writeback_control *wbc)
udf_add_extendedattr(inode,
sizeof(struct deviceSpec) +
sizeof(struct regid), 12, 0x3);
+ if (!dsea) {
+ err = -ENOSPC;
+ goto out_unlock;
+ }
dsea->attrType = cpu_to_le32(12);
dsea->attrSubtype = 1;
dsea->attrLength = cpu_to_le32(
@@ -1828,6 +1852,10 @@ int udf_write_inode(struct inode *inode, struct writeback_control *wbc)
sizeof(struct regid));
dsea->impUseLength = cpu_to_le32(sizeof(struct regid));
}
+ if (!udf_device_spec_valid(dsea)) {
+ err = -EFSCORRUPTED;
+ goto out_unlock;
+ }
eid = (struct regid *)dsea->impUse;
memset(eid, 0, sizeof(*eid));
strcpy(eid->ident, UDF_ID_DEVELOPER);
@@ -1962,6 +1990,11 @@ int udf_write_inode(struct inode *inode, struct writeback_control *wbc)
set_inode_metadata_writeback(inode);
return 0;
+
+out_unlock:
+ unlock_buffer(bh);
+ brelse(bh);
+ return err;
}
struct inode *__udf_iget(struct super_block *sb, struct kernel_lb_addr *ino,
--
2.53.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* [PATCH 6.1.y] udf: validate the device specification EA before using it
2026-11-07 10:40 FAILED: patch "[PATCH] udf: validate the device specification EA before using it" failed to apply to 6.1-stable tree Sasha Levin
@ 2026-11-10 12:02 ` Sasha Levin
0 siblings, 0 replies; 2+ messages in thread
From: Sasha Levin @ 2026-11-10 12:02 UTC (permalink / raw)
To: stable
Cc: Yunpeng Tian, Gongming Wang, Mingda Zhang, Qinrun Dai, Jan Kara,
Sasha Levin
From: Yunpeng Tian <shionthanatos@gmail.com>
[ Upstream commit 9a2390959685ac35a58c80c8016120849a2babf6 ]
udf_get_extendedattr() bounds an extended attribute only against
struct genericFormat, which is 12 bytes. A type-12 device
specification is struct deviceSpec, which is 24 bytes plus a flexible
impUse array. Thus a corrupted filesystem can contain extended attribute
that is accepted by udf_get_extendedattr() but udf_write_inode() or
udf_read_inode() may access beyond the end of provided buffer.
Provide a udf_device_spec_valid() check to validate correctness of
extended attribute that is a deviceSpec. While here, check the result of
udf_add_extendedattr() before dereferencing it as it can return NULL in
case of error.
[JK: Removed duplicated validity checks]
Reported-by: Yunpeng Tian <shionthanatos@gmail.com>
Reported-by: Gongming Wang <gmwgg05@gmail.com>
Reported-by: Mingda Zhang <npczmd@qq.com>
Reported-by: Qinrun Dai <jupmouse@gmail.com>
Cc: stable@vger.kernel.org
Signed-off-by: Yunpeng Tian <shionthanatos@gmail.com>
Signed-off-by: Jan Kara <jack@suse.cz>
[ sashal: adapted changes in udf_write_inode() to udf_update_inode() ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/udf/inode.c | 42 +++++++++++++++++++++++++++++++++++++-----
1 file changed, 37 insertions(+), 5 deletions(-)
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index fd4b8cc20f5f1..6b78df1f1625b 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -1185,6 +1185,26 @@ int udf_setsize(struct inode *inode, loff_t newsize)
return 0;
}
+/*
+ * Verify validity of struct deviceSpec on disk. udf_get_extendedattr() has
+ * already verified the generic header and made sure attribute fits in the
+ * inode so we just have to make sure attribute space is large enough for
+ * deviceSpec struct and required impUse information.
+ */
+static bool udf_device_spec_valid(struct deviceSpec *dsea)
+{
+ u32 attr_length, imp_use_length;
+
+ attr_length = le32_to_cpu(dsea->attrLength);
+ imp_use_length = le32_to_cpu(dsea->impUseLength);
+ if (attr_length < sizeof(struct deviceSpec) ||
+ imp_use_length < sizeof(struct regid) ||
+ imp_use_length > attr_length - sizeof(struct deviceSpec))
+ return false;
+
+ return true;
+}
+
/*
* Maximum length of linked list formed by ICB hierarchy. The chosen number is
* arbitrary - just that we hopefully don't limit any real use of rewritten
@@ -1499,13 +1519,12 @@ static int udf_read_inode(struct inode *inode, bool hidden_inode)
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
struct deviceSpec *dsea =
(struct deviceSpec *)udf_get_extendedattr(inode, 12, 1);
- if (dsea) {
- init_special_inode(inode, inode->i_mode,
+
+ if (!dsea || !udf_device_spec_valid(dsea))
+ goto out;
+ init_special_inode(inode, inode->i_mode,
MKDEV(le32_to_cpu(dsea->majorDeviceIdent),
le32_to_cpu(dsea->minorDeviceIdent)));
- /* Developer ID ??? */
- } else
- goto out;
}
ret = 0;
out:
@@ -1653,6 +1672,10 @@ static int udf_update_inode(struct inode *inode, int do_sync)
udf_add_extendedattr(inode,
sizeof(struct deviceSpec) +
sizeof(struct regid), 12, 0x3);
+ if (!dsea) {
+ err = -ENOSPC;
+ goto out_unlock;
+ }
dsea->attrType = cpu_to_le32(12);
dsea->attrSubtype = 1;
dsea->attrLength = cpu_to_le32(
@@ -1660,6 +1683,10 @@ static int udf_update_inode(struct inode *inode, int do_sync)
sizeof(struct regid));
dsea->impUseLength = cpu_to_le32(sizeof(struct regid));
}
+ if (!udf_device_spec_valid(dsea)) {
+ err = -EFSCORRUPTED;
+ goto out_unlock;
+ }
eid = (struct regid *)dsea->impUse;
memset(eid, 0, sizeof(*eid));
strcpy(eid->ident, UDF_ID_DEVELOPER);
@@ -1799,6 +1826,11 @@ static int udf_update_inode(struct inode *inode, int do_sync)
brelse(bh);
return err;
+
+out_unlock:
+ unlock_buffer(bh);
+ brelse(bh);
+ return err;
}
struct inode *__udf_iget(struct super_block *sb, struct kernel_lb_addr *ino,
--
2.53.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-11-10 12:02 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-07 10:40 FAILED: patch "[PATCH] udf: validate the device specification EA before using it" failed to apply to 6.1-stable tree Sasha Levin
2026-11-10 12:02 ` [PATCH 6.1.y] udf: validate the device specification EA before using it Sasha Levin
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.