diff --git a/src/osal.c b/src/osal.c index 873b94b7..c2a6a649 100644 --- a/src/osal.c +++ b/src/osal.c @@ -3011,6 +3011,29 @@ __cold static LSTATUS mdbx_RegGetValue(HKEY hKey, LPCSTR lpSubKey, } #endif +static size_t hamming_weight(size_t v) { + const size_t m1 = (size_t)UINT64_C(0x5555555555555555); + const size_t m2 = (size_t)UINT64_C(0x3333333333333333); + const size_t m4 = (size_t)UINT64_C(0x0f0f0f0f0f0f0f0f); + const size_t h01 = (size_t)UINT64_C(0x0101010101010101); + v -= (v >> 1) & m1; + v = (v & m2) + ((v >> 2) & m2); + v = (v + (v >> 4)) & m4; + return (v * h01) >> (sizeof(v) * 8 - 8); +} + +static inline size_t hw64(uint64_t v) { + size_t r = hamming_weight((size_t)v); + if (sizeof(v) > sizeof(r)) + r += hamming_weight((size_t)(v >> sizeof(r) * 4 >> sizeof(r) * 4)); + return r; +} + +static bool check_uuid(bin128_t uuid) { + size_t hw = hw64(uuid.x) + hw64(uuid.y) + hw64(uuid.x ^ uuid.y); + return (hw >> 6) == 1; +} + __cold MDBX_MAYBE_UNUSED static bool bootid_parse_uuid(bin128_t *s, const void *p, const size_t n) { if (n > 31) { @@ -3044,7 +3067,7 @@ bootid_parse_uuid(bin128_t *s, const void *p, const size_t n) { s->y += aligned.y; } else bootid_collect(s, p, n); - return true; + return check_uuid(*s); } if (n) @@ -3052,28 +3075,53 @@ bootid_parse_uuid(bin128_t *s, const void *p, const size_t n) { return false; } -__cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) { - bin128_t bin = {{0, 0}}; +#if defined(__linux__) || defined(__gnu_linux__) + +__cold static bool is_inside_lxc(void) { + bool inside_lxc = false; + FILE *mounted = setmntent("/proc/mounts", "r"); + if (mounted) { + const struct mntent *ent; + while (nullptr != (ent = getmntent(mounted))) { + if (strcmp(ent->mnt_fsname, "lxcfs") == 0 && + strncmp(ent->mnt_dir, "/proc/", 6) == 0) { + inside_lxc = true; + break; + } + } + endmntent(mounted); + } + return inside_lxc; +} + +__cold static bool proc_read_uuid(const char *path, bin128_t *target) { + const int fd = open(path, O_RDONLY | O_NOFOLLOW); + if (fd != -1) { + struct statfs fs; + char buf[42]; + const ssize_t len = + (fstatfs(fd, &fs) == 0 && + (fs.f_type == /* procfs */ 0x9FA0 || + (fs.f_type == /* tmpfs */ 0x1021994 && is_inside_lxc()))) + ? read(fd, buf, sizeof(buf)) + : -1; + const int err = close(fd); + assert(err == 0); + (void)err; + if (len > 0) + return bootid_parse_uuid(target, buf, len); + } + return false; +} +#endif /* Linux */ + +__cold bin128_t osal_bootid(void) { + bin128_t uuid = {{0, 0}}; bool got_machineid = false, got_boottime = false, got_bootseq = false; #if defined(__linux__) || defined(__gnu_linux__) - { - const int fd = - open("/proc/sys/kernel/random/boot_id", O_RDONLY | O_NOFOLLOW); - if (fd != -1) { - struct statfs fs; - char buf[42]; - const ssize_t len = - (fstatfs(fd, &fs) == 0 && fs.f_type == /* procfs */ 0x9FA0) - ? read(fd, buf, sizeof(buf)) - : -1; - const int err = close(fd); - assert(err == 0); - (void)err; - if (len > 0 && bootid_parse_uuid(&bin, buf, len)) - return bin; - } - } + if (proc_read_uuid("/proc/sys/kernel/random/boot_id", &uuid)) + return uuid; #endif /* Linux */ #if defined(__APPLE__) || defined(__MACH__) @@ -3081,16 +3129,15 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) { char buf[42]; size_t len = sizeof(buf); if (!sysctlbyname("kern.bootsessionuuid", buf, &len, nullptr, 0) && - bootid_parse_uuid(&bin, buf, len)) - return bin; + bootid_parse_uuid(&uuid, buf, len)) + return uuid; #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && \ __MAC_OS_X_VERSION_MIN_REQUIRED > 1050 - uuid_t uuid; + uuid_t hostuuid; struct timespec wait = {0, 1000000000u / 42}; - if (!gethostuuid(uuid, &wait) && - bootid_parse_uuid(&bin, uuid, sizeof(uuid))) - got_machineid = true; + if (!gethostuuid(hostuuid, &wait)) + got_machineid = bootid_parse_uuid(&uuid, hostuuid, sizeof(hostuuid)); #endif /* > 10.5 */ struct timeval boottime; @@ -3128,7 +3175,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) { "MachineGuid", &buf.MachineGuid, &len) == ERROR_SUCCESS && len < sizeof(buf)) - got_machineid = bootid_parse_uuid(&bin, &buf.MachineGuid, len); + got_machineid = bootid_parse_uuid(&uuid, &buf.MachineGuid, len); if (!got_machineid) { /* again, Windows is madness */ @@ -3146,7 +3193,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) { "DigitalProductId", &buf.DigitalProductId, &len) == ERROR_SUCCESS && len > 42 && len < sizeof(buf)) { - bootid_collect(&bin, &buf.DigitalProductId, len); + bootid_collect(&uuid, &buf.DigitalProductId, len); got_machineid = true; } len = sizeof(buf); @@ -3154,7 +3201,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) { "DigitalProductId", &buf.DigitalProductId, &len) == ERROR_SUCCESS && len > 42 && len < sizeof(buf)) { - bootid_collect(&bin, &buf.DigitalProductId, len); + bootid_collect(&uuid, &buf.DigitalProductId, len); got_machineid = true; } len = sizeof(buf); @@ -3162,7 +3209,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) { "DigitalProductId", &buf.DigitalProductId, &len) == ERROR_SUCCESS && len > 42 && len < sizeof(buf)) { - bootid_collect(&bin, &buf.DigitalProductId, len); + bootid_collect(&uuid, &buf.DigitalProductId, len); got_machineid = true; } } @@ -3174,7 +3221,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) { if (mdbx_RegGetValue(HKEY_LOCAL_MACHINE, HKLM_PrefetcherParams, "BootId", &buf.BootId, &len) == ERROR_SUCCESS && len > 1 && len < sizeof(buf)) { - bootid_collect(&bin, &buf.BootId, len); + bootid_collect(&uuid, &buf.BootId, len); got_bootseq = true; } @@ -3182,7 +3229,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) { if (mdbx_RegGetValue(HKEY_LOCAL_MACHINE, HKLM_PrefetcherParams, "BaseTime", &buf.BaseTime, &len) == ERROR_SUCCESS && len >= sizeof(buf.BaseTime) && buf.BaseTime) { - bootid_collect(&bin, &buf.BaseTime, len); + bootid_collect(&uuid, &buf.BaseTime, len); got_boottime = true; } @@ -3198,7 +3245,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) { buf.SysTimeOfDayInfoHacked.BootTime.QuadPart - buf.SysTimeOfDayInfoHacked.BootTimeBias; if (UnbiasedBootTime) { - bootid_collect(&bin, &UnbiasedBootTime, sizeof(UnbiasedBootTime)); + bootid_collect(&uuid, &UnbiasedBootTime, sizeof(UnbiasedBootTime)); got_boottime = true; } } @@ -3206,7 +3253,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) { if (!got_boottime) { uint64_t boottime = windows_bootime(); if (boottime) { - bootid_collect(&bin, &boottime, sizeof(boottime)); + bootid_collect(&uuid, &boottime, sizeof(boottime)); got_boottime = true; } } @@ -3223,8 +3270,8 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) { (int *) #endif mib, - ARRAY_LENGTH(mib), &buf, &len, NULL, 0) == 0) - got_machineid = bootid_parse_uuid(&bin, buf, len); + ARRAY_LENGTH(mib), &buf, &len, nullptr, 0) == 0) + got_machineid = bootid_parse_uuid(&uuid, buf, len); } #endif /* CTL_HW && HW_UUID */ @@ -3238,8 +3285,8 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) { (int *) #endif mib, - ARRAY_LENGTH(mib), &buf, &len, NULL, 0) == 0) - got_machineid = bootid_parse_uuid(&bin, buf, len); + ARRAY_LENGTH(mib), &buf, &len, nullptr, 0) == 0) + got_machineid = bootid_parse_uuid(&uuid, buf, len); } #endif /* CTL_KERN && KERN_HOSTUUID */ @@ -3247,16 +3294,33 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) { if (!got_machineid) { char buf[42]; size_t len = sizeof(buf); - if (sysctlbyname("machdep.dmi.system-uuid", buf, &len, NULL, 0) == 0) - got_machineid = bootid_parse_uuid(&bin, buf, len); + if (sysctlbyname("machdep.dmi.system-uuid", buf, &len, nullptr, 0) == 0) + got_machineid = bootid_parse_uuid(&uuid, buf, len); } #endif /* __NetBSD__ */ +#if !(defined(_WIN32) || defined(_WIN64)) + if (!got_machineid) { + int fd = open("/etc/machine-id", O_RDONLY); + if (fd == -1) + fd = open("/var/lib/dbus/machine-id", O_RDONLY); + if (fd != -1) { + char buf[42]; + const ssize_t len = read(fd, buf, sizeof(buf)); + const int err = close(fd); + assert(err == 0); + (void)err; + if (len > 0) + got_machineid = bootid_parse_uuid(&uuid, buf, len); + } + } +#endif /* !Windows */ + #if _XOPEN_SOURCE_EXTENDED if (!got_machineid) { - const int hostid = gethostid(); - if (hostid > 0) { - bootid_collect(&bin, &hostid, sizeof(hostid)); + const long hostid = gethostid(); + if (hostid != 0 && hostid != -1) { + bootid_collect(&uuid, &hostid, sizeof(hostid)); got_machineid = true; } } @@ -3264,8 +3328,8 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) { if (!got_machineid) { lack: - bin.x = bin.y = 0; - return bin; + uuid.x = uuid.y = 0; + return uuid; } /*--------------------------------------------------------------------------*/ @@ -3280,9 +3344,9 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) { (int *) #endif mib, - ARRAY_LENGTH(mib), &boottime, &len, NULL, 0) == 0 && + ARRAY_LENGTH(mib), &boottime, &len, nullptr, 0) == 0 && len == sizeof(boottime) && boottime.tv_sec) { - bootid_collect(&bin, &boottime, len); + bootid_collect(&uuid, &boottime, len); got_boottime = true; } } @@ -3299,11 +3363,11 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) { switch (kn->data_type) { case KSTAT_DATA_INT32: case KSTAT_DATA_UINT32: - bootid_collect(&bin, &kn->value, sizeof(int32_t)); + bootid_collect(&uuid, &kn->value, sizeof(int32_t)); got_boottime = true; case KSTAT_DATA_INT64: case KSTAT_DATA_UINT64: - bootid_collect(&bin, &kn->value, sizeof(int64_t)); + bootid_collect(&uuid, &kn->value, sizeof(int64_t)); got_boottime = true; } } @@ -3319,12 +3383,12 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) { const struct utmpx id = {.ut_type = BOOT_TIME}; const struct utmpx *entry = getutxid(&id); if (entry) { - bootid_collect(&bin, entry, sizeof(*entry)); + bootid_collect(&uuid, entry, sizeof(*entry)); got_boottime = true; while (unlikely((entry = getutxid(&id)) != nullptr)) { /* have multiple reboot records, assuming we can distinguish next * bootsession even if RTC is wrong or absent */ - bootid_collect(&bin, entry, sizeof(*entry)); + bootid_collect(&uuid, entry, sizeof(*entry)); got_bootseq = true; } } @@ -3353,7 +3417,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) { goto lack; } - return bin; + return uuid; } __cold int mdbx_get_sysraminfo(intptr_t *page_size, intptr_t *total_pages,