| Summary: |
VUL-0: CVE-2023-42756: kernel-source: Linux kernel race condition in netfilter |
| Product: |
[Novell Products] SUSE Security Incidents
|
Reporter: |
Gianluca Gabrielli <gianluca.gabrielli> |
| Component: |
Incidents | Assignee: |
Security Team bot <security-team> |
| Status: |
RESOLVED
FIXED
|
QA Contact: |
Security Team bot <security-team> |
| Severity: |
Normal
|
|
|
| Priority: |
P3 - Medium
|
CC: |
chester.lin, denis.kirjanov, meissner, mkubecek
|
| Version: |
unspecified | |
|
| Target Milestone: |
--- | |
|
| Hardware: |
Other | |
|
| OS: |
Other | |
|
| URL: |
https://smash.suse.de/issue/379891/
|
| Whiteboard: |
CVSSv3.1:SUSE:CVE-2023-42756:5.5:(AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H) |
|
Found By:
|
---
|
Services Priority:
|
|
|
Business Priority:
|
|
Blocker:
|
---
|
|
Marketing QA Status:
|
---
|
IT Deployment:
|
---
|
From the osss public ML ----------------------- Hi there, I recently found a race condition bug in the Linux kernel between IPSET_CMD_ADD and IPSET_CMD_SWAP in netfilter/ip_set, which can lead to the invocation of `__ip_set_put` on a wrong `set`, triggering the `BUG_ON(set->ref == 0);` check in it, which leads to local DoS. I confirm it at least affect upstream, v6.5.rc7, v6.1, and v5.10. [Root Cause] The bug is in the netfilter subsystem. In `ip_set_swap` function, it will hold the `ip_set_ref_lock` and then do the following to swap the sets: ~~~ strncpy(from_name, from->name, IPSET_MAXNAMELEN); strncpy(from->name, to->name, IPSET_MAXNAMELEN); strncpy(to->name, from_name, IPSET_MAXNAMELEN); swap(from->ref, to->ref); ~~~ But in the retry loop in `call_ad`: ~~~ if (retried) { __ip_set_get(set); nfnl_unlock(NFNL_SUBSYS_IPSET); cond_resched(); nfnl_lock(NFNL_SUBSYS_IPSET); __ip_set_put(set); } ~~~ No lock is hold when it does the `cond_resched()`. As a result, `ip_set_ref_lock` (in thread 2) can swap the set with another when thread 1 is doing the `cond_resched()`. When thread 1 wakes up, the `set` variable alreays means another `set`, calling `__ip_set_put` on it will decrease the refcount on the wrong `set`, triggering the `BUG_ON` call. According to Jozsef Kadlecsik, who fixed the bug, the root cause is that the `call_ad` function is using a wrong ref counter. Instead of using `__ip_set_get`, which operates on `set->ref`, the correct way is to operate on `set->ref_netlink`. [Severity] It will invoke a `BUG_ON` call, leading to kernel panic. In other words, it will lead to local DoS. [Patch] Jozsef Kadlecsik prepared a patch and it got merged into mainline and stables already. The patch can be found here: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=7433b6d2afd512d04398c73aa984d1e285be125b [Proof-of-Concept] A proof-of-concept code to trigger the bug is attached to this email. Best, Kyle