summaryrefslogtreecommitdiff
path: root/fs/ocfs2/xattr.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2025-12-13 20:55:12 +1200
committerLinus Torvalds <torvalds@linux-foundation.org>2025-12-13 20:55:12 +1200
commit9d9c1cfec01cdbf24bd9322ed555713a20422115 (patch)
treec4ba1f4ae0412001f914957dfe335fb7d37ca1a1 /fs/ocfs2/xattr.c
parent2516a87153183e1797021879121ca25c95f1ea3a (diff)
parent601cc399a01049efa76be8f496541315dc9cf914 (diff)
Merge tag 'mm-nonmm-stable-2025-12-11-11-47' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mmHEADmaster
Pull misc updates from Andrew Morton: "There are no significant series in this small merge. Please see the individual changelogs for details" [ Editor's note: it's mainly ocfs2 and a couple of random fixes ] * tag 'mm-nonmm-stable-2025-12-11-11-47' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm: mm: memfd_luo: add CONFIG_SHMEM dependency mm: shmem: avoid build warning for CONFIG_SHMEM=n ocfs2: fix memory leak in ocfs2_merge_rec_left() ocfs2: invalidate inode if i_mode is zero after block read ocfs2: avoid -Wflex-array-member-not-at-end warning ocfs2: convert remaining read-only checks to ocfs2_emergency_state ocfs2: add ocfs2_emergency_state helper and apply to setattr checkpatch: add uninitialized pointer with __free attribute check args: fix documentation to reflect the correct numbers ocfs2: fix kernel BUG in ocfs2_find_victim_chain liveupdate: luo_core: fix redundant bound check in luo_ioctl() ocfs2: validate inline xattr size and entry count in ocfs2_xattr_ibody_list fs/fat: remove unnecessary wrapper fat_max_cache() ocfs2: replace deprecated strcpy with strscpy ocfs2: check tl_used after reading it from trancate log inode liveupdate: luo_file: don't use invalid list iterator
Diffstat (limited to 'fs/ocfs2/xattr.c')
-rw-r--r--fs/ocfs2/xattr.c38
1 files changed, 34 insertions, 4 deletions
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index dc1761e84814..1b21fbc16d73 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -49,9 +49,13 @@
#include "ocfs2_trace.h"
struct ocfs2_xattr_def_value_root {
- struct ocfs2_xattr_value_root xv;
- struct ocfs2_extent_rec er;
+ /* Must be last as it ends in a flexible-array member. */
+ TRAILING_OVERLAP(struct ocfs2_xattr_value_root, xv, xr_list.l_recs,
+ struct ocfs2_extent_rec er;
+ );
};
+static_assert(offsetof(struct ocfs2_xattr_def_value_root, xv.xr_list.l_recs) ==
+ offsetof(struct ocfs2_xattr_def_value_root, er));
struct ocfs2_xattr_bucket {
/* The inode these xattrs are associated with */
@@ -971,13 +975,39 @@ static int ocfs2_xattr_ibody_list(struct inode *inode,
struct ocfs2_xattr_header *header = NULL;
struct ocfs2_inode_info *oi = OCFS2_I(inode);
int ret = 0;
+ u16 xattr_count;
+ size_t max_entries;
+ u16 inline_size;
if (!(oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL))
return ret;
+ inline_size = le16_to_cpu(di->i_xattr_inline_size);
+
+ /* Validate inline size is reasonable */
+ if (inline_size > inode->i_sb->s_blocksize ||
+ inline_size < sizeof(struct ocfs2_xattr_header)) {
+ ocfs2_error(inode->i_sb,
+ "Invalid xattr inline size %u in inode %llu\n",
+ inline_size,
+ (unsigned long long)OCFS2_I(inode)->ip_blkno);
+ return -EFSCORRUPTED;
+ }
+
header = (struct ocfs2_xattr_header *)
- ((void *)di + inode->i_sb->s_blocksize -
- le16_to_cpu(di->i_xattr_inline_size));
+ ((void *)di + inode->i_sb->s_blocksize - inline_size);
+
+ xattr_count = le16_to_cpu(header->xh_count);
+ max_entries = (inline_size - sizeof(struct ocfs2_xattr_header)) /
+ sizeof(struct ocfs2_xattr_entry);
+
+ if (xattr_count > max_entries) {
+ ocfs2_error(inode->i_sb,
+ "xattr entry count %u exceeds maximum %zu in inode %llu\n",
+ xattr_count, max_entries,
+ (unsigned long long)OCFS2_I(inode)->ip_blkno);
+ return -EFSCORRUPTED;
+ }
ret = ocfs2_xattr_list_entries(inode, header, buffer, buffer_size);