DF-2367 / rijnh.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | /* * rijnh.c -- userland driver for the kern.rijnh.test kernel harness * (DF-2367 / DF-2368 verification). Runs on the guest. * * Most ops just write a command string to the sysctl and print the * readback; results are also kprintf'd with tag RIJNH: (dmesg). * * The poison/direct ops set up the user-VA guard layout the kernel * rig walks into: one mapped (pre-faulted) page followed by an * unmapped page, with the rijndael_ctx placed in the last 512 bytes * of the mapped page so the ek[] walk of the runaway round loop * crosses the page boundary after ~16 32-byte steps. * * Build: cc -O -o rijnh rijnh.c */ #include <sys/types.h> #include <sys/sysctl.h> #include <sys/mman.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #define SYSCTL_NAME "kern.rijnh.test" static int do_cmd(const char *cmd) { char buf[512]; size_t len = sizeof(buf); int rc; rc = sysctlbyname(SYSCTL_NAME, buf, &len, cmd, strlen(cmd) + 1); if (rc != 0) { perror("sysctlbyname(write)"); return (rc); } /* read back the harness result string */ memset(buf, 0, sizeof(buf)); len = sizeof(buf); rc = sysctlbyname(SYSCTL_NAME, buf, &len, NULL, 0); if (rc == 0) printf("readback: %s\n", buf); return (0); } static int do_poison(const char *op) { char cmd[128]; char *base; unsigned long addr; base = mmap(NULL, 2 * 4096, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); if (base == MAP_FAILED) { perror("mmap"); return (1); } if (munmap(base + 4096, 4096) != 0) { /* guard page: UNMAPPED */ perror("munmap"); return (1); } memset(base, 0xAA, 4096); /* pre-fault the page */ addr = (unsigned long)(base + 4096 - 512); printf("%s: mapped page %p, guard page %p (unmapped)," " ctx at %lx\n", op, base, base + 4096, addr); fflush(stdout); snprintf(cmd, sizeof(cmd), "%s %lx", op, addr); return (do_cmd(cmd)); } static void usage(void) { fprintf(stderr, "usage: rijnh kat | setkey <bits> | twinval <n> |" " idx <keyhex> <pthex> | idxr1 <keyhex> <pthex> |" " bench <n> <keyhex> | poison | direct\n"); exit(2); } int main(int argc, char **argv) { char cmd[512]; if (argc < 2) usage(); if (strcmp(argv[1], "kat") == 0) return (do_cmd("kat")); if (strcmp(argv[1], "poison") == 0 || strcmp(argv[1], "direct") == 0) return (do_poison(argv[1])); if (strcmp(argv[1], "setkey") == 0 && argc == 3) { snprintf(cmd, sizeof(cmd), "setkey %s", argv[2]); return (do_cmd(cmd)); } if (strcmp(argv[1], "twinval") == 0 && argc == 3) { snprintf(cmd, sizeof(cmd), "twinval %s", argv[2]); return (do_cmd(cmd)); } if ((strcmp(argv[1], "idx") == 0 || strcmp(argv[1], "idxr1") == 0) && argc == 4) { snprintf(cmd, sizeof(cmd), "%s %s %s", argv[1], argv[2], argv[3]); return (do_cmd(cmd)); } if (strcmp(argv[1], "bench") == 0 && argc == 4) { snprintf(cmd, sizeof(cmd), "bench %s %s", argv[2], argv[3]); return (do_cmd(cmd)); } usage(); return (2); } |