Branch data Line data Source code
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 <bitcoin-build-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 : : #else
32 : : #include <fcntl.h>
33 : : #include <netinet/in.h>
34 : : #include <sys/resource.h>
35 : : #include <sys/socket.h>
36 : : #include <sys/stat.h>
37 : : #include <sys/time.h>
38 : : #include <sys/utsname.h>
39 : : #include <unistd.h>
40 : : #endif
41 : : #ifdef HAVE_IFADDRS
42 : : #include <ifaddrs.h>
43 : : #endif
44 : : #ifdef HAVE_SYSCTL
45 : : #include <sys/sysctl.h>
46 : : #if __has_include(<vm/vm_param.h>)
47 : : #include <vm/vm_param.h>
48 : : #endif
49 : : #if __has_include(<sys/resources.h>)
50 : : #include <sys/resources.h>
51 : : #endif
52 : : #if __has_include(<sys/vmmeter.h>)
53 : : #include <sys/vmmeter.h>
54 : : #endif
55 : : #endif
56 : : #if defined(HAVE_STRONG_GETAUXVAL)
57 : : #include <sys/auxv.h>
58 : : #endif
59 : :
60 : : #if defined(__APPLE__) || \
61 : : defined(__FreeBSD__) || \
62 : : defined(__NetBSD__) || \
63 : : defined(__OpenBSD__) || \
64 : : defined(__illumos__)
65 : : extern char** environ; // Necessary on the above platforms
66 : : #endif
67 : :
68 : : namespace {
69 : :
70 : : /** Helper to easily feed data into a CSHA512.
71 : : *
72 : : * Note that this does not serialize the passed object (like stream.h's << operators do).
73 : : * Its raw memory representation is used directly.
74 : : */
75 : : template<typename T>
76 : 507215 : CSHA512& operator<<(CSHA512& hasher, const T& data) {
77 : : static_assert(!std::is_same_v<std::decay_t<T>, char*>, "Calling operator<<(CSHA512, char*) is probably not what you want");
78 : : static_assert(!std::is_same_v<std::decay_t<T>, unsigned char*>, "Calling operator<<(CSHA512, unsigned char*) is probably not what you want");
79 : : static_assert(!std::is_same_v<std::decay_t<T>, const char*>, "Calling operator<<(CSHA512, const char*) is probably not what you want");
80 : : static_assert(!std::is_same_v<std::decay_t<T>, const unsigned char*>, "Calling operator<<(CSHA512, const unsigned char*) is probably not what you want");
81 : 507215 : hasher.Write((const unsigned char*)&data, sizeof(data));
82 : 507215 : return hasher;
83 : : }
84 : :
85 : : #ifndef WIN32
86 : 16044 : void AddSockaddr(CSHA512& hasher, const struct sockaddr *addr)
87 : : {
88 [ + + ]: 16044 : if (addr == nullptr) return;
89 [ + - + ]: 13370 : switch (addr->sa_family) {
90 : 8022 : case AF_INET:
91 : 8022 : hasher.Write((const unsigned char*)addr, sizeof(sockaddr_in));
92 : 8022 : break;
93 : 0 : case AF_INET6:
94 : 0 : hasher.Write((const unsigned char*)addr, sizeof(sockaddr_in6));
95 : 0 : break;
96 : 5348 : default:
97 : 5348 : hasher.Write((const unsigned char*)&addr->sa_family, sizeof(addr->sa_family));
98 : : }
99 : : }
100 : :
101 : 26199 : void AddFile(CSHA512& hasher, const char *path)
102 : : {
103 : 26199 : struct stat sb = {};
104 : 26199 : int f = open(path, O_RDONLY);
105 : 26199 : size_t total = 0;
106 [ + + ]: 26199 : if (f != -1) {
107 : 24862 : unsigned char fbuf[4096];
108 : 24862 : int n;
109 : 24862 : hasher.Write((const unsigned char*)&f, sizeof(f));
110 [ + - ]: 24862 : if (fstat(f, &sb) == 0) hasher << sb;
111 : 28010 : do {
112 : 28010 : n = read(f, fbuf, sizeof(fbuf));
113 [ + - ]: 28010 : if (n > 0) hasher.Write(fbuf, n);
114 : 28010 : total += n;
115 : : /* not bothering with EINTR handling. */
116 [ + + ]: 28010 : } while (n == sizeof(fbuf) && total < 1048576); // Read only the first 1 Mbyte
117 : 24862 : close(f);
118 : : }
119 : 26199 : }
120 : :
121 : 6685 : void AddPath(CSHA512& hasher, const char *path)
122 : : {
123 : 6685 : struct stat sb = {};
124 [ + - ]: 6685 : if (stat(path, &sb) == 0) {
125 : 6685 : hasher.Write((const unsigned char*)path, strlen(path) + 1);
126 : 6685 : hasher << sb;
127 : : }
128 : 6685 : }
129 : : #endif
130 : :
131 : : #ifdef HAVE_SYSCTL
132 : : template<int... S>
133 : : void AddSysctl(CSHA512& hasher)
134 : : {
135 : : int CTL[sizeof...(S)] = {S...};
136 : : unsigned char buffer[65536];
137 : : size_t siz = 65536;
138 : : int ret = sysctl(CTL, sizeof...(S), buffer, &siz, nullptr, 0);
139 : : if (ret == 0 || (ret == -1 && errno == ENOMEM)) {
140 : : hasher << sizeof(CTL);
141 : : hasher.Write((const unsigned char*)CTL, sizeof(CTL));
142 : : if (siz > sizeof(buffer)) siz = sizeof(buffer);
143 : : hasher << siz;
144 : : hasher.Write(buffer, siz);
145 : : }
146 : : }
147 : : #endif
148 : :
149 : : #ifdef HAVE_GETCPUID
150 : 70861 : void inline AddCPUID(CSHA512& hasher, uint32_t leaf, uint32_t subleaf, uint32_t& ax, uint32_t& bx, uint32_t& cx, uint32_t& dx)
151 : : {
152 : 70861 : GetCPUID(leaf, subleaf, ax, bx, cx, dx);
153 : 70861 : hasher << leaf << subleaf << ax << bx << cx << dx;
154 : 70861 : }
155 : :
156 : 1337 : void AddAllCPUID(CSHA512& hasher)
157 : : {
158 : 1337 : uint32_t ax, bx, cx, dx;
159 : : // Iterate over all standard leaves
160 : 1337 : AddCPUID(hasher, 0, 0, ax, bx, cx, dx); // Returns max leaf in ax
161 : 1337 : uint32_t max = ax;
162 [ + + ]: 18718 : for (uint32_t leaf = 1; leaf <= max && leaf <= 0xFF; ++leaf) {
163 : : uint32_t maxsub = 0;
164 [ + - ]: 24066 : for (uint32_t subleaf = 0; subleaf <= 0xFF; ++subleaf) {
165 : 24066 : AddCPUID(hasher, leaf, subleaf, ax, bx, cx, dx);
166 : : // Iterate subleafs for leaf values 4, 7, 11, 13
167 [ + + ]: 24066 : if (leaf == 4) {
168 [ - + ]: 1337 : if ((ax & 0x1f) == 0) break;
169 [ + + ]: 22729 : } else if (leaf == 7) {
170 [ + - ]: 1337 : if (subleaf == 0) maxsub = ax;
171 [ - + ]: 1337 : if (subleaf == maxsub) break;
172 [ + + ]: 21392 : } else if (leaf == 11) {
173 [ + + ]: 4011 : if ((cx & 0xff00) == 0) break;
174 [ + + ]: 17381 : } else if (leaf == 13) {
175 [ + + + - : 5348 : if (ax == 0 && bx == 0 && cx == 0 && dx == 0) break;
+ - - + ]
176 : : } else {
177 : : // For any other leaf, stop after subleaf 0.
178 : : break;
179 : : }
180 : : }
181 : : }
182 : : // Iterate over all extended leaves
183 : 1337 : AddCPUID(hasher, 0x80000000, 0, ax, bx, cx, dx); // Returns max extended leaf in ax
184 : 1337 : uint32_t ext_max = ax;
185 [ + + ]: 45458 : for (uint32_t leaf = 0x80000001; leaf <= ext_max && leaf <= 0x800000FF; ++leaf) {
186 : 44121 : AddCPUID(hasher, leaf, 0, ax, bx, cx, dx);
187 : : }
188 : 1337 : }
189 : : #endif
190 : : } // namespace
191 : :
192 : 1574 : void RandAddDynamicEnv(CSHA512& hasher)
193 : : {
194 : : // Various clocks
195 : : #ifdef WIN32
196 : : FILETIME ftime;
197 : : GetSystemTimeAsFileTime(&ftime);
198 : : hasher << ftime;
199 : : #else
200 : 1574 : struct timespec ts = {};
201 : : # ifdef CLOCK_MONOTONIC
202 : 1574 : clock_gettime(CLOCK_MONOTONIC, &ts);
203 : 1574 : hasher << ts;
204 : : # endif
205 : : # ifdef CLOCK_REALTIME
206 : 1574 : clock_gettime(CLOCK_REALTIME, &ts);
207 : 1574 : hasher << ts;
208 : : # endif
209 : : # ifdef CLOCK_BOOTTIME
210 : 1574 : clock_gettime(CLOCK_BOOTTIME, &ts);
211 : 1574 : hasher << ts;
212 : : # endif
213 : : // gettimeofday is available on all UNIX systems, but only has microsecond precision.
214 : 1574 : struct timeval tv = {};
215 : 1574 : gettimeofday(&tv, nullptr);
216 : 1574 : hasher << tv;
217 : : #endif
218 : : // Probably redundant, but also use all the standard library clocks:
219 : 1574 : hasher << std::chrono::system_clock::now().time_since_epoch().count();
220 : 1574 : hasher << std::chrono::steady_clock::now().time_since_epoch().count();
221 : 1574 : hasher << std::chrono::high_resolution_clock::now().time_since_epoch().count();
222 : :
223 : : #ifndef WIN32
224 : : // Current resource usage.
225 : 1574 : struct rusage usage = {};
226 [ + - ]: 1574 : if (getrusage(RUSAGE_SELF, &usage) == 0) hasher << usage;
227 : : #endif
228 : :
229 : : #ifdef __linux__
230 : 1574 : AddFile(hasher, "/proc/diskstats");
231 : 1574 : AddFile(hasher, "/proc/vmstat");
232 : 1574 : AddFile(hasher, "/proc/schedstat");
233 : 1574 : AddFile(hasher, "/proc/zoneinfo");
234 : 1574 : AddFile(hasher, "/proc/meminfo");
235 : 1574 : AddFile(hasher, "/proc/softirqs");
236 : 1574 : AddFile(hasher, "/proc/stat");
237 : 1574 : AddFile(hasher, "/proc/self/schedstat");
238 : 1574 : AddFile(hasher, "/proc/self/status");
239 : : #endif
240 : :
241 : : #ifdef HAVE_SYSCTL
242 : : # ifdef CTL_KERN
243 : : # if defined(KERN_PROC) && defined(KERN_PROC_ALL)
244 : : AddSysctl<CTL_KERN, KERN_PROC, KERN_PROC_ALL>(hasher);
245 : : # endif
246 : : # endif
247 : : # ifdef CTL_HW
248 : : # ifdef HW_DISKSTATS
249 : : AddSysctl<CTL_HW, HW_DISKSTATS>(hasher);
250 : : # endif
251 : : # endif
252 : : # ifdef CTL_VM
253 : : # ifdef VM_LOADAVG
254 : : AddSysctl<CTL_VM, VM_LOADAVG>(hasher);
255 : : # endif
256 : : # ifdef VM_TOTAL
257 : : AddSysctl<CTL_VM, VM_TOTAL>(hasher);
258 : : # endif
259 : : # ifdef VM_METER
260 : : AddSysctl<CTL_VM, VM_METER>(hasher);
261 : : # endif
262 : : # endif
263 : : #endif
264 : :
265 : : // Stack and heap location
266 : 1574 : void* addr = malloc(4097);
267 : 1574 : hasher << &addr << addr;
268 : 1574 : free(addr);
269 : 1574 : }
270 : :
271 : 1337 : void RandAddStaticEnv(CSHA512& hasher)
272 : : {
273 : : // Some compile-time static properties
274 : 1337 : hasher << (CHAR_MIN < 0) << sizeof(void*) << sizeof(long) << sizeof(int);
275 : : #if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
276 : 1337 : hasher << __GNUC__ << __GNUC_MINOR__ << __GNUC_PATCHLEVEL__;
277 : : #endif
278 : : #ifdef _MSC_VER
279 : : hasher << _MSC_VER;
280 : : #endif
281 : 1337 : hasher << __cplusplus;
282 : : #ifdef _XOPEN_VERSION
283 : 1337 : hasher << _XOPEN_VERSION;
284 : : #endif
285 : : #ifdef __VERSION__
286 : 1337 : const char* COMPILER_VERSION = __VERSION__;
287 : 1337 : hasher.Write((const unsigned char*)COMPILER_VERSION, strlen(COMPILER_VERSION) + 1);
288 : : #endif
289 : :
290 : : // Bitcoin client version
291 : 1337 : hasher << CLIENT_VERSION;
292 : :
293 : : #if defined(HAVE_STRONG_GETAUXVAL)
294 : : // Information available through getauxval()
295 : : # ifdef AT_HWCAP
296 : 1337 : hasher << getauxval(AT_HWCAP);
297 : : # endif
298 : : # ifdef AT_HWCAP2
299 : 1337 : hasher << getauxval(AT_HWCAP2);
300 : : # endif
301 : : # ifdef AT_RANDOM
302 : 1337 : const unsigned char* random_aux = (const unsigned char*)getauxval(AT_RANDOM);
303 [ + - ]: 1337 : if (random_aux) hasher.Write(random_aux, 16);
304 : : # endif
305 : : # ifdef AT_PLATFORM
306 : 1337 : const char* platform_str = (const char*)getauxval(AT_PLATFORM);
307 [ + - ]: 1337 : if (platform_str) hasher.Write((const unsigned char*)platform_str, strlen(platform_str) + 1);
308 : : # endif
309 : : # ifdef AT_EXECFN
310 : 1337 : const char* exec_str = (const char*)getauxval(AT_EXECFN);
311 [ + - ]: 1337 : if (exec_str) hasher.Write((const unsigned char*)exec_str, strlen(exec_str) + 1);
312 : : # endif
313 : : #endif // HAVE_STRONG_GETAUXVAL
314 : :
315 : : #ifdef HAVE_GETCPUID
316 : 1337 : AddAllCPUID(hasher);
317 : : #endif
318 : :
319 : : // Memory locations
320 : 1337 : hasher << &hasher << &RandAddStaticEnv << &malloc << &errno << &environ;
321 : :
322 : : // Hostname
323 : : #ifdef WIN32
324 : : constexpr DWORD max_size = MAX_COMPUTERNAME_LENGTH + 1;
325 : : char hname[max_size];
326 : : DWORD size = max_size;
327 : : if (GetComputerNameA(hname, &size) != 0) {
328 : : hasher.Write(UCharCast(hname), size);
329 : : }
330 : : #else
331 : 1337 : char hname[256];
332 [ + - ]: 1337 : if (gethostname(hname, 256) == 0) {
333 : 1337 : hasher.Write((const unsigned char*)hname, strnlen(hname, 256));
334 : : }
335 : : #endif
336 : :
337 : : #ifdef HAVE_IFADDRS
338 : : // Network interfaces
339 : 1337 : struct ifaddrs *ifad = nullptr;
340 : 1337 : getifaddrs(&ifad);
341 : 1337 : struct ifaddrs *ifit = ifad;
342 [ + + ]: 6685 : while (ifit != nullptr) {
343 : 5348 : hasher.Write((const unsigned char*)&ifit, sizeof(ifit));
344 : 5348 : hasher.Write((const unsigned char*)ifit->ifa_name, strlen(ifit->ifa_name) + 1);
345 : 5348 : hasher.Write((const unsigned char*)&ifit->ifa_flags, sizeof(ifit->ifa_flags));
346 : 5348 : AddSockaddr(hasher, ifit->ifa_addr);
347 : 5348 : AddSockaddr(hasher, ifit->ifa_netmask);
348 : 5348 : AddSockaddr(hasher, ifit->ifa_dstaddr);
349 : 5348 : ifit = ifit->ifa_next;
350 : : }
351 : 1337 : freeifaddrs(ifad);
352 : : #endif
353 : :
354 : : #ifndef WIN32
355 : : // UNIX kernel information
356 : 1337 : struct utsname name;
357 [ + - ]: 1337 : if (uname(&name) != -1) {
358 : 1337 : hasher.Write((const unsigned char*)&name.sysname, strlen(name.sysname) + 1);
359 : 1337 : hasher.Write((const unsigned char*)&name.nodename, strlen(name.nodename) + 1);
360 : 1337 : hasher.Write((const unsigned char*)&name.release, strlen(name.release) + 1);
361 : 1337 : hasher.Write((const unsigned char*)&name.version, strlen(name.version) + 1);
362 : 1337 : hasher.Write((const unsigned char*)&name.machine, strlen(name.machine) + 1);
363 : : }
364 : :
365 : : /* Path and filesystem provided data */
366 : 1337 : AddPath(hasher, "/");
367 : 1337 : AddPath(hasher, ".");
368 : 1337 : AddPath(hasher, "/tmp");
369 : 1337 : AddPath(hasher, "/home");
370 : 1337 : AddPath(hasher, "/proc");
371 : : #ifdef __linux__
372 : 1337 : AddFile(hasher, "/proc/cmdline");
373 : 1337 : AddFile(hasher, "/proc/cpuinfo");
374 : 1337 : AddFile(hasher, "/proc/version");
375 : : #endif
376 : 1337 : AddFile(hasher, "/etc/passwd");
377 : 1337 : AddFile(hasher, "/etc/group");
378 : 1337 : AddFile(hasher, "/etc/hosts");
379 : 1337 : AddFile(hasher, "/etc/resolv.conf");
380 : 1337 : AddFile(hasher, "/etc/timezone");
381 : 1337 : AddFile(hasher, "/etc/localtime");
382 : : #endif
383 : :
384 : : // For MacOS/BSDs, gather data through sysctl instead of /proc. Not all of these
385 : : // will exist on every system.
386 : : #ifdef HAVE_SYSCTL
387 : : # ifdef CTL_HW
388 : : # ifdef HW_MACHINE
389 : : AddSysctl<CTL_HW, HW_MACHINE>(hasher);
390 : : # endif
391 : : # ifdef HW_MODEL
392 : : AddSysctl<CTL_HW, HW_MODEL>(hasher);
393 : : # endif
394 : : # ifdef HW_NCPU
395 : : AddSysctl<CTL_HW, HW_NCPU>(hasher);
396 : : # endif
397 : : # ifdef HW_PHYSMEM
398 : : AddSysctl<CTL_HW, HW_PHYSMEM>(hasher);
399 : : # endif
400 : : # ifdef HW_USERMEM
401 : : AddSysctl<CTL_HW, HW_USERMEM>(hasher);
402 : : # endif
403 : : # ifdef HW_MACHINE_ARCH
404 : : AddSysctl<CTL_HW, HW_MACHINE_ARCH>(hasher);
405 : : # endif
406 : : # ifdef HW_REALMEM
407 : : AddSysctl<CTL_HW, HW_REALMEM>(hasher);
408 : : # endif
409 : : # ifdef HW_CPU_FREQ
410 : : AddSysctl<CTL_HW, HW_CPU_FREQ>(hasher);
411 : : # endif
412 : : # ifdef HW_BUS_FREQ
413 : : AddSysctl<CTL_HW, HW_BUS_FREQ>(hasher);
414 : : # endif
415 : : # ifdef HW_CACHELINE
416 : : AddSysctl<CTL_HW, HW_CACHELINE>(hasher);
417 : : # endif
418 : : # endif
419 : : # ifdef CTL_KERN
420 : : # ifdef KERN_BOOTFILE
421 : : AddSysctl<CTL_KERN, KERN_BOOTFILE>(hasher);
422 : : # endif
423 : : # ifdef KERN_BOOTTIME
424 : : AddSysctl<CTL_KERN, KERN_BOOTTIME>(hasher);
425 : : # endif
426 : : # ifdef KERN_CLOCKRATE
427 : : AddSysctl<CTL_KERN, KERN_CLOCKRATE>(hasher);
428 : : # endif
429 : : # ifdef KERN_HOSTID
430 : : AddSysctl<CTL_KERN, KERN_HOSTID>(hasher);
431 : : # endif
432 : : # ifdef KERN_HOSTUUID
433 : : AddSysctl<CTL_KERN, KERN_HOSTUUID>(hasher);
434 : : # endif
435 : : # ifdef KERN_HOSTNAME
436 : : AddSysctl<CTL_KERN, KERN_HOSTNAME>(hasher);
437 : : # endif
438 : : # ifdef KERN_OSRELDATE
439 : : AddSysctl<CTL_KERN, KERN_OSRELDATE>(hasher);
440 : : # endif
441 : : # ifdef KERN_OSRELEASE
442 : : AddSysctl<CTL_KERN, KERN_OSRELEASE>(hasher);
443 : : # endif
444 : : # ifdef KERN_OSREV
445 : : AddSysctl<CTL_KERN, KERN_OSREV>(hasher);
446 : : # endif
447 : : # ifdef KERN_OSTYPE
448 : : AddSysctl<CTL_KERN, KERN_OSTYPE>(hasher);
449 : : # endif
450 : : # ifdef KERN_POSIX1
451 : : AddSysctl<CTL_KERN, KERN_OSREV>(hasher);
452 : : # endif
453 : : # ifdef KERN_VERSION
454 : : AddSysctl<CTL_KERN, KERN_VERSION>(hasher);
455 : : # endif
456 : : # endif
457 : : #endif
458 : :
459 : : // Env variables
460 [ + - ]: 1337 : if (environ) {
461 [ + + ]: 81766 : for (size_t i = 0; environ[i]; ++i) {
462 : 80429 : hasher.Write((const unsigned char*)environ[i], strlen(environ[i]));
463 : : }
464 : : }
465 : :
466 : : // Process, thread, user, session, group, ... ids.
467 : : #ifdef WIN32
468 : : hasher << GetCurrentProcessId() << GetCurrentThreadId();
469 : : #else
470 : 1337 : hasher << getpid() << getppid() << getsid(0) << getpgid(0) << getuid() << geteuid() << getgid() << getegid();
471 : : #endif
472 : 1337 : hasher << std::this_thread::get_id();
473 : 1337 : }
|