VYPR
Unrated severityNVD Advisory· Published May 27, 2026· Updated May 27, 2026

CVE-2026-46046

CVE-2026-46046

Description

In the Linux kernel, the following vulnerability has been resolved:

ext4: fix missing brelse() in ext4_xattr_inode_dec_ref_all()

The commit c8e008b60492 ("ext4: ignore xattrs past end") introduced a refcount leak in when block_csum is false.

ext4_xattr_inode_dec_ref_all() calls ext4_get_inode_loc() to get iloc.bh, but never releases it with brelse().

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Missing brelse() in ext4_xattr_inode_dec_ref_all() causes a buffer head refcount leak when block checksums are disabled.

Vulnerability

In the Linux kernel, a missing brelse() call in ext4_xattr_inode_dec_ref_all() (introduced by commit c8e008b60492) causes a buffer head refcount leak when block_csum is false. The function calls ext4_get_inode_loc() to obtain iloc.bh, but does not release it, leading to a leak each time this code path is executed. This affects kernels containing the faulty commit. The exact versions are not fully enumerated, but the fix commit is present in stable kernels [1].

Exploitation

An attacker needs no special privileges beyond the ability to trigger operations on an ext4 filesystem that exercise the extended attributes path with block checksums disabled. This can be achieved by mounting an ext4 filesystem without block_validity or with block_csum disabled, and then performing operations that trigger xattr inode reference decrement (e.g., removing extended attributes or files with such attributes). No authentication or user interaction is required beyond local filesystem access [1].

Impact

A refcount leak causes the buffer head reference count to remain elevated, preventing proper cleanup. Over time, this can exhaust kernel memory resources, leading to denial of service. There is no direct confidentiality or integrity impact; the vulnerability is a memory leak that degrades system availability [1].

Mitigation

The fix is commit 1e6b0a69bf2c9c819255c7566e4355536d81d9cf in the Linux kernel stable tree, adding the missing brelse() call. Users should apply this update. No workaround is mentioned. The vulnerability is not listed on the CISA KEV as of publication [1].

AI Insight generated on May 27, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

2

Patches

10
77d059519382

ext4: fix missing brelse() in ext4_xattr_inode_dec_ref_all()

