Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Not relevant uninitialized reads due to glibc heap management #2

Open
kristopher-pellizzi opened this issue May 21, 2021 · 0 comments
Labels
limitation Something that has drawbacks, but is necessary/desirable

Comments

@kristopher-pellizzi
Copy link
Owner

kristopher-pellizzi commented May 21, 2021

Since chunks headers may be reused without rewriting them, they are never re-initialized.
For what concerns the chunk's payload, instead, there are mainly 2 ways to re-initialize the shadow memory corresponding to a heap chunk to be freed:

  1. Re-initialize before actual execution of function Free
  2. Re-initialize after function Free has been executed and returned

Both of them have some drawbacks.

If we apply strategy 1, the free itself will generate some uninitialized reads, because it checks if a certain portion of the payload (i.e. <payload_ptr + 8> already contains a certain pointer.

If we apply strategy 2, instead, an uninitialized read may be generated by the execution of a new malloc which decides to reallocate a previously freed chunk. Indeed, in this case, malloc reads the first 16 bytes of the chunk's payload in order to check the value of the pointers stored there by the previous free.

So, any of the mentioned strategies will lead to additional not relevant uninitialized reads.

However, since we already required a platform specific header to gather some information about heap management functions, we can take advantage of that again, and add in the header's interface a function that returns a set of ranges of addresses that really require to be re-initialize when free is called. Of course, this requires some prior knowledge of how malloc and free manage the chunks.

In this way, we can apply strategy 2, but re-initialize the chunk's payload only starting from <payload_ptr + 16>, so that what the free wrote in the first 16 B will be still considered initialized by successive instructions and, therefore, by successive mallocs.

Commit 5d886cc has been thought to partially fix the aforementioned behavior, as it sometimes happens that not only the first 16 bytes are wrote and then read again by free, but also other bytes in the same chunk.
To fix this, we simply keep track of heap write accesses performed during a call to free and, after the shadow memory has been reset, we'll set again as initialized the portion of shadow memory corresponding to parts of the chunk written during the execution of free. This way, we are able to effectively re-initialize the shadow memory on free, while also avoiding the false positives of strategy 1 and keeping the writes performed by the free itself, so that we can also reduce the false positives of strategy 2.

Note, however, that there is still a small chance that free generates some uninitialized reads.
Indeed, if we don't write at least 16 Bytes (or we don't write at all) in an allocated chunk, the call to free will still read from uninitialized memory, thus reporting it. However, this is not usually the case, and the number of reported reads is highly reduced

@kristopher-pellizzi kristopher-pellizzi added the limitation Something that has drawbacks, but is necessary/desirable label May 21, 2021
kristopher-pellizzi added a commit that referenced this issue May 21, 2021
In order to avoid that malloc reads bytes considered uninitialized, the
first 16 bytes of a chunk's payload on an x86_64 architecture using
glibc implementation are not re-initialized during a call to free.
This is because free itself writes there some pointers that a following
malloc may read.
Note however that some not relevant uninitialized reads may still be
reported, in some cases.
More infos in issue #2.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
limitation Something that has drawbacks, but is necessary/desirable
Projects
None yet
Development

No branches or pull requests

1 participant