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

Fix invalid memory write in case of failing mmap(...) in PosixLockedPageAllocator::AllocateLocked #15117

Merged

Conversation

@practicalswift
Copy link
Contributor

@practicalswift practicalswift commented Jan 6, 2019

mmap(...) returns MAP_FAILED ((void *) -1) in case of allocation failure.

PosixLockedPageAllocator::AllocateLocked(...) did not check for allocation failures prior to this PR.

Instead the invalid memory address (void *) -1 (0xffffffffffffffff) was passed to the caller as if it was a valid address.

After some operations the address is wrapped around from 0xffffffffffffffff to 0x00000003ffdf (0xffffffffffffffff + 262112 == 0x00000003ffdf);

The resulting address 0x00000003ffdf is then written to.

Before this patch (with failing mmap call):

$ src/bitcoind
…
2019-01-06T16:28:14Z Using the 'sse4(1way),sse41(4way)' SHA256 implementation
2019-01-06T16:28:14Z Using RdRand as an additional entropy source
Segmentation fault (core dumped)

Before this patch (under valgrind with failing mmap call):

$ valgrind src/bitcoind
…
2019-01-06T16:28:51Z Using the 'sse4(1way),sse41(4way)' SHA256 implementation
==17812== Invalid write of size 1
==17812==    at 0x500B7E: void __gnu_cxx::new_allocator<unsigned char>::construct<unsigned char>(unsigned char*) (new_allocator.h:136)
==17812==    by 0x500B52: _ZNSt16allocator_traitsI16secure_allocatorIhEE12_S_constructIhJEEENSt9enable_ifIXsr6__and_INS2_18__construct_helperIT_JDpT0_EE4typeEEE5valueEvE4typeERS1_PS6_DpOS7_ (alloc_traits.h:243)
==17812==    by 0x500B22: _ZNSt16allocator_traitsI16secure_allocatorIhEE9constructIhJEEEDTcl12_S_constructfp_fp0_spclsr3stdE7forwardIT0_Efp1_EEERS1_PT_DpOS4_ (alloc_traits.h:344)
==17812==    by 0x500982: unsigned char* std::__uninitialized_default_n_a<unsigned char*, unsigned long, secure_allocator<unsigned char> >(unsigned char*, unsigned long, secure_allocator<unsigned char>&) (stl_uninitialized.h:631)
==17812==    by 0x60BFC2: std::vector<unsigned char, secure_allocator<unsigned char> >::_M_default_initialize(unsigned long) (stl_vector.h:1347)
==17812==    by 0x60BD86: std::vector<unsigned char, secure_allocator<unsigned char> >::vector(unsigned long, secure_allocator<unsigned char> const&) (stl_vector.h:285)
==17812==    by 0x60BB55: ECC_Start() (key.cpp:351)
==17812==    by 0x16AC90: AppInitSanityChecks() (init.cpp:1162)
==17812==    by 0x15BAC9: AppInit(int, char**) (bitcoind.cpp:138)
==17812==    by 0x15B6C8: main (bitcoind.cpp:201)
==17812==  Address 0x3ffdf is not stack'd, malloc'd or (recently) free'd
…
Segmentation fault (core dumped)

After this patch (with failing mmap call):

$ src/bitcoind
…
2019-01-06T15:50:18Z Using the 'sse4(1way),sse41(4way)' SHA256 implementation
2019-01-06T15:50:18Z Using RdRand as an additional entropy source
2019-01-06T15:50:18Z

************************
EXCEPTION: St9bad_alloc
std::bad_alloc
bitcoin in AppInit()



************************
EXCEPTION: St9bad_alloc
std::bad_alloc
bitcoin in AppInit()

2019-01-06T15:50:18Z Shutdown: In progress...
2019-01-06T15:50:18Z Shutdown: done

To simulate the failing mmap call apply the following to master:

