3
3
// Distributed under the MIT software license, see the accompanying
4
4
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
5
6
+ #if defined(HAVE_CONFIG_H)
7
+ #include < config/bitcoin-config.h>
8
+ #endif
9
+
6
10
#include < randomenv.h>
7
11
12
+ #include < clientversion.h>
8
13
#include < crypto/sha512.h>
9
14
#include < support/cleanse.h>
10
15
#include < util/time.h> // for GetTime()
14
19
15
20
#include < algorithm>
16
21
#include < chrono>
22
+ #include < climits>
17
23
#include < thread>
18
24
#include < vector>
19
25
20
26
#include < stdint.h>
21
27
#include < string.h>
22
28
#ifndef WIN32
29
+ #include < sys/types.h> // must go before a number of other headers
30
+ #include < fcntl.h>
31
+ #include < netinet/in.h>
32
+ #include < sys/resource.h>
33
+ #include < sys/socket.h>
34
+ #include < sys/stat.h>
23
35
#include < sys/time.h>
24
- #include < sys/types .h>
36
+ #include < sys/utsname .h>
25
37
#include < unistd.h>
26
38
#endif
27
39
#ifdef __MACH__
28
40
#include < mach/clock.h>
29
41
#include < mach/mach.h>
30
42
#include < mach/mach_time.h>
31
43
#endif
44
+ #if HAVE_DECL_GETIFADDRS
45
+ #include < ifaddrs.h>
46
+ #endif
47
+
48
+ // ! Necessary on some platforms
49
+ extern char ** environ;
32
50
33
51
namespace {
34
52
@@ -85,6 +103,53 @@ CSHA512& operator<<(CSHA512& hasher, const T& data) {
85
103
return hasher;
86
104
}
87
105
106
+ #ifndef WIN32
107
+ void AddSockaddr (CSHA512& hasher, const struct sockaddr *addr)
108
+ {
109
+ if (addr == nullptr ) return ;
110
+ switch (addr->sa_family ) {
111
+ case AF_INET:
112
+ hasher.Write ((const unsigned char *)addr, sizeof (sockaddr_in));
113
+ break ;
114
+ case AF_INET6:
115
+ hasher.Write ((const unsigned char *)addr, sizeof (sockaddr_in6));
116
+ break ;
117
+ default :
118
+ hasher.Write ((const unsigned char *)&addr->sa_family , sizeof (addr->sa_family ));
119
+ }
120
+ }
121
+
122
+ void AddFile (CSHA512& hasher, const char *path)
123
+ {
124
+ struct stat sb = {};
125
+ int f = open (path, O_RDONLY);
126
+ size_t total = 0 ;
127
+ if (f != -1 ) {
128
+ unsigned char fbuf[4096 ];
129
+ int n;
130
+ hasher.Write ((const unsigned char *)&f, sizeof (f));
131
+ if (fstat (f, &sb) == 0 ) hasher << sb;
132
+ do {
133
+ n = read (f, fbuf, sizeof (fbuf));
134
+ if (n > 0 ) hasher.Write (fbuf, n);
135
+ total += n;
136
+ /* not bothering with EINTR handling. */
137
+ } while (n == sizeof (fbuf) && total < 1048576 ); // Read only the first 1 Mbyte
138
+ close (f);
139
+ }
140
+ }
141
+
142
+ void AddPath (CSHA512& hasher, const char *path)
143
+ {
144
+ struct stat sb = {};
145
+ if (stat (path, &sb) == 0 ) {
146
+ hasher.Write ((const unsigned char *)path, strlen (path) + 1 );
147
+ hasher << sb;
148
+ }
149
+ }
150
+ #endif
151
+
152
+
88
153
} // namespace
89
154
90
155
void RandAddDynamicEnv (CSHA512& hasher)
@@ -99,48 +164,157 @@ void RandAddDynamicEnv(CSHA512& hasher)
99
164
#else
100
165
# ifndef __MACH__
101
166
// On non-MacOS systems, use various clock_gettime() calls.
102
- struct timespec ts;
167
+ struct timespec ts = {} ;
103
168
# ifdef CLOCK_MONOTONIC
104
169
clock_gettime (CLOCK_MONOTONIC, &ts);
105
- hasher << ts. tv_sec << ts. tv_nsec ;
170
+ hasher << ts;
106
171
# endif
107
172
# ifdef CLOCK_REALTIME
108
173
clock_gettime (CLOCK_REALTIME, &ts);
109
- hasher << ts. tv_sec << ts. tv_nsec ;
174
+ hasher << ts;
110
175
# endif
111
176
# ifdef CLOCK_BOOTTIME
112
177
clock_gettime (CLOCK_BOOTTIME, &ts);
113
- hasher << ts. tv_sec << ts. tv_nsec ;
178
+ hasher << ts;
114
179
# endif
115
180
# else
116
181
// On MacOS use mach_absolute_time (number of CPU ticks since boot) as a replacement for CLOCK_MONOTONIC,
117
182
// and clock_get_time for CALENDAR_CLOCK as a replacement for CLOCK_REALTIME.
118
183
hasher << mach_absolute_time ();
119
184
// From https://gist.github.com/jbenet/1087739
120
185
clock_serv_t cclock;
121
- mach_timespec_t mts;
186
+ mach_timespec_t mts = {} ;
122
187
if (host_get_clock_service (mach_host_self (), CALENDAR_CLOCK, &cclock) == KERN_SUCCESS && clock_get_time (cclock, &mts) == KERN_SUCCESS) {
123
- hasher << mts. tv_sec << mts. tv_nsec ;
188
+ hasher << mts;
124
189
mach_port_deallocate (mach_task_self (), cclock);
125
190
}
126
191
# endif
127
192
// gettimeofday is available on all UNIX systems, but only has microsecond precision.
128
- struct timeval tv;
193
+ struct timeval tv = {} ;
129
194
gettimeofday (&tv, nullptr );
130
- hasher << tv. tv_sec << tv. tv_usec ;
195
+ hasher << tv;
131
196
#endif
132
197
// Probably redundant, but also use all the clocks C++11 provides:
133
198
hasher << std::chrono::system_clock::now ().time_since_epoch ().count ();
134
199
hasher << std::chrono::steady_clock::now ().time_since_epoch ().count ();
135
200
hasher << std::chrono::high_resolution_clock::now ().time_since_epoch ().count ();
201
+
202
+ #ifndef WIN32
203
+ // Current resource usage.
204
+ struct rusage usage = {};
205
+ if (getrusage (RUSAGE_SELF, &usage) == 0 ) hasher << usage;
206
+ #endif
207
+
208
+ #ifdef __linux__
209
+ AddFile (hasher, " /proc/diskstats" );
210
+ AddFile (hasher, " /proc/vmstat" );
211
+ AddFile (hasher, " /proc/schedstat" );
212
+ AddFile (hasher, " /proc/zoneinfo" );
213
+ AddFile (hasher, " /proc/meminfo" );
214
+ AddFile (hasher, " /proc/softirqs" );
215
+ AddFile (hasher, " /proc/stat" );
216
+ AddFile (hasher, " /proc/self/schedstat" );
217
+ AddFile (hasher, " /proc/self/status" );
218
+ #endif
219
+
220
+ // Stack and heap location
221
+ void * addr = malloc (4097 );
222
+ hasher << &addr << addr;
223
+ free (addr);
136
224
}
137
225
138
226
void RandAddStaticEnv (CSHA512& hasher)
139
227
{
228
+ // Some compile-time static properties
229
+ hasher << (CHAR_MIN < 0 ) << sizeof (void *) << sizeof (long ) << sizeof (int );
230
+ #if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
231
+ hasher << __GNUC__ << __GNUC_MINOR__ << __GNUC_PATCHLEVEL__;
232
+ #endif
233
+ #ifdef _MSC_VER
234
+ hasher << _MSC_VER;
235
+ #endif
236
+ hasher << __cplusplus;
237
+ #ifdef _XOPEN_VERSION
238
+ hasher << _XOPEN_VERSION;
239
+ #endif
240
+ #ifdef __VERSION__
241
+ const char * COMPILER_VERSION = __VERSION__;
242
+ hasher.Write ((const unsigned char *)COMPILER_VERSION, strlen (COMPILER_VERSION) + 1 );
243
+ #endif
244
+
245
+ // Bitcoin client version
246
+ hasher << CLIENT_VERSION;
247
+
248
+ // Memory locations
249
+ hasher << &hasher << &RandAddStaticEnv << &malloc << &errno << &environ;
250
+
251
+ // Hostname
252
+ char hname[256 ];
253
+ if (gethostname (hname, 256 ) == 0 ) {
254
+ hasher.Write ((const unsigned char *)hname, strnlen (hname, 256 ));
255
+ }
256
+
257
+ #if HAVE_DECL_GETIFADDRS
258
+ // Network interfaces
259
+ struct ifaddrs *ifad = NULL ;
260
+ getifaddrs (&ifad);
261
+ struct ifaddrs *ifit = ifad;
262
+ while (ifit != NULL ) {
263
+ hasher.Write ((const unsigned char *)&ifit, sizeof (ifit));
264
+ hasher.Write ((const unsigned char *)ifit->ifa_name , strlen (ifit->ifa_name ) + 1 );
265
+ hasher.Write ((const unsigned char *)&ifit->ifa_flags , sizeof (ifit->ifa_flags ));
266
+ AddSockaddr (hasher, ifit->ifa_addr );
267
+ AddSockaddr (hasher, ifit->ifa_netmask );
268
+ AddSockaddr (hasher, ifit->ifa_dstaddr );
269
+ ifit = ifit->ifa_next ;
270
+ }
271
+ freeifaddrs (ifad);
272
+ #endif
273
+
274
+ #ifndef WIN32
275
+ // UNIX kernel information
276
+ struct utsname name;
277
+ if (uname (&name) != -1 ) {
278
+ hasher.Write ((const unsigned char *)&name.sysname , strlen (name.sysname ) + 1 );
279
+ hasher.Write ((const unsigned char *)&name.nodename , strlen (name.nodename ) + 1 );
280
+ hasher.Write ((const unsigned char *)&name.release , strlen (name.release ) + 1 );
281
+ hasher.Write ((const unsigned char *)&name.version , strlen (name.version ) + 1 );
282
+ hasher.Write ((const unsigned char *)&name.machine , strlen (name.machine ) + 1 );
283
+ }
284
+
285
+ /* Path and filesystem provided data */
286
+ AddPath (hasher, " /" );
287
+ AddPath (hasher, " ." );
288
+ AddPath (hasher, " /tmp" );
289
+ AddPath (hasher, " /home" );
290
+ AddPath (hasher, " /proc" );
291
+ #ifdef __linux__
292
+ AddFile (hasher, " /proc/cmdline" );
293
+ AddFile (hasher, " /proc/cpuinfo" );
294
+ AddFile (hasher, " /proc/version" );
295
+ #endif
296
+ AddFile (hasher, " /etc/passwd" );
297
+ AddFile (hasher, " /etc/group" );
298
+ AddFile (hasher, " /etc/hosts" );
299
+ AddFile (hasher, " /etc/resolv.conf" );
300
+ AddFile (hasher, " /etc/timezone" );
301
+ AddFile (hasher, " /etc/localtime" );
302
+
303
+ /* TODO: sysctl's for OSX to fetch information not available from /proc */
304
+ #endif
305
+
306
+ // Env variables
307
+ if (environ) {
308
+ for (size_t i = 0 ; environ[i]; ++i) {
309
+ hasher.Write ((const unsigned char *)environ[i], strlen (environ[i]));
310
+ }
311
+ }
312
+
313
+ // Process, thread, user, session, group, ... ids.
140
314
#ifdef WIN32
141
315
hasher << GetCurrentProcessId () << GetCurrentThreadId ();
142
316
#else
143
- hasher << getpid ();
317
+ hasher << getpid () << getppid () << getsid ( 0 ) << getpgid ( 0 ) << getuid () << geteuid () << getgid () << getegid () ;
144
318
#endif
145
319
hasher << std::this_thread::get_id ();
146
320
}
0 commit comments