/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2002, 2003, 2004, 2005 Jeffrey Roberson <[email protected]>4* Copyright (c) 2004, 2005 Bosko Milekic <[email protected]>5* All rights reserved.6*7* Redistribution and use in source and binary forms, with or without8* modification, are permitted provided that the following conditions9* are met:10* 1. Redistributions of source code must retain the above copyright11* notice unmodified, this list of conditions, and the following12* disclaimer.13* 2. Redistributions in binary form must reproduce the above copyright14* notice, this list of conditions and the following disclaimer in the15* documentation and/or other materials provided with the distribution.16*17* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR18* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES19* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.20* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,21* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT22* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,23* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY24* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT25* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF26* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.27*/2829/*30* uma_dbg.c Debugging features for UMA users31*32*/3334#include <sys/cdefs.h>35#include "opt_vm.h"3637#include <sys/param.h>38#include <sys/systm.h>39#include <sys/bitset.h>40#include <sys/kernel.h>41#include <sys/types.h>42#include <sys/queue.h>43#include <sys/lock.h>44#include <sys/mutex.h>45#include <sys/malloc.h>4647#include <vm/vm.h>48#include <vm/vm_object.h>49#include <vm/vm_page.h>50#include <vm/uma.h>51#include <vm/uma_int.h>52#include <vm/uma_dbg.h>53#include <vm/memguard.h>5455#include <machine/stack.h>5657static const u_long uma_junk = (u_long)0xdeadc0dedeadc0de;5859/*60* Checks an item to make sure it hasn't been overwritten since it was freed,61* prior to subsequent reallocation.62*63* Complies with standard ctor arg/return. arg should be zone pointer or NULL.64*/65int66trash_ctor(void *mem, int size, void *arg, int flags)67{68struct uma_zone *zone = arg;69u_long *p = mem, *e;70int off;7172#ifdef DEBUG_MEMGUARD73if (is_memguard_addr(mem))74return (0);75#endif7677e = p + size / sizeof(*p);78for (; p < e; p++) {79if (__predict_false(*p != uma_junk))80goto dopanic;81}82return (0);8384dopanic:85off = (uintptr_t)p - (uintptr_t)mem;86panic("Memory modified after free %p (%d, %s) + %d = %lx\n",87mem, size, zone ? zone->uz_name : "", off, *p);88return (0);89}9091/*92* Fills an item with predictable garbage93*94* Complies with standard dtor arg/return95*/96void97trash_dtor(void *mem, int size, void *arg)98{99u_long *p = mem, *e;100101#ifdef DEBUG_MEMGUARD102if (is_memguard_addr(mem))103return;104#endif105106e = p + size / sizeof(*p);107for (; p < e; p++)108*p = uma_junk;109}110111/*112* Fills an item with predictable garbage113*114* Complies with standard init arg/return115*/116int117trash_init(void *mem, int size, int flags)118{119trash_dtor(mem, size, NULL);120return (0);121}122123/*124* Checks an item to make sure it hasn't been overwritten since it was freed,125* prior to freeing it back to available memory.126*127* Complies with standard fini arg/return128*/129void130trash_fini(void *mem, int size)131{132(void)trash_ctor(mem, size, NULL, 0);133}134135/*136* Checks an item to make sure it hasn't been overwritten since it was freed,137* prior to subsequent reallocation.138*139* Complies with standard ctor arg/return. arg should be zone pointer or NULL.140*/141int142mtrash_ctor(void *mem, int size, void *arg, int flags)143{144struct uma_zone *zone = arg;145u_long *p = mem, *e;146struct malloc_type **ksp;147int off, osize = size;148149#ifdef DEBUG_MEMGUARD150if (is_memguard_addr(mem))151return (0);152#endif153154size -= sizeof(struct malloc_type *);155156e = p + size / sizeof(*p);157for (; p < e; p++) {158if (__predict_false(*p != uma_junk))159goto dopanic;160}161return (0);162163dopanic:164off = (uintptr_t)p - (uintptr_t)mem;165ksp = (struct malloc_type **)mem;166ksp += size / sizeof(struct malloc_type *);167if (*ksp != NULL168#ifdef INKERNEL169&& INKERNEL((uintptr_t)*ksp)170#endif171) {172/*173* If *ksp is corrupted we may be unable to panic clean,174* so print what we have reliably while we still can.175*/176printf("Memory modified after free %p (%d, %s, %p) + %d = %lx\n",177mem, osize, zone ? zone->uz_name : "", *ksp, off, *p);178panic("Memory modified after free %p (%d, %s, %s) + %d = %lx\n",179mem, osize, zone ? zone->uz_name : "", (*ksp)->ks_shortdesc,180off, *p);181} else {182panic("Memory modified after free %p (%d, %s, %p) + %d = %lx\n",183mem, osize, zone ? zone->uz_name : "", *ksp, off, *p);184}185return (0);186}187188/*189* Fills an item with predictable garbage190*191* Complies with standard dtor arg/return192*/193void194mtrash_dtor(void *mem, int size, void *arg)195{196u_long *p = mem, *e;197198#ifdef DEBUG_MEMGUARD199if (is_memguard_addr(mem))200return;201#endif202203size -= sizeof(struct malloc_type *);204205e = p + size / sizeof(*p);206for (; p < e; p++)207*p = uma_junk;208}209210/*211* Fills an item with predictable garbage212*213* Complies with standard init arg/return214*/215int216mtrash_init(void *mem, int size, int flags)217{218struct malloc_type **ksp;219220#ifdef DEBUG_MEMGUARD221if (is_memguard_addr(mem))222return (0);223#endif224225mtrash_dtor(mem, size, NULL);226227ksp = (struct malloc_type **)mem;228ksp += (size / sizeof(struct malloc_type *)) - 1;229*ksp = NULL;230return (0);231}232233/*234* Checks an item to make sure it hasn't been overwritten since it was freed,235* prior to freeing it back to available memory.236*237* Complies with standard fini arg/return238*/239void240mtrash_fini(void *mem, int size)241{242(void)mtrash_ctor(mem, size, NULL, 0);243}244245246