1 /* $OpenBSD: subr_poison.c,v 1.14 2017/09/08 05:36:53 deraadt Exp $ */ 2 /* 3 * Copyright (c) 2013 Ted Unangst <tedu@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 20 #include <uvm/uvm_extern.h> 21 22 /* 23 * The POISON is used as known text to copy into free objects so 24 * that modifications after frees can be detected. 25 */ 26 #ifdef DEADBEEF0 27 #define POISON0 ((unsigned) DEADBEEF0) 28 #else 29 #define POISON0 ((unsigned) 0xdeadbeef) 30 #endif 31 #ifdef DEADBEEF1 32 #define POISON1 ((unsigned) DEADBEEF1) 33 #else 34 #define POISON1 ((unsigned) 0xdeafbead) 35 #endif 36 #define POISON_SIZE 64 37 38 uint32_t 39 poison_value(void *v) 40 { 41 ulong l = (u_long)v; 42 43 l = l >> PAGE_SHIFT; 44 45 switch (l & 3) { 46 case 0: 47 return POISON0; 48 case 1: 49 return POISON1; 50 case 2: 51 return (POISON0 & 0xffff0000) | (~POISON0 & 0x0000ffff); 52 case 3: 53 return (POISON1 & 0xffff0000) | (~POISON1 & 0x0000ffff); 54 } 55 return 0; 56 } 57 58 void 59 poison_mem(void *v, size_t len) 60 { 61 uint32_t *ip = v; 62 size_t i; 63 uint32_t poison; 64 65 poison = poison_value(v); 66 67 if (len > POISON_SIZE) 68 len = POISON_SIZE; 69 len = len / sizeof(*ip); 70 for (i = 0; i < len; i++) 71 ip[i] = poison; 72 } 73 74 int 75 poison_check(void *v, size_t len, size_t *pidx, uint32_t *pval) 76 { 77 uint32_t *ip = v; 78 size_t i; 79 uint32_t poison; 80 81 poison = poison_value(v); 82 83 if (len > POISON_SIZE) 84 len = POISON_SIZE; 85 len = len / sizeof(*ip); 86 for (i = 0; i < len; i++) { 87 if (ip[i] != poison) { 88 *pidx = i; 89 *pval = poison; 90 return 1; 91 } 92 } 93 return 0; 94 } 95 96