Skip to content

Commit f73831a

Browse files
committed
Merge: Fix a couple CVEs
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/4751 JIRA: https://issues.redhat.com/browse/RHEL-48517 CVE: CVE-2024-40998 JIRA: https://issues.redhat.com/browse/RHEL-48282 CVE: CVE-2024-40972 Also backport a dependency patch to make things simpler. Signed-off-by: Carlos Maiolino <cmaiolino@redhat.com> Approved-by: Pavel Reichl <preichl@redhat.com> Approved-by: Andrey Albershteyn <aalbersh@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: Lucas Zampieri <lzampier@redhat.com>
2 parents dedba46 + 51416ce commit f73831a

File tree

2 files changed

+82
-91
lines changed

2 files changed

+82
-91
lines changed

fs/ext4/super.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5547,19 +5547,15 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
55475547
if (err)
55485548
goto failed_mount6;
55495549

5550-
err = ext4_register_sysfs(sb);
5551-
if (err)
5552-
goto failed_mount7;
5553-
55545550
err = ext4_init_orphan_info(sb);
55555551
if (err)
5556-
goto failed_mount8;
5552+
goto failed_mount7;
55575553
#ifdef CONFIG_QUOTA
55585554
/* Enable quota usage during mount. */
55595555
if (ext4_has_feature_quota(sb) && !sb_rdonly(sb)) {
55605556
err = ext4_enable_quotas(sb);
55615557
if (err)
5562-
goto failed_mount9;
5558+
goto failed_mount8;
55635559
}
55645560
#endif /* CONFIG_QUOTA */
55655561

@@ -5602,6 +5598,11 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
56025598
atomic_set(&sbi->s_warning_count, 0);
56035599
atomic_set(&sbi->s_msg_count, 0);
56045600

