⬢ DragonFlyBSD Kernel Audit
DF-5051 / mkpatch.c
← back to finding ↓ download raw
/*
 * mkpatch.c - emit kv(8) write commands for the dal_vector fix
 * hot-patches, with all module addresses derived from the live amdgpu
 * base passed as argv[1] (hex, 0x optional).
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

static uint64_t CAVE, INS, DES, KFREE, MDRM;

static void
emit(const char *what, uint64_t addr, const unsigned char *b, size_t n)
{
	size_t i;

	printf("# %s\n/root/kv write %llx ", what, (unsigned long long)addr);
	for (i = 0; i < n; i++)
		printf("%02x", b[i]);
	printf("\n");
}

static void
put32(unsigned char *p, int32_t v)
{
	memcpy(p, &v, 4);
}

int
main(int argc, char **argv)
{
	unsigned char b[128];
	uint64_t base, S1, S2;
	int o;

	if (argc != 2)
		return (2);
	base = strtoull(argv[1], NULL, 16);

	CAVE = 0xffffffff809bda90ULL;
	INS = base + 0x11d2b0;
	DES = base + 0x11d120;
	KFREE = 0xffffffff80657e80ULL;
	MDRM = 0xffffffff810d9800ULL;
	S1 = CAVE + 0x80;
	S2 = CAVE + 0x100;

	/* stub1: insert_at bounds check */
	o = 0;
	memcpy(b + o, "\x3b\x57\x0c", 3); o += 3;	/* cmp 0xc(%rdi),%edx */
	b[o++] = 0x72; b[o++] = 0x0b;			/* jb reject */
	memcpy(b + o, "\x55\x48\x89\xe5\x41\x56", 6); o += 6;
	b[o++] = 0xe9; put32(b + o, (int32_t)(INS + 6 - (S1 + o + 4))); o += 4;
	memcpy(b + o, "\x31\xc0\xc3", 3); o += 3;	/* xor eax,eax; ret */
	emit("stub1 (insert_at bounds check)", S1, b, o);

	o = 0;
	b[o++] = 0xe9; put32(b + o, (int32_t)(S1 - (INS + 5))); o += 4;
	emit("insert_at entry jmp -> stub1", INS, b, o);

	/* stub2: fixed destruct (kfree + container=NULL + count/cap=0) */
	o = 0;
	memcpy(b + o, "\x55\x48\x89\xe5", 4); o += 4;
	memcpy(b + o, "\x53\x48\x89\xfb", 4); o += 4;	/* push rbx; mov rbx,rdi */
	memcpy(b + o, "\x48\x8b\x07", 3); o += 3;	/* mov rax,[rbx] */
	memcpy(b + o, "\x48\x85\xc0", 3); o += 3;	/* test rax,rax */
	b[o++] = 0x74; b[o++] = 0x12;			/* jz .clr */
	memcpy(b + o, "\x48\x89\xc7", 3); o += 3;	/* mov rdi,rax */
	b[o++] = 0x48; b[o++] = 0xbe;			/* mov rsi, imm64 */
	memcpy(b + o, &MDRM, 8); o += 8;
	b[o++] = 0xe8; put32(b + o, (int32_t)(KFREE - (S2 + o + 4))); o += 4;
	memcpy(b + o, "\x48\xc7\x03\x00\x00\x00\x00", 7); o += 7;
	memcpy(b + o, "\xc7\x43\x0c\x00\x00\x00\x00", 7); o += 7;
	memcpy(b + o, "\xc7\x43\x10\x00\x00\x00\x00", 7); o += 7;
	memcpy(b + o, "\x5b\x5d\xc3", 3); o += 3;
	emit("stub2 (fixed destruct)", S2, b, o);

	o = 0;
	b[o++] = 0xe9; put32(b + o, (int32_t)(S2 - (DES + 5))); o += 4;
	emit("destruct entry jmp -> stub2", DES, b, o);

	printf("export VCREATE=%llx VINSERT=%llx VDESTRUCT=%llx\n",
	    (unsigned long long)(base + 0x11d070),
	    (unsigned long long)INS, (unsigned long long)DES);
	return (0);
}