talloc: talloc_set_memlimit causes all reallocs to fail when used on pools. talloc_set_memlimit not enforced correctly on pools.
Arran Cudbard-Bell
a.cudbardb at freeradius.org
Fri Oct 16 20:04:36 UTC 2020
> On Oct 16, 2020, at 2:51 PM, Arran Cudbard-Bell via samba-technical <samba-technical at lists.samba.org> wrote:
>
>
>
>> On Oct 16, 2020, at 2:44 PM, Jeremy Allison <jra at samba.org> wrote:
>>
>> On Fri, Oct 16, 2020 at 01:59:11PM -0500, Arran Cudbard-Bell via samba-technical wrote:
>>> Reviewing the talloc code shows provisions (and test cases) for applying memlimits to pools, unfortunately in practice, memlimit functionality on pools seems fairly broken.
>>>
>>> #include <talloc.h>
>>> #include <stdio.h>
>>>
>>> int main(int argc, char **argv)
>>> {
>>> TALLOC_CTX *pool = talloc_pool(NULL, 1024);
>>> TALLOC_CTX *chunk, *fail_chunk;
>>>
>>> if (pool) {
>>> printf("Pool allocated\n");
>>> } else {
>>> printf("Pool allocation failed\n");
>>> }
>>>
>>> if (talloc_set_memlimit(pool, 512) < 0) {
>>> printf("talloc_set_memlimit failed\n");
>>> } else {
>>> printf("talloc_set_memlimit success\n");
>>> }
>>
>> OK, looking at this more closely, I think this is
>> a fundemental misunderstanding of what a talloc_pool
>> is.
>>
>> A talloc_pool() is pre-allocated memory, that can
>> then be further divided without having to call
>> into malloc.
>
> Yes, we use them for slab allocation and for creating read only regions of memory with mprotect. We have a special wrapper that ensures the first child allocated in the pool is page aligned.
>
> When we do this, we don't want to allow allocations to occur outside of the pool so set a memlimit on the pool. I know this is a really weird use case, but it's ended up being quite a useful debugging tool.
>
>> It's ALREADY allocated memory, so setting a memlimit size
>> smaller than the pool size makes no sense - once you've
>> done that all allocations should fail.
>
> In addition to preventing allocations outside of the pool, It would still be useful to be able to apply limits to pools so that a pool passed into a function cannot be entirely consumed by allocations by that function. i.e. if you want to reserve some space in the pool.
As for what the semantics should be, I was thinking that, yes, a pool in its entirety should be included in the memlimit calculation of its parent chunk, but if a memlimit is set on a pool directly, only the memory used by the children should be included in the memlimit check. I didn't get far enough into the code to see how many assumptions would be broken by this.
An alternative that'd still satisfy our immediate need would be to have talloc_set_memlimit simply fail when someone tried to apply it to a pool (as you suggested), and add an optional flag that'd prevent allocations from occurring outside of the pool.
-Arran
More information about the samba-technical
mailing list