Bug 24775 - Please add a secure way to clear and free memory
Summary: Please add a secure way to clear and free memory
Status: RESOLVED INVALID
Alias: None
Product: glibc
Classification: Unclassified
Component: malloc (show other bugs)
Version: unspecified
: P2 enhancement
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-07-05 17:56 UTC by Topi Miettinen
Modified: 2019-07-06 16:24 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
fweimer: security-


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Topi Miettinen 2019-07-05 17:56:58 UTC
Please add a new function, which securely (not optimized away by the compiler, maybe using memory barriers) clears the memory block being freed in addition to free() functionality. This can be used by programs which read passwords and maybe for cryptographic uses, to lower chances that the passwords or keys are accidentally readable e.g. via attacker controlled pointer.

In absence of such function, programs can clear the memory and then use free() (but this is harder to combine with gcc cleanup extension), or use malloc internals to determine the allocated length (which can confuse gcc memory sanity analyzer MSan).

Possible signature could be

void secure_clear_and_free(void *ptr);

or shorter (but more obscure) and also matching calloc() as

cfree(void *ptr);

The basic functionality without the optimization or memory barriers should be somewhat similar to this:

void secure_clear_and_free(void *ptr)
{
    memset(ptr, 0, malloc_usable_size(ptr));
    free(ptr);
}

-Topi Miettinen
Comment 1 Florian Weimer 2019-07-05 18:02:01 UTC
We already explicit_bzero followed by free.  Why is this not enough?

cfree is already taken, it was used by some old libcs as an alias for free.
Comment 2 Topi Miettinen 2019-07-05 19:59:36 UTC
(In reply to Florian Weimer from comment #1)
> We already explicit_bzero followed by free.  Why is this not enough?

The background is this PR for systemd: 
https://github.com/systemd/systemd/pull/12959

We're using gcc cleanup extension a lot but and it would be nice to use that for clearing memory before free()ing. It's of course possible to use explicit_bzero and free, but combining them to one function would be nicer. Besides systemd, I suppose other programs could use the function if it was provided by glibc.

> 
> cfree is already taken, it was used by some old libcs as an alias for free.

How about clear_and_free() or erase_and_free() then?

-Topi
Comment 3 Carlos O'Donell 2019-07-05 20:18:59 UTC
(In reply to Topi Miettinen from comment #2)
> How about clear_and_free() or erase_and_free() then?

Why? We provide all the functionality you need. You just need to make your own cleanup function which calls explicit_bzero and then free. We want to expose functions which are composable that you can use to implement what you need easily. This reduces the cost for us a system library, we implement smaller functions, they are easier to create, and maintain.

What reason do you have for wanting one function that does both?
Comment 4 Florian Weimer 2019-07-05 20:22:13 UTC
Note that you can get the block size using malloc_usable_size, so not knowing that at the site of the freeing call should not be an obstacle.

(Although malloc_usable_size may not have been interposed by a minimal malloc, but hopefully, none of those are left anymore.)
Comment 5 Topi Miettinen 2019-07-06 08:28:44 UTC
(In reply to Florian Weimer from comment #4)
> Note that you can get the block size using malloc_usable_size, so not
> knowing that at the site of the freeing call should not be an obstacle.
> 
> (Although malloc_usable_size may not have been interposed by a minimal
> malloc, but hopefully, none of those are left anymore.)

The problem with this is that the size returned may be greater than the original size used during allocation and accessing the area beyond allocated size makes MSan very unhappy. What could work is a way to get the original size somehow (size_t malloc_allocated_size(void *ptr)?), then there would be no need for one function that does both clearing and allocation.
Comment 6 Florian Weimer 2019-07-06 15:20:17 UTC
(In reply to Topi Miettinen from comment #5)
> (In reply to Florian Weimer from comment #4)
> > Note that you can get the block size using malloc_usable_size, so not
> > knowing that at the site of the freeing call should not be an obstacle.
> > 
> > (Although malloc_usable_size may not have been interposed by a minimal
> > malloc, but hopefully, none of those are left anymore.)
> 
> The problem with this is that the size returned may be greater than the
> original size used during allocation and accessing the area beyond allocated
> size makes MSan very unhappy. What could work is a way to get the original
> size somehow (size_t malloc_allocated_size(void *ptr)?), then there would be
> no need for one function that does both clearing and allocation.

This is a bug in Msan.  It needs to interpose malloc_usable_size and return the value that it thinks is the correct allocation size.  It's what the implementation of Address Sanitizer in GCC does.
Comment 7 Topi Miettinen 2019-07-06 16:22:37 UTC
(In reply to Florian Weimer from comment #6)
> This is a bug in Msan.  It needs to interpose malloc_usable_size and return
> the value that it thinks is the correct allocation size.  It's what the
> implementation of Address Sanitizer in GCC does.

Yes, I suppose that's the right approach compared to a new function in libc. This bug can be closed. Thanks for the quick responses.

Strangely MSan also seems to do just that and this part hasn't changed in 5 years. I'll check what was the original issue we encountered.
Comment 8 Topi Miettinen 2019-07-06 16:24:54 UTC
Closing.