1 file changed · +3 2
  • fs/ext4/xattr.c+3 2 modified
    diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
    index c6205b405efe43..a4eaee58e54503 100644
    --- a/fs/ext4/xattr.c
    +++ b/fs/ext4/xattr.c
    @@ -1165,7 +1165,7 @@ ext4_xattr_inode_dec_ref_all(handle_t *handle, struct inode *parent,
     {
     	struct inode *ea_inode;
     	struct ext4_xattr_entry *entry;
    -	struct ext4_iloc iloc;
    +	struct ext4_iloc iloc = { .bh = NULL };
     	bool dirty = false;
     	unsigned int ea_ino;
     	int err;
    @@ -1260,6 +1260,8 @@ ext4_xattr_inode_dec_ref_all(handle_t *handle, struct inode *parent,
     			ext4_warning_inode(parent,
     					   "handle dirty metadata err=%d", err);
     	}
    +
    +	brelse(iloc.bh);
     }
     
     /*
    -- 
    cgit 1.3-korg
    
    
    
1bc1107a3a40

ext4: fix missing brelse() in ext4_xattr_inode_dec_ref_all()

1 file changed · +3 2
  • fs/ext4/xattr.c+3 2 modified
    diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
    index c6b14a8fe0d7a5..5b5c3ce7719dc6 100644
    --- a/fs/ext4/xattr.c
    +++ b/fs/ext4/xattr.c
    @@ -1165,7 +1165,7 @@ ext4_xattr_inode_dec_ref_all(handle_t *handle, struct inode *parent,
     {
     	struct inode *ea_inode;
     	struct ext4_xattr_entry *entry;
    -	struct ext4_iloc iloc;
    +	struct ext4_iloc iloc = { .bh = NULL };
     	bool dirty = false;
     	unsigned int ea_ino;
     	int err;
    @@ -1260,6 +1260,8 @@ ext4_xattr_inode_dec_ref_all(handle_t *handle, struct inode *parent,
     			ext4_warning_inode(parent,
     					   "handle dirty metadata err=%d", err);
     	}
    +
    +	brelse(iloc.bh);
     }
     
     /*
    -- 
    cgit 1.3-korg
    
    
    
097227f1ffe1

ext4: fix missing brelse() in ext4_xattr_inode_dec_ref_all()

1 file changed · +3 2
  • fs/ext4/xattr.c+3 2 modified
    diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
    index 2c90217d193647..3f310264385270 100644
    --- a/fs/ext4/xattr.c
    +++ b/fs/ext4/xattr.c
    @@ -1165,7 +1165,7 @@ ext4_xattr_inode_dec_ref_all(handle_t *handle, struct inode *parent,
     {
     	struct inode *ea_inode;
     	struct ext4_xattr_entry *entry;
    -	struct ext4_iloc iloc;
    +	struct ext4_iloc iloc = { .bh = NULL };
     	bool dirty = false;
     	unsigned int ea_ino;
     	int err;
    @@ -1260,6 +1260,8 @@ ext4_xattr_inode_dec_ref_all(handle_t *handle, struct inode *parent,
     			ext4_warning_inode(parent,
     					   "handle dirty metadata err=%d", err);
     	}
    +
    +	brelse(iloc.bh);
     }
     
     /*
    -- 
    cgit 1.3-korg
    
    
    
1e6b0a69bf2c

ext4: fix missing brelse() in ext4_xattr_inode_dec_ref_all()

1 file changed · +3 2
  • fs/ext4/xattr.c+3 2 modified
    diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
    index 6ecdcb389e1b02..f0522a4538d19a 100644
    --- a/fs/ext4/xattr.c
    +++ b/fs/ext4/xattr.c
    @@ -1165,7 +1165,7 @@ ext4_xattr_inode_dec_ref_all(handle_t *handle, struct inode *parent,
     {
     	struct inode *ea_inode;
     	struct ext4_xattr_entry *entry;
    -	struct ext4_iloc iloc;
    +	struct ext4_iloc iloc = { .bh = NULL };
     	bool dirty = false;
     	unsigned int ea_ino;
     	int err;
    @@ -1260,6 +1260,8 @@ ext4_xattr_inode_dec_ref_all(handle_t *handle, struct inode *parent,
     			ext4_warning_inode(parent,
     					   "handle dirty metadata err=%d", err);
     	}
    +
    +	brelse(iloc.bh);
     }
     
     /*
    -- 
    cgit 1.3-korg
    
    
    
f07290668893

ext4: fix missing brelse() in ext4_xattr_inode_dec_ref_all()

1 file changed · +3 2
  • fs/ext4/xattr.c+3 2 modified
    diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
    index c6205b405efe43..a4eaee58e54503 100644
    --- a/fs/ext4/xattr.c
    +++ b/fs/ext4/xattr.c
    @@ -1165,7 +1165,7 @@ ext4_xattr_inode_dec_ref_all(handle_t *handle, struct inode *parent,
     {
     	struct inode *ea_inode;
     	struct ext4_xattr_entry *entry;
    -	struct ext4_iloc iloc;
    +	struct ext4_iloc iloc = { .bh = NULL };
     	bool dirty = false;
     	unsigned int ea_ino;
     	int err;
    @@ -1260,6 +1260,8 @@ ext4_xattr_inode_dec_ref_all(handle_t *handle, struct inode *parent,
     			ext4_warning_inode(parent,
     					   "handle dirty metadata err=%d", err);
     	}
    +
    +	brelse(iloc.bh);
     }
     
     /*
    -- 
    cgit 1.3-korg
    
    
    
77d059519382

ext4: fix missing brelse() in ext4_xattr_inode_dec_ref_all()

1 file changed · +3 2
  • fs/ext4/xattr.c+3 2 modified
    diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
    index c6205b405efe43..a4eaee58e54503 100644
    --- a/fs/ext4/xattr.c
    +++ b/fs/ext4/xattr.c
    @@ -1165,7 +1165,7 @@ ext4_xattr_inode_dec_ref_all(handle_t *handle, struct inode *parent,
     {
     	struct inode *ea_inode;
     	struct ext4_xattr_entry *entry;
    -	struct ext4_iloc iloc;
    +	struct ext4_iloc iloc = { .bh = NULL };
     	bool dirty = false;
     	unsigned int ea_ino;
     	int err;
    @@ -1260,6 +1260,8 @@ ext4_xattr_inode_dec_ref_all(handle_t *handle, struct inode *parent,
     			ext4_warning_inode(parent,
     					   "handle dirty metadata err=%d", err);
     	}
    +
    +	brelse(iloc.bh);
     }
     
     /*
    -- 
    cgit 1.3-korg
    
    
    
1e6b0a69bf2c

ext4: fix missing brelse() in ext4_xattr_inode_dec_ref_all()

1 file changed · +3 2
  • fs/ext4/xattr.c+3 2 modified
    diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
    index 6ecdcb389e1b02..f0522a4538d19a 100644
    --- a/fs/ext4/xattr.c
    +++ b/fs/ext4/xattr.c
    @@ -1165,7 +1165,7 @@ ext4_xattr_inode_dec_ref_all(handle_t *handle, struct inode *parent,
     {
     	struct inode *ea_inode;
     	struct ext4_xattr_entry *entry;
    -	struct ext4_iloc iloc;
    +	struct ext4_iloc iloc = { .bh = NULL };
     	bool dirty = false;
     	unsigned int ea_ino;
     	int err;
    @@ -1260,6 +1260,8 @@ ext4_xattr_inode_dec_ref_all(handle_t *handle, struct inode *parent,
     			ext4_warning_inode(parent,
     					   "handle dirty metadata err=%d", err);
     	}
    +
    +	brelse(iloc.bh);
     }
     
     /*
    -- 
    cgit 1.3-korg
    
    
    
097227f1ffe1

ext4: fix missing brelse() in ext4_xattr_inode_dec_ref_all()

1 file changed · +3 2
  • fs/ext4/xattr.c+3 2 modified
    diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
    index 2c90217d193647..3f310264385270 100644
    --- a/fs/ext4/xattr.c
    +++ b/fs/ext4/xattr.c
    @@ -1165,7 +1165,7 @@ ext4_xattr_inode_dec_ref_all(handle_t *handle, struct inode *parent,
     {
     	struct inode *ea_inode;
     	struct ext4_xattr_entry *entry;
    -	struct ext4_iloc iloc;
    +	struct ext4_iloc iloc = { .bh = NULL };
     	bool dirty = false;
     	unsigned int ea_ino;
     	int err;
    @@ -1260,6 +1260,8 @@ ext4_xattr_inode_dec_ref_all(handle_t *handle, struct inode *parent,
     			ext4_warning_inode(parent,
     					   "handle dirty metadata err=%d", err);
     	}
    +
    +	brelse(iloc.bh);
     }
     
     /*
    -- 
    cgit 1.3-korg
    
    
    
1bc1107a3a40

ext4: fix missing brelse() in ext4_xattr_inode_dec_ref_all()

1 file changed · +3 2
  • fs/ext4/xattr.c+3 2 modified
    diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
    index c6b14a8fe0d7a5..5b5c3ce7719dc6 100644
    --- a/fs/ext4/xattr.c
    +++ b/fs/ext4/xattr.c
    @@ -1165,7 +1165,7 @@ ext4_xattr_inode_dec_ref_all(handle_t *handle, struct inode *parent,
     {
     	struct inode *ea_inode;
     	struct ext4_xattr_entry *entry;
    -	struct ext4_iloc iloc;
    +	struct ext4_iloc iloc = { .bh = NULL };
     	bool dirty = false;
     	unsigned int ea_ino;
     	int err;
    @@ -1260,6 +1260,8 @@ ext4_xattr_inode_dec_ref_all(handle_t *handle, struct inode *parent,
     			ext4_warning_inode(parent,
     					   "handle dirty metadata err=%d", err);
     	}
    +
    +	brelse(iloc.bh);
     }
     
     /*
    -- 
    cgit 1.3-korg
    
    
    
f07290668893

ext4: fix missing brelse() in ext4_xattr_inode_dec_ref_all()

1 file changed · +3 2
  • fs/ext4/xattr.c+3 2 modified
    diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
    index c6205b405efe43..a4eaee58e54503 100644
    --- a/fs/ext4/xattr.c
    +++ b/fs/ext4/xattr.c
    @@ -1165,7 +1165,7 @@ ext4_xattr_inode_dec_ref_all(handle_t *handle, struct inode *parent,
     {
     	struct inode *ea_inode;
     	struct ext4_xattr_entry *entry;
    -	struct ext4_iloc iloc;
    +	struct ext4_iloc iloc = { .bh = NULL };
     	bool dirty = false;
     	unsigned int ea_ino;
     	int err;
    @@ -1260,6 +1260,8 @@ ext4_xattr_inode_dec_ref_all(handle_t *handle, struct inode *parent,
     			ext4_warning_inode(parent,
     					   "handle dirty metadata err=%d", err);
     	}
    +
    +	brelse(iloc.bh);
     }
     
     /*
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"Missing brelse() call after ext4_get_inode_loc() in ext4_xattr_inode_dec_ref_all() causes a buffer head reference leak."

Attack vector

An attacker with the ability to trigger extended attribute operations on an ext4 filesystem that has block checksums disabled (`block_csum` false) can cause a buffer head reference leak. Each call to `ext4_xattr_inode_dec_ref_all()` acquires a buffer head via `ext4_get_inode_loc()` that is never freed. Repeated operations exhaust the buffer head cache, leading to a denial of service. No special network path is required — the attack is local, triggered through filesystem operations such as removing extended attributes or deleting files with xattr inodes.

Affected code

The bug is in the function `ext4_xattr_inode_dec_ref_all()` in `fs/ext4/xattr.c` [patch_id=2660168]. The function calls `ext4_get_inode_loc()` to obtain a buffer head (`iloc.bh`) but never releases it with `brelse()` when `block_csum` is false.

What the fix does

The patch makes two changes in `fs/ext4/xattr.c` [patch_id=2660168]. First, it initializes `iloc` with `{ .bh = NULL }` to ensure a clean starting state. Second, it adds a `brelse(iloc.bh)` call at the end of the function, just before the closing brace, to release the buffer head that was acquired by `ext4_get_inode_loc()`. This closes the reference leak that was introduced by commit c8e008b60492 ("ext4: ignore xattrs past end").

Preconditions

  • configThe ext4 filesystem must have block checksums disabled (block_csum == false)
  • inputThe attacker must be able to trigger operations that call ext4_xattr_inode_dec_ref_all(), such as removing extended attributes or deleting files with xattr inodes

Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.