talloc: talloc_set_memlimit causes all reallocs to fail when used on pools. talloc_set_memlimit not enforced correctly on pools.

Jeremy Allison jra at samba.org
Fri Oct 16 19:36:53 UTC 2020

On Fri, Oct 16, 2020 at 01:59:11PM -0500, Arran Cudbard-Bell via samba-technical wrote:
> Apologies if this is a repost.  The original message didn't make it into the archives, so I'm assuming it also didn't make it to mailing list subscribers.
> First I'd like to thank the contributors to the Samba project.  We've been using talloc since ~2013 and it has made an immeasurably large contribution to code clarity and the general stability of FreeRADIUS.
> -
> Reviewing the talloc code shows provisions (and test cases) for applying memlimits to pools, unfortunately in practice, memlimit functionality on pools seems fairly broken.
> 1. Calling talloc_set_memlimit on a pool results in a limit structure being created with limit->cur_size being set to the size of the pool + chunk header + pool header.  This seems to effectively mark the entire pool as already in use.

As suspected, this one is on me :-(.

commit 4159a78ed7eda340758e22286f16186987a20f2f
Author: Jeremy Allison <jra at samba.org>
Date:   Tue Aug 27 12:46:09 2013 -0700

    Change _talloc_total_mem_internal() to ignore memory allocated from a pool when calculating limit size.
    We must only count normal tallocs, or a talloc pool itself.
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Simo Sorce <idra at samba.org>

diff --git a/lib/talloc/talloc.c b/lib/talloc/talloc.c
index 7b827ca0c15..1e25dfde4e1 100644
--- a/lib/talloc/talloc.c
+++ b/lib/talloc/talloc.c
@@ -1817,7 +1817,14 @@ static size_t _talloc_total_mem_internal(const void *ptr,
        case TOTAL_MEM_LIMIT:
                if (likely(tc->name != TALLOC_MAGIC_REFERENCE)) {
-                       total = tc->size + TC_HDR_SIZE;
+                       /*
+                        * Don't count memory allocated from a pool
+                        * when calculating limits. Only count the
+                        * pool itself.
+                        */
+                       if (!(tc->flags & TALLOC_FLAG_POOLMEM)) {
+                               total = tc->size + TC_HDR_SIZE;
+                       }

I'm not sure talloc_set_memlimit() should actually *work*
when applied to a pool pointer. Maybe we should just
return an error ?

More information about the samba-technical mailing list