On Thu, Mar 30, 2023 at 04:53:05PM +0200, Otto Moerbeek wrote:
> Hi,
> 
> this came up after a remark by tb@; it does a more thorough check of
> the chunks in the delay list if malloc option F (which is included in
> S).
> 
> Catches way more use-after-free's as otherwise we'll have to wait
> until a chunk is actively re-used. With the new bucket code that might
> take longer (or not happen at all because the program terminates). The
> catch also happens closer (in time) to the actual write after free.
> That might help finding the root cause.

Thank you. This works indeed a lot better in my testing.

ok tb

> 
>       -Otto
> 
> Index: stdlib/malloc.3
> ===================================================================
> RCS file: /home/cvs/src/lib/libc/stdlib/malloc.3,v
> retrieving revision 1.129
> diff -u -p -r1.129 malloc.3
> --- stdlib/malloc.3   31 Mar 2022 17:27:16 -0000      1.129
> +++ stdlib/malloc.3   30 Mar 2023 14:47:19 -0000
> @@ -293,7 +293,8 @@ order to have any effect.
>  .It Cm F
>  .Dq Freecheck .
>  Enable more extensive double free and use after free detection.
> -All chunks in the delayed free list will be checked for double frees.
> +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
>  cause a segmentation fault upon access.
>  .It Cm G
> Index: stdlib/malloc.c
> ===================================================================
> RCS file: /home/cvs/src/lib/libc/stdlib/malloc.c,v
> retrieving revision 1.278
> diff -u -p -r1.278 malloc.c
> --- stdlib/malloc.c   25 Mar 2023 15:22:06 -0000      1.278
> +++ stdlib/malloc.c   30 Mar 2023 14:47:19 -0000
> @@ -1554,11 +1554,25 @@ ofree(struct dir_info **argpool, void *p
>               find_chunknum(pool, info, p, mopts.chunk_canaries);
>  
>               if (mopts.malloc_freecheck) {
> -                     for (i = 0; i <= MALLOC_DELAYED_CHUNK_MASK; i++)
> -                             if (p == pool->delayed_chunks[i])
> +                     for (i = 0; i <= MALLOC_DELAYED_CHUNK_MASK; i++) {
> +                             tmp = pool->delayed_chunks[i];
> +                             if (tmp == p)
>                                       wrterror(pool,
>                                           "double free %p", p);
> +                             if (tmp != NULL) {
> +                                     size_t tmpsz;
> +
> +                                     r = find(pool, tmp);
> +                                     if (r == NULL)
> +                                             wrterror(pool,
> +                                                 "bogus pointer ("
> +                                                 "double free?) %p", tmp);
> +                                     REALSIZE(tmpsz, r);
> +                                     validate_junk(pool, tmp, tmpsz);
> +                             }
> +                     }
>               }
> +
>               if (clear && argsz > 0)
>                       explicit_bzero(p, argsz);
>               junk_free(pool->malloc_junk, p, sz);
> @@ -1574,8 +1588,10 @@ ofree(struct dir_info **argpool, void *p
>                       if (r == NULL)
>                               wrterror(pool,
>                                   "bogus pointer (double free?) %p", p);
> -                     REALSIZE(sz, r);
> -                     validate_junk(pool, p, sz);
> +                     if (!mopts.malloc_freecheck) {
> +                             REALSIZE(sz, r);
> +                             validate_junk(pool, p, sz);
> +                     }
>                       free_bytes(pool, r, p);
>               }
>       }
> 

Reply via email to