⬢ DragonFlyBSD Kernel Audit
DF-5707 / devmem.c
← back to finding ↓ download raw
/*
 * devmem.c - read/write u64 at a kernel virtual address via /dev/mem
 * (DragonFly x86_64: KERNBASE = 0xFFFFFFFF80000000, phys = va - KERNBASE)
 *
 * usage: devmem r <hexaddr>          -> prints "0x<value>"
 *        devmem w <hexaddr> <hexval> -> writes, then reads back
 */
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <inttypes.h>
#include <string.h>
#include <err.h>

#define KERNBASE 0xFFFFFFFF80000000ULL

int main(int argc, char **argv)
{
    unsigned long long addr, val = 0;
    off_t phys;
    int fd, wr = 0;
    uint64_t buf;

    if (argc >= 3 && !strcmp(argv[1], "r")) {
        addr = strtoull(argv[2], NULL, 0);
    } else if (argc >= 4 && !strcmp(argv[1], "w")) {
        addr = strtoull(argv[2], NULL, 0);
        val  = strtoull(argv[3], NULL, 0);
        wr = 1;
    } else {
        fprintf(stderr, "usage: devmem r|w <hexaddr> [hexval]\n");
        return 2;
    }
    if (addr < KERNBASE)
        errx(1, "addr below KERNBASE");
    phys = (off_t)(addr - KERNBASE);

    fd = open("/dev/mem", wr ? O_RDWR : O_RDONLY);
    if (fd < 0)
        err(1, "open /dev/mem");
    if (pread(fd, &buf, 8, phys) != 8)
        err(1, "pread");
    if (wr) {
        buf = val;
        if (pwrite(fd, &buf, 8, phys) != 8)
            err(1, "pwrite");
        if (pread(fd, &buf, 8, phys) != 8)
            err(1, "pread-back");
    }
    printf("0x%llx\n", (unsigned long long)buf);
    return 0;
}