All projects with patches now have outreach docs. 276 new docs covering CWE-407, CWE-312, CWE-362 across C, C++, Java, Python, Go, Rust, C#, PHP, Ruby, JavaScript, Dart, Erlang, R, and more. Outreach gap: 276 -> 0.
74 lines
2.8 KiB
Markdown
74 lines
2.8 KiB
Markdown
# systemd — CWE-407 Disclosure Brief (systemd-0003)
|
||
**2026-04-13 · Patch available — awaiting upstream merge**
|
||
|
||
## Finding
|
||
|
||
One O(n²) defect in systemd's D-Bus cgroup BPF filter path deduplication. `strv_contains()` performs linear scans on a growing string vector during IPIngressFilterPath/IPEgressFilterPath processing. Patched.
|
||
|
||
## The Defects
|
||
|
||
**systemd-0003 (PATCHED — LOW-MEDIUM):** `src/core/dbus-cgroup.c` (~line 578)
|
||
|
||
```c
|
||
// In BPF filter path setter — fires per D-Bus property set:
|
||
for (;;) {
|
||
const char *path;
|
||
r = sd_bus_message_read(message, "s", &path);
|
||
...
|
||
if (!UNIT_WRITE_FLAGS_NOOP(flags) && !strv_contains(*filters, path)) {
|
||
r = strv_extend(filters, path); // O(N) scan before each append
|
||
}
|
||
n++;
|
||
}
|
||
```
|
||
|
||
`strv_contains` expands to `strv_find()`, an O(N) linear scan of all previously accepted paths. For N paths in the incoming message, total cost is O(N²) string comparisons. In normal operation BPF program lists are short (< 10 entries), but a misbehaving or malicious D-Bus client can send a large array, triggering pathological CPU usage in PID 1.
|
||
|
||
## Complexity Proof
|
||
|
||
**systemd-0003:** At N=500 duplicate filter paths via D-Bus:
|
||
- Defective: ~125,000 string comparisons
|
||
- Fixed: ~500 hash lookups
|
||
- **~250× op reduction.** Severity escalates with adversarial input to PID 1.
|
||
|
||
## Impact
|
||
|
||
systemd is the init system for virtually all major Linux distributions, running as PID 1. The BPF filter path dedup runs inside PID 1's D-Bus message handler. While typical deployments use few BPF filter paths, a misbehaving or malicious D-Bus client sending large arrays can cause pathological CPU usage in the most critical process on the system.
|
||
|
||
The same `strv_contains` pattern appears in `src/core/load-fragment.c` inside `config_parse_ip_filter_bpf_progs()` which builds BPF prog path lists from unit files.
|
||
|
||
## The Fix
|
||
|
||
**systemd-0003:** Build a `Set*` (hashmap-backed, O(1) lookup) from accepted paths before the loop:
|
||
|
||
```c
|
||
// Before — O(N²)
|
||
strv_contains(*filters, path)
|
||
|
||
// After — O(N)
|
||
_cleanup_set_free_ Set *seen = NULL;
|
||
STRV_FOREACH(e, *filters)
|
||
set_put_strdup(&seen, *e);
|
||
// ... in loop:
|
||
if (!set_contains(seen, path)) {
|
||
set_put_strdup(&seen, path);
|
||
strv_extend(filters, path);
|
||
}
|
||
```
|
||
|
||
## Patch
|
||
|
||
Fix available: `defects/systemd/patch/systemd-0003-dbus-cgroup-bpf-filter-strv-dedup.patch`
|
||
|
||
Single-file patch in `src/core/dbus-cgroup.c`.
|
||
|
||
## What We Ask
|
||
|
||
A patch is ready for review.
|
||
|
||
1. Confirm receipt and assign an issue reference (systemd/systemd).
|
||
2. Assess severity — fires in PID 1 D-Bus handler; adversarial input amplifies impact.
|
||
3. Coordinate a disclosure date — we are targeting 90 days from first contact.
|
||
4. We will credit the systemd team in the public disclosure. Preferred acknowledgment format welcome.
|
||
|
||
Contact: see cover email. This brief is confidential until coordinated disclosure.
|