Skip to content

Commit 3061084

Browse files
author
CKI KWF Bot
committed
Merge: CVE-2025-22121: ext4: fix out-of-bound read in ext4_xattr_inode_dec_ref_all()
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10/-/merge_requests/1154 JIRA: https://issues.redhat.com/browse/RHEL-93568 CVE: CVE-2025-22121 * 69f3a30 ext4: introduce ITAIL helper * 5701875 ext4: fix out-of-bound read in ext4_xattr_inode_dec_ref_all() Signed-off-by: CKI Backport Bot <cki-ci-bot+cki-gitlab-backport-bot@redhat.com> --- <small>Created 2025-07-03 17:46 UTC by backporter - [KWF FAQ](https://red.ht/kernel_workflow_doc) - [Slack #team-kernel-workflow](https://redhat-internal.slack.com/archives/C04LRUPMJQ5) - [Source](https://gitlab.com/cki-project/kernel-workflow/-/blob/main/webhook/utils/backporter.py) - [Documentation](https://gitlab.com/cki-project/kernel-workflow/-/blob/main/docs/README.backporter.md) - [Report an issue](https://issues.redhat.com/secure/CreateIssueDetails!init.jspa?pid=12334433&issuetype=1&priority=4&summary=backporter+webhook+issue&components=kernel-workflow+/+backporter)</small> Approved-by: Jarod Wilson <jarod@redhat.com> Approved-by: Brian Foster <bfoster@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: CKI GitLab Kmaint Pipeline Bot <26919896-cki-kmaint-pipeline-bot@users.noreply.gitlab.com>
2 parents 7e951cb + 95c2e49 commit 3061084

File tree

3 files changed

+19
-28
lines changed

3 files changed

+19
-28
lines changed

fs/ext4/inode.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4679,6 +4679,11 @@ static inline int ext4_iget_extra_inode(struct inode *inode,
46794679
*magic == cpu_to_le32(EXT4_XATTR_MAGIC)) {
46804680
int err;
46814681

4682+
err = xattr_check_inode(inode, IHDR(inode, raw_inode),
4683+
ITAIL(inode, raw_inode));
4684+
if (err)
4685+
return err;
4686+
46824687
ext4_set_inode_state(inode, EXT4_STATE_XATTR);
46834688
err = ext4_find_inline_data_nolock(inode);
46844689
if (!err && ext4_has_inline_data(inode))

fs/ext4/xattr.c

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -308,17 +308,14 @@ __ext4_xattr_check_block(struct inode *inode, struct buffer_head *bh,
308308
__ext4_xattr_check_block((inode), (bh), __func__, __LINE__)
309309

310310

311-
static inline int
311+
int
312312
__xattr_check_inode(struct inode *inode, struct ext4_xattr_ibody_header *header,
313313
void *end, const char *function, unsigned int line)
314314
{
315315
return check_xattrs(inode, NULL, IFIRST(header), end, IFIRST(header),
316316
function, line);
317317
}
318318

319-
#define xattr_check_inode(inode, header, end) \
320-
__xattr_check_inode((inode), (header), (end), __func__, __LINE__)
321-
322319
static int
323320
xattr_find_entry(struct inode *inode, struct ext4_xattr_entry **pentry,
324321
void *end, int name_index, const char *name, int sorted)
@@ -649,10 +646,7 @@ ext4_xattr_ibody_get(struct inode *inode, int name_index, const char *name,
649646
return error;
650647
raw_inode = ext4_raw_inode(&iloc);
651648
header = IHDR(inode, raw_inode);
652-
end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
653-
error = xattr_check_inode(inode, header, end);
654-
if (error)
655-
goto cleanup;
649+
end = ITAIL(inode, raw_inode);
656650
entry = IFIRST(header);
657651
error = xattr_find_entry(inode, &entry, end, name_index, name, 0);
658652
if (error)
@@ -783,7 +777,6 @@ ext4_xattr_ibody_list(struct dentry *dentry, char *buffer, size_t buffer_size)
783777
struct ext4_xattr_ibody_header *header;
784778
struct ext4_inode *raw_inode;
785779
struct ext4_iloc iloc;
786-
void *end;
787780
int error;
788781

789782
if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR))
@@ -793,14 +786,9 @@ ext4_xattr_ibody_list(struct dentry *dentry, char *buffer, size_t buffer_size)
793786
return error;
794787
raw_inode = ext4_raw_inode(&iloc);
795788
header = IHDR(inode, raw_inode);
796-
end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
797-
error = xattr_check_inode(inode, header, end);
798-
if (error)
799-
goto cleanup;
800789
error = ext4_xattr_list_entries(dentry, IFIRST(header),
801790
buffer, buffer_size);
802791

803-
cleanup:
804792
brelse(iloc.bh);
805793
return error;
806794
}
@@ -868,7 +856,6 @@ int ext4_get_inode_usage(struct inode *inode, qsize_t *usage)
868856
struct ext4_xattr_ibody_header *header;
869857
struct ext4_xattr_entry *entry;
870858
qsize_t ea_inode_refs = 0;
871-
void *end;
872859
int ret;
873860

