views:

765

answers:

16

When we free() memory in C, why is that memory not filled with zero? Is there a good way to ensure this happens as a matter of course when calling free()?

I'd rather not risk leaving sensitive data in memory released back to the operating system...

+4  A: 

C why is the memory not explictly set to zero in the free implementation .

Because of speed.

Because after we free the memory any how we set it to zero after freeing.

Eh?

maykeye
A: 

Because it would be a pure waste of time.

cedrou
+3  A: 

If you want the memory to be set to 0 when you free it, you'll have to do it yourself before you free() it. If you try after you free() it there are no guarantees that it hasn't been allocated again. For instance you can use memset() for that.

free() doesn't guarantee that the memory will be cleared because C doesn't guarantee that malloc() will return initialized memory. Either way you have to initialize it yourself after it's been allocated, so there's no point in clearing it when it's free()'d

Nathan Fellman
+5  A: 
memset(ptr, 0, size);
free(ptr);

i think you want this...

tr3
What is the point of setting memory to 0 and then freeing it?
Avi
i don't know, but he asked for it...
tr3
It can be useful for buffers used to store passwords and cryptographic keys http://stackoverflow.com/questions/786093/does-using-securezeromemory-really-help-to-make-the-application-more-secure
sharptooth
+17  A: 

Zeroing out the memory block when freeing it will require extra time. Since most of time there's actually no need in it it is not done by default.

If you really need (say you used memory for storing a password or a cryptographic key) - call memset() before freeing the block. Writing an utility function that chains memset() and free() is not a problem either.

