From 68cad0ef99b071cf03b8477d828f732485fca16b Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 7 Nov 2017 08:34:06 -0800 Subject: QSysInfo: Remove the caches in {boot,machine}UniqueId() Looks like there are conditions in which they could be used during shut down and thus access an already-destroyed static. This was tested in test tst_lockfile.cpp:LockFileUsageInGlobalDtor. Change-Id: I57a1bd6e0c194530b732fffd14f4dae39ab1ae2c Reviewed-by: Kai Koehne --- src/corelib/global/qglobal.cpp | 116 +++++++++++++++++++---------------------- 1 file changed, 54 insertions(+), 62 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 619436e3db..7200f55777 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -2877,57 +2877,53 @@ enum { */ QByteArray QSysInfo::machineUniqueId() { - // the machine unique ID cannot change - static const QByteArray cache = []() { #ifdef Q_OS_BSD4 - char uuid[UuidStringLen]; - size_t uuidlen = sizeof(uuid); + char uuid[UuidStringLen]; + size_t uuidlen = sizeof(uuid); # ifdef KERN_HOSTUUID - int name[] = { CTL_KERN, KERN_HOSTUUID }; - if (sysctl(name, sizeof name / sizeof name[0], &uuid, &uuidlen, nullptr, 0) == 0 - && uuidlen == sizeof(uuid)) - return QByteArray(uuid, uuidlen); + int name[] = { CTL_KERN, KERN_HOSTUUID }; + if (sysctl(name, sizeof name / sizeof name[0], &uuid, &uuidlen, nullptr, 0) == 0 + && uuidlen == sizeof(uuid)) + return QByteArray(uuid, uuidlen); # else - // Darwin: no fixed value, we need to search by name - if (sysctlbyname("kern.uuid", uuid, &uuidlen, nullptr, 0) == 0 && uuidlen == sizeof(uuid)) - return QByteArray(uuid, uuidlen); + // Darwin: no fixed value, we need to search by name + if (sysctlbyname("kern.uuid", uuid, &uuidlen, nullptr, 0) == 0 && uuidlen == sizeof(uuid)) + return QByteArray(uuid, uuidlen); # endif #elif defined(Q_OS_UNIX) - // The modern name on Linux is /etc/machine-id, but that path is - // unlikely to exist on non-Linux (non-systemd) systems. The old - // path is more than enough. - static const char fullfilename[] = "/usr/local/var/lib/dbus/machine-id"; - const char *firstfilename = fullfilename + sizeof("/usr/local") - 1; - int fd = qt_safe_open(firstfilename, O_RDONLY); - if (fd == -1 && errno == ENOENT) - fd = qt_safe_open(fullfilename, O_RDONLY); - - if (fd != -1) { - char buffer[32]; // 128 bits, hex-encoded - qint64 len = qt_safe_read(fd, buffer, sizeof(buffer)); - qt_safe_close(fd); + // The modern name on Linux is /etc/machine-id, but that path is + // unlikely to exist on non-Linux (non-systemd) systems. The old + // path is more than enough. + static const char fullfilename[] = "/usr/local/var/lib/dbus/machine-id"; + const char *firstfilename = fullfilename + sizeof("/usr/local") - 1; + int fd = qt_safe_open(firstfilename, O_RDONLY); + if (fd == -1 && errno == ENOENT) + fd = qt_safe_open(fullfilename, O_RDONLY); + + if (fd != -1) { + char buffer[32]; // 128 bits, hex-encoded + qint64 len = qt_safe_read(fd, buffer, sizeof(buffer)); + qt_safe_close(fd); - if (len != -1) - return QByteArray(buffer, len); - } + if (len != -1) + return QByteArray(buffer, len); + } #elif defined(Q_OS_WIN) && !defined(Q_OS_WINRT) - // Let's poke at the registry - HKEY key = NULL; - if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Cryptography", 0, KEY_READ, &key) - == ERROR_SUCCESS) { - wchar_t buffer[UuidStringLen + 1]; - DWORD size = sizeof(buffer); - bool ok = (RegQueryValueEx(key, L"MachineGuid", NULL, NULL, (LPBYTE)buffer, &size) == - ERROR_SUCCESS); - RegCloseKey(key); - if (ok) - return QStringView(buffer, (size - 1) / 2).toLatin1(); - } + // Let's poke at the registry + HKEY key = NULL; + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Cryptography", 0, KEY_READ, &key) + == ERROR_SUCCESS) { + wchar_t buffer[UuidStringLen + 1]; + DWORD size = sizeof(buffer); + bool ok = (RegQueryValueEx(key, L"MachineGuid", NULL, NULL, (LPBYTE)buffer, &size) == + ERROR_SUCCESS); + RegCloseKey(key); + if (ok) + return QStringView(buffer, (size - 1) / 2).toLatin1(); + } #endif - return QByteArray(); - }(); - return cache; + return QByteArray(); } /*! @@ -2945,29 +2941,25 @@ QByteArray QSysInfo::machineUniqueId() */ QByteArray QSysInfo::bootUniqueId() { - // the boot unique ID cannot change - static const QByteArray cache = []() { #ifdef Q_OS_LINUX - // use low-level API here for simplicity - int fd = qt_safe_open("/proc/sys/kernel/random/boot_id", O_RDONLY); - if (fd != -1) { - char uuid[UuidStringLen]; - qint64 len = qt_safe_read(fd, uuid, sizeof(uuid)); - qt_safe_close(fd); - if (len == UuidStringLen) - return QByteArray(uuid, UuidStringLen); - } -#elif defined(Q_OS_DARWIN) - // "kern.bootsessionuuid" is only available by name + // use low-level API here for simplicity + int fd = qt_safe_open("/proc/sys/kernel/random/boot_id", O_RDONLY); + if (fd != -1) { char uuid[UuidStringLen]; - size_t uuidlen = sizeof(uuid); - if (sysctlbyname("kern.bootsessionuuid", uuid, &uuidlen, nullptr, 0) == 0 - && uuidlen == sizeof(uuid)) - return QByteArray(uuid, uuidlen); + qint64 len = qt_safe_read(fd, uuid, sizeof(uuid)); + qt_safe_close(fd); + if (len == UuidStringLen) + return QByteArray(uuid, UuidStringLen); + } +#elif defined(Q_OS_DARWIN) + // "kern.bootsessionuuid" is only available by name + char uuid[UuidStringLen]; + size_t uuidlen = sizeof(uuid); + if (sysctlbyname("kern.bootsessionuuid", uuid, &uuidlen, nullptr, 0) == 0 + && uuidlen == sizeof(uuid)) + return QByteArray(uuid, uuidlen); #endif - return QByteArray(); - }(); - return cache; + return QByteArray(); }; /*! -- cgit v1.2.3