int main(void) { int *array, *array3; int x; array = custom_alloc(sizeof(int) * 10); array[8] = 8; array[9] = 8; array[10] = 10; // invalid write (ok w/o MALLOCLIKE -- in superblock) custom_free(array); // ok custom_free((void*)0x1); // invalid free array3 = malloc(sizeof(int) * 10); custom_free(array3); // mismatched free (ok without MALLOCLIKE) make_leak(); x = array[0]; // use after free (ok without MALLOCLIKE/MAKE_MEM_NOACCESS) // (nb: initialised because is_zeroed==1 above) // unfortunately not identified as being in a free'd // block because the freeing of the block and shadow // chunk isn't postponed. // Bug 137073: passing 0 to MALLOCLIKE_BLOCK was causing an assertion // failure. Test for this (and likewise for FREELIKE_BLOCK). VALGRIND_MALLOCLIKE_BLOCK(0,0,0,0); VALGRIND_FREELIKE_BLOCK(0,0); return x; // leak from make_leak() }
void pool_free(size_t index, void* p) { #ifdef USE_VALGRIND VALGRIND_DISABLE_ERROR_REPORTING; #endif TRACK_FREE(p, POOL_MIN << index); assert(index < POOL_COUNT); pool_local_t* thread = &pool_local[index]; pool_global_t* global = &pool_global[index]; if(thread->length >= global->count) pool_push(thread, global); pool_item_t* lp = (pool_item_t*)p; lp->next = thread->pool; thread->pool = (pool_item_t*)p; thread->length++; #ifdef USE_VALGRIND VALGRIND_ENABLE_ERROR_REPORTING; VALGRIND_FREELIKE_BLOCK(p, 0); #endif }
void releaseToIonMemory(char *fileName, int lineNbr, void *block) { PsmPartition ionwm = _ionwm(NULL); Psm_free(fileName, lineNbr, ionwm, psa(ionwm, (char *) block)); #ifdef HAVE_VALGRIND_VALGRIND_H VALGRIND_FREELIKE_BLOCK(block, 0); #endif }
void free_mem(unsigned long int size, void *location) { size_t msize = get_multiple_of_pagesize(size); /* we ignore the return value, because the only way this will return in a bad way is whenever people pass invalid data to this function, which in turn would either lead to serious issues with the kernel or other parts of the programme. */ (void)munmap (location, msize); VALGRIND_FREELIKE_BLOCK(location, 0); }
int GDKmunmap(void *addr, size_t size) { int ret; ALLOCDEBUG fprintf(stderr, "#GDKmunmap " SZFMT " " PTRFMT "\n", size, PTRFMTCAST addr); ret = MT_munmap(addr, size); VALGRIND_FREELIKE_BLOCK(addr, 0); if (ret == 0) memdec(size, "GDKunmap"); return ret; }
void qxl_free (struct qxl_mem *mem, void *d) { mspace_free (mem->space, d); #ifdef DEBUG_QXL_MEM #ifdef DEBUG_QXL_MEM_VERBOSE fprintf(stderr, "free %p\n", d); #endif VALGRIND_FREELIKE_BLOCK(d, 0); #endif }
void pool_free_size(size_t size, void* p) { size_t index = pool_index(size); if(index < POOL_COUNT) return pool_free(index, p); virtual_free(p, size); #ifdef USE_VALGRIND VALGRIND_FREELIKE_BLOCK(p, 0); #endif }
int main(void) { int *array, *array3; int x; array = custom_alloc(sizeof(int) * 10); array[8] = 8; array[9] = 8; array[10] = 10; // invalid write (ok w/o MALLOCLIKE -- in superblock) VALGRIND_RESIZEINPLACE_BLOCK(array, sizeof(int) * 10, sizeof(int) * 5, RZ); array[4] = 7; array[5] = 9; // invalid write // Make the entire array defined again such that it can be verified whether // the red zone is marked properly when resizing in place. VALGRIND_MAKE_MEM_DEFINED(array, sizeof(int) * 10); VALGRIND_RESIZEINPLACE_BLOCK(array, sizeof(int) * 5, sizeof(int) * 7, RZ); if (array[5]) array[4]++; // uninitialized read of array[5] array[5] = 11; array[6] = 7; array[7] = 8; // invalid write // invalid realloc VALGRIND_RESIZEINPLACE_BLOCK(array+1, sizeof(int) * 7, sizeof(int) * 8, RZ); custom_free(array); // ok custom_free((void*)0x1); // invalid free array3 = malloc(sizeof(int) * 10); custom_free(array3); // mismatched free (ok without MALLOCLIKE) make_leak(); x = array[0]; // use after free (ok without MALLOCLIKE/MAKE_MEM_NOACCESS) // (nb: initialised because is_zeroed==1 above) // unfortunately not identified as being in a free'd // block because the freeing of the block and shadow // chunk isn't postponed. // Bug 137073: passing 0 to MALLOCLIKE_BLOCK was causing an assertion // failure. Test for this (and likewise for FREELIKE_BLOCK). VALGRIND_MALLOCLIKE_BLOCK(0,0,0,0); VALGRIND_FREELIKE_BLOCK(0,0); return x; // leak from make_leak() }
void egg_secure_free_full (void *memory, int flags) { Block *block = NULL; if (memory == NULL) return; DO_LOCK (); /* Find out where it belongs to */ for (block = all_blocks; block; block = block->next) { if (sec_is_valid_word (block, memory)) break; } #ifdef WITH_VALGRIND /* We like valgrind's warnings, so give it a first whack at checking for errors */ if (block != NULL || !(flags & GKR_SECURE_USE_FALLBACK)) VALGRIND_FREELIKE_BLOCK (memory, sizeof (word_t)); #endif if (block != NULL) { sec_free (block, memory); if (block->used == 0) sec_block_destroy (block); } DO_UNLOCK (); if (!block) { if ((flags & GKR_SECURE_USE_FALLBACK)) { egg_memory_fallback (memory, 0); } else { if (egg_secure_warnings) fprintf (stderr, "memory does not belong to mate-keyring: 0x%08lx\n", (unsigned long)memory); ASSERT (0 && "memory does does not belong to mate-keyring"); } } }
void stat_mem_deallocate(void *ptr) { stat_mem_block_t *info = NULL; if (GMQCC_UNLIKELY(!ptr)) return; info = ((stat_mem_block_t*)ptr - 1); /* * we need access to the redzone that represents the info block * so lets do that. */ VALGRIND_MAKE_MEM_DEFINED(info, sizeof(stat_mem_block_t)); stat_mem_deallocated += info->size; stat_mem_high -= info->size; stat_mem_deallocated_total ++; if (info->prev) { /* just need access for a short period */ VALGRIND_MAKE_MEM_DEFINED(info->prev, sizeof(stat_mem_block_t)); info->prev->next = info->next; /* don't need access anymore */ VALGRIND_MAKE_MEM_NOACCESS(info->prev, sizeof(stat_mem_block_t)); } if (info->next) { /* just need access for a short period */ VALGRIND_MAKE_MEM_DEFINED(info->next, sizeof(stat_mem_block_t)); info->next->prev = info->prev; /* don't need access anymore */ VALGRIND_MAKE_MEM_NOACCESS(info->next, sizeof(stat_mem_block_t)); } /* move ahead */ if (info == stat_mem_block_root) stat_mem_block_root = info->next; free(info); VALGRIND_MAKE_MEM_NOACCESS(info, sizeof(stat_mem_block_t)); VALGRIND_FREELIKE_BLOCK(ptr, sizeof(stat_mem_block_t)); }
void pool_free_size(size_t size, void* p) { size_t index = pool_index(size); if(index < POOL_COUNT) return pool_free(index, p); #ifdef USE_VALGRIND VALGRIND_DISABLE_ERROR_REPORTING; #endif size = pool_adjust_size(size); pool_free_pages(p, size); TRACK_FREE(p, size); #ifdef USE_VALGRIND VALGRIND_ENABLE_ERROR_REPORTING; VALGRIND_FREELIKE_BLOCK(p, 0); #endif }
void* egg_secure_realloc_full (void *memory, size_t length, int flags) { Block *block = NULL; size_t previous = 0; int donew = 0; void *alloc = NULL; if (length > 0xFFFFFFFF / 2) { if (egg_secure_warnings) fprintf (stderr, "tried to allocate an insane amount of memory: %lu\n", (unsigned long)length); return NULL; } if (memory == NULL) return egg_secure_alloc_full (length, flags); if (!length) { egg_secure_free_full (memory, flags); return NULL; } DO_LOCK (); /* Find out where it belongs to */ for (block = all_blocks; block; block = block->next) { if (sec_is_valid_word (block, memory)) { previous = sec_allocated (block, memory); #ifdef WITH_VALGRIND /* Let valgrind think we are unallocating so that it'll validate */ VALGRIND_FREELIKE_BLOCK (memory, sizeof (word_t)); #endif alloc = sec_realloc (block, memory, length); #ifdef WITH_VALGRIND /* Now tell valgrind about either the new block or old one */ VALGRIND_MALLOCLIKE_BLOCK (alloc ? alloc : memory, alloc ? length : previous, sizeof (word_t), 1); #endif break; } } /* If it didn't work we may need to allocate a new block */ if (block && !alloc) donew = 1; if (block && block->used == 0) sec_block_destroy (block); DO_UNLOCK (); if (!block) { if ((flags & GKR_SECURE_USE_FALLBACK)) { /* * In this case we can't zero the returned memory, * because we don't know what the block size was. */ return egg_memory_fallback (memory, length); } else { if (egg_secure_warnings) fprintf (stderr, "memory does not belong to mate-keyring: 0x%08lx\n", (unsigned long)memory); ASSERT (0 && "memory does does not belong to mate-keyring"); return NULL; } } if (donew) { alloc = egg_secure_alloc_full (length, flags); if (alloc) { memcpy (alloc, memory, previous); egg_secure_free_full (memory, flags); } } if (!alloc) errno = ENOMEM; return alloc; }
static void custom_free(void* p) { // don't actually free any memory... but mark it as freed VALGRIND_FREELIKE_BLOCK( p, RZ ); }
void *stat_mem_reallocate(void *ptr, size_t size, size_t line, const char *file) { stat_mem_block_t *oldinfo = NULL; stat_mem_block_t *newinfo; if (GMQCC_UNLIKELY(!ptr)) return stat_mem_allocate(size, line, file); /* stay consistent with glibc */ if (GMQCC_UNLIKELY(!size)) { stat_mem_deallocate(ptr); return NULL; } oldinfo = ((stat_mem_block_t*)ptr - 1); newinfo = ((stat_mem_block_t*)malloc(sizeof(stat_mem_block_t) + size)); if (GMQCC_UNLIKELY(!newinfo)) { stat_mem_deallocate(ptr); return NULL; } VALGRIND_MALLOCLIKE_BLOCK(newinfo + 1, size, sizeof(stat_mem_block_t), 0); /* we need access to the old info redzone */ VALGRIND_MAKE_MEM_DEFINED(oldinfo, sizeof(stat_mem_block_t)); memcpy(newinfo+1, oldinfo+1, oldinfo->size); if (oldinfo->prev) { /* just need access for a short period */ VALGRIND_MAKE_MEM_DEFINED(oldinfo->prev, sizeof(stat_mem_block_t)); oldinfo->prev->next = oldinfo->next; /* don't need access anymore */ VALGRIND_MAKE_MEM_NOACCESS(oldinfo->prev, sizeof(stat_mem_block_t)); } if (oldinfo->next) { /* just need access for a short period */ VALGRIND_MAKE_MEM_DEFINED(oldinfo->next, sizeof(stat_mem_block_t)); oldinfo->next->prev = oldinfo->prev; /* don't need access anymore */ VALGRIND_MAKE_MEM_NOACCESS(oldinfo->next, sizeof(stat_mem_block_t)); } /* move ahead */ if (oldinfo == stat_mem_block_root) stat_mem_block_root = oldinfo->next; /* we need access to the redzone for the newinfo block */ VALGRIND_MAKE_MEM_DEFINED(newinfo, sizeof(stat_mem_block_t)); newinfo->line = line; newinfo->size = size; newinfo->file = file; newinfo->prev = NULL; newinfo->next = stat_mem_block_root; /* * likely since the only time there is no root is when it's * being initialized first. */ if (GMQCC_LIKELY(stat_mem_block_root != NULL)) { /* we need access to the root */ VALGRIND_MAKE_MEM_DEFINED(stat_mem_block_root, sizeof(stat_mem_block_t)); stat_mem_block_root->prev = newinfo; /* kill access */ VALGRIND_MAKE_MEM_NOACCESS(stat_mem_block_root, sizeof(stat_mem_block_t)); } stat_mem_block_root = newinfo; stat_mem_allocated -= oldinfo->size; stat_mem_high -= oldinfo->size; stat_mem_allocated += newinfo->size; stat_mem_high += newinfo->size; /* * we're finished with the redzones, lets kill the access * to them. */ VALGRIND_MAKE_MEM_NOACCESS(newinfo, sizeof(stat_mem_block_t)); VALGRIND_MAKE_MEM_NOACCESS(oldinfo, sizeof(stat_mem_block_t)); if (stat_mem_high > stat_mem_peak) stat_mem_peak = stat_mem_high; free(oldinfo); VALGRIND_FREELIKE_BLOCK(ptr, sizeof(stat_mem_block_t)); return newinfo + 1; }
void valgrind_freelike_block(void *ptr, size_t usize) { VALGRIND_FREELIKE_BLOCK(ptr, usize); }
void stat_mem_deallocate(void *ptr, size_t line, const char *file) { stat_mem_block_t *info = NULL; char *ident = (char *)ptr - IDENT_SIZE; if (GMQCC_UNLIKELY(!ptr)) return; /* Validate usage */ VALGRIND_MAKE_MEM_DEFINED(ident, IDENT_SIZE); if (!strcmp(ident, IDENT_VEC)) { vector_t *vec = (vector_t*)((char *)ptr - IDENT_VEC_TOP); stat_mem_block_t *block = (stat_mem_block_t*)((char *)vec - IDENT_MEM_TOP); VALGRIND_MAKE_MEM_DEFINED(block, sizeof(stat_mem_block_t)); con_err("internal warning: invalid use of mem_d:\n"); con_err("internal warning: vector (used elements: %u, allocated elements: %u)\n", (unsigned)vec->used, (unsigned)vec->allocated ); con_err("internal warning: vector was last (re)allocated with (size: %u (bytes), at location: %s:%u)\n", (unsigned)block->size, block->file, (unsigned)block->line ); con_err("internal warning: released with wrong routine at %s:%u\n", file, (unsigned)line); con_err("internal warning: forwarding to vec_free, please fix it\n"); VALGRIND_MAKE_MEM_NOACCESS(block, sizeof(stat_mem_block_t)); VALGRIND_MAKE_MEM_NOACCESS(ident, IDENT_SIZE); vec_free(ptr); return; } VALGRIND_MAKE_MEM_NOACCESS(ident, IDENT_SIZE); info = (stat_mem_block_t*)((char *)ptr - IDENT_MEM_TOP); /* * we need access to the redzone that represents the info block * so lets do that. */ VALGRIND_MAKE_MEM_DEFINED(info, IDENT_MEM_TOP); stat_mem_deallocated += info->size; stat_mem_high -= info->size; stat_mem_deallocated_total ++; if (info->prev) { /* just need access for a short period */ VALGRIND_MAKE_MEM_DEFINED(info->prev, IDENT_MEM_TOP); info->prev->next = info->next; /* don't need access anymore */ VALGRIND_MAKE_MEM_NOACCESS(info->prev, IDENT_MEM_TOP); } if (info->next) { /* just need access for a short period */ VALGRIND_MAKE_MEM_DEFINED(info->next, IDENT_MEM_TOP); info->next->prev = info->prev; /* don't need access anymore */ VALGRIND_MAKE_MEM_NOACCESS(info->next, IDENT_MEM_TOP); } /* move ahead */ if (info == stat_mem_block_root) stat_mem_block_root = info->next; free(info); VALGRIND_MAKE_MEM_NOACCESS(info, IDENT_MEM_TOP); VALGRIND_FREELIKE_BLOCK(ptr, IDENT_MEM_TOP); }
static inline void ucm_mem_free(void *ptr, size_t size) { VALGRIND_FREELIKE_BLOCK(ptr, 0); VALGRIND_MAKE_MEM_UNDEFINED(ptr, size); /* Make memory accessible to ptmalloc3 */ ucm_dlfree(ptr); }
/* This is just a wrapper around munmap, but it also notifies valgrind that * this map is no longer valid. Pair this with anv_gem_mmap(). */ void anv_gem_munmap(void *p, uint64_t size) { VG(VALGRIND_FREELIKE_BLOCK(p, 0)); munmap(p, size); }