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

CVE-2026-45884

CVE-2026-45884

Description

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

apparmor: avoid per-cpu hold underflow in aa_get_buffer

When aa_get_buffer() pulls from the per-cpu list it unconditionally decrements cache->hold. If hold reaches 0 while count is still non-zero, the unsigned decrement wraps to UINT_MAX. This keeps hold non-zero for a very long time, so aa_put_buffer() never returns buffers to the global list, which can starve other CPUs and force repeated kmalloc(aa_g_path_max) allocations.

Guard the decrement so hold never underflows.

Affected products

1

Patches

8
202824a1f89a

apparmor: avoid per-cpu hold underflow in aa_get_buffer

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitZhengmian HuJan 20, 2026Fixed in 6.12.75via kernel-cna
1 file changed · +2 2
  • security/apparmor/lsm.c+2 2 modified
    diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
    index 9a78fd36542d62..8855fb4b883428 100644
    --- a/security/apparmor/lsm.c
    +++ b/security/apparmor/lsm.c
    @@ -1863,7 +1863,8 @@ char *aa_get_buffer(bool in_atomic)
     	if (!list_empty(&cache->head)) {
     		aa_buf = list_first_entry(&cache->head, union aa_buffer, list);
     		list_del(&aa_buf->list);
    -		cache->hold--;
    +		if (cache->hold)
    +			cache->hold--;
     		cache->count--;
     		put_cpu_ptr(&aa_local_buffers);
     		return &aa_buf->buffer[0];
    -- 
    cgit 1.3-korg
    
    
    
80c334acc6d0

apparmor: avoid per-cpu hold underflow in aa_get_buffer

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitZhengmian HuJan 20, 2026Fixed in 6.18.14via kernel-cna
1 file changed · +2 2
  • security/apparmor/lsm.c+2 2 modified
    diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
    index be3678d08ed23c..13c9bfdf65ff57 100644
    --- a/security/apparmor/lsm.c
    +++ b/security/apparmor/lsm.c
    @@ -2136,7 +2136,8 @@ char *aa_get_buffer(bool in_atomic)
     	if (!list_empty(&cache->head)) {
     		aa_buf = list_first_entry(&cache->head, union aa_buffer, list);
     		list_del(&aa_buf->list);
    -		cache->hold--;
    +		if (cache->hold)
    +			cache->hold--;
     		cache->count--;
     		put_cpu_ptr(&aa_local_buffers);
     		return &aa_buf->buffer[0];
    -- 
    cgit 1.3-korg
    
    
    
640cf2f09575

apparmor: avoid per-cpu hold underflow in aa_get_buffer

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitZhengmian HuJan 20, 2026Fixed in 7.0via kernel-cna
1 file changed · +2 2
  • security/apparmor/lsm.c+2 2 modified
    diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
    index 8d5d9a966b719e..9175fd677ef3db 100644
    --- a/security/apparmor/lsm.c
    +++ b/security/apparmor/lsm.c
    @@ -2137,7 +2137,8 @@ char *aa_get_buffer(bool in_atomic)
     	if (!list_empty(&cache->head)) {
     		aa_buf = list_first_entry(&cache->head, union aa_buffer, list);
     		list_del(&aa_buf->list);
    -		cache->hold--;
    +		if (cache->hold)
    +			cache->hold--;
     		cache->count--;
     		put_cpu_ptr(&aa_local_buffers);
     		return &aa_buf->buffer[0];
    -- 
    cgit 1.3-korg
    
    
    
4bcddd0f6b2e

apparmor: avoid per-cpu hold underflow in aa_get_buffer

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitZhengmian HuJan 20, 2026Fixed in 6.19.4via kernel-cna
1 file changed · +2 2
  • security/apparmor/lsm.c+2 2 modified
    diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
    index 8d5d9a966b719e..9175fd677ef3db 100644
    --- a/security/apparmor/lsm.c
    +++ b/security/apparmor/lsm.c
    @@ -2137,7 +2137,8 @@ char *aa_get_buffer(bool in_atomic)
     	if (!list_empty(&cache->head)) {
     		aa_buf = list_first_entry(&cache->head, union aa_buffer, list);
     		list_del(&aa_buf->list);
    -		cache->hold--;
    +		if (cache->hold)
    +			cache->hold--;
     		cache->count--;
     		put_cpu_ptr(&aa_local_buffers);
     		return &aa_buf->buffer[0];
    -- 
    cgit 1.3-korg
    
    
    
202824a1f89a

apparmor: avoid per-cpu hold underflow in aa_get_buffer

1 file changed · +2 2
  • security/apparmor/lsm.c+2 2 modified
    diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
    index 9a78fd36542d62..8855fb4b883428 100644
    --- a/security/apparmor/lsm.c
    +++ b/security/apparmor/lsm.c
    @@ -1863,7 +1863,8 @@ char *aa_get_buffer(bool in_atomic)
     	if (!list_empty(&cache->head)) {
     		aa_buf = list_first_entry(&cache->head, union aa_buffer, list);
     		list_del(&aa_buf->list);
    -		cache->hold--;
    +		if (cache->hold)
    +			cache->hold--;
     		cache->count--;
     		put_cpu_ptr(&aa_local_buffers);
     		return &aa_buf->buffer[0];
    -- 
    cgit 1.3-korg
    
    
    
80c334acc6d0

apparmor: avoid per-cpu hold underflow in aa_get_buffer

1 file changed · +2 2
  • security/apparmor/lsm.c+2 2 modified
    diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
    index be3678d08ed23c..13c9bfdf65ff57 100644
    --- a/security/apparmor/lsm.c
    +++ b/security/apparmor/lsm.c
    @@ -2136,7 +2136,8 @@ char *aa_get_buffer(bool in_atomic)
     	if (!list_empty(&cache->head)) {
     		aa_buf = list_first_entry(&cache->head, union aa_buffer, list);
     		list_del(&aa_buf->list);
    -		cache->hold--;
    +		if (cache->hold)
    +			cache->hold--;
     		cache->count--;
     		put_cpu_ptr(&aa_local_buffers);
     		return &aa_buf->buffer[0];
    -- 
    cgit 1.3-korg
    
    
    
640cf2f09575

apparmor: avoid per-cpu hold underflow in aa_get_buffer

1 file changed · +2 2
  • security/apparmor/lsm.c+2 2 modified
    diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
    index 8d5d9a966b719e..9175fd677ef3db 100644
    --- a/security/apparmor/lsm.c
    +++ b/security/apparmor/lsm.c
    @@ -2137,7 +2137,8 @@ char *aa_get_buffer(bool in_atomic)
     	if (!list_empty(&cache->head)) {
     		aa_buf = list_first_entry(&cache->head, union aa_buffer, list);
     		list_del(&aa_buf->list);
    -		cache->hold--;
    +		if (cache->hold)
    +			cache->hold--;
     		cache->count--;
     		put_cpu_ptr(&aa_local_buffers);
     		return &aa_buf->buffer[0];
    -- 
    cgit 1.3-korg
    
    
    
4bcddd0f6b2e

apparmor: avoid per-cpu hold underflow in aa_get_buffer

1 file changed · +2 2
  • security/apparmor/lsm.c+2 2 modified
    diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
    index 8d5d9a966b719e..9175fd677ef3db 100644
    --- a/security/apparmor/lsm.c
    +++ b/security/apparmor/lsm.c
    @@ -2137,7 +2137,8 @@ char *aa_get_buffer(bool in_atomic)
     	if (!list_empty(&cache->head)) {
     		aa_buf = list_first_entry(&cache->head, union aa_buffer, list);
     		list_del(&aa_buf->list);
    -		cache->hold--;
    +		if (cache->hold)
    +			cache->hold--;
     		cache->count--;
     		put_cpu_ptr(&aa_local_buffers);
     		return &aa_buf->buffer[0];
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"Missing guard on unsigned integer decrement in aa_get_buffer allows cache->hold to underflow when it reaches 0 while count is still non-zero."

Attack vector

An attacker on the same system can trigger AppArmor path operations that call aa_get_buffer() repeatedly on a given CPU. When the per-CPU buffer cache's hold counter reaches 0 while count is still non-zero, the unconditional decrement wraps the unsigned hold to UINT_MAX [patch_id=2661697]. This prevents aa_put_buffer() from returning buffers to the global list, starving other CPUs and forcing repeated kmalloc(aa_g_path_max) allocations, leading to performance degradation or denial of service.

Affected code

The vulnerable code is in the aa_get_buffer() function in security/apparmor/lsm.c. The unconditional `cache->hold--` on line 2137 (or 1863 in some backport versions) is the specific fault [patch_id=2661697].

What the fix does

The patch adds a guard (`if (cache->hold) cache->hold--`) before the decrement in aa_get_buffer() inside security/apparmor/lsm.c [patch_id=2661697]. This ensures the unsigned hold counter never underflows when it is already 0. By preventing the wrap to UINT_MAX, the fix restores the correct behavior where aa_put_buffer() can eventually return buffers to the global list when hold reaches 0.

Preconditions

  • inputAttacker must be able to trigger AppArmor path operations on the same CPU that invoke aa_get_buffer()
  • configThe per-CPU buffer cache's hold counter must reach 0 while count is still non-zero

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

References

4

News mentions

0

No linked articles in our index yet.