* [PATCH] hpfs: reject oversized indirect extended attributes
@ 2026-07-01 21:50 이상호
0 siblings, 0 replies; only message in thread
From: 이상호 @ 2026-07-01 21:50 UTC (permalink / raw)
To: Mikulas Patocka; +Cc: 이상호, linux-kernel, stable
HPFS stores the length of an indirect extended attribute as an unsigned
32-bit on-disk value. hpfs_get_ea() exposes the selected EA length
through an int-sized output parameter, and get_indirect_ea() currently
also receives the length as an int.
That conversion is unsafe for malformed metadata. If a crafted fnode
describes an indirect EA with length 0xffffffff, hpfs_get_ea() assigns
that value to *size as -1 and passes it to get_indirect_ea(). The
allocation then uses size + 1, which wraps to zero, while hpfs_ea_read()
receives the same negative value through an unsigned length parameter and
attempts to copy sector data into the zero-sized allocation.
Keep the indirect EA length unsigned until it has been validated. Reject
values that cannot be represented by the existing int output parameter or
cannot be allocated together with the trailing NUL byte. Also store the
output size only after hpfs_ea_read() succeeds, so callers never observe a
length for data that was not read.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Signed-off-by: 이상호 <kudo3228@gmail.com>
---
fs/hpfs/ea.c | 22 +++++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)
diff --git a/fs/hpfs/ea.c b/fs/hpfs/ea.c
index 4664f9ab06ee..d23de4f9e2f5 100644
--- a/fs/hpfs/ea.c
+++ b/fs/hpfs/ea.c
@@ -7,6 +7,8 @@
* handling extended attributes
*/
+#include <linux/limits.h>
+
#include "hpfs_fn.h"
/* Remove external extended attributes. ano specifies whether a is a
@@ -48,9 +50,14 @@ void hpfs_ea_ext_remove(struct super_block *s, secno a, int ano, unsigned len)
}
}
-static char *get_indirect_ea(struct super_block *s, int ano, secno a, int size)
+static char *get_indirect_ea(struct super_block *s, int ano, secno a,
+ unsigned int size, int *out_size)
{
char *ret;
+ if (size > S32_MAX || (size_t)size + 1 > KMALLOC_MAX_SIZE) {
+ hpfs_error(s, "indirect EA is too large: %u", size);
+ return NULL;
+ }
if (!(ret = kmalloc(size + 1, GFP_NOFS))) {
pr_err("out of memory for EA\n");
return NULL;
@@ -60,6 +67,7 @@ static char *get_indirect_ea(struct super_block *s, int ano, secno a, int size)
return NULL;
}
ret[size] = 0;
+ *out_size = size;
return ret;
}
@@ -138,7 +146,9 @@ char *hpfs_get_ea(struct super_block *s, struct fnode *fnode, char *key, int *si
for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea))
if (!strcmp(ea->name, key)) {
if (ea_indirect(ea))
- return get_indirect_ea(s, ea_in_anode(ea), ea_sec(ea), *size = ea_len(ea));
+ return get_indirect_ea(s, ea_in_anode(ea),
+ ea_sec(ea), ea_len(ea),
+ size);
if (!(ret = kmalloc((*size = ea_valuelen(ea)) + 1, GFP_NOFS))) {
pr_err("out of memory for EA\n");
return NULL;
@@ -164,7 +174,9 @@ char *hpfs_get_ea(struct super_block *s, struct fnode *fnode, char *key, int *si
return NULL;
if (!strcmp(ea->name, key)) {
if (ea_indirect(ea))
- return get_indirect_ea(s, ea_in_anode(ea), ea_sec(ea), *size = ea_len(ea));
+ return get_indirect_ea(s, ea_in_anode(ea),
+ ea_sec(ea), ea_len(ea),
+ size);
if (!(ret = kmalloc((*size = ea_valuelen(ea)) + 1, GFP_NOFS))) {
pr_err("out of memory for EA\n");
return NULL;
--
2.43.0
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-07-01 21:50 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-01 21:50 [PATCH] hpfs: reject oversized indirect extended attributes 이상호
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.