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