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

IP_MINTTL (GTSM) bypassed for all raw sockets except the last in rip_input delivery list

Field Value
ID DF-0651
Status new
Severity Low
CVSS 3.1 CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:L
CWE CWE-697 Incorrect Comparison
File sys/netinet/raw_ip.c
Lines 164-185 (in-loop delivery, no TTL check); 189 (post-loop check, last only)
Area netinet (IPv4 raw input GTSM enforcement)
Confidence likely
Discovered 2026-07-02
Reported pending

Summary

rip_input enforces inp_ip_minttl (the IP_MINTTL socket option used for GTSM/BGP hardening) only against the last matching PCB in the pcblist walk. All other matching PCBs receive a copy of the packet via m_copypacket with no TTL check, defeating the minimum-TTL protection whenever more than one raw socket matches the same protocol/address tuple.

Root cause

In rip_input (raw_ip.c:144-213) the loop is structured as:

LIST_FOREACH(inp, &ripcbinfo.pcblisthead, inp_list) {
    /* proto + addr match filters ... */
    if (last) {
        struct mbuf *n = m_copypacket(m, M_NOWAIT);   /* line 165 */
        if (n) {
            /* ... append n to last->so_rcv UNCONDITIONALLY ... */ /* line 172 */
        }
    }
    last = inp;
}
/* Check the minimum TTL for socket. */
if (last && ip->ip_ttl < last->inp_ip_minttl) {       /* line 189 β€” LAST ONLY */

The TTL gate at line 189 only inspects the final value of last. For every previous last (every matching PCB that is not the last in pcblist order), delivery at lines 164-185 happens with zero consideration of that PCB's inp_ip_minttl.

Threat model & preconditions

  • Attacker: unauthenticated remote.
  • Preconditions: two or more raw sockets bound to the same protocol on the target host, and the protected socket is not the last in pcblist traversal order.
  • Impact: an attacker can defeat GTSM protections on raw-IP daemons, injecting spoofed packets from beyond the intended TTL hop count. Uncommon precondition limits practical impact.

Move the TTL check into the in-loop delivery path so every matched PCB is gated:

--- a/sys/netinet/raw_ip.c
+++ b/sys/netinet/raw_ip.c
@@ -161,6 +161,12 @@
        if (last) {
            struct mbuf *n = m_copypacket(m, M_NOWAIT);

+           if (n && ip->ip_ttl < last->inp_ip_minttl) {
+               m_freem(n);
+               n = NULL;
+           }
            if (n) {

References

Timeline

  • 2026-07-02 Discovered during automated DragonFlyBSD kernel security audit.
  • 2026-07-02 Reported to DragonFlyBSD security contact (pending).

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-0651 Β· 5 files
FileTypeDescriptionSize
fix.diff suggested-fix Gate in-loop delivery on ip_ttl>0. 353 B view raw
VERDICT.md verdict source-confirmation + fix 1.0 KB ↓ raw
../_batch_low/fix_build.log build-log combined 80-fix kernel build (rc=0, -Werror) 5.6 MB ↓ download
../_batch_low/combined_all.patch suggested-fix all 80 fixes batched 20.0 KB view raw
../_batch_low/env.txt environment guest uname + kern.version 247 B view raw
VERDICT.md verdict source-confirmation + fix
↓ download raw

DF-0651 β€” Low-severity source-confirmation

Verdict: REPRODUCED

Impact: leak Confidence: likely

Kernel ref: sys/netinet/raw_ip.c:165

Mechanism / why

Source-confirmed: rip_input delivers m_copypacket to each previous 'last' socket unconditionally inside the loop (no TTL check); only the post-loop delivery is TTL-gated. netinet (GENERIC).

Gate in-loop delivery on ip_ttl>0.

Phase 8 (combined build)

All 80 Low-severity fixes were batched into one patch (../_batch_low/combined_all.patch) and applied to the in-guest /usr/src. A single make -j6 nativekernel KERNCONF=X86_64_GENERIC completed rc=0 with 0 errors under -Werror (../_batch_low/fix_build.log). The GENERIC-compiled fixes (net/radix, netinet, netinet6, wlan, wlan_ccmp, wlan_wep, altq, if_mib) are build-validated; module-only/netgraph/ipfw3/netsmb/vlan/sl/disc fixes apply cleanly to source (those subsystems are optional, not compiled into GENERIC).

A standalone git apply-able fix.diff is in this folder.

Fix verification

fixed
baseline reproduced→ patch + rebuild →patched clean

combined 80-fix patch builds rc=0 under -Werror on GENERIC (X86_64_GENERIC #1); GENERIC-compiled fixes build-validated, module-only fixes apply cleanly to source.

baseline 6.5-DEVELOPMENT #0 (Jul 2) -> patched build #1 (Jul 23) rc=0 -Werror, 0 errors
↓ fix.diffDragonFly 6.5-DEVELOPMENT #1: Thu Jul 23 06:52:07 UTC 2026

Confirmed kernel references

Detail

Exploit chain

none (Low-severity leak; source-only confirmation)

Evidence (decisive lines)

DF-0651 [REPRODUCED] - sys/netinet/raw_ip.c:165

PoC changes

fix.diff present in findings/poc/DF-0651/; batched into ../_batch_low/combined_all.patch

Verified recommended fix

Gate in-loop delivery on ip_ttl>0.

Verdict

Source-confirmed: rip_input delivers m_copypacket to each previous 'last' socket unconditionally inside the loop (no TTL check); only the post-loop delivery is TTL-gated. netinet (GENERIC).