5601+
/* Register sysfs after all initializations are complete. */
5602+
err = ext4_register_sysfs(sb);
5603+
if (err)
5604+
goto failed_mount9;
5605+
56055606
if (ext4_has_feature_verity(sb)) {
56065607
static bool printed = false;
56075608

@@ -5614,10 +5615,9 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
56145615
return 0;
56155616

56165617
failed_mount9:
5618+
ext4_quota_off_umount(sb);
5619+
failed_mount8: __maybe_unused
56175620
ext4_release_orphan_info(sb);
5618-
failed_mount8:
5619-
ext4_unregister_sysfs(sb);
5620-
kobject_put(&sbi->s_kobj);
56215621
failed_mount7:
56225622
ext4_unregister_li_request(sb);
56235623
failed_mount6:

fs/ext4/xattr.c

Lines changed: 73 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1566,46 +1566,49 @@ ext4_xattr_inode_cache_find(struct inode *inode, const void *value,
15661566
/*
15671567
* Add value of the EA in an inode.
15681568
*/
1569-
static int ext4_xattr_inode_lookup_create(handle_t *handle, struct inode *inode,
1570-
const void *value, size_t value_len,
1571-
struct inode **ret_inode)
1569+
static struct inode *ext4_xattr_inode_lookup_create(handle_t *handle,
1570+
struct inode *inode, const void *value, size_t value_len)
15721571
{
15731572
struct inode *ea_inode;
15741573
u32 hash;
15751574
int err;
15761575

1576+
/* Account inode & space to quota even if sharing... */
1577+
err = ext4_xattr_inode_alloc_quota(inode, value_len);
1578+
if (err)
1579+
return ERR_PTR(err);
1580+
15771581
hash = ext4_xattr_inode_hash(EXT4_SB(inode->i_sb), value, value_len);
15781582
ea_inode = ext4_xattr_inode_cache_find(inode, value, value_len, hash);
15791583
if (ea_inode) {
15801584
err = ext4_xattr_inode_inc_ref(handle, ea_inode);
1581-
if (err) {
1582-
iput(ea_inode);
1583-
return err;
1584-
}
1585-
1586-
*ret_inode = ea_inode;
1587-
return 0;
1585+
if (err)
1586+
goto out_err;
1587+
return ea_inode;
15881588
}
15891589

15901590
/* Create an inode for the EA value */
15911591
ea_inode = ext4_xattr_inode_create(handle, inode, hash);
1592-
if (IS_ERR(ea_inode))
1593-
return PTR_ERR(ea_inode);
1592+
if (IS_ERR(ea_inode)) {
1593+
ext4_xattr_inode_free_quota(inode, NULL, value_len);
1594+
return ea_inode;
1595+
}
15941596

15951597
err = ext4_xattr_inode_write(handle, ea_inode, value, value_len);
15961598
if (err) {
15971599
if (ext4_xattr_inode_dec_ref(handle, ea_inode))
15981600
ext4_warning_inode(ea_inode, "cleanup dec ref error %d", err);
1599-
iput(ea_inode);
1600-
return err;
1601+
goto out_err;
16011602
}
16021603

16031604
if (EA_INODE_CACHE(inode))
16041605
mb_cache_entry_create(EA_INODE_CACHE(inode), GFP_NOFS, hash,
16051606
ea_inode->i_ino, true /* reusable */);
1606-
1607-
*ret_inode = ea_inode;
1608-
return 0;
1607+
return ea_inode;
1608+
out_err:
1609+
iput(ea_inode);
1610+
ext4_xattr_inode_free_quota(inode, NULL, value_len);
1611+
return ERR_PTR(err);
16091612
}
16101613

16111614
/*
@@ -1617,14 +1620,14 @@ static int ext4_xattr_inode_lookup_create(handle_t *handle, struct inode *inode,
16171620
static int ext4_xattr_set_entry(struct ext4_xattr_info *i,
16181621
struct ext4_xattr_search *s,
16191622
handle_t *handle, struct inode *inode,
1623+
struct inode *new_ea_inode,
16201624
bool is_block)
16211625
{
16221626
struct ext4_xattr_entry *last, *next;
16231627
struct ext4_xattr_entry *here = s->here;
16241628
size_t min_offs = s->end - s->base, name_len = strlen(i->name);
16251629
int in_inode = i->in_inode;
16261630
struct inode *old_ea_inode = NULL;
1627-
struct inode *new_ea_inode = NULL;
16281631
size_t old_size, new_size;
16291632
int ret;
16301633

@@ -1709,43 +1712,11 @@ static int ext4_xattr_set_entry(struct ext4_xattr_info *i,
17091712
old_ea_inode = NULL;
17101713
goto out;
17111714
}
1712-
}
1713-
if (i->value && in_inode) {
1714-
WARN_ON_ONCE(!i->value_len);
1715-
1716-
ret = ext4_xattr_inode_alloc_quota(inode, i->value_len);
1717-
if (ret)
1718-
goto out;
1719-
1720-
ret = ext4_xattr_inode_lookup_create(handle, inode, i->value,
1721-
i->value_len,
1722-
&new_ea_inode);
1723-
if (ret) {
1724-
new_ea_inode = NULL;
1725-
ext4_xattr_inode_free_quota(inode, NULL, i->value_len);
1726-
goto out;
1727-
}
1728-
}
17291715

1730-
if (old_ea_inode) {
17311716
/* We are ready to release ref count on the old_ea_inode. */
17321717
ret = ext4_xattr_inode_dec_ref(handle, old_ea_inode);
1733-
if (ret) {
1734-
/* Release newly required ref count on new_ea_inode. */
1735-
if (new_ea_inode) {
1736-
int err;
1737-
1738-
err = ext4_xattr_inode_dec_ref(handle,
1739-
new_ea_inode);
1740-
if (err)
1741-
ext4_warning_inode(new_ea_inode,
1742-
"dec ref new_ea_inode err=%d",
1743-
err);
1744-
ext4_xattr_inode_free_quota(inode, new_ea_inode,
1745-
i->value_len);
1746-
}
1718+
if (ret)
17471719
goto out;
1748-
}
17491720

17501721
ext4_xattr_inode_free_quota(inode, old_ea_inode,
17511722
le32_to_cpu(here->e_value_size));
@@ -1855,7 +1826,6 @@ static int ext4_xattr_set_entry(struct ext4_xattr_info *i,
18551826
ret = 0;
18561827
out:
18571828
iput(old_ea_inode);
1858-
iput(new_ea_inode);
18591829
return ret;
18601830
}
18611831

@@ -1918,9 +1888,21 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
19181888
size_t old_ea_inode_quota = 0;
19191889
unsigned int ea_ino;
19201890

1921-
19221891
#define header(x) ((struct ext4_xattr_header *)(x))
19231892

1893+
/* If we need EA inode, prepare it before locking the buffer */
1894+
if (i->value && i->in_inode) {
1895+
WARN_ON_ONCE(!i->value_len);
1896+
1897+
ea_inode = ext4_xattr_inode_lookup_create(handle, inode,
1898+
i->value, i->value_len);
1899+
if (IS_ERR(ea_inode)) {
1900+
error = PTR_ERR(ea_inode);
1901+
ea_inode = NULL;
1902+
goto cleanup;
1903+
}
1904+
}
1905+
19241906
if (s->base) {
19251907
int offset = (char *)s->here - bs->bh->b_data;
19261908

@@ -1929,6 +1911,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
19291911
EXT4_JTR_NONE);
19301912
if (error)
19311913
goto cleanup;
1914+
19321915
lock_buffer(bs->bh);
19331916

19341917
if (header(s->base)->h_refcount == cpu_to_le32(1)) {
@@ -1955,7 +1938,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
19551938
}
19561939
ea_bdebug(bs->bh, "modifying in-place");
19571940
error = ext4_xattr_set_entry(i, s, handle, inode,
1958-
true /* is_block */);
1941+
ea_inode, true /* is_block */);
19591942
ext4_xattr_block_csum_set(inode, bs->bh);
19601943
unlock_buffer(bs->bh);
19611944
if (error == -EFSCORRUPTED)
@@ -2023,29 +2006,13 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
20232006
s->end = s->base + sb->s_blocksize;
20242007
}
20252008

