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

ena_com_set_hash_function() inverts the device-support check β€” RSS hash function is never programmed on compliant devices

Summary

The check returns ENA_COM_UNSUPPORTED exactly when the function IS supported (Linux reference has the negation). On every compliant ENA device the SET_FEATURE hash-function command is never sent; the RSS init tolerates the EOPNOTSUPP, so RSS hashing silently stays in device-default mode. Missing '!' fix.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-3936 Β· 6 files
FileTypeDescriptionSize
README.md β€” 1.9 KB ↓ raw
VERDICT.md β€” 2.1 KB ↓ raw
fix.diff β€” 477 B view raw
env.txt β€” 984 B view raw
manifest.json β€” 775 B view raw
verdict.json β€” 2.0 KB view raw

DF-3936 β€” ena_com_set_hash_function() inverts the hash-function support check

Finding

sys/dev/virtual/amazon/ena/ena-com/ena_com.c:2238-2242

    if (get_resp.u.flow_hash_func.supported_func & (1 << rss->hash_func)) {
        ena_trc_err("Func hash %d isn't supported by device, abort\n",
                rss->hash_func);
        return ENA_COM_UNSUPPORTED;
    }

The condition aborts exactly when the device DOES support the selected hash function. Every reference implementation (Linux ena_com.c) uses if (!(get_resp.u.flow_hash_func.supported_func & (1 << rss->hash_func))). Note 1 << rss->hash_func uses enum positions (TOEPLITZ=1 β†’ bit 1, CRC32=2 β†’ bit 2) consistent with the spec's funcs bitmask.

Impact

On any compliant ENA device, ena_com_set_hash_function() always fails with ENA_COM_UNSUPPORTED == EOPNOTSUPP (ena_plat.h:175). ena_com_fill_hash_function() (ena_com.c:2323-2329) then takes its restore path, and the caller ena_rss_init_default (ena.c:3081-3087) treats EOPNOTSUPP as tolerable β€” so RSS hash-function configuration (including the driver-chosen CRC32 init value 0xFFFFFFFF) is silently never programmed. Result: receive-side steering stays in whatever mode the device had (default), degrading the multi-queue RSS contract the driver advertises (netisr steering assumes RSS hashing); no memory-safety impact. Confusion vector (hypervisor boundary): a malicious device cannot exploit the inversion for memory corruption β€” it is a pure functional/logic defect (CWE-628/606-style inverted check).

Trigger

Attach any ENA device that advertises RSS hash function support; observe "Func hash %d isn't supported by device, abort" in the trace although the function IS supported, and ena_com_fill_hash_function returning EOPNOTSUPP.

Why inconclusive on this guest

The audit guest has no Amazon ENA PCI function (vendor 0x1d0f absent, env.txt); the path requires the AWS Nitro hypervisor device.

VERDICT.md
↓ download raw

DF-3936 β€” VERDICT

Status: inconclusive (hardware-gated) β€” source-level certainty: certain. Impact: logic defect on the hypervisor boundary (RSS hash function never programmed); no memory corruption.

Proof from source

  • sys/dev/virtual/amazon/ena/ena-com/ena_com.c:2238: if (get_resp.u.flow_hash_func.supported_func & (1 << rss->hash_func)) immediately followed by the "isn't supported" error + return ENA_COM_UNSUPPORTED (:2239-2242). The success path (executing the SET_FEATURE at :2244-2267) is only reachable when the device does NOT support the function β€” i.e. the command is only ever sent for functions the device rejects (and then fails server-side), or never sent at all for the one that matters.
  • Upstream reference (Linux drivers/net/ethernet/amazon/ena) has the negated form; the FreeBSD/DragonFly port dropped the !.
  • Chain: ena_rss_init_default (sys/dev/virtual/amazon/ena/ena.c:3081-3087) calls ena_com_fill_hash_function(ena_dev, ENA_ADMIN_CRC32, NULL, ENA_HASH_KEY_SIZE, 0xFFFFFFFF) β†’ ena_com_set_hash_function() β†’ inverted check fires (device supports CRC32) β†’ EOPNOTSUPP β†’ caller tolerates it (rc != EOPNOTSUPP guard at ena.c:3082) β†’ the hash function/init value are never programmed, and ena_com_get_hash_function(NULL,NULL) runs as "restore" (ena_com.c:2326-2328).

Why not reproduced

Requires an ENA PCI function (Amazon EC2 Nitro); the audit QEMU guest's pciconf -l (env.txt) shows only Intel PIIX4 + virtio devices β€” vendor 0x1d0f absent. Classified inconclusive per batch convention.

Fix

fix.diff adds the missing ! (one character), matching Linux.

fix_status

not_testable β€” no ENA hardware on the guest; the diff is a 1-token logic correction against the exact cited line.

Fix status (batch validation)

Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.

Fix verification

not_testable
baseline no→ patch + rebuild →patched clean

Fix not validated on the guest: requires an ENA PCI function (Amazon Nitro), absent from the audit guest (env.txt). fix.diff is the one-token logic correction (missing '!') at ena_com.c:2238, matching the Linux reference driver.

findings/poc/DF-3936/fix.diff + VERDICT.md
↓ fix.diffper-fix-DF-3936

Confirmed kernel references

Detail

Evidence (decisive lines)

findings/poc/DF-3936/VERDICT.md + fix.diff (1-token diff) + env.txt

PoC changes

No seed PoC; hardware-gated.

Verified recommended fix

Negate the support check at ena_com.c:2238 (see fix.diff).

Verdict

ena_com_set_hash_function inverts its device-support check (ena_com.c:2238): it returns ENA_COM_UNSUPPORTED exactly when the device DOES support the selected hash function (Linux has the negated form). On any compliant ENA device the RSS hash function (driver selects CRC32 with init 0xFFFFFFFF via ena.c:3081) is therefore never programmed; ena_rss_init_default tolerates the EOPNOTSUPP (ena.c:3082) so the failure is silent and receive-side steering degrades to whatever the device default is. Pure logic defect on the hypervisor boundary - no memory-safety impact. Hardware-gated (no vendor-0x1d0f function on the guest) => inconclusive, source-certain.