Re: malloc: more info in error message for write-after-free with option D

2023-10-22 Thread Masato Asou
Hi,

I wanted an extension to malloc() that would report the caller of all
memory leaks.  It works fine for me!

ok asou@
--
ASOU Masato

From: Otto Moerbeek 
Date: Tue, 10 Oct 2023 12:39:00 +0200

> Hi,
> 
> This diff adds better error reporting for write-after-free or the more
> general write of free memory if malloc option D is active. Knowing the
> place where allocations were done often helps to find out where the
> overwrite happened.
> 
> If option D is active malloc now saves caller info in a separate page
> instead of only doing that for chunk index 0. It also reports about
> the preceding chunk if applicable. A report looks like this:
> 
> X(12489) in calloc(): write to free chunk 0x851ec6066d0[0..7]@16
> allocated at /usr/X11R6/lib/modules/dri/radeonsi_dri.so 0x88c949
> (preceding chunk 0x851ec6066c0 allocated at /usr/X11R6/bin/X 0x177374 (now 
> free))
> 
> You can use addr2line -e to get the file and linenumber the allocation
> was done (if the object was compiled with debug info).
> 
> If D is not used only the first part is printed, as no caller info is
> saved. So no extra overhead if D is not useed.
> 
> Also: the leak report now do not contain unknown locations anymore, as
> each allocation gets its caller recorded if D is active.
> 
>   -Otto
> 
> Index: stdlib/malloc.3
> ===
> RCS file: /home/cvs/src/lib/libc/stdlib/malloc.3,v
> retrieving revision 1.137
> diff -u -p -r1.137 malloc.3
> --- stdlib/malloc.3   1 Jul 2023 18:35:14 -   1.137
> +++ stdlib/malloc.3   10 Oct 2023 10:23:19 -
> @@ -307,7 +307,7 @@ These malloc options imply
>  .Cm D .
>  .It Cm F
>  .Dq Freecheck .
> -Enable more extensive double free and use after free detection.
> +Enable more extensive double free and write after free detection.
>  All chunks in the delayed free list will be checked for double frees and
>  write after frees.
>  Unused pages on the freelist are read and write protected to
> @@ -641,18 +641,34 @@ or
>  reallocate an unallocated pointer was made.
>  .It Dq double free
>  There was an attempt to free an allocation that had already been freed.
> -.It Dq write after free
> -An allocation has been modified after it was freed.
> +.It Dq write of free mem Va address Ns [ Va start Ns .. Ns Va end Ns ]@ Ns 
> Va size
> +An allocation has been modified after it was freed,
> +or a chunk that was never allocated was written to.
> +The
> +.Va range
> +at which corruption was detected is printed between [ and ].
> +.Pp
> +Enabling option
> +.Cm D
> +allows malloc to print information about where the allocation
> +was done.
>  .It Dq modified chunk-pointer
>  The pointer passed to
>  .Fn free
>  or a reallocation function has been modified.
> -.It Dq canary corrupted address offset@length
> -A byte after the requested size has been overwritten,
> +.It Dq canary corrupted Va address Ns [ Va offset Ns ]@ Ns Va length Ns / Ns 
> Va size
> +A byte after the requested
> +.Va length has been overwritten,
>  indicating a heap overflow.
> -The offset at which corruption was detected is printed before the @,
> -and the requested length of the allocation after the @.
> -.It Dq recorded size oldsize inconsistent with size
> +The
> +.Va offset
> +at which corruption was detected is printed between [ and ],
> +the requested
> +.Va length
> +of the allocation is printed before the / and the
> +.Va size
> +of the allocation after the /.
> +.It Dq recorded size Va oldsize No inconsistent with Va size
>  .Fn recallocarray
>  or
>  .Fn freezero
> @@ -676,7 +692,7 @@ functions nor utilize any other function
>  (e.g.,
>  .Xr stdio 3
>  routines).
> -.It Dq unknown char in MALLOC_OPTIONS
> +.It Dq unknown char in Ev MALLOC_OPTIONS
>  We found something we didn't understand.
>  .It any other error
>  .Fn malloc
> Index: stdlib/malloc.c
> ===
> RCS file: /home/cvs/src/lib/libc/stdlib/malloc.c,v
> retrieving revision 1.290
> diff -u -p -r1.290 malloc.c
> --- stdlib/malloc.c   9 Sep 2023 06:52:40 -   1.290
> +++ stdlib/malloc.c   10 Oct 2023 10:23:19 -
> @@ -112,7 +112,7 @@ struct region_info {
>   void *p;/* page; low bits used to mark chunks */
>   uintptr_t size; /* size for pages, or chunk_info pointer */
>  #ifdef MALLOC_STATS
> - void *f;/* where allocated from */
> + void **f;   /* where allocated from */
>  #endif
>  };
>  
> @@ -146,7 +146,7 @@ struct dir_info {
>   size_t regions_total;   /* number of region slots */
>   size_t regions_free;/* number of free slots */
>   size_t rbytesused;  /* random bytes used */
> - char *func; /* current function */
> + const char *func;   /* current function */
>   int malloc_junk;/* junk fill? */
>   int mmap_flag;  /* extra flag for mmap */
>  

malloc: more info in error message for write-after-free with option D

2023-10-10 Thread Otto Moerbeek
Hi,

This diff adds better error reporting for write-after-free or the more
general write of free memory if malloc option D is active. Knowing the
place where allocations were done often helps to find out where the
overwrite happened.

If option D is active malloc now saves caller info in a separate page
instead of only doing that for chunk index 0. It also reports about
the preceding chunk if applicable. A report looks like this:

X(12489) in calloc(): write to free chunk 0x851ec6066d0[0..7]@16
allocated at /usr/X11R6/lib/modules/dri/radeonsi_dri.so 0x88c949
(preceding chunk 0x851ec6066c0 allocated at /usr/X11R6/bin/X 0x177374 (now 
free))

You can use addr2line -e to get the file and linenumber the allocation
was done (if the object was compiled with debug info).

If D is not used only the first part is printed, as no caller info is
saved. So no extra overhead if D is not useed.

Also: the leak report now do not contain unknown locations anymore, as
each allocation gets its caller recorded if D is active.

-Otto

Index: stdlib/malloc.3
===
RCS file: /home/cvs/src/lib/libc/stdlib/malloc.3,v
retrieving revision 1.137
diff -u -p -r1.137 malloc.3
--- stdlib/malloc.3 1 Jul 2023 18:35:14 -   1.137
+++ stdlib/malloc.3 10 Oct 2023 10:23:19 -
@@ -307,7 +307,7 @@ These malloc options imply
 .Cm D .
 .It Cm F
 .Dq Freecheck .
-Enable more extensive double free and use after free detection.
+Enable more extensive double free and write after free detection.
 All chunks in the delayed free list will be checked for double frees and
 write after frees.
 Unused pages on the freelist are read and write protected to
@@ -641,18 +641,34 @@ or
 reallocate an unallocated pointer was made.
 .It Dq double free
 There was an attempt to free an allocation that had already been freed.
-.It Dq write after free
-An allocation has been modified after it was freed.
+.It Dq write of free mem Va address Ns [ Va start Ns .. Ns Va end Ns ]@ Ns Va 
size
+An allocation has been modified after it was freed,
+or a chunk that was never allocated was written to.
+The
+.Va range
+at which corruption was detected is printed between [ and ].
+.Pp
+Enabling option
+.Cm D
+allows malloc to print information about where the allocation
+was done.
 .It Dq modified chunk-pointer
 The pointer passed to
 .Fn free
 or a reallocation function has been modified.
-.It Dq canary corrupted address offset@length
-A byte after the requested size has been overwritten,
+.It Dq canary corrupted Va address Ns [ Va offset Ns ]@ Ns Va length Ns / Ns 
Va size
+A byte after the requested
+.Va length has been overwritten,
 indicating a heap overflow.
-The offset at which corruption was detected is printed before the @,
-and the requested length of the allocation after the @.
-.It Dq recorded size oldsize inconsistent with size
+The
+.Va offset
+at which corruption was detected is printed between [ and ],
+the requested
+.Va length
+of the allocation is printed before the / and the
+.Va size
+of the allocation after the /.
+.It Dq recorded size Va oldsize No inconsistent with Va size
 .Fn recallocarray
 or
 .Fn freezero
@@ -676,7 +692,7 @@ functions nor utilize any other function
 (e.g.,
 .Xr stdio 3
 routines).
-.It Dq unknown char in MALLOC_OPTIONS
+.It Dq unknown char in Ev MALLOC_OPTIONS
 We found something we didn't understand.
 .It any other error
 .Fn malloc
Index: stdlib/malloc.c
===
RCS file: /home/cvs/src/lib/libc/stdlib/malloc.c,v
retrieving revision 1.290
diff -u -p -r1.290 malloc.c
--- stdlib/malloc.c 9 Sep 2023 06:52:40 -   1.290
+++ stdlib/malloc.c 10 Oct 2023 10:23:19 -
@@ -112,7 +112,7 @@ struct region_info {
void *p;/* page; low bits used to mark chunks */
uintptr_t size; /* size for pages, or chunk_info pointer */
 #ifdef MALLOC_STATS
-   void *f;/* where allocated from */
+   void **f;   /* where allocated from */
 #endif
 };
 
@@ -146,7 +146,7 @@ struct dir_info {
size_t regions_total;   /* number of region slots */
size_t regions_free;/* number of free slots */
size_t rbytesused;  /* random bytes used */
-   char *func; /* current function */
+   const char *func;   /* current function */
int malloc_junk;/* junk fill? */
int mmap_flag;  /* extra flag for mmap */
int mutex;
@@ -166,6 +166,7 @@ struct dir_info {
void *chunk_pages;
size_t chunk_pages_used;
 #ifdef MALLOC_STATS
+   void *caller;
size_t inserts;
size_t insert_collisions;
size_t finds;
@@ -183,12 +184,16 @@ struct dir_info {
 #define STATS_INC(x)   ((x)++)
 #define STATS_ZERO(x)  ((x) = 0)
 #define STATS_SETF(x,y)((x)->f = (y))
+#define