Skip to content

crazyrealloc might cause spurious issues (buffer overread + undefined behavior in preeny, UAF in target program) #85

@cao

Description

@cao

crazyrealloc might cause spurious issues due to undefined behavior that can lead to UAF in the target program because it does not implement realloc correctly:

One reason is that there are currently no size checks. If the new size is larger than the old size and we end up in the block at L45, then we memcpy from possibly unallocated memory (after the old pointer). This is undefined, can crash, and it might also trigger ASAN (though in preeny, so it will likely not cause issues for triaging, but could cause substantial false crashes).

Another reason is that the return value of the malloc L46 call is not properly checked, causing issues in case of ENOMEM (e.g., because of fragmentation):

  1. If ptr is not a null pointer and original_realloc returns the same pointer, we enter the block at L45.

  2. If malloc then returns a null pointer and sets errno = ENOMEM, we encounter undefined behavior on L49 in the memcpy(NULL, r, size) because the arguments to memcpy must be valid pointers (Section 7.24.1 and Section 7.1.4; see also memcpy (and friends) with NULL pointers (26 Jun 2016) by Adam Langley).

  3. Additionally, if the undefined behavior of the memcpy does not cause problems during execution (e.g., ignored or no immediate effect), we will then original_free the original pointer. realloc then returns a null pointer with errno = ENOMEM (correct if new space could not be allocated; memcpy and free do not change errno). However, from the manpage of realloc:

    If there is not enough available memory, realloc() shall return a
    null pointer and set errno to [ENOMEM].  If realloc() returns a
    null pointer and errno has been set to [ENOMEM], the memory
    referenced by ptr shall not be changed.
    

    crazyrealloc has free'd ptr though, causing a UAF in the target program that does not actually exist, because a correct realloc implementation should have not free'd ptr and the program can correctly assume that ptr has not changed.

Unfortunately, I currently do not have the cycles to send a pull request to fix the issues.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions