Security: Attacker may get access to arbitrary memory through prevector's change_capacity #11162

issue danra opened this issue on August 26, 2017
  1. danra commented at 2:42 PM on August 26, 2017: contributor

    Describe the issue

    An attacker may corrupt memory if he is able to trigger an allocation of a big prevector while memory is low. When either a new prevector is created or an existing one is resized, change_capacity is called:

    void change_capacity(size_type new_capacity) {
            if (new_capacity <= N) {
                   ... // code omitted
                }
            } else {
                if (!is_direct()) {
                    /* FIXME: Because malloc/realloc here won't call new_handler if allocation fails, assert
                        success. These should instead use an allocator or new/delete so that handlers
                        are called as necessary, but performance would be slightly degraded by doing so. */
                    _union.indirect = static_cast<char*>(realloc(_union.indirect, ((size_t)sizeof(T)) * new_capacity));
                    assert(_union.indirect);
                    _union.capacity = new_capacity;
                } else {
                    char* new_indirect = static_cast<char*>(malloc(((size_t)sizeof(T)) * new_capacity));
                    assert(new_indirect);
                    T* src = direct_ptr(0);
                    T* dst = reinterpret_cast<T*>(new_indirect);
                    memcpy(dst, src, size() * sizeof(T));
                    _union.indirect = new_indirect;
                    _union.capacity = new_capacity;
                    _size += N + 1;
                }
            }
        }
    
    

    If either realloc or malloc above fail for some reason, e.g., due to out of memory, in Release builds the capacity would still be increased even though no memory was allocated, so any arbitrary data written to the prevector would overwrite unrelated memory.

    Can you reliably reproduce the issue?

    I haven't exploited this yet. Since the serialize module uses prevector, it looks like a good attack vector: get the victim to serialize or deserialize a big piece of data, when memory is very low (either just because that's the system's state or because the attacker drained the memory somehow).

    Even if this isn't currently exploitable, since this is an infrastructure which might become exploitable through future uses, it should be fixed quickly.

    Expected behaviour

    An exception should be thrown if memory fails to allocate, as already mentioned in the inline FIXME comment in the code.

    What version of bitcoin-core are you using?

    commit 7fd49d01dc2ea444ba4d81d0cfa17486b03c8515

  2. achow101 commented at 2:47 PM on August 26, 2017: member

    I don't think this is a problem.asserts are enabled on our release builds so this will always bail out at the assert regardless of release or debug.

  3. danra commented at 2:51 PM on August 26, 2017: contributor

    Oh! Thanks for that clarification, I was not aware of that.

    Dan

    On 26 Aug 2017, at 17:48, Andrew Chow notifications@github.com wrote:

    I don't think this is a problem.asserts are enabled on our release builds so this will always bail out at the assert regardless of release or debug.

    — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or mute the thread.

  4. danra closed this on Aug 26, 2017

  5. MarcoFalke locked this on Sep 8, 2021
Contributors

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-05-02 21:15 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me