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):
0$ src/bitcoind
1…
22019-01-06T16:28:14Z Using the 'sse4(1way),sse41(4way)' SHA256 implementation
32019-01-06T16:28:14Z Using RdRand as an additional entropy source
4Segmentation fault (core dumped)
Before this patch (under valgrind
with failing mmap
call):
0$ valgrind src/bitcoind
1…
22019-01-06T16:28:51Z Using the 'sse4(1way),sse41(4way)' SHA256 implementation
3==17812== Invalid write of size 1
4==17812== at 0x500B7E: void __gnu_cxx::new_allocator<unsigned char>::construct<unsigned char>(unsigned char*) (new_allocator.h:136)
5==17812== by 0x500B52: _ZNSt16allocator_traitsI16secure_allocatorIhEE12_S_constructIhJEEENSt9enable_ifIXsr6__and_INS2_18__construct_helperIT_JDpT0_EE4typeEEE5valueEvE4typeERS1_PS6_DpOS7_ (alloc_traits.h:243)
6==17812== by 0x500B22: _ZNSt16allocator_traitsI16secure_allocatorIhEE9constructIhJEEEDTcl12_S_constructfp_fp0_spclsr3stdE7forwardIT0_Efp1_EEERS1_PT_DpOS4_ (alloc_traits.h:344)
7==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)
8==17812== by 0x60BFC2: std::vector<unsigned char, secure_allocator<unsigned char> >::_M_default_initialize(unsigned long) (stl_vector.h:1347)
9==17812== by 0x60BD86: std::vector<unsigned char, secure_allocator<unsigned char> >::vector(unsigned long, secure_allocator<unsigned char> const&) (stl_vector.h:285)
10==17812== by 0x60BB55: ECC_Start() (key.cpp:351)
11==17812== by 0x16AC90: AppInitSanityChecks() (init.cpp:1162)
12==17812== by 0x15BAC9: AppInit(int, char**) (bitcoind.cpp:138)
13==17812== by 0x15B6C8: main (bitcoind.cpp:201)
14==17812== Address 0x3ffdf is not stack'd, malloc'd or (recently) free'd
15…
16Segmentation fault (core dumped)
After this patch (with failing mmap
call):
0$ src/bitcoind
1…
22019-01-06T15:50:18Z Using the 'sse4(1way),sse41(4way)' SHA256 implementation
32019-01-06T15:50:18Z Using RdRand as an additional entropy source
42019-01-06T15:50:18Z
5
6************************
7EXCEPTION: St9bad_alloc
8std::bad_alloc
9bitcoin in AppInit()
10
11
12
13************************
14EXCEPTION: St9bad_alloc
15std::bad_alloc
16bitcoin in AppInit()
17
182019-01-06T15:50:18Z Shutdown: In progress...
192019-01-06T15:50:18Z Shutdown: done
To simulate the failing mmap
call apply the following to master
:
0diff --git a/src/support/lockedpool.cpp b/src/support/lockedpool.cpp
1index 8d577cf52..ce79e569b 100644
2--- a/src/support/lockedpool.cpp
3+++ b/src/support/lockedpool.cpp
4@@ -247,7 +247,8 @@ void *PosixLockedPageAllocator::AllocateLocked(size_t len, bool *lockingSuccess)
5 {
6 void *addr;
7 len = align_up(len, page_size);
8- addr = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
9+ // addr = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
10+ addr = MAP_FAILED;
11 if (addr) {
12 *lockingSuccess = mlock(addr, len) == 0;
13 }