β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-0303

HMAC precomputed context torn-read race between config and input paths

Summary

carp_hmac_prepare(:504) rewrites sc_sha1 in-place on CPU0. carp_hmac_verify/generate(:562) bcopy sc_sha1 on packet-input CPU (any). No lock/barrier. Code admits XXX: possible race here(:517). Torn SHA1_CTX -> legitimate adv fails HMAC -> failover disruption. Timing-dependent.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-0303 Β· 8 files
FileTypeDescriptionSize
fix.diff suggested-fix Add crit_enter/crit_exit around sc_sha1/sc_pad access 1.3 KB view raw
VERDICT.md verdict Full analysis of HMAC torn-read race 2.7 KB ↓ raw
README.md readme Finding summary 825 B ↓ raw
build.sh build-script No binary (code analysis) 146 B view raw
run.sh run-script Verify torn-read race code path 378 B view raw
env.txt environment Guest environment 442 B view raw
../fix_build_combined.log build-log Combined 41-finding kernel build (rc=0, -Werror clean) 5.6 MB ↓ download
../fix_build_summary.txt build-summary Summary of the combined 41-finding kernel build 826 B view raw
README.md readme Finding summary
↓ download raw

DF-0303: CARP HMAC Precomputed Context Torn-Read Race

Finding

carp_hmac_prepare() (ip_carp.c:504) rewrites sc_sha1 in-place. The code admits /* XXX: possible race here */ at line 517. carp_hmac_generate() (line 556) and carp_hmac_verify() (line 575) bcopy sc_sha1 on any CPU. No lock/barrier. Torn SHA1_CTX causes legitimate adv to fail HMAC β†’ failover disruption.

Reproduction

Code-confirmed. Race requires concurrent SIOCSVH ioctl (carp_hmac_prepare) + packet input (carp_hmac_generate) on different CPUs. The CARP receive path cannot be exercised on this QEMU guest. The bug is self-evident from the XXX comment at line 517 and the unlocked bcopy at line 562.

Fix

See fix.diff β€” adds crit_enter/crit_exit around sc_sha1/sc_pad writes in carp_hmac_prepare and the bcopy in carp_hmac_generate.

VERDICT.md verdict Full analysis of HMAC torn-read race
↓ download raw

DF-0303 VERDICT: CARP HMAC Precomputed Context Torn-Read Race

Verdict: REPRODUCED (code-confirmed)

Mechanism

carp_hmac_prepare() at ip_carp.c:504 rewrites sc->sc_sha1 (a SHA1_CTX) in-place on whatever CPU calls it (typically CPU 0 during configuration via SIOCSVH). The code itself admits the race at line 517:

/* XXX: possible race here */

carp_hmac_generate() at ip_carp.c:556 does a bcopy(&sc->sc_sha1, &sha1ctx, sizeof(sha1ctx)) on the packet-input CPU (which can be any CPU). carp_hmac_verify() at ip_carp.c:575 calls carp_hmac_generate().

If carp_hmac_prepare() is running on CPU 0 (rewriting sc_sha1) while carp_hmac_generate() is running on another CPU (reading sc_sha1 via bcopy), the bcopy can read a partially-updated (torn) SHA1_CTX. This produces an incorrect HMAC, causing legitimate advertisements to fail verification. The result: a BACKUP rejects a valid MASTER's advertisement, potentially disrupting failover.

The sc_pad array (used for the outer hash) has the same issue: it's rewritten by carp_hmac_prepare (lines 520-523, 551-552) and read by carp_hmac_generate (line 569) without synchronization.

Impact

Timing-dependent failover disruption. An administrator reconfiguring CARP (e.g., changing the key or addresses via ifconfig) while advertisements are being processed can cause a torn SHA1_CTX, leading to HMAC verification failure of legitimate advertisements. The BACKUP may fail to track the MASTER, causing unnecessary failover or black-holing. Requires concurrent configuration change + packet input.

Dynamic Demonstration

This is a timing-dependent race condition. On this single QEMU guest: - The CARP receive path cannot be exercised (QEMU doesn't loopback multicast) - The race requires concurrent SIOCSVH ioctl + packet input on different CPUs - The code explicitly admits the race with /* XXX: possible race here */

Confirmed by code analysis: carp_hmac_prepare writes sc_sha1/sc_pad without holding any lock, while carp_hmac_generate reads them via bcopy on a potentially different CPU.

Fix

Added crit_enter()/crit_exit() around the critical sections in both carp_hmac_prepare() (protecting the sc_sha1/sc_pad writes) and carp_hmac_generate() (protecting the bcopy of sc_sha1). Combined with the ASSERT_NETISR0 fix from DF-0302 (which serializes the input path to CPU 0), this closes the torn-read window. See fix.diff.

Kernel Refs

Fix verification

not_testable

compile validated

see evidence pack

Confirmed kernel references

β€”

Detail

Exploit chain

none

Evidence (decisive lines)

β€”

Verdict

Source-confirmed. carp_hmac_prepare in-place rewrite with / XXX: possible race here / + no lock. Torn SHA1_CTX read. QEMU no multicast.