diff --git a/src/support/lockedpool.cpp b/src/support/lockedpool.cpp
index 8d577cf52..ce79e569b 100644
--- a/src/support/lockedpool.cpp
+++ b/src/support/lockedpool.cpp
@@ -247,7 +247,8 @@ void *PosixLockedPageAllocator::AllocateLocked(size_t len, bool *lockingSuccess)
 {
     void *addr;
     len = align_up(len, page_size);
-    addr = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+    // addr = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+    addr = MAP_FAILED;
     if (addr) {
         *lockingSuccess = mlock(addr, len) == 0;
     }
@practicalswift practicalswift changed the title Fix out-of-bounds write in case of failing mmap(...) in PosixLockedPageAllocator::AllocateLocked Fix invalid memory write write in case of failing mmap(...) in PosixLockedPageAllocator::AllocateLocked Jan 6, 2019
@practicalswift practicalswift changed the title Fix invalid memory write write in case of failing mmap(...) in PosixLockedPageAllocator::AllocateLocked Fix invalid memory write in case of failing mmap(...) in PosixLockedPageAllocator::AllocateLocked Jan 6, 2019
return static_cast<T*>(LockedPoolManager::Instance().alloc(sizeof(T) * n));
T* allocation = static_cast<T*>(LockedPoolManager::Instance().alloc(sizeof(T) * n));
if (!allocation) {
throw std::bad_alloc();
Copy link
Member

@Empact Empact Jan 7, 2019

Maybe propagate errno info?

Copy link
Contributor Author

@practicalswift practicalswift Jan 7, 2019

I don't think bad_alloc have any parameterized ctor:s?

Copy link
Member

@Empact Empact Jan 7, 2019

Indeed - I guess the other option would be to log it in the allocate method. (nit only)

@@ -248,6 +248,9 @@ void *PosixLockedPageAllocator::AllocateLocked(size_t len, bool *lockingSuccess)
void *addr;
len = align_up(len, page_size);
addr = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if (addr == MAP_FAILED) {
return nullptr;
}
Copy link
Member

@Empact Empact Jan 7, 2019

Judging from leveldb's handling, and the mmap docs, the null value case is negligible:

void* base = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
if (base != MAP_FAILED) {
*result = new PosixMmapReadableFile(fname, base, size, &mmap_limit_);
} else {
s = IOError(fname, errno);
}

Copy link
Contributor Author

@practicalswift practicalswift Jan 7, 2019

I'm not sure how to parse TBH: are you suggesting a change here? :-)

Copy link
Member

@Empact Empact Jan 7, 2019

Just that the if (addr) is strictly unnecessary.

@Empact
Copy link
Member

@Empact Empact commented Jan 7, 2019

Concept ACK

@laanwj
Copy link
Member

@laanwj laanwj commented Jan 7, 2019

TIL. Always thought it returned NULL on error.

RETURN VALUE
       On success, mmap() returns a pointer to the mapped area.  On error, the
       value MAP_FAILED (that is, (void *) -1) is returned, and errno  is  set
       to indicate the cause of the error.

utACK ca126d4

@gmaxwell
Copy link
Contributor

@gmaxwell gmaxwell commented Jan 7, 2019

Concept ACK. I too assumed mmap returned NULL on failure.

@donaloconnor
Copy link
Contributor

@donaloconnor donaloconnor commented Jan 7, 2019

Concept ACK - good spot!

@laanwj laanwj merged commit ca126d4 into bitcoin:master Jan 9, 2019
2 checks passed
laanwj added a commit that referenced this issue Jan 9, 2019
…n PosixLockedPageAllocator::AllocateLocked

ca126d4 Fix out-of-bounds write in case of failing mmap(...) in PosixLockedPageAllocator::AllocateLocked (practicalswift)

Pull request description:

  `mmap(...)` returns `MAP_FAILED` (`(void *) -1`) in case of allocation failure.

  `PosixLockedPageAllocator::AllocateLocked(...)` did not check for allocation failures prior to this PR.

  Instead the invalid memory address `(void *) -1` (`0xffffffffffffffff`) was passed to the caller as if it was a valid address.

  After some operations the address is wrapped around from `0xffffffffffffffff` to `0x00000003ffdf` (`0xffffffffffffffff + 262112 == 0x00000003ffdf`);

  The resulting address `0x00000003ffdf` is then written to.

  Before this patch (with failing `mmap` call):

  ```
  $ src/bitcoind
  …
  2019-01-06T16:28:14Z Using the 'sse4(1way),sse41(4way)' SHA256 implementation
  2019-01-06T16:28:14Z Using RdRand as an additional entropy source
  Segmentation fault (core dumped)
  ```

  Before this patch (under `valgrind` with failing `mmap` call):

  ```
  $ valgrind src/bitcoind
  …
  2019-01-06T16:28:51Z Using the 'sse4(1way),sse41(4way)' SHA256 implementation
  ==17812== Invalid write of size 1
  ==17812==    at 0x500B7E: void __gnu_cxx::new_allocator<unsigned char>::construct<unsigned char>(unsigned char*) (new_allocator.h:136)
  ==17812==    by 0x500B52: _ZNSt16allocator_traitsI16secure_allocatorIhEE12_S_constructIhJEEENSt9enable_ifIXsr6__and_INS2_18__construct_helperIT_JDpT0_EE4typeEEE5valueEvE4typeERS1_PS6_DpOS7_ (alloc_traits.h:243)
  ==17812==    by 0x500B22: _ZNSt16allocator_traitsI16secure_allocatorIhEE9constructIhJEEEDTcl12_S_constructfp_fp0_spclsr3stdE7forwardIT0_Efp1_EEERS1_PT_DpOS4_ (alloc_traits.h:344)
  ==17812==    by 0x500982: unsigned char* std::__uninitialized_default_n_a<unsigned char*, unsigned long, secure_allocator<unsigned char> >(unsigned char*, unsigned long, secure_allocator<unsigned char>&) (stl_uninitialized.h:631)
  ==17812==    by 0x60BFC2: std::vector<unsigned char, secure_allocator<unsigned char> >::_M_default_initialize(unsigned long) (stl_vector.h:1347)
  ==17812==    by 0x60BD86: std::vector<unsigned char, secure_allocator<unsigned char> >::vector(unsigned long, secure_allocator<unsigned char> const&) (stl_vector.h:285)
  ==17812==    by 0x60BB55: ECC_Start() (key.cpp:351)
  ==17812==    by 0x16AC90: AppInitSanityChecks() (init.cpp:1162)
  ==17812==    by 0x15BAC9: AppInit(int, char**) (bitcoind.cpp:138)
  ==17812==    by 0x15B6C8: main (bitcoind.cpp:201)
  ==17812==  Address 0x3ffdf is not stack'd, malloc'd or (recently) free'd
  …
  Segmentation fault (core dumped)
  ```

  After this patch (with failing `mmap` call):

  ```
  $ src/bitcoind
  …
  2019-01-06T15:50:18Z Using the 'sse4(1way),sse41(4way)' SHA256 implementation
  2019-01-06T15:50:18Z Using RdRand as an additional entropy source
  2019-01-06T15:50:18Z

  ************************
  EXCEPTION: St9bad_alloc
  std::bad_alloc
  bitcoin in AppInit()

  ************************
  EXCEPTION: St9bad_alloc
  std::bad_alloc
  bitcoin in AppInit()

  2019-01-06T15:50:18Z Shutdown: In progress...
  2019-01-06T15:50:18Z Shutdown: done
  ```

  To simulate the failing `mmap` call apply the following to `master`:

  ```diff
  diff --git a/src/support/lockedpool.cpp b/src/support/lockedpool.cpp
  index 8d577cf52..ce79e569b 100644
  --- a/src/support/lockedpool.cpp
  +++ b/src/support/lockedpool.cpp
  @@ -247,7 +247,8 @@ void *PosixLockedPageAllocator::AllocateLocked(size_t len, bool *lockingSuccess)
   {
       void *addr;
       len = align_up(len, page_size);
  -    addr = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
  +    // addr = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
  +    addr = MAP_FAILED;
       if (addr) {
           *lockingSuccess = mlock(addr, len) == 0;
       }
  ```

Tree-SHA512: 66947f5fc0fbb19afb3e1edbd51df07df9d16b77018cff3d48d30f378a53d6a0dc62bc36622b3966b7e374e61edbcca114ef4ac8ae8d725022c1a597edcbf7c7
zkbot added a commit to zcash/zcash that referenced this issue Jul 31, 2020
Locked memory manager

Add a pool for locked memory chunks, replacing `LockedPageManager`.

Cherry-picked from the following upstream PRs:
- bitcoin/bitcoin#8321
- bitcoin/bitcoin#8753
- bitcoin/bitcoin#9063
- bitcoin/bitcoin#9070
- bitcoin/bitcoin#11385
- bitcoin/bitcoin#12048
  - Excludes change to benchmark.
- bitcoin/bitcoin#15117
- bitcoin/bitcoin#16161
  - Excludes Travis CI changes.
  - Includes change from bitcoin/bitcoin#13163
- bitcoin/bitcoin#15600
- bitcoin/bitcoin#18443
- Assorted small changes from:
  - bitcoin/bitcoin#9233
  - bitcoin/bitcoin#10483
  - bitcoin/bitcoin#10645
  - bitcoin/bitcoin#10969
  - bitcoin/bitcoin#11351
- bitcoin/bitcoin#19111
  - Excludes change to `src/rpc/server.cpp`
zkbot added a commit to zcash/zcash that referenced this issue Sep 29, 2020
Locked memory manager

Add a pool for locked memory chunks, replacing `LockedPageManager`.

Cherry-picked from the following upstream PRs:
- bitcoin/bitcoin#8321
- bitcoin/bitcoin#8753
- bitcoin/bitcoin#9063
- bitcoin/bitcoin#9070
- bitcoin/bitcoin#11385
- bitcoin/bitcoin#12048
  - Excludes change to benchmark.
- bitcoin/bitcoin#15117
- bitcoin/bitcoin#16161
  - Excludes Travis CI changes.
  - Includes change from bitcoin/bitcoin#13163
- bitcoin/bitcoin#15600
- bitcoin/bitcoin#18443
- Assorted small changes from:
  - bitcoin/bitcoin#9233
  - bitcoin/bitcoin#10483
  - bitcoin/bitcoin#10645
  - bitcoin/bitcoin#10969
  - bitcoin/bitcoin#11351
- bitcoin/bitcoin#19111
  - Excludes change to `src/rpc/server.cpp`
- bitcoin/bitcoin#9804
  - Only the commit for `src/key.cpp`
- bitcoin/bitcoin#9598
jasonbcox pushed a commit to Bitcoin-ABC/bitcoin-abc that referenced this issue Nov 11, 2020
…geAllocator::AllocateLocked

Summary:
PR description:
> mmap(...) returns MAP_FAILED ((void *) -1) in case of allocation failure.
>
> PosixLockedPageAllocator::AllocateLocked(...) did not check for allocation failures prior to this PR.
>
> Instead the invalid memory address (void *) -1 (0xffffffffffffffff) was passed to the caller as if it was a valid address.
>
> After some operations the address is wrapped around from 0xffffffffffffffff to 0x00000003ffdf (0xffffffffffffffff + 262112 == 0x00000003ffdf);
>
> The resulting address 0x00000003ffdf is then written to.
>
> Before this patch (with failing mmap call):
>
> ```
> $ src/bitcoind
> …
> 2019-01-06T16:28:14Z Using the 'sse4(1way),sse41(4way)' SHA256 implementation
> 2019-01-06T16:28:14Z Using RdRand as an additional entropy source
> Segmentation fault (core dumped)
> ```
>
> After this patch (with failing mmap call):
> ```
> $ src/bitcoind
> …
> 2019-01-06T15:50:18Z Using the 'sse4(1way),sse41(4way)' SHA256 implementation
> 2019-01-06T15:50:18Z Using RdRand as an additional entropy source
> 2019-01-06T15:50:18Z
>
> ************************
> EXCEPTION: St9bad_alloc
> std::bad_alloc
> bitcoin in AppInit()
>
>
>
> ************************
> EXCEPTION: St9bad_alloc
> std::bad_alloc
> bitcoin in AppInit()
>
> 2019-01-06T15:50:18Z Shutdown: In progress...
> 2019-01-06T15:50:18Z Shutdown: done
> ```

This is a backport of Core [[bitcoin/bitcoin#15117 | PR15117]]

Test Plan: `ninja all check-all`

Reviewers: #bitcoin_abc, majcosta

Reviewed By: #bitcoin_abc, majcosta

Differential Revision: https://reviews.bitcoinabc.org/D8354
@practicalswift practicalswift deleted the gracefully-handle-mmap-failure branch Apr 10, 2021
PastaPastaPasta added a commit to PastaPastaPasta/dash that referenced this issue Jun 26, 2021
…(...) in PosixLockedPageAllocator::AllocateLocked

ca126d4 Fix out-of-bounds write in case of failing mmap(...) in PosixLockedPageAllocator::AllocateLocked (practicalswift)

Pull request description:

  `mmap(...)` returns `MAP_FAILED` (`(void *) -1`) in case of allocation failure.

  `PosixLockedPageAllocator::AllocateLocked(...)` did not check for allocation failures prior to this PR.

  Instead the invalid memory address `(void *) -1` (`0xffffffffffffffff`) was passed to the caller as if it was a valid address.

  After some operations the address is wrapped around from `0xffffffffffffffff` to `0x00000003ffdf` (`0xffffffffffffffff + 262112 == 0x00000003ffdf`);

  The resulting address `0x00000003ffdf` is then written to.

  Before this patch (with failing `mmap` call):

  ```
  $ src/bitcoind
  …
  2019-01-06T16:28:14Z Using the 'sse4(1way),sse41(4way)' SHA256 implementation
  2019-01-06T16:28:14Z Using RdRand as an additional entropy source
  Segmentation fault (core dumped)
  ```

  Before this patch (under `valgrind` with failing `mmap` call):

  ```
  $ valgrind src/bitcoind
  …
  2019-01-06T16:28:51Z Using the 'sse4(1way),sse41(4way)' SHA256 implementation
  ==17812== Invalid write of size 1
  ==17812==    at 0x500B7E: void __gnu_cxx::new_allocator<unsigned char>::construct<unsigned char>(unsigned char*) (new_allocator.h:136)
  ==17812==    by 0x500B52: _ZNSt16allocator_traitsI16secure_allocatorIhEE12_S_constructIhJEEENSt9enable_ifIXsr6__and_INS2_18__construct_helperIT_JDpT0_EE4typeEEE5valueEvE4typeERS1_PS6_DpOS7_ (alloc_traits.h:243)
  ==17812==    by 0x500B22: _ZNSt16allocator_traitsI16secure_allocatorIhEE9constructIhJEEEDTcl12_S_constructfp_fp0_spclsr3stdE7forwardIT0_Efp1_EEERS1_PT_DpOS4_ (alloc_traits.h:344)
  ==17812==    by 0x500982: unsigned char* std::__uninitialized_default_n_a<unsigned char*, unsigned long, secure_allocator<unsigned char> >(unsigned char*, unsigned long, secure_allocator<unsigned char>&) (stl_uninitialized.h:631)
  ==17812==    by 0x60BFC2: std::vector<unsigned char, secure_allocator<unsigned char> >::_M_default_initialize(unsigned long) (stl_vector.h:1347)
  ==17812==    by 0x60BD86: std::vector<unsigned char, secure_allocator<unsigned char> >::vector(unsigned long, secure_allocator<unsigned char> const&) (stl_vector.h:285)
  ==17812==    by 0x60BB55: ECC_Start() (key.cpp:351)
  ==17812==    by 0x16AC90: AppInitSanityChecks() (init.cpp:1162)
  ==17812==    by 0x15BAC9: AppInit(int, char**) (bitcoind.cpp:138)
  ==17812==    by 0x15B6C8: main (bitcoind.cpp:201)
  ==17812==  Address 0x3ffdf is not stack'd, malloc'd or (recently) free'd
  …
  Segmentation fault (core dumped)
  ```

  After this patch (with failing `mmap` call):

  ```
  $ src/bitcoind
  …
  2019-01-06T15:50:18Z Using the 'sse4(1way),sse41(4way)' SHA256 implementation
  2019-01-06T15:50:18Z Using RdRand as an additional entropy source
  2019-01-06T15:50:18Z

  ************************
  EXCEPTION: St9bad_alloc
  std::bad_alloc
  bitcoin in AppInit()

  ************************
  EXCEPTION: St9bad_alloc
  std::bad_alloc
  bitcoin in AppInit()

  2019-01-06T15:50:18Z Shutdown: In progress...
  2019-01-06T15:50:18Z Shutdown: done
  ```

  To simulate the failing `mmap` call apply the following to `master`:

  ```diff
  diff --git a/src/support/lockedpool.cpp b/src/support/lockedpool.cpp
  index 8d577cf52..ce79e569b 100644
  --- a/src/support/lockedpool.cpp
  +++ b/src/support/lockedpool.cpp
  @@ -247,7 +247,8 @@ void *PosixLockedPageAllocator::AllocateLocked(size_t len, bool *lockingSuccess)
   {
       void *addr;
       len = align_up(len, page_size);
  -    addr = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
  +    // addr = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
  +    addr = MAP_FAILED;
       if (addr) {
           *lockingSuccess = mlock(addr, len) == 0;
       }
  ```

Tree-SHA512: 66947f5fc0fbb19afb3e1edbd51df07df9d16b77018cff3d48d30f378a53d6a0dc62bc36622b3966b7e374e61edbcca114ef4ac8ae8d725022c1a597edcbf7c7
PastaPastaPasta added a commit to PastaPastaPasta/dash that referenced this issue Jun 28, 2021
…(...) in PosixLockedPageAllocator::AllocateLocked

ca126d4 Fix out-of-bounds write in case of failing mmap(...) in PosixLockedPageAllocator::AllocateLocked (practicalswift)

Pull request description:

  `mmap(...)` returns `MAP_FAILED` (`(void *) -1`) in case of allocation failure.

  `PosixLockedPageAllocator::AllocateLocked(...)` did not check for allocation failures prior to this PR.

  Instead the invalid memory address `(void *) -1` (`0xffffffffffffffff`) was passed to the caller as if it was a valid address.

  After some operations the address is wrapped around from `0xffffffffffffffff` to `0x00000003ffdf` (`0xffffffffffffffff + 262112 == 0x00000003ffdf`);

  The resulting address `0x00000003ffdf` is then written to.

  Before this patch (with failing `mmap` call):

  ```
  $ src/bitcoind
  …
  2019-01-06T16:28:14Z Using the 'sse4(1way),sse41(4way)' SHA256 implementation
  2019-01-06T16:28:14Z Using RdRand as an additional entropy source
  Segmentation fault (core dumped)
  ```

  Before this patch (under `valgrind` with failing `mmap` call):

  ```
  $ valgrind src/bitcoind
  …
  2019-01-06T16:28:51Z Using the 'sse4(1way),sse41(4way)' SHA256 implementation
  ==17812== Invalid write of size 1
  ==17812==    at 0x500B7E: void __gnu_cxx::new_allocator<unsigned char>::construct<unsigned char>(unsigned char*) (new_allocator.h:136)
  ==17812==    by 0x500B52: _ZNSt16allocator_traitsI16secure_allocatorIhEE12_S_constructIhJEEENSt9enable_ifIXsr6__and_INS2_18__construct_helperIT_JDpT0_EE4typeEEE5valueEvE4typeERS1_PS6_DpOS7_ (alloc_traits.h:243)
  ==17812==    by 0x500B22: _ZNSt16allocator_traitsI16secure_allocatorIhEE9constructIhJEEEDTcl12_S_constructfp_fp0_spclsr3stdE7forwardIT0_Efp1_EEERS1_PT_DpOS4_ (alloc_traits.h:344)
  ==17812==    by 0x500982: unsigned char* std::__uninitialized_default_n_a<unsigned char*, unsigned long, secure_allocator<unsigned char> >(unsigned char*, unsigned long, secure_allocator<unsigned char>&) (stl_uninitialized.h:631)
  ==17812==    by 0x60BFC2: std::vector<unsigned char, secure_allocator<unsigned char> >::_M_default_initialize(unsigned long) (stl_vector.h:1347)
  ==17812==    by 0x60BD86: std::vector<unsigned char, secure_allocator<unsigned char> >::vector(unsigned long, secure_allocator<unsigned char> const&) (stl_vector.h:285)
  ==17812==    by 0x60BB55: ECC_Start() (key.cpp:351)
  ==17812==    by 0x16AC90: AppInitSanityChecks() (init.cpp:1162)
  ==17812==    by 0x15BAC9: AppInit(int, char**) (bitcoind.cpp:138)
  ==17812==    by 0x15B6C8: main (bitcoind.cpp:201)
  ==17812==  Address 0x3ffdf is not stack'd, malloc'd or (recently) free'd
  …
  Segmentation fault (core dumped)
  ```

  After this patch (with failing `mmap` call):

  ```
  $ src/bitcoind
  …
  2019-01-06T15:50:18Z Using the 'sse4(1way),sse41(4way)' SHA256 implementation
  2019-01-06T15:50:18Z Using RdRand as an additional entropy source
  2019-01-06T15:50:18Z

  ************************
  EXCEPTION: St9bad_alloc
  std::bad_alloc
  bitcoin in AppInit()

  ************************
  EXCEPTION: St9bad_alloc
  std::bad_alloc
  bitcoin in AppInit()

  2019-01-06T15:50:18Z Shutdown: In progress...
  2019-01-06T15:50:18Z Shutdown: done
  ```

  To simulate the failing `mmap` call apply the following to `master`:

  ```diff
  diff --git a/src/support/lockedpool.cpp b/src/support/lockedpool.cpp
  index 8d577cf52..ce79e569b 100644
  --- a/src/support/lockedpool.cpp
  +++ b/src/support/lockedpool.cpp
  @@ -247,7 +247,8 @@ void *PosixLockedPageAllocator::AllocateLocked(size_t len, bool *lockingSuccess)
   {
       void *addr;
       len = align_up(len, page_size);
  -    addr = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
  +    // addr = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
  +    addr = MAP_FAILED;
       if (addr) {
           *lockingSuccess = mlock(addr, len) == 0;
       }
  ```

Tree-SHA512: 66947f5fc0fbb19afb3e1edbd51df07df9d16b77018cff3d48d30f378a53d6a0dc62bc36622b3966b7e374e61edbcca114ef4ac8ae8d725022c1a597edcbf7c7
furszy added a commit to PIVX-Project/PIVX that referenced this issue Sep 11, 2021
9295568 Fix segfault in allocator_tests/arena_tests (Jeffrey Czyz)
f7d88f5 Define ARENA_DEBUG in GA test runs (furszy)
cae2e13 Fix compilation errors in support/lockedpool.cpp (Jeffrey Czyz)
d19359f fix nits: variable naming, typos (Martin Ankerl)
5cbd967 Use best-fit strategy in Arena, now O(log(n)) instead O(n) (Martin Ankerl)
1ccd62e Fix out-of-bounds write in case of failing mmap(...) in PosixLockedPageAllocator::AllocateLocked (practicalswift)
7ad7157 LockedPool: avoid quadratic-time allocation (Kaz Wesley)
39e1b3b LockedPool: fix explosion for illegal-sized alloc (Kaz Wesley)
adb1f1c LockedPool: test handling of invalid allocations (Kaz Wesley)
626b865 Do not shadow variable, use deprecated MAP_ANON if MAP_ANONYMOUS is not defined. (Pavel Janík)

Pull request description:

  Follow up to #2276. Completing the locked memory manager todo list.

  Back porting:
  * bitcoin#9063.
  * bitcoin#9070.
  * bitcoin#12048.
  * bitcoin#15117.
  * bitcoin#16161.

ACKs for top commit:
  random-zebra:
    ACK 9295568
  Fuzzbawls:
    ACK 9295568

Tree-SHA512: 0d14c7e8231386ee32f1fefac08de9ee278c02d6b0e5172c055851d33c803b0be3398fc5173457e539179712a13d4736033a926f318e576789b4d57b67eb0596
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet

5 participants