sharptooth
Actually, memset isn't always enough. memset is typically a compiler intrinsic and can be removed if the compiler determine that you won't use the data again (this probably won't happen for a call to free() but is entirely possible for a buffer on the stack). Windows provides the SecureZeroMemory function which won't be optimized away. More info here: https://www.securecoding.cert.org/confluence/display/cplusplus/MSC06-CPP.+Be+aware+of+compiler+optimization+when+dealing+with+sensitive+data
Michael
+6  A: 

Are you perhaps asking about code similar to the following?

free(ptr);
ptr = NULL;

If so, you may want to refer to the answers to Setting variable to NULL after free.

Greg Hewgill
I think he want's the area that the data was held to be set to 0's.
graham.reeds
Yes, that's what it sounds like but I'm reading between the lines.
Greg Hewgill
+5  A: 

[Edit: this is an attempt to answer the original poster's question. The question may or may not have been changed by shog9's edit - it's hard to say since the original was unclear...]

If you mean, as others have assumed, setting 0 for every byte of the memory block being freed, then you cannot do that after freeing the block. Attempting to do it yields undefined behaviour. So if you're doing that, then you have badly misunderstood memory allocation.

But I'm guessing when you say "we set it to zero after freeing", you're maybe talking about code like this:

free(ptr);
ptr = NULL;

If so, then the reason free can't set ptr to NULL, is that free only receives the value from the variable ptr. It has no way of modifying ptr, because you aren't passing the variable ptr itself into free. You're just passing the address currently stored in it. This is part of the design of the C language - when you call a function passing a value, then the callee cannot tell how that value was computed, or what variable might contain it in the caller's code. Making an exception to this language rule just for free would be crazy, even if it were possible.

In any case, not everyone zeroes out pointers after freeing them. Some people think it's a good safety measure, other people think it is not. Whatever you think of it, though, the code doesn't zero the memory, it only zeros the pointer to the memory. If you want to write a function which clears the pointer for you, then you can:

void free_and_clear(void **pptr) {
    free(*pptr);
    *pptr = NULL;
}

Then use it like this:

free_and_clear(&ptr);

Note that this passes a pointer to the variable ptr, instead of the value of ptr. So free_and_clear can modify ptr. But this puts some restrictions on how you can use it which don't apply to free - you need a pointer to a modifiable value, rather than just a value.

Steve Jessop
Chris Lutz
True, although I'm scared of macros which evaluate their argument twice (because I'm scared that one day I'll use them without thinking how many times they do it). In this case the argument has to be an lvalue, which reduces the chance of it having side-effects, but still. You can probably workaround with a temp variable, but once a macro has temp variables I'm always thinking "please, there must be some way to make this a static inline function". I don't think asking the caller to take a pointer is all that bad.
Steve Jessop
A: 

Once you free memory using free(), the value & the memory allocated at that particular address gets deleted (freed) but the pointer still points to that address. If you try to de-reference that pointer you will get Segmentation fault or Bus error. So, its safe to assign NULL value to the pointer once the memory pointed by the pointer is freed. You may refer < http://stackoverflow.com/questions/1025589/setting-variable-to-null-after-free >

Naveen
+1  A: 

A very specific answer to the question "Why is the memory not set to 0 after freeing it?" is "Because the language specification does not define that behavior.

From the draft ANSI C spec: "The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation."

peterb
A: 

This is a FAQ: Why isn't a pointer null after calling free?

Sinan Ünür
+1  A: 

Setting the result of a freed pointer to zero may seem to be bullshit, but if the pointer is inadvertently accessed later, you'll get a segfault (at least in a real OS), and the debugger will point to where this abomination is happening. But as others have noted, when you call "free" later, all free has is the address to free, and nothing else.

xcramps
+3  A: 

The original C philosophy was to have keep implicit effects to an absolute minimum. If a programmer wants a pointer zeroed after the memory pointed to is freed, that's what the programmer should write. Those of us who do often use a macro like this one:

#define FREE(P) ((void)(free((P)), (P) = NULL))

Of course if the expression passed to FREE has side effects, one has just opened a large can of worms...

Norman Ramsey
+1  A: 

If I understand the question correctly the OP wants to not leave sensitive information "out there" in fear of it being compromised. As the previous posters pointed out freeing the memory before releasing it is the answer to wiping the data.

However, it is far from the answer to what the OP is trying to achieve. For starters zeroing the memory is 100% useless in securing your application. Even if the memory page is allocated to another running process, in most OSs this procedure is non-deterministic and no sane hacker will EVER use such a technique to compromise your data.

What a sane hacker would do is whack your program into a disassembler and debug through it until they figure out where the data is and then use it. Since a call to memset is bleedingly obvious once you are a competent disassemblerator(yes, disassemblerator :) ) our hypothetical hacker would just get to the data before memset happens.

To really answer your question. If you are trying to protect some sensitive data inside your C program you are getting in the domain that is far beyond normal C/C++ programmers(like myself) into realm of writing virtual machines for executing your data sensitive operations.

The fact that you even ask this question means that it would be reckless for you to develop something that requires this level of protection. Also it will absolutely not be the first stop in protecting your data. Pick the low hanging fruit first and there is plenty info on the web about that.

Igor Zevaka
You should explicitly zero-out memory for high-risk data such as passwords, credit card numbers, and so on, as soon as they aren't needed. While this can't prevent all attempts from stealing the data, it at least shrinks the window where it could be stolen.
Michael
I don't really agree with that. You are getting into the area where you are second guessing the compiler and the OS. If you want to do that, that's fine, but you really really MUST know what you are doing. For starters it's highly likely that the compiler optimizes the memset call. Secondly, as I said before, it's pretty useless as, unless you obfuscate, the hacker will just get in when he knows the data is going to be available. It is far from providing any meaningful protection and it's likely your app has a thousand other security deficiencies that you should fix first.
Igor Zevaka
One should do a secure_memset (that isn't subject to being optimized away) in particular on multi-user systems. That's because the memory that gets `free`d may be returned by a future call to malloc by another (OS) user. May be unlikely, but could be exploited.
Inshallah
+1  A: 

free() doesn't release memory back to the OS - it releases back to the process's heap manager. For efficiency reasons, it is not zero'd out.

When a process allocates virtual memory, most OS's will hand it a zero'd page. This prevents memory from "leaking" from one process to the other and causing a security issue like you mention.

If you have data in your process that you don't want to keep in memory (for example, a user's password), you are responsible for zeroing it out. Windows provides the SecureZeroMemory API for this.

Michael
A: 

There's also bzero(3).

A: 

C was originally designed as a system implementation language, and so C operations are generally as fast and as close to the metal as is practical. One key point in the design philosophy is that you can take several fast operations and make them into one slower and safer operation, but you can't take slower and safer operations and make a faster one.

If you want a zero-and-free function, you can write one, and use it instead of free(). If you're concerned with security, I'd recommend it.

David Thornley