DF-1880 / harness.c
/* * DF-1880 source-confirmation harness (oce_hw_update_multicast mac[32] OOB). * * sys/dev/netif/oce/oce_hw.c:547-585 oce_hw_update_multicast: * TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { * if (req->params.req.num_mac == OCE_MAX_MC_FILTER_SIZE) break; // L568 * bcopy(LLADDR(...), &req->params.req.mac[num_mac], ETH_ADDR_LEN); // L576 * req->params.req.num_mac++; * } * * OCE_MAX_MC_FILTER_SIZE = 64 (oce_hw.h:180) but the mac[] array is * declared mac[32] inside mbx_set_common_iface_multicast (oce_hw.h:1119). * Joining 33+ multicast groups writes 6 bytes past mac[32] starting at * byte offset 192 in the DMA alloc; joining 64 groups writes 192 bytes * off the end. * * Live trigger needs an Emulex OneConnect NIC (device oce is in GENERIC * but no HW on this guest). The harness reproduces the index math with * a flat byte buffer. * * Build: cc -O2 -o harness harness.c * Run: ./harness */ #include <stdio.h> #include <stdlib.h> #include <string.h> #define OCE_MAX_MC_FILTER_SIZE 64 /* oce_hw.h:180 (loop bound — WRONG) */ #define MAC_ARRAY_SIZE 32 /* oce_hw.h:1119 mac[32] (actual) */ #define ETH_ADDR_LEN 6 #define MAC_BYTES (MAC_ARRAY_SIZE * ETH_ADDR_LEN) /* 192 */ int main(void) { /* Model the DMA alloc as a flat byte buffer with a sentinel tail. */ size_t blob_sz = 8192; unsigned char *buf = calloc(1, blob_sz); unsigned char *mac = buf; /* mac[32][6] is first 192 bytes */ unsigned char *sentinel = buf + MAC_BYTES; /* "past the mac array" */ for (size_t i = MAC_BYTES; i < blob_sz; i++) buf[i] = 0xEE; unsigned int num_mac = 0; int groups = 64; for (int g = 0; g < groups; g++) { if (num_mac == OCE_MAX_MC_FILTER_SIZE) break; /* oce_hw.c:568 — bound is 64 */ unsigned char lladdr[ETH_ADDR_LEN] = { 0x01,0x00,0x5e, (unsigned char)((g >> 16) & 0x7f), (unsigned char)((g >> 8) & 0xff), (unsigned char)(g & 0xff) }; memcpy(mac + num_mac * ETH_ADDR_LEN, lladdr, ETH_ADDR_LEN); /* L576 OOB when num_mac>=32 */ num_mac++; } int corrupted = 0; for (size_t i = MAC_BYTES; i < blob_sz; i++) if (buf[i] != 0xEE) corrupted++; int overflow_slots = (num_mac > MAC_ARRAY_SIZE) ? (int)num_mac - MAC_ARRAY_SIZE : 0; printf("DF-1880: oce_hw_update_multicast (oce_hw.c:547-585)\n"); printf(" joined %u multicast groups (loop bound OCE_MAX_MC_FILTER_SIZE=%d, " "mac[] array size=%d slots)\n", num_mac, OCE_MAX_MC_FILTER_SIZE, MAC_ARRAY_SIZE); printf(" OOB writes = %d MAC slots x %d bytes = %d bytes past mac[32] " "into the DMA alloc\n", overflow_slots, ETH_ADDR_LEN, overflow_slots * ETH_ADDR_LEN); printf(" Harness: simulated bcopy touched %d sentinel bytes past mac[32]\n", corrupted); printf(" Fix: loop bound should be nitems(req->params.req.mac)=32, not " "OCE_MAX_MC_FILTER_SIZE=64.\n"); free(buf); return 0; } |