lockedpool: When possible, use madvise to avoid including sensitive information in core dumps #15600

pull luke-jr wants to merge 1 commits into bitcoin:master from luke-jr:lockedpool_dontdump changing 1 files +3 −0
  1. luke-jr commented at 1:40 PM on March 14, 2019: member

    If we're mlocking something, it's because it's sensitive information. Therefore, don't include it in core dump files, and unmap it from forked processes.

    The return value is not checked because the madvise calls might fail on older kernels as a rule (unsure).

  2. luke-jr force-pushed on Mar 14, 2019
  3. MarcoFalke added the label Utils/log/libs on Mar 14, 2019
  4. luke-jr commented at 4:46 AM on May 5, 2019: member

    No apparent reviewer interest, and it seems to break -daemon with no obvious solution.

  5. luke-jr closed this on May 5, 2019

  6. lockedpool: When possible, use madvise to avoid including sensitive information in core dumps d831831822
  7. luke-jr reopened this on Mar 4, 2020

  8. luke-jr force-pushed on Mar 4, 2020
  9. luke-jr commented at 8:16 PM on March 4, 2020: member

    Reopened due to renewed interest, and removed the DONTFORK part that was broken

  10. luke-jr renamed this:
    lockedpool: When possible, use madvise to avoid including sensitive information in core dumps or forked process memory spaces
    lockedpool: When possible, use madvise to avoid including sensitive information in core dumps
    on Mar 4, 2020
  11. MarcoFalke added the label Needs gitian build on Mar 4, 2020
  12. practicalswift commented at 11:07 PM on March 4, 2020: contributor

    Concept ACK

  13. DrahtBot commented at 2:05 PM on March 5, 2020: member

    <!--a722867cd34abeea1fadc8d60700f111-->

    Gitian builds

    File commit a71c34742c24245a0d642e68f9e61f46cc7573fb<br>(master) commit 2d320372aa2aba3512512d30e2e6b5c4483cd5c0<br>(master and this pull)
    bitcoin-0.19.99-aarch64-linux-gnu-debug.tar.gz 263dd4df65588db4... 87a836ebe2640c24...
    bitcoin-0.19.99-aarch64-linux-gnu.tar.gz 3f779204013ffde0... b25121535f4b3e4e...
    bitcoin-0.19.99-arm-linux-gnueabihf-debug.tar.gz f6cc7d17fdf2b4f0... 9bf22b2ea053fe9f...
    bitcoin-0.19.99-arm-linux-gnueabihf.tar.gz b08643b04f8d69c0... 0811dc229d30b135...
    bitcoin-0.19.99-osx-unsigned.dmg 82112ea8d8b8dfb7... 3f15eeb9c8995188...
    bitcoin-0.19.99-osx64.tar.gz e7408d167771af4e... 452145dfff313f76...
    bitcoin-0.19.99-riscv64-linux-gnu-debug.tar.gz af924ded182d7648... 98cdc0cf6d4dcb61...
    bitcoin-0.19.99-riscv64-linux-gnu.tar.gz d6a4f981ad9fa31f... f71881fa68838b30...
    bitcoin-0.19.99-win64-debug.zip b0796bf49b421fa0... 8b6b299372408b9b...
    bitcoin-0.19.99-win64-setup-unsigned.exe 3a473d863012b1fe... 340157f6bb540f2b...
    bitcoin-0.19.99-win64.zip f658d68b14d640c3... 5a0e6165b71cc67f...
    bitcoin-0.19.99-x86_64-linux-gnu-debug.tar.gz dbab3fa3cc95a255... 554ef07154623a5d...
    bitcoin-0.19.99-x86_64-linux-gnu.tar.gz fa419172b1f67f66... de1b54355262591a...
    bitcoin-0.19.99.tar.gz 38d9e79747ecfb3b... 558c333681cb5459...
    bitcoin-core-linux-0.20-res.yml 0bb8e45015337601... 4e8a46fb1c0d3f43...
    bitcoin-core-osx-0.20-res.yml 587b85f6de99b01c... 14718c9a1dc15f0c...
    bitcoin-core-win-0.20-res.yml 4cb36ab35ba216ed... 903f3ad4472eea5e...
    linux-build.log 17b4963debeaff4c... cb1bc7e73f69d362...
    osx-build.log de1d4010171bee32... 30eed6610c634837...
    win-build.log a7428da768940c64... 6a23faa140bab3c4...
    bitcoin-core-linux-0.20-res.yml.diff 88743d508c492414...
    bitcoin-core-osx-0.20-res.yml.diff a6e23042337e3f57...
    bitcoin-core-win-0.20-res.yml.diff c308f24f99ffc760...
    linux-build.log.diff 50481d877cfcb295...
    osx-build.log.diff 1125ea1d898b8949...
    win-build.log.diff 7e982717b61ae018...
  14. DrahtBot removed the label Needs gitian build on Mar 5, 2020
  15. laanwj added this to the milestone 0.20.0 on Mar 5, 2020
  16. laanwj commented at 7:16 PM on March 5, 2020: member

    Concept ACK

  17. practicalswift commented at 8:12 PM on March 5, 2020: contributor

    Code review ACK d831831822885717e9841f1ff67c19add566fa45 -- patch looks correct

    Please note that I have not verified that the desired end result is achieved.

    That should be done before merge :)

  18. in src/support/lockedpool.cpp:255 in d831831822
     249 | @@ -250,6 +250,9 @@ void *PosixLockedPageAllocator::AllocateLocked(size_t len, bool *lockingSuccess)
     250 |      addr = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
     251 |      if (addr) {
     252 |          *lockingSuccess = mlock(addr, len) == 0;
     253 | +#ifdef MADV_DONTDUMP
     254 | +        madvise(addr, len, MADV_DONTDUMP);
     255 | +#endif
    


    vasild commented at 3:08 PM on March 25, 2020:

    FreeBSD has the same functionality under a different name MADV_NOCORE:

    #if defined(MADV_DONTDUMP) // Linux
            madvise(addr, len, MADV_DONTDUMP);
    #elif defined(MADV_NOCORE) // FreeBSD
            madvise(addr, len, MADV_NOCORE);
    #endif
    
  19. in src/support/lockedpool.cpp:254 in d831831822
     249 | @@ -250,6 +250,9 @@ void *PosixLockedPageAllocator::AllocateLocked(size_t len, bool *lockingSuccess)
     250 |      addr = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
     251 |      if (addr) {
     252 |          *lockingSuccess = mlock(addr, len) == 0;
     253 | +#ifdef MADV_DONTDUMP
     254 | +        madvise(addr, len, MADV_DONTDUMP);
    


    jonatack commented at 3:30 PM on March 25, 2020:

    should the return value be used to signal success/failure to the user?

  20. jonatack commented at 3:31 PM on March 25, 2020: member

    ACK d831831822885717e9841f1ff67c19add566fa45

    Code review and rebased on master/built/tests/ran bitcoind. The concept appears correct according to man core

      There are various circumstances in which a core dump file is not produced:
    
      ... / ...
    
      In addition, a core dump may exclude part of the address space of the
      process if the madvise(2) MADV_DONTDUMP flag was employed.
    

    and implementation correct as per man madvise

      MADV_DONTDUMP (since Linux 3.4)
        Exclude from a core dump those pages in the range specified by
        addr and length.  This is useful in applications that have
        large areas of memory that are known not to be useful in a
        core dump.  The effect of MADV_DONTDUMP takes precedence over
        the bit mask that is set via the /proc/[pid]/coredump_filter
        file (see core(5)).
    
      ... / ...
    
      RETURN VALUE
        On success, madvise() returns zero. 
        On error, it returns -1 and errno is set appropriately.
    

    EDIT: tested as described in #15600 (comment) below

  21. laanwj commented at 3:35 PM on March 25, 2020: member

    I checked the manual page for madvise and I think the usage is correct.

    Not checking the return value is okay in this case because if it fails, there's no problem. The function is not marked as "warn_unused_result" so this won't result in compiler warnings either.

    /usr/include/x86_64-linux-gnu/sys/mman.h:

    extern int madvise (void *__addr, size_t __len, int __advice) __THROW;
    

    ACK d831831822885717e9841f1ff67c19add566fa45

  22. jonatack commented at 3:38 PM on March 25, 2020: member

    Agree.

    /usr/include/x86_64-linux-gnu/sys/mman.h:

    #ifdef __USE_MISC
    /* Advise the system about particular usage patterns the program follows
       for the region starting at ADDR and extending LEN bytes.  */
    extern int madvise (void *__addr, size_t __len, int __advice) __THROW;
    #endif
    
  23. vasild approved
  24. vasild commented at 4:12 PM on March 25, 2020: member

    ACK d831831822885717e9841f1ff67c19add566fa45

    But notice support for FreeBSD is easy to hook, so I would suggest to add it.

    I tested this on FreeBSD by writing some specific string to the allocated memory and calling abort();. Then ./src/bitcoind crashes immediately. It works as expected: without madvise() the string is present in the core file. With madvise() the string is absent.

    I also verified that the effects of the new call need not be explicitly undone when freeing up the memory. For example we undo the mlock() call in FreeLocked() by doing munlock(). I was worried that if we don't do madvise(MADV_DODUMP) when we free the page to the OS, then maybe later, if we allocate it again then MADV_DONTDUMP would be in effect without us asking for it. But this is not the case.

    For reference here are the changes I did to test it:

    <details> <summary>basic test</summary>

    --- i/src/support/lockedpool.cpp
    +++ w/src/support/lockedpool.cpp
    @@ -250,15 +250,23 @@ void *PosixLockedPageAllocator::AllocateLocked(size_t len, bool *lockingSuccess)
         addr = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
         if (addr == MAP_FAILED) {
             return nullptr;
         }
         if (addr) {
             *lockingSuccess = mlock(addr, len) == 0;
    -#ifdef MADV_DONTDUMP
    +#if 1
    +#if defined(MADV_DONTDUMP) // Linux
             madvise(addr, len, MADV_DONTDUMP);
    +#elif defined(MADV_NOCORE) // FreeBSD
    +        madvise(addr, len, MADV_NOCORE);
     #endif
    +#endif
    +        memset(addr, 'A', 16);
    +        memset((char*)addr + 16, 'B', 16);
    +        memset((char*)addr + 32, 'C', 16);
    +        abort();
         }
         return addr;
     }
     void PosixLockedPageAllocator::FreeLocked(void* addr, size_t len)
     {
         len = align_up(len, page_size);
    

    </details>

    <details> <summary>test that undo is not necessary</summary>

    --- i/src/support/lockedpool.cpp
    +++ w/src/support/lockedpool.cpp
    @@ -250,15 +250,36 @@ void *PosixLockedPageAllocator::AllocateLocked(size_t len, bool *lockingSuccess)
         addr = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
         if (addr == MAP_FAILED) {
             return nullptr;
         }
         if (addr) {
             *lockingSuccess = mlock(addr, len) == 0;
    -#ifdef MADV_DONTDUMP
    +#if 1
    +#if defined(MADV_DONTDUMP) // Linux
             madvise(addr, len, MADV_DONTDUMP);
    +#elif defined(MADV_NOCORE) // FreeBSD
    +        madvise(addr, len, MADV_NOCORE);
     #endif
    +#endif
    +        FreeLocked(addr, len);
    +
    +        // Allocate again to confirm that the effect of MADV_DONTDUMP/MADV_NOCORE
    +        // has vanished. The string must be in the core file.
    +        void* new_addr = mmap(addr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
    +
    +        if (new_addr == MAP_FAILED) {
    +            perror("mmap");
    +            exit(1);
    +        }
    +
    +        assert(new_addr == addr);
    +
    +        memset(addr, 'A', 16);
    +        memset((char*)addr + 16, 'B', 16);
    +        memset((char*)addr + 32, 'C', 16);
    +        abort();
         }
         return addr;
     }
     void PosixLockedPageAllocator::FreeLocked(void* addr, size_t len)
     {
         len = align_up(len, page_size);
    

    </details>

  25. jonatack commented at 11:33 PM on March 25, 2020: member

    @vasild thanks for the interesting tests! Good idea. Here are similar steps I took to reproduce them:

    <details> <summary>test that without madvise string is present in core dump</summary> <p>

    (pr/15600)$ uname -a
    Linux 4.19.0-5-amd64 [#1](/bitcoin-bitcoin/1/) SMP Debian 4.19.37-5+deb10u2 (2019-08-08) x86_64 GNU/Linux
    (pr/15600)$ ulimit -c unlimited && git diff && make
    
    --- a/src/support/lockedpool.cpp
    +++ b/src/support/lockedpool.cpp
    @@ -23,6 +23,7 @@
     #include <algorithm>
    +#include <cstring>
     #ifdef ARENA_DEBUG
    @@ -253,9 +254,14 @@ void *PosixLockedPageAllocator::AllocateLocked(size_t len, bool *lockingSuccess)
         if (addr) {
             *lockingSuccess = mlock(addr, len) == 0;
    -#ifdef MADV_DONTDUMP
    -        madvise(addr, len, MADV_DONTDUMP);
    -#endif
    +        memset(addr, 'A', 16);
    +        memset((char*)addr + 16, 'B', 16);
    +        memset((char*)addr + 32, 'C', 16);
    +        printf("\n");
    +        printf("Process is aborting\n");
    +        abort();
    +        printf("Control not reaching here\n");
    +        return 0;
         }
         return addr;
     }
    
    (pr/15600)$ bitcoind
    
    Process is aborting
    Aborted (core dumped)
    (pr/15600)$ grep AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCC core
    Binary file core matches
    (pr/15600)$
    

    </p> </details>

    <details> <summary>test that with madvise string is absent from core dump</summary> <p>

    (pr/15600)$ uname -a
    Linux 4.19.0-5-amd64 [#1](/bitcoin-bitcoin/1/) SMP Debian 4.19.37-5+deb10u2 (2019-08-08) x86_64 GNU/Linux
    (pr/15600)$ ulimit -c unlimited && git diff && make
    
    --- a/src/support/lockedpool.cpp
    +++ b/src/support/lockedpool.cpp
    @@ -23,6 +23,7 @@
     #include <algorithm>
    +#include <cstring>
     #ifdef ARENA_DEBUG
     #include <iomanip>
     #include <iostream>
    @@ -253,9 +254,21 @@ void *PosixLockedPageAllocator::AllocateLocked(size_t len, bool *lockingSuccess)
         if (addr) {
             *lockingSuccess = mlock(addr, len) == 0;
    -#ifdef MADV_DONTDUMP
    +#if defined(MADV_DONTDUMP) // Linux
             madvise(addr, len, MADV_DONTDUMP);
    +#elif defined(MADV_NOCORE) // FreeBSD
    +        madvise(addr, len, MADV_NOCORE);
     #endif
    +        memset(addr, 'A', 16);
    +        memset((char*)addr + 16, 'B', 16);
    +        memset((char*)addr + 32, 'C', 16);
    +        printf("\n");
    +        printf("Process is aborting\n");
    +        abort();
    +        printf("Control not reaching here\n");
    +        return 0;
         }
         return addr;
     }
    
    (pr/15600)$ bitcoind
    
    Process is aborting
    Aborted (core dumped)
    (pr/15600)$ grep AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCC core
    (pr/15600)$
    

    </p> </details>

  26. laanwj commented at 3:55 PM on March 26, 2020: member

    I'm going ahead to merge this. Let's add FreeBSD support in a new PR.

  27. laanwj merged this on Mar 26, 2020
  28. laanwj closed this on Mar 26, 2020

  29. vasild referenced this in commit f85203097f on Mar 26, 2020
  30. sidhujag referenced this in commit 36c5db22d2 on Mar 28, 2020
  31. laanwj referenced this in commit b549cb1bd2 on May 4, 2020
  32. sidhujag referenced this in commit 5df88526d3 on May 4, 2020
  33. rvagg referenced this in commit 0d98fbcd0c on May 5, 2020
  34. str4d referenced this in commit 71b79b85d1 on Jul 31, 2020
  35. zkbot referenced this in commit 5ef5d8d268 on Jul 31, 2020
  36. zkbot referenced this in commit 7d94064616 on Sep 29, 2020
  37. van-orton referenced this in commit b7395c0a9d on Oct 30, 2020
  38. Fabcien referenced this in commit ebb8bddb6c on Jan 12, 2021
  39. Fabcien referenced this in commit 72559fd656 on Jan 12, 2021
  40. lordmahan referenced this in commit 6a6a99b1a8 on Apr 27, 2021
  41. PastaPastaPasta referenced this in commit 880efd0a1e on Jun 27, 2021
  42. PastaPastaPasta referenced this in commit 615c39bd6d on Jun 27, 2021
  43. PastaPastaPasta referenced this in commit e4a850aac9 on Jun 28, 2021
  44. PastaPastaPasta referenced this in commit 148371619e on Jun 28, 2021
  45. PastaPastaPasta referenced this in commit d2cbd077ee on Jun 29, 2021
  46. PastaPastaPasta referenced this in commit 77b5e61dfd on Jun 29, 2021
  47. PastaPastaPasta referenced this in commit 735ffa2dd5 on Jul 1, 2021
  48. PastaPastaPasta referenced this in commit a7457f9828 on Jul 1, 2021
  49. PastaPastaPasta referenced this in commit 56a8e0b30d on Jul 1, 2021
  50. PastaPastaPasta referenced this in commit 425a7c88fa on Jul 1, 2021
  51. PastaPastaPasta referenced this in commit 8e8048e1c3 on Jul 14, 2021
  52. PastaPastaPasta referenced this in commit aaaffab9d0 on Jul 14, 2021
  53. PastaPastaPasta referenced this in commit b566c464ed on Jul 15, 2021
  54. patricklodder referenced this in commit 09f86e7494 on Nov 5, 2021
  55. random-zebra referenced this in commit 353346c454 on Dec 27, 2021
  56. furszy referenced this in commit 771c84b2d3 on Jan 3, 2022
  57. DrahtBot locked this on Feb 15, 2022

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-04-13 15:15 UTC

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