SIOCSVH accepts advbase=0 (missing lower-bound validation): advertisement interval collapses to tick rate, master-down timeout to zero
Summary
carp_ioctl_setvh_dispatch stores sc_advbase=0 whenever the same SIOCSVH request carries advskew>0 (checks only upper bounds). advbase=0 makes carp_setrun compute tv_sec=0 for MASTER ads and 3*0=0s for the BACKUP master-down timeout. REPRODUCED on guest stock kernel with plain ifconfig: stores/displays 'advbase 0'; with advskew=1 the interface emitted 150 ads in 3s (50/s, tick rate) vs the >=1/s protocol minimum - an L2/IGMP/CPU flood from one config line, and instant master-down flapping destabilizing failover clusters. FreeBSD/OpenBSD reject advbase<=0. Privileged misconfiguration -> Low. Fix: substitute CARP_DFLTINTV when 0.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3300 Β· 4 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 2.1 KB | β raw | |
| run1.log | β | 392 B | view raw | |
| run2.log | β | 312 B | view raw | |
| verdict.json | β | 2.3 KB | view raw |
DF-3300 β SIOCSVH accepts advbase=0 (missing lower-bound validation)
Static claim
sys/netinet/ip_carp.c:2463-2474 (carp_ioctl_setvh_dispatch):
if (carpr->carpr_advbase > 0 || carpr->carpr_advskew > 0) {
if (carpr->carpr_advskew >= 255) { error = EINVAL; goto back; }
if (carpr->carpr_advbase > 255) { error = EINVAL; goto back; }
sc->sc_advbase = carpr->carpr_advbase; /* 0 accepted here */
sc->sc_advskew = carpr->carpr_advskew;
error--;
}
There is no advbase <= 0 rejection: a request carrying advskew>0 and
advbase=0 stores sc_advbase = 0, which collapses the advertisement
interval to tick-resolution (tv.tv_sec = 0) in carp_setrun()
(ip_carp.c:1839-1841) and the master-down timeout to 3*0 = 0 s
(ip_carp.c:1812). FreeBSD's carp validates
carpr_advbase <= 0 || > 255 -> EINVAL; OpenBSD likewise rejects <= 0.
Reproduced (guest, stock kernel, ifconfig only)
# ifconfig carp0 vhid 1 pass pocpass advbase 1 advskew 0; ... up; (force MASTER) # ifconfig carp0 advskew 100 # ifconfig carp0 advbase 0 carp: MASTER vhid 1 advbase 0 advskew 100 <- 0 accepted & stored # 3 s of advertisements: 14 -> 21 packets sent (advbase 0, advskew 100: ~2.3 ads/s) # ifconfig carp0 advskew 1 21 -> 171 packets sent (advbase 0, advskew 1: 50 ads/s = tick rate)
50 advertisements/second per carp(4) interface vs the protocol minimum of 1/s (advbase>=1) β an L2/IGMP-state/CPU flood from one config line. Trigger is privileged (root ifconfig), so severity: Low (validation gap / foot-gun), but it also breaks the CARP protocol invariant (RFC-style advbase >= 1s) that peer implementations rely on for failover math.
Fix
- if (carpr->carpr_advbase > 255) {
+ if (carpr->carpr_advbase == 0 || carpr->carpr_advbase > 255) {
error = EINVAL;
goto back;
}
+ /* keep current advbase if caller passes 0 */
i.e. mirror FreeBSD:
sc->sc_advbase = carpr->carpr_advbase ? carpr->carpr_advbase
: CARP_DFLTINTV;
Files
- run1.log / run2.log β guest console transcripts (ifconfig + netstat)
Fix verification
fixedadvbase=0 substituted with CARP_DFLTINTV at setvh: the stock trigger (ifconfig advbase 0 with advskew>0) no longer stores 0; per pack the reviewer verified the store/display path on the rebuilt kernel. Reviewer's verdict.json omitted fix_* keys; sidecar reconstructed by the orchestrator from the pack.
['findings/poc/DF-3300/README.md', 'findings/poc/DF-3300/run.log']
Confirmed kernel references
Detail
Evidence (decisive lines)
["run2.log: 'carp: MASTER vhid 1 advbase 0 advskew 100' (0 accepted and stored)", 'run2.log: packets sent 14->21 over 3 s at 0/100, then 21->171 over 3 s at 0/1 (50 ads/sec)', 'sys/netinet/ip_carp.c:2463-2474 (missing advbase<=0 rejection)', 'sys/netinet/ip_carp.c:1812,1839-1841 (tv_sec = advbase / 3*advbase)']
PoC changes
No PoC source needed - plain ifconfig sequence: 'advskew 100' then 'advbase 0' (a bare 'advbase 0' with advskew==0 is skipped by the >0||>0 guard, so advskew must be non-zero in the stored state first), then 'advskew 1'.
Verified recommended fix
Reject advbase==0 in carp_ioctl_setvh_dispatch (or substitute CARP_DFLTINTV for 0), matching FreeBSD's lower-bound validation.
Verdict
Reproduced on the stock guest kernel with ifconfig only: SIOCSVH stores sc_advbase=0 whenever the same request carries advskew>0 (ip_carp.c:2463-2474 lacks the lower-bound check FreeBSD/OpenBSD have). With advbase=0/advskew=1 the carp(4) interface advertises at tick rate - measured 150 advertisements in 3 s (50/s) vs the protocol minimum of 1/s - and the BACKUP master-down timeout collapses to 3*0=0 s. Privileged trigger only (root ifconfig), hence Low severity, but it breaks the >=1 s CARP interval invariant for every peer.
No comments yet.