2026-
error = ext4_xattr_set_entry(i, s, handle, inode, true /* is_block */);
2009+
error = ext4_xattr_set_entry(i, s, handle, inode, ea_inode,
2010+
true /* is_block */);
20272011
if (error == -EFSCORRUPTED)
20282012
goto bad_block;
20292013
if (error)
20302014
goto cleanup;
20312015

2032-
if (i->value && s->here->e_value_inum) {
2033-
/*
2034-
* A ref count on ea_inode has been taken as part of the call to
2035-
* ext4_xattr_set_entry() above. We would like to drop this
2036-
* extra ref but we have to wait until the xattr block is
2037-
* initialized and has its own ref count on the ea_inode.
2038-
*/
2039-
ea_ino = le32_to_cpu(s->here->e_value_inum);
2040-
error = ext4_xattr_inode_iget(inode, ea_ino,
2041-
le32_to_cpu(s->here->e_hash),
2042-
&ea_inode);
2043-
if (error) {
2044-
ea_inode = NULL;
2045-
goto cleanup;
2046-
}
2047-
}
2048-
20492016
inserted:
20502017
if (!IS_LAST_ENTRY(s->first)) {
20512018
new_bh = ext4_xattr_block_cache_find(inode, header(s->base),
@@ -2198,17 +2165,16 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
21982165

21992166
cleanup:
22002167
if (ea_inode) {
2201-
int error2;
2202-
2203-
error2 = ext4_xattr_inode_dec_ref(handle, ea_inode);
2204-
if (error2)
2205-
ext4_warning_inode(ea_inode, "dec ref error=%d",
2206-
error2);
2168+
if (error) {
2169+
int error2;
22072170

2208-
/* If there was an error, revert the quota charge. */
2209-
if (error)
2171+
error2 = ext4_xattr_inode_dec_ref(handle, ea_inode);
2172+
if (error2)
2173+
ext4_warning_inode(ea_inode, "dec ref error=%d",
2174+
error2);
22102175
ext4_xattr_inode_free_quota(inode, ea_inode,
22112176
i_size_read(ea_inode));
2177+
}
22122178
iput(ea_inode);
22132179
}
22142180
if (ce)
@@ -2266,14 +2232,38 @@ int ext4_xattr_ibody_set(handle_t *handle, struct inode *inode,
22662232
{
22672233
struct ext4_xattr_ibody_header *header;
22682234
struct ext4_xattr_search *s = &is->s;
2235+
struct inode *ea_inode = NULL;
22692236
int error;
22702237

22712238
if (!EXT4_INODE_HAS_XATTR_SPACE(inode))
22722239
return -ENOSPC;
22732240

2274-
error = ext4_xattr_set_entry(i, s, handle, inode, false /* is_block */);
2275-
if (error)
2241+
/* If we need EA inode, prepare it before locking the buffer */
2242+
if (i->value && i->in_inode) {
2243+
WARN_ON_ONCE(!i->value_len);
2244+
2245+
ea_inode = ext4_xattr_inode_lookup_create(handle, inode,
2246+
i->value, i->value_len);
2247+
if (IS_ERR(ea_inode))
2248+
return PTR_ERR(ea_inode);
2249+
}
2250+
error = ext4_xattr_set_entry(i, s, handle, inode, ea_inode,
2251+
false /* is_block */);
2252+
if (error) {
2253+
if (ea_inode) {
2254+
int error2;
2255+
2256+
error2 = ext4_xattr_inode_dec_ref(handle, ea_inode);
2257+
if (error2)
2258+
ext4_warning_inode(ea_inode, "dec ref error=%d",
2259+
error2);
2260+
2261+
ext4_xattr_inode_free_quota(inode, ea_inode,
2262+
i_size_read(ea_inode));
2263+
iput(ea_inode);
2264+
}
22762265
return error;
2266+
}
22772267
header = IHDR(inode, ext4_raw_inode(&is->iloc));
22782268
if (!IS_LAST_ENTRY(s->first)) {
22792269
header->h_magic = cpu_to_le32(EXT4_XATTR_MAGIC);
@@ -2282,6 +2272,7 @@ int ext4_xattr_ibody_set(handle_t *handle, struct inode *inode,
22822272
header->h_magic = cpu_to_le32(0);
22832273
ext4_clear_inode_state(inode, EXT4_STATE_XATTR);
22842274
}
2275+
iput(ea_inode);
22852276
return 0;
22862277
}
22872278

0 commit comments

Comments
 (0)