← Back to Feed CACHED · 2026-07-09 08:28:06 · CACHE_KEY CVE-2026-57589
CVE-2026-57589 · CWE-416 · Disclosed 2026-06-25

sys/kern/sysv_sem

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
Do you agree?
01 · The Real Story

A memory corruption bug hiding in OpenBSD's dusty SysV semaphore attic — you need a shell first, then you have to race the kernel

The bug lives in sys/kern/sysv_sem.c in the sys_semget() path, where a context switch after tsleep() leaves a freed semaphore descriptor reachable and reusable. An attacker with a local user account crafts a concurrent workload that reallocates the freed slab into an attacker-controlled structure, then triggers the dangling reference to corrupt kernel memory and escalate to root. Affected: OpenBSD through 7.9, with the fix landing in the tree at commit 1957873d20. Any host still on 7.9 or earlier release/stable branches — including -current snapshots before the commit — is exposed.

The vendor's HIGH / 7.4 rating with AV:L/AC:H/PR:N/UI:N/C:H/I:H/A:H is honest: local-only, high complexity (race window), no privileges required beyond a shell, full compromise on success. That said, on the fleet-realistic OpenBSD population — which skews heavily toward firewalls, bastion hosts, and appliances that *don't hand out shells* — this bug is a MEDIUM by exposure. The vector is accurate; the urgency depends entirely on whether your OpenBSD boxes are multi-user Unix or single-purpose network appliances.

"Local-only UAF in an obscure syscall path on OpenBSD — vendor HIGH is defensible, but real-world urgency is MEDIUM outside bastion/firewall roles."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Obtain local code execution on the OpenBSD host

The attacker needs an interactive shell or the ability to run an arbitrary binary as any local user. On OpenBSD deployments this typically means either a legitimate developer/operator account, a chained RCE in a userland service (rare on OpenBSD given pledge/unveil), or an insider. No network reach to the box is sufficient by itself.
Conditions required:
  • Local user account or arbitrary code execution as any UID
  • Ability to invoke semget(2) — no pledge restrictions blocking sysvsem
Where this breaks in practice:
  • Most production OpenBSD hosts are single-purpose (pf firewall, relayd, httpd, spamd) with no interactive users
  • Bastion/jump hosts are typically the only multi-user OpenBSD role
Detection/coverage: None — normal shell access is not an alert-worthy event
STEP 02

Prime the SysV semaphore subsystem

The attacker calls semget(2) repeatedly to allocate semaphore identifiers, then arranges a workload that will cause sys_semget() to sleep via tsleep() — typically by contending on the semaphore table lock or semid_ds allocation. This sets up the racy window where a freed descriptor can be observed after context switch.
Conditions required:
  • kern.seminfo limits allow allocation
  • Ability to spawn multiple threads/processes to force contention
Where this breaks in practice:
  • Default OpenBSD kern.seminfo.semmni and semmns limits are conservative — enumeration is trivial but not silent under audit
  • Some hardened installs disable SysV IPC entirely
Detection/coverage: kern.seminfo telemetry and syscall audit (if enabled) will show anomalous semget volume
STEP 03

Race the free-and-reallocate window

Weaponized exploit (no public PoC observed as of disclosure) would use a second thread to free the semaphore descriptor while the first is still sleeping, then heap-spray the kmalloc slab that backed the descriptor with attacker-controlled data — likely via another syscall that allocates similar-sized kernel objects. Success requires winning a tight race across a tsleep() boundary.
Conditions required:
  • Reliable kernel heap primitive for reallocation
  • Knowledge of OpenBSD kernel slab layout for the target release
  • Multi-core host — single-CPU VMs make the race harder
Where this breaks in practice:
  • AC:H is real — the race window is narrow and non-deterministic
  • OpenBSD kernel ASLR (KARL re-links per boot) rerandomizes symbol layout, defeating hardcoded gadget offsets
  • W^X, SMEP-equivalents, and mimmutable(2) reduce viable payload shapes
Detection/coverage: Kernel panics on failed exploitation attempts are a strong signal — capture savecore output
STEP 04

Corrupt kernel state and pivot to root

Once the UAF fires, the attacker overwrites function pointers, credential structures (struct ucred), or a syscall dispatch structure to hand themselves UID 0. Standard technique: locate the current process's credentials via the corrupted primitive, patch cr_uid = 0, return from the syscall as root.
Conditions required:
  • Arbitrary kernel write primitive derived from the UAF
  • No further mitigation blocking credential overwrite
Where this breaks in practice:
  • OpenBSD does not implement CFI on kernel indirect calls the way Linux does, but KARL still complicates target selection
  • No published exploitation guide for this specific class on OpenBSD 7.9
Detection/coverage: Post-exploitation: UID transitions logged by accounting (if accton enabled), unexpected root-owned processes in ps
03 · Intelligence Metadata

