⬢ DragonFlyBSD Kernel Audit
DF-3439 / krules.c
← back to finding ↓ download raw
/*
 * krules.c - walk fw3_ctx[cpu]->rules and dump raw ip_fw rule bytes via kvm
 * verifies exactly what ip_fw3_chk walks on each CPU.
 */
#include <sys/param.h>
#include <sys/types.h>
#include <fcntl.h>
#include <kvm.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct insn {
	uint8_t  opcode;
	uint8_t  len;
	uint16_t arg1;
	uint8_t  module;
	uint8_t  arg3;
	uint16_t arg2;
};

struct ipfwhdr {
	unsigned long next;
	unsigned long next_rule;
	uint16_t act_ofs;
	uint16_t cmd_len;
	uint16_t rulenum;
	uint8_t  set;
	uint8_t  flags;
	uint64_t pcnt;
	uint64_t bcnt;
	uint32_t timestamp;
	unsigned long sibling;
};

static kvm_t *kd;

static int
rd(unsigned long addr, void *buf, size_t len)
{
	return kvm_read(kd, addr, buf, len) == (ssize_t)len ? 0 : -1;
}

int
main(int argc, char **argv)
{
	struct nlist nl[2];
	unsigned long ctxs[64];
	unsigned long ctx;
	struct ipfwhdr h;
	struct insn in;
	int cpu, ncpu = (argc > 1) ? atoi(argv[1]) : 1;

	memset(nl, 0, sizeof(nl));
	nl[0].n_name = "fw3_ctx";
	kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, NULL);
	if (!kd) { fprintf(stderr, "kvm: %s\n", kvm_geterr(kd)); return 1; }
	if (kvm_nlist(kd, nl) < 0 || !nl[0].n_value) {
		fprintf(stderr, "nlist: %s\n", kvm_geterr(kd));
		return 1;
	}
	if (rd(nl[0].n_value, ctxs, sizeof(ctxs))) {
		fprintf(stderr, "read fw3_ctx: %s\n", kvm_geterr(kd));
		return 1;
	}
	for (cpu = 0; cpu < ncpu; cpu++) {
		unsigned long rule;
		int n;

		ctx = ctxs[cpu];
		if (!ctx) { printf("cpu%d: no ctx\n", cpu); continue; }
		if (rd(ctx, &rule, sizeof(rule))) { printf("cpu%d: ctx read fail\n", cpu); continue; }
		printf("cpu%d rules @ 0x%lx:\n", cpu, rule);
		for (n = 0; rule && n < 20; n++, rule = h.next) {
			int i;
			if (rd(rule, &h, sizeof(h))) { printf("  read fail 0x%lx\n", rule); break; }
			printf("  rule 0x%lx num=%u set=%u act_ofs=%u cmd_len=%u "
			    "pcnt=%llu next=0x%lx next_rule=0x%lx\n",
			    rule, h.rulenum, h.set, h.act_ofs, h.cmd_len,
			    (unsigned long long)h.pcnt, h.next, h.next_rule);
			for (i = 0; i < h.cmd_len; i += 2) {
				if (rd(rule + 56 + i * 4, &in, sizeof(in)))
					break;
				printf("    insn%d: opcode=%u len=%u arg1=%u "
				    "module=%u arg3=%u arg2=%u\n",
				    i / 2, in.opcode, in.len, in.arg1,
				    in.module, in.arg3, in.arg2);
			}
		}
	}
	return 0;
}