Index: subr_poison.c =================================================================== RCS file: /cvs/src/sys/kern/subr_poison.c,v retrieving revision 1.13 diff -u -p -r1.13 subr_poison.c --- subr_poison.c 14 Mar 2015 03:38:50 -0000 1.13 +++ subr_poison.c 18 May 2015 20:07:41 -0000 @@ -20,6 +20,9 @@ #include +#define KEYSTREAM_ONLY +#include + /* * The POISON is used as known text to copy into free objects so * that modifications after frees can be detected. @@ -57,40 +60,75 @@ poison_value(void *v) } void +poison_ctx(chacha_ctx *ctx) +{ + static chacha_ctx template; + static int poison_init; + + if (__predict_false(poison_init == 0)) { + uint8_t key[32]; /* 256 bits */ + arc4random_buf(&key, sizeof(key)); + chacha_keysetup(&template, key, sizeof(key) * 8, 0); + poison_init = 1; + } + + memcpy(ctx, &template, sizeof(*ctx)); +} + +void poison_mem(void *v, size_t len) { - uint32_t *ip = v; - size_t i; - uint32_t poison; - - poison = poison_value(v); - - if (len > POISON_SIZE) - len = POISON_SIZE; - len = len / sizeof(*ip); - for (i = 0; i < len; i++) - ip[i] = poison; + uint8_t block[64]; /* chacha block len */ + chacha_ctx ctx; + u_int64_t iv = (vaddr_t)v; + uint8_t *m = v; + + poison_ctx(&ctx); + chacha_ivsetup(&ctx, (uint8_t *)&iv); + chacha_encrypt_bytes(&ctx, block, block, sizeof(block)); + + while (len > sizeof(block)) { + memcpy(m, block, sizeof(block)); + m += sizeof(block); + len -= sizeof(block); + } + + if (len > 0) + memcpy(m, block, len); } int poison_check(void *v, size_t len, size_t *pidx, uint32_t *pval) { - uint32_t *ip = v; - size_t i; - uint32_t poison; - - poison = poison_value(v); - - if (len > POISON_SIZE) - len = POISON_SIZE; - len = len / sizeof(*ip); - for (i = 0; i < len; i++) { - if (ip[i] != poison) { - *pidx = i; - *pval = poison; - return 1; - } - } - return 0; + uint8_t block[64]; /* chacha block len */ + chacha_ctx ctx; + u_int64_t iv = (vaddr_t)v; + u_int *b = (u_int *)block, *m = v; + u_int bv, mv; + int rv = 0; + u_int i; + + poison_ctx(&ctx); + chacha_ivsetup(&ctx, (uint8_t *)&iv); + chacha_encrypt_bytes(&ctx, block, block, sizeof(block)); + + len /= sizeof(mv); + + for (i = 0; i < len; i++) { + mv = m[i]; + bv = b[i % (sizeof(block) / sizeof(bv))]; + if (mv != bv) { + *pidx = i; + *pval = bv; + + printf("%s: %p+%zu: memory 0x%08x != poison 0x%08x" + " (^=0x%08x)\n", __func__, v, i * sizeof(mv), + mv, bv, mv ^ bv); + + rv = 1; + } + } + + return (rv); }