The supporting signals.

In-the-wild exploitationNone observed. Not on CISA KEV. No campaigns tied to CVE-2026-57589 as of 2026-07-09.
Public PoCNo public exploit code published. Bug details are in commit 1957873d20 and NVD; weaponization would require independent kernel-race development.
EPSS0.00125 (≈0.1%) — bottom quartile probability of exploitation in the next 30 days.
KEV statusNot listed.
CVSS 3.1 vectorAV:L/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H — local, high complexity, no privs, full CIA impact. Vendor 7.4 HIGH.
Affected versionsOpenBSD ≤ 7.9 (including 7.9-stable and -current pre-fix). Older branches (7.8, 7.7, 7.6…) also carry the vulnerable code path.
Fixed versionOpenBSD tree commit 1957873d20; syspatch for 7.9 and 7.8 stable branches. -current snapshots after the commit date.
Internet exposureNot remotely reachable — no Shodan/Censys/GreyNoise footprint applies. Attack surface = user population on OpenBSD hosts.
Disclosure2026-06-25, credited via NVD assignment; upstream commit landed shortly after.
CWECWE-416 Use-After-Free — context-switch race after tsleep() in sys_semget().
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to MEDIUM (6.2/10)

Downgraded from vendor HIGH to MEDIUM because the decisive factor is local-only attack vector on a platform whose dominant deployment role is single-purpose network appliance with no interactive users — the exposed population that can even reach semget() is a small minority of OpenBSD hosts. High attack complexity (kernel race) and zero observed in-the-wild activity compound the downgrade; the vendor score is technically correct but blind to OpenBSD's deployment reality.

HIGH Vulnerability class and root cause (UAF in `sys_semget` tsleep path)
HIGH Absence of public PoC / KEV listing as of 2026-07-09
MEDIUM Real-world exploitability of the race window on modern OpenBSD kernels

Why this verdict

  • Local-only vector (AV:L): attacker must already be running code on the box. On OpenBSD's dominant footprint — pf firewalls, relayd/httpd appliances, spamd hosts — no unprivileged users exist. Adjustment: −1.0.
  • High attack complexity (AC:H): narrow race window across tsleep() context switch, requires reliable heap-reallocation primitive, KARL rerandomizes kernel layout per boot. Adjustment: −0.5.
  • No public exploit + EPSS 0.00125: no researcher has published a working weaponization, and market-signal probability of exploitation is bottom-quartile. Adjustment: −0.2.
  • Role multiplier — bastion / jump host (typical high-value OpenBSD role): where OpenBSD IS multi-user, it's often the SSH jump box or admin bastion. Local root here yields credential harvesting for the entire operator population. Chain succeeds → outcome: credential-plane pivot. This is why the floor is MEDIUM, not LOW.
  • Role multiplier — pf firewall / edge appliance (dominant OpenBSD role): no local users, no shell access, chain never fires. Represents the majority of installed base, which is why the floor is not HIGH.
  • Role multiplier — developer workstation / lab: chain succeeds; blast radius is one host. Neutral.
  • Floor check: OpenBSD-as-bastion is a plausible high-value role but does NOT dominate the installed base (>10% share is not credible relative to appliance role), so the HIGH floor does not clamp. MEDIUM stands.

Why not higher?

HIGH would require either an unauthenticated network vector, a public PoC lowering the complexity barrier, or evidence that most OpenBSD hosts run in a role with unprivileged user shells. None of those hold: it is local, no PoC exists, and the modal OpenBSD box is an appliance without local users.

Why not lower?

LOW would ignore the bastion-host role and the reality that a local root on an SSH jump host is a credential-plane compromise, not a single-host incident. It would also disregard that the fix is real, the code path is reachable by any local user by default, and a determined attacker with kernel expertise can weaponize this within days once someone publishes a race harness.

05 · Compensating Control

What to do — in priority order.

  1. Inventory OpenBSD hosts by role and shell-access population — Enumerate every OpenBSD ≤7.9 host and tag as (a) appliance-no-users, (b) bastion/jump, (c) developer/multi-user. Only (b) and (c) need urgent attention. Complete within the 30-day mitigation window applicable to bastion hosts specifically (see bottom line); appliance hosts fall to the MEDIUM 365-day remediation SLA.
  2. Restrict SysV semaphore access via pledge and login classes on bastions — For bastion hosts that MUST remain online before patching, wrap operator shells in login classes that omit sysvsem from pledge where practical, and use sysctl kern.seminfo.semmni=0 on hosts that don't need SysV IPC. Deploy within 30 days on bastions.
  3. Apply syspatch to 7.9-stable and 7.8-stable branches — Run syspatch on all affected hosts to pull the semget UAF fix. Bastions and multi-user hosts: within 30 days (noisgate mitigation SLA for HIGH-role hosts). Appliances: within the 365-day MEDIUM remediation window, aligned with next scheduled maintenance.
  4. Enable process accounting and savecore on bastions — Turn on accton so unexpected UID transitions are logged, and confirm savecore is configured so crash dumps from failed exploit attempts are captured for IR review.
  5. Rotate credentials that pass through OpenBSD bastions — Treat bastion patching as a credential-hygiene event: rotate SSH host keys, revoke long-lived operator sessions, and reissue any secrets that traversed the host.
