1 /* $OpenBSD: subr_poison.c,v 1.15 2022/08/14 01:58:28 jsg 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 /* 21 * The POISON is used as known text to copy into free objects so 22 * that modifications after frees can be detected. 23 */ 24 #ifdef DEADBEEF0 25 #define POISON0 ((unsigned) DEADBEEF0) 26 #else 27 #define POISON0 ((unsigned) 0xdeadbeef) 28 #endif 29 #ifdef DEADBEEF1 30 #define POISON1 ((unsigned) DEADBEEF1) 31 #else 32 #define POISON1 ((unsigned) 0xdeafbead) 33 #endif 34 #define POISON_SIZE 64 35 36 uint32_t 37 poison_value(void *v) 38 { 39 ulong l = (u_long)v; 40 41 l = l >> PAGE_SHIFT; 42 43 switch (l & 3) { 44 case 0: 45 return POISON0; 46 case 1: 47 return POISON1; 48 case 2: 49 return (POISON0 & 0xffff0000) | (~POISON0 & 0x0000ffff); 50 case 3: 51 return (POISON1 & 0xffff0000) | (~POISON1 & 0x0000ffff); 52 } 53 return 0; 54 } 55 56 void 57 poison_mem(void *v, size_t len) 58 { 59 uint32_t *ip = v; 60 size_t i; 61 uint32_t poison; 62 63 poison = poison_value(v); 64 65 if (len > POISON_SIZE) 66 len = POISON_SIZE; 67 len = len / sizeof(*ip); 68 for (i = 0; i < len; i++) 69 ip[i] = poison; 70 } 71 72 int 73 poison_check(void *v, size_t len, size_t *pidx, uint32_t *pval) 74 { 75 uint32_t *ip = v; 76 size_t i; 77 uint32_t poison; 78 79 poison = poison_value(v); 80 81 if (len > POISON_SIZE) 82 len = POISON_SIZE; 83 len = len / sizeof(*ip); 84 for (i = 0; i < len; i++) { 85 if (ip[i] != poison) { 86 *pidx = i; 87 *pval = poison; 88 return 1; 89 } 90 } 91 return 0; 92 } 93 94