DragonFlyBSD Kernel Audit
DF-2931 / uuidoff.c
← back to finding ↓ download raw
/*
 * DF-2931 proof module: show exactly what if_getanyethermac() reads
 * for the first IFT_ETHER interface, versus that interface's real MAC,
 * plus the offsets that decide in-struct vs out-of-bounds.
 */
#include <sys/param.h>
#include <sys/module.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/bus.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_arp.h>
#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/if_media.h>
#include <net/ifq_var.h>
#include <sys/eventhandler.h>

#include "virtio_net.h"
#include "if_vtnetvar.h"

static void
uuidoff_dump(void)
{
	struct ifnet *ifp;
	size_t off = __offsetof(struct arpcom, ac_enaddr);
	int n = 0;

	kprintf("uuidoff: sizeof(struct ifnet)             = %zu\n",
	    sizeof(struct ifnet));
	kprintf("uuidoff: offsetof(struct arpcom,ac_enaddr)= %zu\n", off);
	kprintf("uuidoff: sizeof(struct vtnet_softc)       = %zu\n",
	    sizeof(struct vtnet_softc));

	TAILQ_FOREACH(ifp, &ifnetlist, if_link) {
		uint8_t *p;
		struct sockaddr_dl *sdl;
		uint8_t *mac;

		if (ifp->if_type != IFT_ETHER)
			continue;
		p = (uint8_t *)ifp->if_softc + off;
		sdl = IF_LLSOCKADDR(ifp);
		mac = (uint8_t *)LLADDR(sdl);
		kprintf("uuidoff: ether[%d] %s if_softc=%p\n",
		    n, ifp->if_xname, ifp->if_softc);
		kprintf("uuidoff:   bytes at if_softc+%zu (what "
		    "if_getanyethermac copies into UUID node): "
		    "%02x:%02x:%02x:%02x:%02x:%02x\n",
		    off, p[0], p[1], p[2], p[3], p[4], p[5]);
		kprintf("uuidoff:   real MAC from sdl (sdl_alen=%u): "
		    "%02x:%02x:%02x:%02x:%02x:%02x\n",
		    sdl->sdl_alen, mac[0], mac[1], mac[2], mac[3], mac[4],
		    mac[5]);
		n++;
	}
	kprintf("uuidoff: %d IFT_ETHER interface(s); "
	    "if_getanyethermac uses the FIRST\n", n);
}

static int
uuidoff_modevent(module_t mod, int type, void *data)
{
	switch (type) {
	case MOD_LOAD:
		uuidoff_dump();
		return (0);
	case MOD_UNLOAD:
		kprintf("uuidoff: unloaded\n");
		return (0);
	}
	return (EOPNOTSUPP);
}

static moduledata_t uuidoff_mod = {
	"uuidoff",
	uuidoff_modevent,
	NULL
};

DECLARE_MODULE(uuidoff, uuidoff_mod, SI_SUB_DRIVERS, SI_ORDER_ANY);
MODULE_VERSION(uuidoff, 1);