What doesn't work
  • Network segmentation / WAF / IPS: the bug is local (AV:L) — no network signature will fire because no packets are involved.
  • Disabling network services (httpd, relayd, pf): doesn't affect sys_semget() reachability; any local user can still invoke the syscall.
  • EDR on Linux/Windows: OpenBSD has no first-party EDR ecosystem; expecting your Falcon/Defender fleet to catch this is a category error.
  • MFA on SSH: doesn't stop a legitimate operator or an attacker with valid creds from triggering the syscall — MFA gates login, not post-login syscall behavior.
06 · Verification

Crowdsourced verification payload.

Run this on each OpenBSD host as any user (root not required for the version check; root recommended for the syspatch check). Invoke as ./check-cve-2026-57589.sh. Outputs VULNERABLE, PATCHED, or UNKNOWN and exits with 0/1/2 respectively.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/bin/sh
# check-cve-2026-57589.sh
# Determines whether the current OpenBSD host has the sysv_sem UAF fix.
# Exit codes: 0 = PATCHED, 1 = VULNERABLE, 2 = UNKNOWN

set -u

OS=$(uname -s)
if [ "$OS" != "OpenBSD" ]; then
  echo "UNKNOWN: not an OpenBSD host (uname -s = $OS)"
  exit 2
fi

REL=$(uname -r)         # e.g. 7.9
KERN=$(uname -v)        # e.g. GENERIC.MP#123

# Any release <= 7.9 is in scope unless syspatch applied.
case "$REL" in
  7.9|7.8|7.7|7.6|7.5|7.4|7.3|7.2|7.1|7.0|6.*|5.*)
    IN_SCOPE=1
    ;;
  *)
    IN_SCOPE=0
    ;;
esac

if [ "$IN_SCOPE" -eq 0 ]; then
  echo "PATCHED: OpenBSD $REL is newer than affected range (>7.9)"
  exit 0
fi

# Check for the syspatch entry addressing sysv_sem / semget UAF.
# syspatch -l lists applied patches; the fix will appear as e.g. 79-XXX_semget.
if command -v syspatch >/dev/null 2>&1; then
  if syspatch -l 2>/dev/null | grep -Eiq 'sem(get)?|sysv_sem'; then
    echo "PATCHED: OpenBSD $REL with sysv_sem syspatch applied ($KERN)"
    exit 0
  fi
fi

# Check for -current snapshot post-fix (heuristic: build date after 2026-06-25).
BUILD_EPOCH=$(sysctl -n kern.osrevision 2>/dev/null || echo 0)
CUTOFF=202606250000   # YYYYMMDDHHMM style cutoff — adjust if your fleet uses snapshots
if [ "$BUILD_EPOCH" -gt "$CUTOFF" ] 2>/dev/null; then
  echo "PATCHED: kernel osrevision $BUILD_EPOCH is after fix cutoff"
  exit 0
fi

echo "VULNERABLE: OpenBSD $REL ($KERN) — no sysv_sem syspatch found"
exit 1
07 · Bottom Line

If you remember one thing.

TL;DR
Split your OpenBSD fleet by role first — do not patch uniformly. Monday–Wednesday: enumerate every OpenBSD ≤7.9 host and tag it as appliance (no users), bastion/jump, or multi-user. Bastions and multi-user hosts are the real risk surface — treat them as HIGH-role targets and apply syspatch (or rebuild from post-fix snapshot) within 30 days, matching the noisgate mitigation SLA for HIGH; rotate SSH host keys and operator credentials as part of the same maintenance window. Appliance-role OpenBSD hosts (pf firewalls, relayd/httpd, spamd) fall under the noisgate remediation SLA for MEDIUM — no mitigation SLA required, and the vendor patch can land in the 365-day window at the next scheduled maintenance. If CISA adds this to KEV or a public race harness ships, escalate everything to immediate-hours patching regardless of role.

Sources

  1. NVD — CVE-2026-57589
  2. OpenCVE — CVE-2026-57589
  3. THREATINT — CVE-2026-57589
  4. Mondoo Vulnerability Intelligence
  5. Threat-Modeling.com — Vuln Intel Report June 26 2026
  6. GCVE FKIE record
  7. OpenBSD syspatch documentation
  8. OpenBSD KARL (kernel address randomized link) overview
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.