RFC: malloc and secure memory.

Carlos O'Donell carlos@redhat.com
Fri Sep 25 16:10:01 GMT 2020


On 9/25/20 2:39 AM, Florian Weimer wrote:
> * Carlos O'Donell via Libc-alpha:
> 
>> I wonder if we can't do this in some generic way:
>>
>> - Make arenas a first class construct.
>>
>> /* Get arena with special properties.  */
>> malloc_arena *secure_arena = NULL;
>> /* Get a handle to an arena that has secure heaps.  If glibc can make this
>>    kind of arena and heap then it does, otherwise it returns NULL.  */
>> secure_arena = malloc_arena_get (HEAP_SECURE);
>> /* Does this glibc support his kind of arena?  */
>> if (secure_arena == NULL)
>>   abort();
>>
>> - Bind the malloc call site to a specific arena with specific properties.
>>
>> For example:
>>
>>   /* malloc_arena takes an opaque arena pointer that is a global
>>      variable that the implementation provides, a function pointer
>>      the memory allocator routine e.g. malloc, and a size.  */
>>   password_storage = malloc_arena (secure_arena, malloc, size);
>>   ...
>>   /* Completely different TU, or scope... */
>>   free (password_storage);
> 
> How is this going to work with existing out-of-tree mallocs?  Do you
> want them all to change?  Why would these implementations want to add
> the overhead to support memory they have not allocated?  How would they
> discover the actual implementation of free to call?

The call to malloc_arena is passed a function pointer for malloc, and my intent
was to use that to compare if there was an interposed allocator that didn't
implement the call. Granted this would have to be tested and the code
verified if it would even work e.g. address of PLT / canonical address etc.
In which case we would fail the call and return an error to show that the
mixed-allocator use case is not supported. This opens a big problem though
in that you now have the following scenarios:

(1) Uninterposed: Works fine.
(2) Interposed: Works sometimes depending on interposer and testing.

Which is not a great situation, but supports the "I don't control the point
of free" requirement in the design.
 
> If we want to add new allocator interfaces, they need to have completely
> separate names, and should follow an existing, well-understood design
> (e.g., the APR pool interfaces, libtalloc with its pointers-as-pools,
> the Windows 2.x heap interfaces with its handles).

This is the other way to take the decision and it has better scenarios:

(1) Before using APIs: works fine.
(2) Using new APIs: works fine.

There is no potentially tricky case where you have to check for the new
allocator and if it fails have a fallback.

If we agree that a new API should be used, then it doesn't need to be
solved in glibc. Other runtimes can provide "secure memory" handling
and the applications have to use those APIs.

In summary:

(a) Is calling free with this memory important enough to design an API
    around that use case?

(b) Should applications develop new APIs to solve this problem?

My feeling is (a) "No" because it's a lot of design and maintenance
overhead for a limited problem with bad runtime scenarios.

My feeling is (b) "Yes" because it yields a better runtime scenario.

Thoughts?

-- 
Cheers,
Carlos.



More information about the Libc-alpha mailing list