DF-5755 / cesu_witness.c
/* DF-5755/DF-5756 — kernel-side witness module. * * Loads libiconv (MODULE_DEPEND), opens the exact converter pairs the * msdosfs KICONV mount opens, and runs iconv_convchr() on the adversarial * sequences with an 8-byte output buffer — proving, from inside the kernel, * what sys/libiconv/iconv_ucs.c actually accepts and emits: * * overlong-slash : "\xC0\xAF" UTF-8 -> UTF-16BE expect 00 2F ('/'!) * overlong-4b : "\xF0\x8F\xBF\xBF" UTF-8 -> UTF-16BE expect DB FF DC FF * (encode_surrogate() uint32 wrap: overlong U+FFFF -> 0x4FFFF) * lowsur : "\xDC\x00" UTF-16BE -> UTF-8 expect ED B0 80 (CESU-8!) * highsur-lone : "\xD8\x3D" UTF-16BE -> UTF-8 expect ret=-1 (rejected) * valid-slash : "\x2F" UTF-8 -> UTF-16BE expect 00 2F * valid-pair : "\xD8\x3D\xDE\x48" UTF-16BE -> UTF-8 expect F0 9F 98 80 * * Output in dmesg: lines prefixed "witness[". */ #include <sys/param.h> #include <sys/kernel.h> #include <sys/module.h> #include <sys/systm.h> #include <sys/iconv.h> static void witness(const char *tag, const char *to, const char *from, const char *in, size_t il) { void *h = NULL; const char *src; char *dst; char out[16]; size_t ilen, olen; int ret; if (iconv_open(to, from, &h) != 0) { kprintf("witness[%s]: open %s<-%s FAILED\n", tag, to, from); return; } memset(out, 0xAA, sizeof(out)); src = in; ilen = il; dst = out; olen = sizeof(out); ret = iconv_convchr(h, &src, &ilen, &dst, &olen); kprintf("witness[%s]: convchr ret=%d consumed=%zu oleft=%zu " "out=%02x %02x %02x %02x\n", tag, ret, il - ilen, olen, (unsigned char)out[0], (unsigned char)out[1], (unsigned char)out[2], (unsigned char)out[3]); iconv_close(h); } static int witness_modevent(module_t m, int what, void *arg) { switch (what) { case MOD_LOAD: witness("overlong-slash", "UTF-16BE", "UTF-8", "\xC0\xAF", 2); witness("overlong-4b", "UTF-16BE", "UTF-8", "\xF0\x8F\xBF\xBF", 4); witness("lowsur", "UTF-8", "UTF-16BE", "\xDC\x00", 2); witness("highsur-lone", "UTF-8", "UTF-16BE", "\xD8\x3D", 2); witness("valid-slash", "UTF-16BE", "UTF-8", "\x2F", 1); witness("valid-pair", "UTF-8", "UTF-16BE", "\xD8\x3D\xDE\x48", 4); return 0; default: return (EOPNOTSUPP); } } static moduledata_t witness_mod = { "cesu_witness", witness_modevent, NULL }; DECLARE_MODULE(cesu_witness, witness_mod, SI_SUB_DRIVERS, SI_ORDER_ANY); MODULE_DEPEND(cesu_witness, libiconv, 2, 2, 2); |