DF-2252 / harness_hexncpy.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 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | /* * ========================================================================== * DF-2252 / DF-2253 audit verification harness (GUEST-ONLY, NOT FOR UPSTREAM) * * Compiled into the kernel by appending to sys/libkern/hexncpy.c so that it * links against the REAL production hexncpy() in the same translation unit. * Runtime kldload GPFs this guest, so the harness is built into the kernel * via `make nativekernel`. * * Trigger (root): sysctl kern.df_hexncpy=1 -> canary/output matrix * sysctl kern.df_hexncpy=2 -> m_print() with a legal * zero-m_len mbuf in the chain * Output goes to console + msgbuf (dmesg / serial log), lines prefixed DFTEST. * ========================================================================== */ #include <sys/kernel.h> #include <sys/sysctl.h> #include <sys/malloc.h> #include <sys/mbuf.h> static int df_hexncpy_run(int mode); static int sysctl_df_hexncpy(SYSCTL_HANDLER_ARGS) { int error, mode = 0; error = sysctl_handle_int(oidp, &mode, 0, req); if (error != 0 || req->newptr == NULL) return (error); return (df_hexncpy_run(mode)); } SYSCTL_PROC(_kern, OID_AUTO, df_hexncpy, (CTLTYPE_INT | CTLFLAG_RW), 0, 0, sysctl_df_hexncpy, "I", "DF-2252/DF-2253 hexncpy audit harness"); #define DF_CANARY 0xAA static int df_hexncpy_run(int mode) { u_char inbuf[8] = { 0xde, 0xad, 0xbe, 0xef, 0x12, 0x34, 0x56, 0x78 }; u_char hrd1244[2] = { 0x12, 0x34 }; /* ar_hrd wire bytes for 0x1234 */ u_char *region; char *outb; int i, underflows = 0; if (mode == 2) { /* m_print() path: legal zero-m_len mbuf leading the chain */ struct mbuf *mh, *m2; mh = m_gethdr(M_WAITOK, MT_DATA); m2 = m_get(M_WAITOK, MT_DATA); if (mh == NULL || m2 == NULL) return (ENOMEM); mh->m_pkthdr.len = 8; mh->m_len = 0; /* legal: empty leading mbuf */ m2->m_len = 8; mh->m_next = m2; kprintf("DFTEST M1 m_print begin (pkthdr.len=8, m_len=0 lead)\n"); m_print(mh); kprintf("DFTEST M1 m_print returned\n"); m_freem(mh); return (0); } if (mode != 1) return (EINVAL); /* * Canary-guarded matrix: kmalloc 32 bytes, all 0xAA, hand hexncpy * ®ion[16] as the destination. Any write to region[15] is a * 1-byte underflow before the caller buffer (DF-2252). */ region = kmalloc(32, M_TEMP, M_WAITOK | M_ZERO); outb = (char *)®ion[16]; for (i = 0; i < 32; i++) region[i] = DF_CANARY; kprintf("DFTEST C1 sep=\"-\" inlen=4 outlen=12 (control)\n"); kprintf("DFTEST C1 canary_before=0x%02x\n", region[15]); kprintf("DFTEST C1 out=[%s]\n", hexncpy(inbuf, 4, outb, 12, "-")); kprintf("DFTEST C1 canary_after=0x%02x\n", region[15]); underflows += (region[15] != DF_CANARY); for (i = 0; i < 32; i++) region[i] = DF_CANARY; kprintf("DFTEST C2 inlen=0 outlen=12 sep=\"-\" (DF-2252 core)\n"); kprintf("DFTEST C2 canary_before=0x%02x\n", region[15]); hexncpy(inbuf, 0, outb, 12, "-"); kprintf("DFTEST C2 canary_after=0x%02x buf0=0x%02x\n", region[15], region[16]); underflows += (region[15] != DF_CANARY); for (i = 0; i < 32; i++) region[i] = DF_CANARY; kprintf("DFTEST C3 inlen=-1 outlen=12 sep=\"-\" (DF-2252 core)\n"); kprintf("DFTEST C3 canary_before=0x%02x\n", region[15]); hexncpy(inbuf, -1, outb, 12, "-"); kprintf("DFTEST C3 canary_after=0x%02x buf0=0x%02x\n", region[15], region[16]); underflows += (region[15] != DF_CANARY); for (i = 0; i < 32; i++) region[i] = DF_CANARY; kprintf("DFTEST C4 sep=NULL inlen=6 outlen=18 (DF-2253 generic)\n"); kprintf("DFTEST C4 out=[%s]\n", hexncpy(inbuf, 6, outb, 18, NULL)); kprintf("DFTEST C4 canary_after=0x%02x\n", region[15]); underflows += (region[15] != DF_CANARY); for (i = 0; i < 32; i++) region[i] = DF_CANARY; kprintf("DFTEST C5 if_ether.c:643 shape inlen=2 outlen=5 sep=NULL\n"); kprintf("DFTEST C5 out=[%s]\n", hexncpy(hrd1244, 2, outb, 5, NULL)); kprintf("DFTEST C5 canary_after=0x%02x\n", region[15]); underflows += (region[15] != DF_CANARY); for (i = 0; i < 32; i++) region[i] = DF_CANARY; kprintf("DFTEST C6 mly.c:1344 shape inlen=4 outlen=12 sep=NULL\n"); kprintf("DFTEST C6 out=[%s]\n", hexncpy(inbuf, 4, outb, 12, NULL)); kprintf("DFTEST C6 canary_after=0x%02x\n", region[15]); underflows += (region[15] != DF_CANARY); kfree(region, M_TEMP); kprintf("DFTEST matrix done underflow_canary_hits=%d\n", underflows); return (0); } |