Branch data Line data Source code
1 : : // Copyright (c) 2009-2010 Satoshi Nakamoto
2 : : // Copyright (c) 2009-2021 The Bitcoin Core developers
3 : : // Distributed under the MIT software license, see the accompanying
4 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 : :
6 : : #ifndef BITCOIN_SUPPORT_ALLOCATORS_SECURE_H
7 : : #define BITCOIN_SUPPORT_ALLOCATORS_SECURE_H
8 : :
9 : : #include <support/lockedpool.h>
10 : : #include <support/cleanse.h>
11 : :
12 : : #include <memory>
13 : : #include <string>
14 : :
15 : : //
16 : : // Allocator that locks its contents from being paged
17 : : // out of memory and clears its contents before deletion.
18 : : //
19 : : template <typename T>
20 : : struct secure_allocator {
21 : : using value_type = T;
22 : :
23 : : secure_allocator() = default;
24 : : template <typename U>
25 : : secure_allocator(const secure_allocator<U>&) noexcept {}
26 : :
27 : 79427 : T* allocate(std::size_t n)
28 : : {
29 : 79427 : T* allocation = static_cast<T*>(LockedPoolManager::Instance().alloc(sizeof(T) * n));
30 [ - + ]: 79427 : if (!allocation) {
31 : 0 : throw std::bad_alloc();
32 : : }
33 : 79427 : return allocation;
34 : : }
35 : :
36 : 79427 : void deallocate(T* p, std::size_t n)
37 : : {
38 [ + - ]: 79427 : if (p != nullptr) {
39 : 79427 : memory_cleanse(p, sizeof(T) * n);
40 : : }
41 : 79427 : LockedPoolManager::Instance().free(p);
42 : 79427 : }
43 : :
44 : : template <typename U>
45 : : friend bool operator==(const secure_allocator&, const secure_allocator<U>&) noexcept
46 : : {
47 : : return true;
48 : : }
49 : : template <typename U>
50 : : friend bool operator!=(const secure_allocator&, const secure_allocator<U>&) noexcept
51 : : {
52 : : return false;
53 : : }
54 : : };
55 : :
56 : : // This is exactly like std::string, but with a custom allocator.
57 : : // TODO: Consider finding a way to make incoming RPC request.params[i] mlock()ed as well
58 : : typedef std::basic_string<char, std::char_traits<char>, secure_allocator<char> > SecureString;
59 : :
60 : : template<typename T>
61 : : struct SecureUniqueDeleter {
62 : 40792 : void operator()(T* t) noexcept {
63 : 40792 : secure_allocator<T>().deallocate(t, 1);
64 : 40792 : }
65 : : };
66 : :
67 : : template<typename T>
68 : : using secure_unique_ptr = std::unique_ptr<T, SecureUniqueDeleter<T>>;
69 : :
70 : : template<typename T, typename... Args>
71 : 40792 : secure_unique_ptr<T> make_secure_unique(Args&&... as)
72 : : {
73 : 40792 : T* p = secure_allocator<T>().allocate(1);
74 : :
75 : : // initialize in place, and return as secure_unique_ptr
76 : : try {
77 : 40792 : return secure_unique_ptr<T>(new (p) T(std::forward(as)...));
78 : : } catch (...) {
79 : : secure_allocator<T>().deallocate(p, 1);
80 : : throw;
81 : : }
82 : : }
83 : :
84 : : #endif // BITCOIN_SUPPORT_ALLOCATORS_SECURE_H
|