1 | /* |
2 | Copyright (C) 1999-2007 The Botan Project. All rights reserved. |
3 | |
4 | Redistribution and use in source and binary forms, for any use, with or without |
5 | modification, is permitted provided that the following conditions are met: |
6 | |
7 | 1. Redistributions of source code must retain the above copyright notice, this |
8 | list of conditions, and the following disclaimer. |
9 | |
10 | 2. Redistributions in binary form must reproduce the above copyright notice, |
11 | this list of conditions, and the following disclaimer in the documentation |
12 | and/or other materials provided with the distribution. |
13 | |
14 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) "AS IS" AND ANY EXPRESS OR IMPLIED |
15 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
16 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. |
17 | |
18 | IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE LIABLE FOR ANY DIRECT, |
19 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
20 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
21 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
22 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
23 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
24 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
25 | */ |
26 | // LICENSEHEADER_END |
27 | namespace QCA { // WRAPNS_LINE |
28 | /************************************************* |
29 | * Memory Mapping Allocator Source File * |
30 | * (C) 1999-2007 The Botan Project * |
31 | *************************************************/ |
32 | |
33 | } // WRAPNS_LINE |
34 | #include <botan/mmap_mem.h> |
35 | namespace QCA { // WRAPNS_LINE |
36 | } // WRAPNS_LINE |
37 | #include <cstring> |
38 | namespace QCA { // WRAPNS_LINE |
39 | |
40 | #ifndef _XOPEN_SOURCE |
41 | #define _XOPEN_SOURCE 500 |
42 | #endif |
43 | |
44 | #ifndef _XOPEN_SOURCE_EXTENDED |
45 | #define _XOPEN_SOURCE_EXTENDED 1 |
46 | #endif |
47 | |
48 | } // WRAPNS_LINE |
49 | #include <sys/types.h> |
50 | namespace QCA { // WRAPNS_LINE |
51 | } // WRAPNS_LINE |
52 | #include <sys/mman.h> |
53 | namespace QCA { // WRAPNS_LINE |
54 | } // WRAPNS_LINE |
55 | #include <sys/stat.h> |
56 | namespace QCA { // WRAPNS_LINE |
57 | } // WRAPNS_LINE |
58 | #include <unistd.h> |
59 | namespace QCA { // WRAPNS_LINE |
60 | } // WRAPNS_LINE |
61 | #include <cstdlib> |
62 | namespace QCA { // WRAPNS_LINE |
63 | } // WRAPNS_LINE |
64 | #include <fcntl.h> |
65 | namespace QCA { // WRAPNS_LINE |
66 | |
67 | #ifndef MAP_FAILED |
68 | #define MAP_FAILED -1 |
69 | #endif |
70 | |
71 | namespace Botan { |
72 | |
73 | namespace { |
74 | |
75 | /************************************************* |
76 | * MemoryMapping_Allocator Exception * |
77 | *************************************************/ |
78 | class MemoryMapping_Failed : public Exception |
79 | { |
80 | public: |
81 | MemoryMapping_Failed(const std::string &msg) |
82 | : Exception("MemoryMapping_Allocator: " + msg) |
83 | { |
84 | } |
85 | }; |
86 | |
87 | } |
88 | |
89 | /************************************************* |
90 | * Memory Map a File into Memory * |
91 | *************************************************/ |
92 | void *MemoryMapping_Allocator::alloc_block(u32bit n) |
93 | { |
94 | class TemporaryFile |
95 | { |
96 | public: |
97 | int get_fd() const |
98 | { |
99 | return fd; |
100 | } |
101 | const std::string path() const |
102 | { |
103 | return filepath; |
104 | } |
105 | |
106 | TemporaryFile(const std::string &base) |
107 | { |
108 | const std::string path = base + "XXXXXX" ; |
109 | |
110 | filepath = new char[path.length() + 1]; |
111 | std::strcpy(dest: filepath, src: path.c_str()); |
112 | |
113 | mode_t old_umask = umask(mask: 077); |
114 | fd = mkstemp(template: filepath); |
115 | umask(mask: old_umask); |
116 | } |
117 | |
118 | ~TemporaryFile() QCA_NOEXCEPT(false) |
119 | { |
120 | delete[] filepath; |
121 | if (fd != -1 && close(fd: fd) == -1) |
122 | throw MemoryMapping_Failed("Could not close file" ); |
123 | } |
124 | |
125 | TemporaryFile(const TemporaryFile &) = delete; |
126 | TemporaryFile &operator=(const TemporaryFile &) = delete; |
127 | |
128 | private: |
129 | int fd; |
130 | char *filepath; |
131 | }; |
132 | |
133 | TemporaryFile file("/tmp/botan_" ); |
134 | |
135 | if (file.get_fd() == -1) |
136 | throw MemoryMapping_Failed("Could not create file" ); |
137 | |
138 | if (unlink(name: file.path().c_str())) |
139 | throw MemoryMapping_Failed("Could not unlink file " + file.path()); |
140 | |
141 | lseek(fd: file.get_fd(), offset: n - 1, SEEK_SET); |
142 | if (write(fd: file.get_fd(), buf: "\0" , n: 1) != 1) |
143 | throw MemoryMapping_Failed("Could not write to file" ); |
144 | |
145 | void *ptr = mmap(addr: nullptr, len: n, PROT_READ | PROT_WRITE, MAP_SHARED, fd: file.get_fd(), offset: 0); |
146 | |
147 | if (ptr == (void *)MAP_FAILED) |
148 | throw MemoryMapping_Failed("Could not map file" ); |
149 | |
150 | return ptr; |
151 | } |
152 | |
153 | /************************************************* |
154 | * Remove a Memory Mapping * |
155 | *************************************************/ |
156 | void MemoryMapping_Allocator::dealloc_block(void *ptr, u32bit n) |
157 | { |
158 | if (ptr == nullptr) |
159 | return; |
160 | #ifdef MLOCK_NOT_VOID_PTR |
161 | #define MLOCK_TYPE_CAST (char *) |
162 | #else |
163 | #define MLOCK_TYPE_CAST |
164 | #endif |
165 | |
166 | const u32bit OVERWRITE_PASSES = 12; |
167 | const byte PATTERNS[] = { |
168 | 0x00, 0xFF, 0xAA, 0x55, 0x73, 0x8C, 0x5F, 0xA0, 0x6E, 0x91, 0x30, 0xCF, 0xD3, 0x2C, 0xAC, 0x53}; |
169 | |
170 | for (u32bit j = 0; j != OVERWRITE_PASSES; j++) { |
171 | std::memset(s: ptr, c: PATTERNS[j % sizeof(PATTERNS)], n: n); |
172 | if (msync(MLOCK_TYPE_CAST addr: ptr, len: n, MS_SYNC)) |
173 | throw MemoryMapping_Failed("Sync operation failed" ); |
174 | } |
175 | std::memset(s: ptr, c: 0, n: n); |
176 | if (msync(MLOCK_TYPE_CAST addr: ptr, len: n, MS_SYNC)) |
177 | throw MemoryMapping_Failed("Sync operation failed" ); |
178 | |
179 | if (munmap(MLOCK_TYPE_CAST addr: ptr, len: n)) |
180 | throw MemoryMapping_Failed("Could not unmap file" ); |
181 | } |
182 | |
183 | } |
184 | } // WRAPNS_LINE |
185 | |