DF-3777 / manifest.json
{ "finding_id": "DF-3777", "file": "sys/dev/netif/jme/if_jme.c", "verdict": "inconclusive", "impact_class": "none", "reproduce": { "build": "scp findings/poc/DF-3777/{Makefile,jme_callout_replica.c} dfbsd:/root/kmod/ ; vm.sh run_root 'cd /root/kmod && make'", "run": "vm.sh run_root 'kldload /root/kmod/jme_callout_replica.ko; sysctl kern.jmereplica.rxspin=1; sysctl kern.jmereplica.rxspin_fix=1; dmesg | grep rxspin | tail -2'", "expected": "Broken shape: 'guard=-1 iterations=200000000 reposts=0 rx_cons 0 -> 0' - the verbatim jme_rxeof loop (if_jme.c:2494-2562, count=-1) against a simulated OWN-clear/VALID-set (nsegs=0,pktlen=0) descriptor provably never terminates (the 200M guard is the only exit; zero reposts; consumer unchanged). Fix shape (fix.diff): 'iterations=2 reposts=1 rx_cons 0 -> 1 (terminates; degenerate desc reposted)'. The (0,0) pair passes the only descriptor validation, 'nsegs != howmany(pktlen, MCLBYTES)' (if_jme.c:2513), because howmany(0,2048)==0; jme_rxpkt with nsegs==0 neither reposts (jme_newbuf loop :2361 / jme_discard_rxbufs :2350 never run) nor advances jme_rx_cons (:2484) - on faulty/malicious controller hardware the RX interrupt thread spins forever holding the ring serializer. Compliant silicon always reports nsegs>=1; guest has no JMicron NIC (hardware-gated, inconclusive per family convention)." }, "kernel_refs": [ "sys/dev/netif/jme/if_jme.c:2494", "sys/dev/netif/jme/if_jme.c:2513", "sys/dev/netif/jme/if_jme.c:2350", "sys/dev/netif/jme/if_jme.c:2361", "sys/dev/netif/jme/if_jme.c:2484", "sys/dev/netif/jme/if_jme.c:3845", "sys/dev/netif/jme/if_jme.c:3500", "sys/dev/netif/jme/if_jmereg.h:985", "sys/dev/netif/jme/if_jmereg.h:995", "sys/net/if_ethersubr.c:1501" ], "artifacts": [ "README.md", "VERDICT.md", "jme_callout_replica.c", "Makefile", "build.log", "run.log", "fix_build.log", "env.txt", "fix.diff", "manifest.json", "verdict.json" ] } |