874861
lockdep_assert_held_read(&EXT4_I(inode)->xattr_sem);
@@ -879,10 +866,6 @@ int ext4_get_inode_usage(struct inode *inode, qsize_t *usage)
879866
goto out;
880867
raw_inode = ext4_raw_inode(&iloc);
881868
header = IHDR(inode, raw_inode);
882-
end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
883-
ret = xattr_check_inode(inode, header, end);
884-
if (ret)
885-
goto out;
886869

887870
for (entry = IFIRST(header); !IS_LAST_ENTRY(entry);
888871
entry = EXT4_XATTR_NEXT(entry))
@@ -2244,11 +2227,8 @@ int ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i,
22442227
header = IHDR(inode, raw_inode);
22452228
is->s.base = is->s.first = IFIRST(header);
22462229
is->s.here = is->s.first;
2247-
is->s.end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
2230+
is->s.end = ITAIL(inode, raw_inode);
22482231
if (ext4_test_inode_state(inode, EXT4_STATE_XATTR)) {
2249-
error = xattr_check_inode(inode, header, is->s.end);
2250-
if (error)
2251-
return error;
22522232
/* Find the named attribute. */
22532233
error = xattr_find_entry(inode, &is->s.here, is->s.end,
22542234
i->name_index, i->name, 0);
@@ -2795,14 +2775,10 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
27952775
*/
27962776

27972777
base = IFIRST(header);
2798-
end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
2778+
end = ITAIL(inode, raw_inode);
27992779
min_offs = end - base;
28002780
total_ino = sizeof(struct ext4_xattr_ibody_header) + sizeof(u32);
28012781

2802-
error = xattr_check_inode(inode, header, end);
2803-
if (error)
2804-
goto cleanup;
2805-
28062782
ifree = ext4_xattr_free_space(base, &min_offs, base, &total_ino);
28072783
if (ifree >= isize_diff)
28082784
goto shift;

fs/ext4/xattr.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ struct ext4_xattr_entry {
6767
((void *)raw_inode + \
6868
EXT4_GOOD_OLD_INODE_SIZE + \
6969
EXT4_I(inode)->i_extra_isize))
70+
#define ITAIL(inode, raw_inode) \
71+
((void *)(raw_inode) + \
72+
EXT4_SB((inode)->i_sb)->s_inode_size)
7073
#define IFIRST(hdr) ((struct ext4_xattr_entry *)((hdr)+1))
7174

7275
/*
@@ -206,6 +209,13 @@ extern int ext4_xattr_ibody_set(handle_t *handle, struct inode *inode,
206209
extern struct mb_cache *ext4_xattr_create_cache(void);
207210
extern void ext4_xattr_destroy_cache(struct mb_cache *);
208211

212+
extern int
213+
__xattr_check_inode(struct inode *inode, struct ext4_xattr_ibody_header *header,
214+
void *end, const char *function, unsigned int line);
215+
216+
#define xattr_check_inode(inode, header, end) \
217+
__xattr_check_inode((inode), (header), (end), __func__, __LINE__)
218+
209219
#ifdef CONFIG_EXT4_FS_SECURITY
210220
extern int ext4_init_security(handle_t *handle, struct inode *inode,
211221
struct inode *dir, const struct qstr *qstr);

0 commit comments

Comments
 (0)