In June 2024, a significant vulnerability was identified and patched in the Linux kernel's Workqueue subsystem. CVE-2024-44981 is a logic flaw that causes an undefined behavior sanitizer (UBSAN) error, triggered by an integer subtraction overflow during system boot, most notably on virtualized Android environments. This bug can panic or crash the kernel due to a mishandled left-shift and subtraction when building bit masks.

This post breaks down the vulnerability, its exploitability, the patch, and what kernel developers and system admins should do.

What is the Workqueue Bug?

The workqueue is a generic subsystem in the Linux kernel for deferred or background task processing. The function shift_and_mask() helps encode and decode complex bitfields for workqueue scheduling.

The bug:
The function used to build its mask using a _signed_ integer constant. When the shift parameter reached 31 (as is the case for WORK_OFFQ_POOL_SHIFT), the shift operation caused a subtraction that underflowed the integer, wrapping its value and triggering a UBSAN panic.

Here’s a snippet from the crash log (trimmed for clarity)

Internal error: UBSAN: integer subtraction overflow: 00000000f2005515 [#1] PREEMPT SMP
...
cancel_delayed_work+x34/x44
deferred_probe_extend_timeout+x20/x70
driver_register+xa8/x110
...
Code: f900fbf 97fffa2f 39400268 37100048 (d42aa2a)
...
Kernel panic - not syncing: UBSAN: integer subtraction overflow: Fatal exception

Root cause:

The shift_and_mask() macro was written as

#define shift_and_mask(val, shift, mask)    (((val) >> (shift)) & ((1 << (mask))))

If shift is 31, this attempts 1 << 31 using a signed 32-bit integer. In C, 1 is signed by default, but valid positive range is only up to INT_MAX (2,147,483,647). 1 << 31 becomes -2,147,483,648 which, when used in further calculation, causes an integer subtraction overflow. UBSAN, a kernel runtime sanitizer, catches and panics on this error.

The Patch: Using Unsigned Constants

Fix:
By using an unsigned constant (1U), the dangerous shift stays within valid range for a 32-bit unsigned integer, avoiding undefined (overflow) behavior even at bit 31.

Here’s how the kernel team fixed it

/* Old (buggy) */
((1 << (mask)))

/* Fixed */
((1U << (mask)))

Full diff

-   return ((val) >> (shift)) & ((1 << (mask)));
+   return ((val) >> (shift)) & ((1U << (mask)));

Now, 1U << 31 yields x80000000, not a negative number, so all arithmetic operates correctly.

Crash on Boot:

The specific usage leads to a panic and a denial of service during system startup, especially on certain virtual machines and ARM systems (as seen on Android).

Privilege Escalation:

Currently, there's no direct path to code execution or privilege escalation through this bug. It mainly causes Denial of Service (DoS), which could still be abused in multi-tenant or critical systems.

No remote exploit is known; triggering likely requires local access or a misconfigured kernel build where workqueue bitfield macros are used with high shifts.

Exploit Example

While not a traditional "remote exploit," here’s a pseudo-exploit showing how a custom kernel module (or a local root user) might trigger the overflow:

// Example only! Do not run on production systems.

#include <linux/module.h>
#include <linux/init.h>

static int __init trigger_ubsan(void)
{
    int shift = 31; // Dangerous shift
    int mask = 1;
    // Triggers the buggy behavior (before patch)
    int result = (1 << shift) - mask;
    printk("Result: %d\n", result); // May panic kernel if sanitized!
    return ;
}

static void __exit cleanup(void) {}

module_init(trigger_ubsan);
module_exit(cleanup);
MODULE_LICENSE("GPL");

When compiled and inserted on a vulnerable kernel, this could trip the same UBSAN panic.

This bug is fixed in upstream Linux as of v6.10. Any kernel with the following commit is patched

- workqueue: Fix UBSAN 'subtraction overflow' error in shift_and_mask()

Downstream patches:

- Patch on lore.kernel.org
- Red Hat bug report

Sanitizer config:

If unable to upgrade, kernel can be built without UBSAN, but this is NOT recommended as it hides other bugs.

References

- Upstream commit (kernel.org)
- Linux Kernel workqueue.c source
- CVE Entry at cve.org (pending)
- Kernel discussion on LWN

Summary Table

| Impact | Denial of Service (kernel panic during boot) |
|------------------|-------------------------------------------------------|
| Privex Escalate? | Unlikely; mainly DoS |
| Affected versions| Linux kernels before v6.10 (with UBSAN enabled) |
| Fix available? | Yes; apply update or relevant backport |
| Exploitable? | Local access (DoS), rare; not remote or widespread |

Always run recent, supported kernels and keep them updated for both security and stability.

> Are you vulnerable?
> If you run custom kernels or distros based on Linux prior to 6.10, especially if using Android, embedded, or ARM systems with UBSAN enabled: Update ASAP!


*This post provides an exclusive, clear breakdown of CVE-2024-44981 for system admins, kernel hackers, and anyone interested in Linux security. Reproduction, modification, or red-teaming is for education and patch verification only.*

Timeline

Published on: 09/04/2024 20:15:07 UTC
Last modified on: 09/05/2024 17:54:19 UTC