mirror of
https://github.com/dashpay/dash.git
synced 2024-12-27 13:03:17 +01:00
fb3d9a16bf
4446ef0a549d567a88d82b606aa8c47f115673f9 build: remove support for weak linking getauxval() (fanquake) e56100c5b4daf2285dde9807bf654599aa19bd6b build: remove arm includes from getauxval() check (fanquake) Pull request description: It was [pointed out in #23030](https://github.com/bitcoin/bitcoin/pull/23030#issuecomment-922893367) that we might be able to get rid of our weak linking of [`getauxval()`](https://man7.org/linux/man-pages/man3/getauxval.3.html) (`HAVE_WEAK_GETAUXVAL`) entirely, with only Android being a potential holdout: > I wonder if it's time to get rid of HAVE_WEAK_GETAUXVAL. I think it's confusing. Either we build against a C library that has this functionality, or not. We don't do this weak linking thing for any other symbols and recently got rid of the other glibc backwards compatibility stuff. > Unless there is still a current platform that really needs it (Android?), I'd prefer to remove it from the build system, it has caused enough issues. After looking at Android further, it would seem that given we are moving to using `std::filesystem`, which [requires NDK version 22 and later](https://github.com/android/ndk/wiki/Changelog-r22), and `getauxval` has been available in the since [API version 18](https://developer.android.com/ndk/guides/cpu-features#features_using_libcs_getauxval3), that shouldn't really be an issue. Support for API levels < 19 will be dropped with the NDK 24 release, and according to [one website](https://apilevels.com/), supporting API level 18+ will cover ~99% of devices. Note that in the CI we currently build with NDK version 22 and API level 28. The other change in this PR is removing the include of headers for ARM intrinsics, from the check for strong `getauxval()` support in configure, as they shouldn't be needed. Including these headers also meant that the check would basically only succeed when building for ARM. This would be an issue if we remove weak linking, as we wouldn't detect `getauxval()` as supported on other platforms. Note that we also use `getauxval()` in our RNG when it's available. I've checked that with these changes we detect support for strong `getauxval()` on Alpine (muslibc). On Linux, previously we'd be detecting support for weak getauxval(), now we detect strong support. Note that we already require glibc 2.17, and `getauxval()` was introduced in `2.16`. This is an alternative / supersedes #23030. ACKs for top commit: laanwj: Code review and tested ACK 4446ef0a549d567a88d82b606aa8c47f115673f9 Tree-SHA512: 5f2a9e9cc2d63bddab73f0dcb169d4d6beda74622af82bc0439722f1189f81d052e2fc1eaf27056a7a606320d5ddc4c11075f0d051dd93d77c5e1c15337f354a
501 lines
15 KiB
C++
501 lines
15 KiB
C++
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|
// Copyright (c) 2009-2020 The Bitcoin Core developers
|
|
// Distributed under the MIT software license, see the accompanying
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
#if defined(HAVE_CONFIG_H)
|
|
#include <config/bitcoin-config.h>
|
|
#endif
|
|
|
|
#include <randomenv.h>
|
|
|
|
#include <clientversion.h>
|
|
#include <compat/cpuid.h>
|
|
#include <crypto/sha512.h>
|
|
#include <support/cleanse.h>
|
|
#include <util/time.h> // for GetTime()
|
|
#ifdef WIN32
|
|
#include <compat.h> // for Windows API
|
|
#endif
|
|
|
|
#include <algorithm>
|
|
#include <atomic>
|
|
#include <chrono>
|
|
#include <climits>
|
|
#include <thread>
|
|
#include <vector>
|
|
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#ifndef WIN32
|
|
#include <sys/types.h> // must go before a number of other headers
|
|
#include <fcntl.h>
|
|
#include <netinet/in.h>
|
|
#include <sys/resource.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/time.h>
|
|
#include <sys/utsname.h>
|
|
#include <unistd.h>
|
|
#endif
|
|
#if HAVE_DECL_GETIFADDRS && HAVE_DECL_FREEIFADDRS
|
|
#include <ifaddrs.h>
|
|
#endif
|
|
#if HAVE_SYSCTL
|
|
#include <sys/sysctl.h>
|
|
#if HAVE_VM_VM_PARAM_H
|
|
#include <vm/vm_param.h>
|
|
#endif
|
|
#if HAVE_SYS_RESOURCES_H
|
|
#include <sys/resources.h>
|
|
#endif
|
|
#if HAVE_SYS_VMMETER_H
|
|
#include <sys/vmmeter.h>
|
|
#endif
|
|
#endif
|
|
#if defined(HAVE_STRONG_GETAUXVAL)
|
|
#include <sys/auxv.h>
|
|
#endif
|
|
|
|
//! Necessary on some platforms
|
|
extern char** environ;
|
|
|
|
namespace {
|
|
|
|
void RandAddSeedPerfmon(CSHA512& hasher)
|
|
{
|
|
#ifdef WIN32
|
|
// Seed with the entire set of perfmon data
|
|
|
|
// This can take up to 2 seconds, so only do it every 10 minutes.
|
|
// Initialize last_perfmon to 0 seconds, we don't skip the first call.
|
|
static std::atomic<std::chrono::seconds> last_perfmon{0s};
|
|
auto last_time = last_perfmon.load();
|
|
auto current_time = GetTime<std::chrono::seconds>();
|
|
if (current_time < last_time + std::chrono::minutes{10}) return;
|
|
last_perfmon = current_time;
|
|
|
|
std::vector<unsigned char> vData(250000, 0);
|
|
long ret = 0;
|
|
unsigned long nSize = 0;
|
|
const size_t nMaxSize = 10000000; // Bail out at more than 10MB of performance data
|
|
while (true) {
|
|
nSize = vData.size();
|
|
ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", nullptr, nullptr, vData.data(), &nSize);
|
|
if (ret != ERROR_MORE_DATA || vData.size() >= nMaxSize)
|
|
break;
|
|
vData.resize(std::min((vData.size() * 3) / 2, nMaxSize)); // Grow size of buffer exponentially
|
|
}
|
|
RegCloseKey(HKEY_PERFORMANCE_DATA);
|
|
if (ret == ERROR_SUCCESS) {
|
|
hasher.Write(vData.data(), nSize);
|
|
memory_cleanse(vData.data(), nSize);
|
|
} else {
|
|
// Performance data is only a best-effort attempt at improving the
|
|
// situation when the OS randomness (and other sources) aren't
|
|
// adequate. As a result, failure to read it is isn't considered critical,
|
|
// so we don't call RandFailure().
|
|
// TODO: Add logging when the logger is made functional before global
|
|
// constructors have been invoked.
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/** Helper to easily feed data into a CSHA512.
|
|
*
|
|
* Note that this does not serialize the passed object (like stream.h's << operators do).
|
|
* Its raw memory representation is used directly.
|
|
*/
|
|
template<typename T>
|
|
CSHA512& operator<<(CSHA512& hasher, const T& data) {
|
|
static_assert(!std::is_same<typename std::decay<T>::type, char*>::value, "Calling operator<<(CSHA512, char*) is probably not what you want");
|
|
static_assert(!std::is_same<typename std::decay<T>::type, unsigned char*>::value, "Calling operator<<(CSHA512, unsigned char*) is probably not what you want");
|
|
static_assert(!std::is_same<typename std::decay<T>::type, const char*>::value, "Calling operator<<(CSHA512, const char*) is probably not what you want");
|
|
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");
|
|
hasher.Write((const unsigned char*)&data, sizeof(data));
|
|
return hasher;
|
|
}
|
|
|
|
#ifndef WIN32
|
|
void AddSockaddr(CSHA512& hasher, const struct sockaddr *addr)
|
|
{
|
|
if (addr == nullptr) return;
|
|
switch (addr->sa_family) {
|
|
case AF_INET:
|
|
hasher.Write((const unsigned char*)addr, sizeof(sockaddr_in));
|
|
break;
|
|
case AF_INET6:
|
|
hasher.Write((const unsigned char*)addr, sizeof(sockaddr_in6));
|
|
break;
|
|
default:
|
|
hasher.Write((const unsigned char*)&addr->sa_family, sizeof(addr->sa_family));
|
|
}
|
|
}
|
|
|
|
void AddFile(CSHA512& hasher, const char *path)
|
|
{
|
|
struct stat sb = {};
|
|
int f = open(path, O_RDONLY);
|
|
size_t total = 0;
|
|
if (f != -1) {
|
|
unsigned char fbuf[4096];
|
|
int n;
|
|
hasher.Write((const unsigned char*)&f, sizeof(f));
|
|
if (fstat(f, &sb) == 0) hasher << sb;
|
|
do {
|
|
n = read(f, fbuf, sizeof(fbuf));
|
|
if (n > 0) hasher.Write(fbuf, n);
|
|
total += n;
|
|
/* not bothering with EINTR handling. */
|
|
} while (n == sizeof(fbuf) && total < 1048576); // Read only the first 1 Mbyte
|
|
close(f);
|
|
}
|
|
}
|
|
|
|
void AddPath(CSHA512& hasher, const char *path)
|
|
{
|
|
struct stat sb = {};
|
|
if (stat(path, &sb) == 0) {
|
|
hasher.Write((const unsigned char*)path, strlen(path) + 1);
|
|
hasher << sb;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if HAVE_SYSCTL
|
|
template<int... S>
|
|
void AddSysctl(CSHA512& hasher)
|
|
{
|
|
int CTL[sizeof...(S)] = {S...};
|
|
unsigned char buffer[65536];
|
|
size_t siz = 65536;
|
|
int ret = sysctl(CTL, sizeof...(S), buffer, &siz, nullptr, 0);
|
|
if (ret == 0 || (ret == -1 && errno == ENOMEM)) {
|
|
hasher << sizeof(CTL);
|
|
hasher.Write((const unsigned char*)CTL, sizeof(CTL));
|
|
if (siz > sizeof(buffer)) siz = sizeof(buffer);
|
|
hasher << siz;
|
|
hasher.Write(buffer, siz);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef HAVE_GETCPUID
|
|
void inline AddCPUID(CSHA512& hasher, uint32_t leaf, uint32_t subleaf, uint32_t& ax, uint32_t& bx, uint32_t& cx, uint32_t& dx)
|
|
{
|
|
GetCPUID(leaf, subleaf, ax, bx, cx, dx);
|
|
hasher << leaf << subleaf << ax << bx << cx << dx;
|
|
}
|
|
|
|
void AddAllCPUID(CSHA512& hasher)
|
|
{
|
|
uint32_t ax, bx, cx, dx;
|
|
// Iterate over all standard leaves
|
|
AddCPUID(hasher, 0, 0, ax, bx, cx, dx); // Returns max leaf in ax
|
|
uint32_t max = ax;
|
|
for (uint32_t leaf = 1; leaf <= max && leaf <= 0xFF; ++leaf) {
|
|
uint32_t maxsub = 0;
|
|
for (uint32_t subleaf = 0; subleaf <= 0xFF; ++subleaf) {
|
|
AddCPUID(hasher, leaf, subleaf, ax, bx, cx, dx);
|
|
// Iterate subleafs for leaf values 4, 7, 11, 13
|
|
if (leaf == 4) {
|
|
if ((ax & 0x1f) == 0) break;
|
|
} else if (leaf == 7) {
|
|
if (subleaf == 0) maxsub = ax;
|
|
if (subleaf == maxsub) break;
|
|
} else if (leaf == 11) {
|
|
if ((cx & 0xff00) == 0) break;
|
|
} else if (leaf == 13) {
|
|
if (ax == 0 && bx == 0 && cx == 0 && dx == 0) break;
|
|
} else {
|
|
// For any other leaf, stop after subleaf 0.
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
// Iterate over all extended leaves
|
|
AddCPUID(hasher, 0x80000000, 0, ax, bx, cx, dx); // Returns max extended leaf in ax
|
|
uint32_t ext_max = ax;
|
|
for (uint32_t leaf = 0x80000001; leaf <= ext_max && leaf <= 0x800000FF; ++leaf) {
|
|
AddCPUID(hasher, leaf, 0, ax, bx, cx, dx);
|
|
}
|
|
}
|
|
#endif
|
|
} // namespace
|
|
|
|
void RandAddDynamicEnv(CSHA512& hasher)
|
|
{
|
|
RandAddSeedPerfmon(hasher);
|
|
|
|
// Various clocks
|
|
#ifdef WIN32
|
|
FILETIME ftime;
|
|
GetSystemTimeAsFileTime(&ftime);
|
|
hasher << ftime;
|
|
#else
|
|
struct timespec ts = {};
|
|
# ifdef CLOCK_MONOTONIC
|
|
clock_gettime(CLOCK_MONOTONIC, &ts);
|
|
hasher << ts;
|
|
# endif
|
|
# ifdef CLOCK_REALTIME
|
|
clock_gettime(CLOCK_REALTIME, &ts);
|
|
hasher << ts;
|
|
# endif
|
|
# ifdef CLOCK_BOOTTIME
|
|
clock_gettime(CLOCK_BOOTTIME, &ts);
|
|
hasher << ts;
|
|
# endif
|
|
// gettimeofday is available on all UNIX systems, but only has microsecond precision.
|
|
struct timeval tv = {};
|
|
gettimeofday(&tv, nullptr);
|
|
hasher << tv;
|
|
#endif
|
|
// Probably redundant, but also use all the clocks C++11 provides:
|
|
hasher << std::chrono::system_clock::now().time_since_epoch().count();
|
|
hasher << std::chrono::steady_clock::now().time_since_epoch().count();
|
|
hasher << std::chrono::high_resolution_clock::now().time_since_epoch().count();
|
|
|
|
#ifndef WIN32
|
|
// Current resource usage.
|
|
struct rusage usage = {};
|
|
if (getrusage(RUSAGE_SELF, &usage) == 0) hasher << usage;
|
|
#endif
|
|
|
|
#ifdef __linux__
|
|
AddFile(hasher, "/proc/diskstats");
|
|
AddFile(hasher, "/proc/vmstat");
|
|
AddFile(hasher, "/proc/schedstat");
|
|
AddFile(hasher, "/proc/zoneinfo");
|
|
AddFile(hasher, "/proc/meminfo");
|
|
AddFile(hasher, "/proc/softirqs");
|
|
AddFile(hasher, "/proc/stat");
|
|
AddFile(hasher, "/proc/self/schedstat");
|
|
AddFile(hasher, "/proc/self/status");
|
|
#endif
|
|
|
|
#if HAVE_SYSCTL
|
|
# ifdef CTL_KERN
|
|
# if defined(KERN_PROC) && defined(KERN_PROC_ALL)
|
|
AddSysctl<CTL_KERN, KERN_PROC, KERN_PROC_ALL>(hasher);
|
|
# endif
|
|
# endif
|
|
# ifdef CTL_HW
|
|
# ifdef HW_DISKSTATS
|
|
AddSysctl<CTL_HW, HW_DISKSTATS>(hasher);
|
|
# endif
|
|
# endif
|
|
# ifdef CTL_VM
|
|
# ifdef VM_LOADAVG
|
|
AddSysctl<CTL_VM, VM_LOADAVG>(hasher);
|
|
# endif
|
|
# ifdef VM_TOTAL
|
|
AddSysctl<CTL_VM, VM_TOTAL>(hasher);
|
|
# endif
|
|
# ifdef VM_METER
|
|
AddSysctl<CTL_VM, VM_METER>(hasher);
|
|
# endif
|
|
# endif
|
|
#endif
|
|
|
|
// Stack and heap location
|
|
void* addr = malloc(4097);
|
|
hasher << &addr << addr;
|
|
free(addr);
|
|
}
|
|
|
|
void RandAddStaticEnv(CSHA512& hasher)
|
|
{
|
|
// Some compile-time static properties
|
|
hasher << (CHAR_MIN < 0) << sizeof(void*) << sizeof(long) << sizeof(int);
|
|
#if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
|
|
hasher << __GNUC__ << __GNUC_MINOR__ << __GNUC_PATCHLEVEL__;
|
|
#endif
|
|
#ifdef _MSC_VER
|
|
hasher << _MSC_VER;
|
|
#endif
|
|
hasher << __cplusplus;
|
|
#ifdef _XOPEN_VERSION
|
|
hasher << _XOPEN_VERSION;
|
|
#endif
|
|
#ifdef __VERSION__
|
|
const char* COMPILER_VERSION = __VERSION__;
|
|
hasher.Write((const unsigned char*)COMPILER_VERSION, strlen(COMPILER_VERSION) + 1);
|
|
#endif
|
|
|
|
// Bitcoin client version
|
|
hasher << CLIENT_VERSION;
|
|
|
|
#if defined(HAVE_STRONG_GETAUXVAL)
|
|
// Information available through getauxval()
|
|
# ifdef AT_HWCAP
|
|
hasher << getauxval(AT_HWCAP);
|
|
# endif
|
|
# ifdef AT_HWCAP2
|
|
hasher << getauxval(AT_HWCAP2);
|
|
# endif
|
|
# ifdef AT_RANDOM
|
|
const unsigned char* random_aux = (const unsigned char*)getauxval(AT_RANDOM);
|
|
if (random_aux) hasher.Write(random_aux, 16);
|
|
# endif
|
|
# ifdef AT_PLATFORM
|
|
const char* platform_str = (const char*)getauxval(AT_PLATFORM);
|
|
if (platform_str) hasher.Write((const unsigned char*)platform_str, strlen(platform_str) + 1);
|
|
# endif
|
|
# ifdef AT_EXECFN
|
|
const char* exec_str = (const char*)getauxval(AT_EXECFN);
|
|
if (exec_str) hasher.Write((const unsigned char*)exec_str, strlen(exec_str) + 1);
|
|
# endif
|
|
#endif // HAVE_STRONG_GETAUXVAL
|
|
|
|
#ifdef HAVE_GETCPUID
|
|
AddAllCPUID(hasher);
|
|
#endif
|
|
|
|
// Memory locations
|
|
hasher << &hasher << &RandAddStaticEnv << &malloc << &errno << &environ;
|
|
|
|
// Hostname
|
|
char hname[256];
|
|
if (gethostname(hname, 256) == 0) {
|
|
hasher.Write((const unsigned char*)hname, strnlen(hname, 256));
|
|
}
|
|
|
|
#if HAVE_DECL_GETIFADDRS && HAVE_DECL_FREEIFADDRS
|
|
// Network interfaces
|
|
struct ifaddrs *ifad = NULL;
|
|
getifaddrs(&ifad);
|
|
struct ifaddrs *ifit = ifad;
|
|
while (ifit != NULL) {
|
|
hasher.Write((const unsigned char*)&ifit, sizeof(ifit));
|
|
hasher.Write((const unsigned char*)ifit->ifa_name, strlen(ifit->ifa_name) + 1);
|
|
hasher.Write((const unsigned char*)&ifit->ifa_flags, sizeof(ifit->ifa_flags));
|
|
AddSockaddr(hasher, ifit->ifa_addr);
|
|
AddSockaddr(hasher, ifit->ifa_netmask);
|
|
AddSockaddr(hasher, ifit->ifa_dstaddr);
|
|
ifit = ifit->ifa_next;
|
|
}
|
|
freeifaddrs(ifad);
|
|
#endif
|
|
|
|
#ifndef WIN32
|
|
// UNIX kernel information
|
|
struct utsname name;
|
|
if (uname(&name) != -1) {
|
|
hasher.Write((const unsigned char*)&name.sysname, strlen(name.sysname) + 1);
|
|
hasher.Write((const unsigned char*)&name.nodename, strlen(name.nodename) + 1);
|
|
hasher.Write((const unsigned char*)&name.release, strlen(name.release) + 1);
|
|
hasher.Write((const unsigned char*)&name.version, strlen(name.version) + 1);
|
|
hasher.Write((const unsigned char*)&name.machine, strlen(name.machine) + 1);
|
|
}
|
|
|
|
/* Path and filesystem provided data */
|
|
AddPath(hasher, "/");
|
|
AddPath(hasher, ".");
|
|
AddPath(hasher, "/tmp");
|
|
AddPath(hasher, "/home");
|
|
AddPath(hasher, "/proc");
|
|
#ifdef __linux__
|
|
AddFile(hasher, "/proc/cmdline");
|
|
AddFile(hasher, "/proc/cpuinfo");
|
|
AddFile(hasher, "/proc/version");
|
|
#endif
|
|
AddFile(hasher, "/etc/passwd");
|
|
AddFile(hasher, "/etc/group");
|
|
AddFile(hasher, "/etc/hosts");
|
|
AddFile(hasher, "/etc/resolv.conf");
|
|
AddFile(hasher, "/etc/timezone");
|
|
AddFile(hasher, "/etc/localtime");
|
|
#endif
|
|
|
|
// For MacOS/BSDs, gather data through sysctl instead of /proc. Not all of these
|
|
// will exist on every system.
|
|
#if HAVE_SYSCTL
|
|
# ifdef CTL_HW
|
|
# ifdef HW_MACHINE
|
|
AddSysctl<CTL_HW, HW_MACHINE>(hasher);
|
|
# endif
|
|
# ifdef HW_MODEL
|
|
AddSysctl<CTL_HW, HW_MODEL>(hasher);
|
|
# endif
|
|
# ifdef HW_NCPU
|
|
AddSysctl<CTL_HW, HW_NCPU>(hasher);
|
|
# endif
|
|
# ifdef HW_PHYSMEM
|
|
AddSysctl<CTL_HW, HW_PHYSMEM>(hasher);
|
|
# endif
|
|
# ifdef HW_USERMEM
|
|
AddSysctl<CTL_HW, HW_USERMEM>(hasher);
|
|
# endif
|
|
# ifdef HW_MACHINE_ARCH
|
|
AddSysctl<CTL_HW, HW_MACHINE_ARCH>(hasher);
|
|
# endif
|
|
# ifdef HW_REALMEM
|
|
AddSysctl<CTL_HW, HW_REALMEM>(hasher);
|
|
# endif
|
|
# ifdef HW_CPU_FREQ
|
|
AddSysctl<CTL_HW, HW_CPU_FREQ>(hasher);
|
|
# endif
|
|
# ifdef HW_BUS_FREQ
|
|
AddSysctl<CTL_HW, HW_BUS_FREQ>(hasher);
|
|
# endif
|
|
# ifdef HW_CACHELINE
|
|
AddSysctl<CTL_HW, HW_CACHELINE>(hasher);
|
|
# endif
|
|
# endif
|
|
# ifdef CTL_KERN
|
|
# ifdef KERN_BOOTFILE
|
|
AddSysctl<CTL_KERN, KERN_BOOTFILE>(hasher);
|
|
# endif
|
|
# ifdef KERN_BOOTTIME
|
|
AddSysctl<CTL_KERN, KERN_BOOTTIME>(hasher);
|
|
# endif
|
|
# ifdef KERN_CLOCKRATE
|
|
AddSysctl<CTL_KERN, KERN_CLOCKRATE>(hasher);
|
|
# endif
|
|
# ifdef KERN_HOSTID
|
|
AddSysctl<CTL_KERN, KERN_HOSTID>(hasher);
|
|
# endif
|
|
# ifdef KERN_HOSTUUID
|
|
AddSysctl<CTL_KERN, KERN_HOSTUUID>(hasher);
|
|
# endif
|
|
# ifdef KERN_HOSTNAME
|
|
AddSysctl<CTL_KERN, KERN_HOSTNAME>(hasher);
|
|
# endif
|
|
# ifdef KERN_OSRELDATE
|
|
AddSysctl<CTL_KERN, KERN_OSRELDATE>(hasher);
|
|
# endif
|
|
# ifdef KERN_OSRELEASE
|
|
AddSysctl<CTL_KERN, KERN_OSRELEASE>(hasher);
|
|
# endif
|
|
# ifdef KERN_OSREV
|
|
AddSysctl<CTL_KERN, KERN_OSREV>(hasher);
|
|
# endif
|
|
# ifdef KERN_OSTYPE
|
|
AddSysctl<CTL_KERN, KERN_OSTYPE>(hasher);
|
|
# endif
|
|
# ifdef KERN_POSIX1
|
|
AddSysctl<CTL_KERN, KERN_OSREV>(hasher);
|
|
# endif
|
|
# ifdef KERN_VERSION
|
|
AddSysctl<CTL_KERN, KERN_VERSION>(hasher);
|
|
# endif
|
|
# endif
|
|
#endif
|
|
|
|
// Env variables
|
|
if (environ) {
|
|
for (size_t i = 0; environ[i]; ++i) {
|
|
hasher.Write((const unsigned char*)environ[i], strlen(environ[i]));
|
|
}
|
|
}
|
|
|
|
// Process, thread, user, session, group, ... ids.
|
|
#ifdef WIN32
|
|
hasher << GetCurrentProcessId() << GetCurrentThreadId();
|
|
#else
|
|
hasher << getpid() << getppid() << getsid(0) << getpgid(0) << getuid() << geteuid() << getgid() << getegid();
|
|
#endif
|
|
hasher << std::this_thread::get_id();
|
|
}
|