โฌข DragonFlyBSD Kernel Audit
DF-1075 / df1075_fixed_pattern.c
โ† back to finding โ†“ download raw
/*
 * DF-1075 "FIXED PATTERN" harness โ€” replicates the CORRECTED allocation
 * order from the fix: read descriptor FIRST, then allocate with the real
 * multicast filter count, then memcpy.  This module must NOT panic.
 *
 * Contrast with df1075_harness.c (buggy pattern: kmalloc(0) โ†’ ZERO_LENGTH_PTR
 * โ†’ memcpy โ†’ panic).
 *
 * The fix moves sc_mcfilters allocation from kue_attach() to kue_attach_post()
 * AFTER kue_ctl(KUE_CMD_GET_ETHER_DESCRIPTOR) fills sc->sc_desc.  So
 * KUE_MCFILTCNT(sc) now reflects the device-reported count (e.g. 32), the
 * kmalloc gets a real size, and the memcpy writes to valid memory.
 *
 * Load: kldload ./df1075_fixed_pattern.ko
 * Effect: prints success messages, returns 0, NO PANIC.
 */

#include <sys/param.h>
#include <sys/module.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/errno.h>
#include <sys/types.h>

#define HARNESS_ETHER_ADDR_LEN 6

/* Simulate the device-reported kue_mcastfilt value (N=32 filters).
 * Real KL5KUSB101B hardware advertises 128 (if_kue.c:51 comment). */
#define HARNESS_NFILTERS_FROM_DESC 32

MALLOC_DECLARE(M_HARNESS2);
MALLOC_DEFINE(M_HARNESS2, "df1075_fixed", "DF-1075 fixed pattern");

static int
df1075_fixed_event(module_t mod, int type, void *arg)
{
	char *mcfilters;
	char fake_mac[HARNESS_ETHER_ADDR_LEN] = {0x33, 0x33, 0xff, 0x00, 0x00, 0x01};

	switch (type) {
	case MOD_LOAD:
		/*
		 * FIXED kue_attach_post() pattern (if_kue.c after fix):
		 *   kue_ctl(... KUE_CMD_GET_ETHER_DESCRIPTOR ...);  // fills sc_desc
		 *   sc->sc_mcfilters = kmalloc(KUE_MCFILTCNT(sc) * ETHER_ADDR_LEN, ...);
		 * KUE_MCFILTCNT(sc) is now 32 (from the descriptor), so size=192.
		 */
		mcfilters = kmalloc(HARNESS_NFILTERS_FROM_DESC * HARNESS_ETHER_ADDR_LEN,
		    M_HARNESS2, M_WAITOK);

		kprintf("DF-1075-FIXED: kmalloc(%d*%d=%d) returned %p\n",
		    HARNESS_NFILTERS_FROM_DESC, HARNESS_ETHER_ADDR_LEN,
		    HARNESS_NFILTERS_FROM_DESC * HARNESS_ETHER_ADDR_LEN,
		    mcfilters);

		if (mcfilters == NULL) {
			kprintf("DF-1075-FIXED: allocation FAILED (unexpected)\n");
			return (ENOMEM);
		}
		if (mcfilters == (void *)-8) {
			kprintf("DF-1075-FIXED: BUG STILL PRESENT: got ZERO_LENGTH_PTR!\n");
			return (EFAULT);
		}

		/*
		 * kue_setmulti() memcpy โ€” now writes into a properly-sized buffer.
		 */
		memcpy(&mcfilters[0], fake_mac, HARNESS_ETHER_ADDR_LEN);
		kprintf("DF-1075-FIXED: memcpy into &mcfilters[0]=%p SUCCEEDED, no panic\n",
		    &mcfilters[0]);
		kprintf("DF-1075-FIXED: wrote %02x:%02x:%02x:%02x:%02x:%02x\n",
		    (unsigned char)mcfilters[0], (unsigned char)mcfilters[1],
		    (unsigned char)mcfilters[2], (unsigned char)mcfilters[3],
		    (unsigned char)mcfilters[4], (unsigned char)mcfilters[5]);

		kfree(mcfilters, M_HARNESS2);
		kprintf("DF-1075-FIXED: kfree OK โ€” fix verified, no panic\n");
		return (0);

	case MOD_UNLOAD:
		return (0);
	default:
		return (EOPNOTSUPP);
	}
}

static moduledata_t df1075_fixed_mod = {
	"df1075_fixed",
	df1075_fixed_event,
	NULL
};

DECLARE_MODULE(df1075_fixed, df1075_fixed_mod, SI_SUB_EXEC, SI_ORDER_ANY);
MODULE_VERSION(df1075_fixed, 1);