/workdir/bitcoin/src/randomenv.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) 2009-2010 Satoshi Nakamoto |
2 | | // Copyright (c) 2009-2022 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 | | #include <config/bitcoin-config.h> // IWYU pragma: keep |
7 | | |
8 | | #include <randomenv.h> |
9 | | |
10 | | #include <clientversion.h> |
11 | | #include <compat/compat.h> |
12 | | #include <compat/cpuid.h> |
13 | | #include <crypto/sha512.h> |
14 | | #include <span.h> |
15 | | #include <support/cleanse.h> |
16 | | #include <util/time.h> |
17 | | |
18 | | #include <algorithm> |
19 | | #include <atomic> |
20 | | #include <cstdint> |
21 | | #include <cstring> |
22 | | #include <chrono> |
23 | | #include <climits> |
24 | | #include <thread> |
25 | | #include <vector> |
26 | | |
27 | | #include <sys/types.h> // must go before a number of other headers |
28 | | |
29 | | #ifdef WIN32 |
30 | | #include <windows.h> |
31 | | #include <winreg.h> |
32 | | #else |
33 | | #include <fcntl.h> |
34 | | #include <netinet/in.h> |
35 | | #include <sys/resource.h> |
36 | | #include <sys/socket.h> |
37 | | #include <sys/stat.h> |
38 | | #include <sys/time.h> |
39 | | #include <sys/utsname.h> |
40 | | #include <unistd.h> |
41 | | #endif |
42 | | #if HAVE_DECL_GETIFADDRS && HAVE_DECL_FREEIFADDRS |
43 | | #include <ifaddrs.h> |
44 | | #endif |
45 | | #ifdef HAVE_SYSCTL |
46 | | #include <sys/sysctl.h> |
47 | | #ifdef HAVE_VM_VM_PARAM_H |
48 | | #include <vm/vm_param.h> |
49 | | #endif |
50 | | #ifdef HAVE_SYS_RESOURCES_H |
51 | | #include <sys/resources.h> |
52 | | #endif |
53 | | #ifdef HAVE_SYS_VMMETER_H |
54 | | #include <sys/vmmeter.h> |
55 | | #endif |
56 | | #endif |
57 | | #if defined(HAVE_STRONG_GETAUXVAL) |
58 | | #include <sys/auxv.h> |
59 | | #endif |
60 | | |
61 | | #ifndef _MSC_VER |
62 | | extern char** environ; // NOLINT(readability-redundant-declaration): Necessary on some platforms |
63 | | #endif |
64 | | |
65 | | namespace { |
66 | | |
67 | | void RandAddSeedPerfmon(CSHA512& hasher) |
68 | 0 | { |
69 | | #ifdef WIN32 |
70 | | // Seed with the entire set of perfmon data |
71 | | |
72 | | // This can take up to 2 seconds, so only do it every 10 minutes. |
73 | | // Initialize last_perfmon to 0 seconds, we don't skip the first call. |
74 | | static std::atomic<SteadyClock::time_point> last_perfmon{SteadyClock::time_point{0s}}; |
75 | | auto last_time = last_perfmon.load(); |
76 | | auto current_time = SteadyClock::now(); |
77 | | if (current_time < last_time + 10min) return; |
78 | | last_perfmon = current_time; |
79 | | |
80 | | std::vector<unsigned char> vData(250000, 0); |
81 | | long ret = 0; |
82 | | unsigned long nSize = 0; |
83 | | const size_t nMaxSize = 10000000; // Bail out at more than 10MB of performance data |
84 | | while (true) { |
85 | | nSize = vData.size(); |
86 | | ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", nullptr, nullptr, vData.data(), &nSize); |
87 | | if (ret != ERROR_MORE_DATA || vData.size() >= nMaxSize) |
88 | | break; |
89 | | vData.resize(std::min((vData.size() * 3) / 2, nMaxSize)); // Grow size of buffer exponentially |
90 | | } |
91 | | RegCloseKey(HKEY_PERFORMANCE_DATA); |
92 | | if (ret == ERROR_SUCCESS) { |
93 | | hasher.Write(vData.data(), nSize); |
94 | | memory_cleanse(vData.data(), nSize); |
95 | | } else { |
96 | | // Performance data is only a best-effort attempt at improving the |
97 | | // situation when the OS randomness (and other sources) aren't |
98 | | // adequate. As a result, failure to read it is isn't considered critical, |
99 | | // so we don't call RandFailure(). |
100 | | // TODO: Add logging when the logger is made functional before global |
101 | | // constructors have been invoked. |
102 | | } |
103 | | #endif |
104 | 0 | } |
105 | | |
106 | | /** Helper to easily feed data into a CSHA512. |
107 | | * |
108 | | * Note that this does not serialize the passed object (like stream.h's << operators do). |
109 | | * Its raw memory representation is used directly. |
110 | | */ |
111 | | template<typename T> |
112 | 0 | CSHA512& operator<<(CSHA512& hasher, const T& data) { |
113 | 0 | static_assert(!std::is_same<typename std::decay<T>::type, char*>::value, "Calling operator<<(CSHA512, char*) is probably not what you want"); |
114 | 0 | static_assert(!std::is_same<typename std::decay<T>::type, unsigned char*>::value, "Calling operator<<(CSHA512, unsigned char*) is probably not what you want"); |
115 | 0 | static_assert(!std::is_same<typename std::decay<T>::type, const char*>::value, "Calling operator<<(CSHA512, const char*) is probably not what you want"); |
116 | 0 | static_assert(!std::is_same<typename std::decay<T>::type, const unsigned char*>::value, "Calling operator<<(CSHA512, const unsigned char*) is probably not what you want"); |
117 | 0 | hasher.Write((const unsigned char*)&data, sizeof(data)); |
118 | 0 | return hasher; |
119 | 0 | } Unexecuted instantiation: randomenv.cpp:CSHA512& (anonymous namespace)::operator<< <stat>(CSHA512&, stat const&) Unexecuted instantiation: randomenv.cpp:CSHA512& (anonymous namespace)::operator<< <timespec>(CSHA512&, timespec const&) Unexecuted instantiation: randomenv.cpp:CSHA512& (anonymous namespace)::operator<< <timeval>(CSHA512&, timeval const&) Unexecuted instantiation: randomenv.cpp:CSHA512& (anonymous namespace)::operator<< <long>(CSHA512&, long const&) Unexecuted instantiation: randomenv.cpp:CSHA512& (anonymous namespace)::operator<< <rusage>(CSHA512&, rusage const&) Unexecuted instantiation: randomenv.cpp:CSHA512& (anonymous namespace)::operator<< <void**>(CSHA512&, void** const&) Unexecuted instantiation: randomenv.cpp:CSHA512& (anonymous namespace)::operator<< <void*>(CSHA512&, void* const&) Unexecuted instantiation: randomenv.cpp:CSHA512& (anonymous namespace)::operator<< <bool>(CSHA512&, bool const&) Unexecuted instantiation: randomenv.cpp:CSHA512& (anonymous namespace)::operator<< <unsigned long>(CSHA512&, unsigned long const&) Unexecuted instantiation: randomenv.cpp:CSHA512& (anonymous namespace)::operator<< <int>(CSHA512&, int const&) Unexecuted instantiation: randomenv.cpp:CSHA512& (anonymous namespace)::operator<< <CSHA512*>(CSHA512&, CSHA512* const&) Unexecuted instantiation: randomenv.cpp:CSHA512& (anonymous namespace)::operator<< <void (*)(CSHA512&)>(CSHA512&, void (* const&)(CSHA512&)) Unexecuted instantiation: randomenv.cpp:CSHA512& (anonymous namespace)::operator<< <void* (*)(unsigned long) noexcept>(CSHA512&, void* (* const&)(unsigned long) noexcept) Unexecuted instantiation: randomenv.cpp:CSHA512& (anonymous namespace)::operator<< <int*>(CSHA512&, int* const&) Unexecuted instantiation: randomenv.cpp:CSHA512& (anonymous namespace)::operator<< <char***>(CSHA512&, char*** const&) Unexecuted instantiation: randomenv.cpp:CSHA512& (anonymous namespace)::operator<< <unsigned int>(CSHA512&, unsigned int const&) Unexecuted instantiation: randomenv.cpp:CSHA512& (anonymous namespace)::operator<< <std::thread::id>(CSHA512&, std::thread::id const&) |
120 | | |
121 | | #ifndef WIN32 |
122 | | void AddSockaddr(CSHA512& hasher, const struct sockaddr *addr) |
123 | 0 | { |
124 | 0 | if (addr == nullptr) return; Branch (124:9): [True: 0, False: 0]
|
125 | 0 | switch (addr->sa_family) { |
126 | 0 | case AF_INET: Branch (126:5): [True: 0, False: 0]
|
127 | 0 | hasher.Write((const unsigned char*)addr, sizeof(sockaddr_in)); |
128 | 0 | break; |
129 | 0 | case AF_INET6: Branch (129:5): [True: 0, False: 0]
|
130 | 0 | hasher.Write((const unsigned char*)addr, sizeof(sockaddr_in6)); |
131 | 0 | break; |
132 | 0 | default: Branch (132:5): [True: 0, False: 0]
|
133 | 0 | hasher.Write((const unsigned char*)&addr->sa_family, sizeof(addr->sa_family)); |
134 | 0 | } |
135 | 0 | } |
136 | | |
137 | | void AddFile(CSHA512& hasher, const char *path) |
138 | 0 | { |
139 | 0 | struct stat sb = {}; |
140 | 0 | int f = open(path, O_RDONLY); |
141 | 0 | size_t total = 0; |
142 | 0 | if (f != -1) { Branch (142:9): [True: 0, False: 0]
|
143 | 0 | unsigned char fbuf[4096]; |
144 | 0 | int n; |
145 | 0 | hasher.Write((const unsigned char*)&f, sizeof(f)); |
146 | 0 | if (fstat(f, &sb) == 0) hasher << sb; Branch (146:13): [True: 0, False: 0]
|
147 | 0 | do { |
148 | 0 | n = read(f, fbuf, sizeof(fbuf)); |
149 | 0 | if (n > 0) hasher.Write(fbuf, n); Branch (149:17): [True: 0, False: 0]
|
150 | 0 | total += n; |
151 | | /* not bothering with EINTR handling. */ |
152 | 0 | } while (n == sizeof(fbuf) && total < 1048576); // Read only the first 1 Mbyte Branch (152:18): [True: 0, False: 0]
Branch (152:39): [True: 0, False: 0]
|
153 | 0 | close(f); |
154 | 0 | } |
155 | 0 | } |
156 | | |
157 | | void AddPath(CSHA512& hasher, const char *path) |
158 | 0 | { |
159 | 0 | struct stat sb = {}; |
160 | 0 | if (stat(path, &sb) == 0) { Branch (160:9): [True: 0, False: 0]
|
161 | 0 | hasher.Write((const unsigned char*)path, strlen(path) + 1); |
162 | 0 | hasher << sb; |
163 | 0 | } |
164 | 0 | } |
165 | | #endif |
166 | | |
167 | | #ifdef HAVE_SYSCTL |
168 | | template<int... S> |
169 | | void AddSysctl(CSHA512& hasher) |
170 | | { |
171 | | int CTL[sizeof...(S)] = {S...}; |
172 | | unsigned char buffer[65536]; |
173 | | size_t siz = 65536; |
174 | | int ret = sysctl(CTL, sizeof...(S), buffer, &siz, nullptr, 0); |
175 | | if (ret == 0 || (ret == -1 && errno == ENOMEM)) { |
176 | | hasher << sizeof(CTL); |
177 | | hasher.Write((const unsigned char*)CTL, sizeof(CTL)); |
178 | | if (siz > sizeof(buffer)) siz = sizeof(buffer); |
179 | | hasher << siz; |
180 | | hasher.Write(buffer, siz); |
181 | | } |
182 | | } |
183 | | #endif |
184 | | |
185 | | #ifdef HAVE_GETCPUID |
186 | | void inline AddCPUID(CSHA512& hasher, uint32_t leaf, uint32_t subleaf, uint32_t& ax, uint32_t& bx, uint32_t& cx, uint32_t& dx) |
187 | | { |
188 | | GetCPUID(leaf, subleaf, ax, bx, cx, dx); |
189 | | hasher << leaf << subleaf << ax << bx << cx << dx; |
190 | | } |
191 | | |
192 | | void AddAllCPUID(CSHA512& hasher) |
193 | | { |
194 | | uint32_t ax, bx, cx, dx; |
195 | | // Iterate over all standard leaves |
196 | | AddCPUID(hasher, 0, 0, ax, bx, cx, dx); // Returns max leaf in ax |
197 | | uint32_t max = ax; |
198 | | for (uint32_t leaf = 1; leaf <= max && leaf <= 0xFF; ++leaf) { |
199 | | uint32_t maxsub = 0; |
200 | | for (uint32_t subleaf = 0; subleaf <= 0xFF; ++subleaf) { |
201 | | AddCPUID(hasher, leaf, subleaf, ax, bx, cx, dx); |
202 | | // Iterate subleafs for leaf values 4, 7, 11, 13 |
203 | | if (leaf == 4) { |
204 | | if ((ax & 0x1f) == 0) break; |
205 | | } else if (leaf == 7) { |
206 | | if (subleaf == 0) maxsub = ax; |
207 | | if (subleaf == maxsub) break; |
208 | | } else if (leaf == 11) { |
209 | | if ((cx & 0xff00) == 0) break; |
210 | | } else if (leaf == 13) { |
211 | | if (ax == 0 && bx == 0 && cx == 0 && dx == 0) break; |
212 | | } else { |
213 | | // For any other leaf, stop after subleaf 0. |
214 | | break; |
215 | | } |
216 | | } |
217 | | } |
218 | | // Iterate over all extended leaves |
219 | | AddCPUID(hasher, 0x80000000, 0, ax, bx, cx, dx); // Returns max extended leaf in ax |
220 | | uint32_t ext_max = ax; |
221 | | for (uint32_t leaf = 0x80000001; leaf <= ext_max && leaf <= 0x800000FF; ++leaf) { |
222 | | AddCPUID(hasher, leaf, 0, ax, bx, cx, dx); |
223 | | } |
224 | | } |
225 | | #endif |
226 | | } // namespace |
227 | | |
228 | | void RandAddDynamicEnv(CSHA512& hasher) |
229 | 0 | { |
230 | 0 | RandAddSeedPerfmon(hasher); |
231 | | |
232 | | // Various clocks |
233 | | #ifdef WIN32 |
234 | | FILETIME ftime; |
235 | | GetSystemTimeAsFileTime(&ftime); |
236 | | hasher << ftime; |
237 | | #else |
238 | 0 | struct timespec ts = {}; |
239 | 0 | # ifdef CLOCK_MONOTONIC |
240 | 0 | clock_gettime(CLOCK_MONOTONIC, &ts); |
241 | 0 | hasher << ts; |
242 | 0 | # endif |
243 | 0 | # ifdef CLOCK_REALTIME |
244 | 0 | clock_gettime(CLOCK_REALTIME, &ts); |
245 | 0 | hasher << ts; |
246 | 0 | # endif |
247 | 0 | # ifdef CLOCK_BOOTTIME |
248 | 0 | clock_gettime(CLOCK_BOOTTIME, &ts); |
249 | 0 | hasher << ts; |
250 | 0 | # endif |
251 | | // gettimeofday is available on all UNIX systems, but only has microsecond precision. |
252 | 0 | struct timeval tv = {}; |
253 | 0 | gettimeofday(&tv, nullptr); |
254 | 0 | hasher << tv; |
255 | 0 | #endif |
256 | | // Probably redundant, but also use all the standard library clocks: |
257 | 0 | hasher << std::chrono::system_clock::now().time_since_epoch().count(); |
258 | 0 | hasher << std::chrono::steady_clock::now().time_since_epoch().count(); |
259 | 0 | hasher << std::chrono::high_resolution_clock::now().time_since_epoch().count(); |
260 | |
|
261 | 0 | #ifndef WIN32 |
262 | | // Current resource usage. |
263 | 0 | struct rusage usage = {}; |
264 | 0 | if (getrusage(RUSAGE_SELF, &usage) == 0) hasher << usage; Branch (264:9): [True: 0, False: 0]
|
265 | 0 | #endif |
266 | |
|
267 | 0 | #ifdef __linux__ |
268 | 0 | AddFile(hasher, "/proc/diskstats"); |
269 | 0 | AddFile(hasher, "/proc/vmstat"); |
270 | 0 | AddFile(hasher, "/proc/schedstat"); |
271 | 0 | AddFile(hasher, "/proc/zoneinfo"); |
272 | 0 | AddFile(hasher, "/proc/meminfo"); |
273 | 0 | AddFile(hasher, "/proc/softirqs"); |
274 | 0 | AddFile(hasher, "/proc/stat"); |
275 | 0 | AddFile(hasher, "/proc/self/schedstat"); |
276 | 0 | AddFile(hasher, "/proc/self/status"); |
277 | 0 | #endif |
278 | |
|
279 | | #ifdef HAVE_SYSCTL |
280 | | # ifdef CTL_KERN |
281 | | # if defined(KERN_PROC) && defined(KERN_PROC_ALL) |
282 | | AddSysctl<CTL_KERN, KERN_PROC, KERN_PROC_ALL>(hasher); |
283 | | # endif |
284 | | # endif |
285 | | # ifdef CTL_HW |
286 | | # ifdef HW_DISKSTATS |
287 | | AddSysctl<CTL_HW, HW_DISKSTATS>(hasher); |
288 | | # endif |
289 | | # endif |
290 | | # ifdef CTL_VM |
291 | | # ifdef VM_LOADAVG |
292 | | AddSysctl<CTL_VM, VM_LOADAVG>(hasher); |
293 | | # endif |
294 | | # ifdef VM_TOTAL |
295 | | AddSysctl<CTL_VM, VM_TOTAL>(hasher); |
296 | | # endif |
297 | | # ifdef VM_METER |
298 | | AddSysctl<CTL_VM, VM_METER>(hasher); |
299 | | # endif |
300 | | # endif |
301 | | #endif |
302 | | |
303 | | // Stack and heap location |
304 | 0 | void* addr = malloc(4097); |
305 | 0 | hasher << &addr << addr; |
306 | 0 | free(addr); |
307 | 0 | } |
308 | | |
309 | | void RandAddStaticEnv(CSHA512& hasher) |
310 | 0 | { |
311 | | // Some compile-time static properties |
312 | 0 | hasher << (CHAR_MIN < 0) << sizeof(void*) << sizeof(long) << sizeof(int); |
313 | 0 | #if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) |
314 | 0 | hasher << __GNUC__ << __GNUC_MINOR__ << __GNUC_PATCHLEVEL__; |
315 | 0 | #endif |
316 | | #ifdef _MSC_VER |
317 | | hasher << _MSC_VER; |
318 | | #endif |
319 | 0 | hasher << __cplusplus; |
320 | 0 | #ifdef _XOPEN_VERSION |
321 | 0 | hasher << _XOPEN_VERSION; |
322 | 0 | #endif |
323 | 0 | #ifdef __VERSION__ |
324 | 0 | const char* COMPILER_VERSION = __VERSION__; |
325 | 0 | hasher.Write((const unsigned char*)COMPILER_VERSION, strlen(COMPILER_VERSION) + 1); |
326 | 0 | #endif |
327 | | |
328 | | // Bitcoin client version |
329 | 0 | hasher << CLIENT_VERSION; |
330 | |
|
331 | 0 | #if defined(HAVE_STRONG_GETAUXVAL) |
332 | | // Information available through getauxval() |
333 | 0 | # ifdef AT_HWCAP |
334 | 0 | hasher << getauxval(AT_HWCAP); |
335 | 0 | # endif |
336 | 0 | # ifdef AT_HWCAP2 |
337 | 0 | hasher << getauxval(AT_HWCAP2); |
338 | 0 | # endif |
339 | 0 | # ifdef AT_RANDOM |
340 | 0 | const unsigned char* random_aux = (const unsigned char*)getauxval(AT_RANDOM); |
341 | 0 | if (random_aux) hasher.Write(random_aux, 16); Branch (341:9): [True: 0, False: 0]
|
342 | 0 | # endif |
343 | 0 | # ifdef AT_PLATFORM |
344 | 0 | const char* platform_str = (const char*)getauxval(AT_PLATFORM); |
345 | 0 | if (platform_str) hasher.Write((const unsigned char*)platform_str, strlen(platform_str) + 1); Branch (345:9): [True: 0, False: 0]
|
346 | 0 | # endif |
347 | 0 | # ifdef AT_EXECFN |
348 | 0 | const char* exec_str = (const char*)getauxval(AT_EXECFN); |
349 | 0 | if (exec_str) hasher.Write((const unsigned char*)exec_str, strlen(exec_str) + 1); Branch (349:9): [True: 0, False: 0]
|
350 | 0 | # endif |
351 | 0 | #endif // HAVE_STRONG_GETAUXVAL |
352 | |
|
353 | | #ifdef HAVE_GETCPUID |
354 | | AddAllCPUID(hasher); |
355 | | #endif |
356 | | |
357 | | // Memory locations |
358 | 0 | hasher << &hasher << &RandAddStaticEnv << &malloc << &errno << &environ; |
359 | | |
360 | | // Hostname |
361 | | #ifdef WIN32 |
362 | | constexpr DWORD max_size = MAX_COMPUTERNAME_LENGTH + 1; |
363 | | char hname[max_size]; |
364 | | DWORD size = max_size; |
365 | | if (GetComputerNameA(hname, &size) != 0) { |
366 | | hasher.Write(UCharCast(hname), size); |
367 | | } |
368 | | #else |
369 | 0 | char hname[256]; |
370 | 0 | if (gethostname(hname, 256) == 0) { Branch (370:9): [True: 0, False: 0]
|
371 | 0 | hasher.Write((const unsigned char*)hname, strnlen(hname, 256)); |
372 | 0 | } |
373 | 0 | #endif |
374 | |
|
375 | 0 | #if HAVE_DECL_GETIFADDRS && HAVE_DECL_FREEIFADDRS |
376 | | // Network interfaces |
377 | 0 | struct ifaddrs *ifad = nullptr; |
378 | 0 | getifaddrs(&ifad); |
379 | 0 | struct ifaddrs *ifit = ifad; |
380 | 0 | while (ifit != nullptr) { Branch (380:12): [True: 0, False: 0]
|
381 | 0 | hasher.Write((const unsigned char*)&ifit, sizeof(ifit)); |
382 | 0 | hasher.Write((const unsigned char*)ifit->ifa_name, strlen(ifit->ifa_name) + 1); |
383 | 0 | hasher.Write((const unsigned char*)&ifit->ifa_flags, sizeof(ifit->ifa_flags)); |
384 | 0 | AddSockaddr(hasher, ifit->ifa_addr); |
385 | 0 | AddSockaddr(hasher, ifit->ifa_netmask); |
386 | 0 | AddSockaddr(hasher, ifit->ifa_dstaddr); |
387 | 0 | ifit = ifit->ifa_next; |
388 | 0 | } |
389 | 0 | freeifaddrs(ifad); |
390 | 0 | #endif |
391 | |
|
392 | 0 | #ifndef WIN32 |
393 | | // UNIX kernel information |
394 | 0 | struct utsname name; |
395 | 0 | if (uname(&name) != -1) { Branch (395:9): [True: 0, False: 0]
|
396 | 0 | hasher.Write((const unsigned char*)&name.sysname, strlen(name.sysname) + 1); |
397 | 0 | hasher.Write((const unsigned char*)&name.nodename, strlen(name.nodename) + 1); |
398 | 0 | hasher.Write((const unsigned char*)&name.release, strlen(name.release) + 1); |
399 | 0 | hasher.Write((const unsigned char*)&name.version, strlen(name.version) + 1); |
400 | 0 | hasher.Write((const unsigned char*)&name.machine, strlen(name.machine) + 1); |
401 | 0 | } |
402 | | |
403 | | /* Path and filesystem provided data */ |
404 | 0 | AddPath(hasher, "/"); |
405 | 0 | AddPath(hasher, "."); |
406 | 0 | AddPath(hasher, "/tmp"); |
407 | 0 | AddPath(hasher, "/home"); |
408 | 0 | AddPath(hasher, "/proc"); |
409 | 0 | #ifdef __linux__ |
410 | 0 | AddFile(hasher, "/proc/cmdline"); |
411 | 0 | AddFile(hasher, "/proc/cpuinfo"); |
412 | 0 | AddFile(hasher, "/proc/version"); |
413 | 0 | #endif |
414 | 0 | AddFile(hasher, "/etc/passwd"); |
415 | 0 | AddFile(hasher, "/etc/group"); |
416 | 0 | AddFile(hasher, "/etc/hosts"); |
417 | 0 | AddFile(hasher, "/etc/resolv.conf"); |
418 | 0 | AddFile(hasher, "/etc/timezone"); |
419 | 0 | AddFile(hasher, "/etc/localtime"); |
420 | 0 | #endif |
421 | | |
422 | | // For MacOS/BSDs, gather data through sysctl instead of /proc. Not all of these |
423 | | // will exist on every system. |
424 | | #ifdef HAVE_SYSCTL |
425 | | # ifdef CTL_HW |
426 | | # ifdef HW_MACHINE |
427 | | AddSysctl<CTL_HW, HW_MACHINE>(hasher); |
428 | | # endif |
429 | | # ifdef HW_MODEL |
430 | | AddSysctl<CTL_HW, HW_MODEL>(hasher); |
431 | | # endif |
432 | | # ifdef HW_NCPU |
433 | | AddSysctl<CTL_HW, HW_NCPU>(hasher); |
434 | | # endif |
435 | | # ifdef HW_PHYSMEM |
436 | | AddSysctl<CTL_HW, HW_PHYSMEM>(hasher); |
437 | | # endif |
438 | | # ifdef HW_USERMEM |
439 | | AddSysctl<CTL_HW, HW_USERMEM>(hasher); |
440 | | # endif |
441 | | # ifdef HW_MACHINE_ARCH |
442 | | AddSysctl<CTL_HW, HW_MACHINE_ARCH>(hasher); |
443 | | # endif |
444 | | # ifdef HW_REALMEM |
445 | | AddSysctl<CTL_HW, HW_REALMEM>(hasher); |
446 | | # endif |
447 | | # ifdef HW_CPU_FREQ |
448 | | AddSysctl<CTL_HW, HW_CPU_FREQ>(hasher); |
449 | | # endif |
450 | | # ifdef HW_BUS_FREQ |
451 | | AddSysctl<CTL_HW, HW_BUS_FREQ>(hasher); |
452 | | # endif |
453 | | # ifdef HW_CACHELINE |
454 | | AddSysctl<CTL_HW, HW_CACHELINE>(hasher); |
455 | | # endif |
456 | | # endif |
457 | | # ifdef CTL_KERN |
458 | | # ifdef KERN_BOOTFILE |
459 | | AddSysctl<CTL_KERN, KERN_BOOTFILE>(hasher); |
460 | | # endif |
461 | | # ifdef KERN_BOOTTIME |
462 | | AddSysctl<CTL_KERN, KERN_BOOTTIME>(hasher); |
463 | | # endif |
464 | | # ifdef KERN_CLOCKRATE |
465 | | AddSysctl<CTL_KERN, KERN_CLOCKRATE>(hasher); |
466 | | # endif |
467 | | # ifdef KERN_HOSTID |
468 | | AddSysctl<CTL_KERN, KERN_HOSTID>(hasher); |
469 | | # endif |
470 | | # ifdef KERN_HOSTUUID |
471 | | AddSysctl<CTL_KERN, KERN_HOSTUUID>(hasher); |
472 | | # endif |
473 | | # ifdef KERN_HOSTNAME |
474 | | AddSysctl<CTL_KERN, KERN_HOSTNAME>(hasher); |
475 | | # endif |
476 | | # ifdef KERN_OSRELDATE |
477 | | AddSysctl<CTL_KERN, KERN_OSRELDATE>(hasher); |
478 | | # endif |
479 | | # ifdef KERN_OSRELEASE |
480 | | AddSysctl<CTL_KERN, KERN_OSRELEASE>(hasher); |
481 | | # endif |
482 | | # ifdef KERN_OSREV |
483 | | AddSysctl<CTL_KERN, KERN_OSREV>(hasher); |
484 | | # endif |
485 | | # ifdef KERN_OSTYPE |
486 | | AddSysctl<CTL_KERN, KERN_OSTYPE>(hasher); |
487 | | # endif |
488 | | # ifdef KERN_POSIX1 |
489 | | AddSysctl<CTL_KERN, KERN_OSREV>(hasher); |
490 | | # endif |
491 | | # ifdef KERN_VERSION |
492 | | AddSysctl<CTL_KERN, KERN_VERSION>(hasher); |
493 | | # endif |
494 | | # endif |
495 | | #endif |
496 | | |
497 | | // Env variables |
498 | 0 | if (environ) { Branch (498:9): [True: 0, False: 0]
|
499 | 0 | for (size_t i = 0; environ[i]; ++i) { Branch (499:28): [True: 0, False: 0]
|
500 | 0 | hasher.Write((const unsigned char*)environ[i], strlen(environ[i])); |
501 | 0 | } |
502 | 0 | } |
503 | | |
504 | | // Process, thread, user, session, group, ... ids. |
505 | | #ifdef WIN32 |
506 | | hasher << GetCurrentProcessId() << GetCurrentThreadId(); |
507 | | #else |
508 | 0 | hasher << getpid() << getppid() << getsid(0) << getpgid(0) << getuid() << geteuid() << getgid() << getegid(); |
509 | 0 | #endif |
510 | 0 | hasher << std::this_thread::get_id(); |
511 | 0 | } |