Skip to content

Commit 4f09e57

Browse files
Julian Lettneryln
authored andcommitted
GetMacosAlignedVersion() fails if sysctl is not setup
`GetMacosAlignedVersion()` fails for ASan-ified launchd because the sanitizer initialization code runs before `sysctl` has been setup by launchd. In this situation, `sysctl kern.osproductversion` returns a non-empty string that does not match our expectations of a well-formatted version string. Retrieving the kernel version (via `sysctl kern.osrelease`) still works, so we can use it to add a fallback for this corner case. Differential Revision: https://reviews.llvm.org/D94190 Radar-Id: rdar://72253635 (cherry picked from commit 84de4fa)
1 parent 120bf0c commit 4f09e57

File tree

1 file changed

+32
-13
lines changed

1 file changed

+32
-13
lines changed

compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,23 @@ constexpr u16 GetOSMajorKernelOffset() {
620620

621621
using VersStr = char[64];
622622

623+
static uptr ApproximateOSVersionViaKernelVersion(VersStr vers) {
624+
u16 kernel_major = GetDarwinKernelVersion().major;
625+
u16 offset = GetOSMajorKernelOffset();
626+
CHECK_GE(kernel_major, offset);
627+
u16 os_major = kernel_major - offset;
628+
629+
const char *format = "%d.0";
630+
if (TARGET_OS_OSX) {
631+
if (os_major >= 16) { // macOS 11+
632+
os_major -= 5;
633+
} else { // macOS 10.15 and below
634+
format = "10.%d";
635+
}
636+
}
637+
return internal_snprintf(vers, sizeof(VersStr), format, os_major);
638+
}
639+
623640
static void GetOSVersion(VersStr vers) {
624641
uptr len = sizeof(VersStr);
625642
if (SANITIZER_IOSSIM) {
@@ -633,17 +650,19 @@ static void GetOSVersion(VersStr vers) {
633650
} else {
634651
int res =
635652
internal_sysctlbyname("kern.osproductversion", vers, &len, nullptr, 0);
636-
if (res) {
637-
// Fallback for XNU 17 (macOS 10.13) and below that do not provide the
638-
// `kern.osproductversion` property.
639-
u16 kernel_major = GetDarwinKernelVersion().major;
640-
u16 offset = GetOSMajorKernelOffset();
641-
CHECK_LE(kernel_major, 17);
642-
CHECK_GE(kernel_major, offset);
643-
u16 os_major = kernel_major - offset;
644-
645-
auto format = TARGET_OS_OSX ? "10.%d" : "%d.0";
646-
len = internal_snprintf(vers, len, format, os_major);
653+
654+
// XNU 17 (macOS 10.13) and below do not provide the sysctl
655+
// `kern.osproductversion` entry (res != 0).
656+
bool no_os_version = res != 0;
657+
658+
// For launchd, sanitizer initialization runs before sysctl is setup
659+
// (res == 0 && len != strlen(vers), vers is not a valid version). However,
660+
// the kernel version `kern.osrelease` is available.
661+
bool launchd = (res == 0 && internal_strlen(vers) < 3);
662+
if (launchd) CHECK_EQ(internal_getpid(), 1);
663+
664+
if (no_os_version || launchd) {
665+
len = ApproximateOSVersionViaKernelVersion(vers);
647666
}
648667
}
649668
CHECK_LT(len, sizeof(VersStr));
@@ -681,7 +700,7 @@ static void MapToMacos(u16 *major, u16 *minor) {
681700
}
682701

683702
static MacosVersion GetMacosAlignedVersionInternal() {
684-
VersStr vers;
703+
VersStr vers = {};
685704
GetOSVersion(vers);
686705

687706
u16 major, minor;
@@ -707,7 +726,7 @@ MacosVersion GetMacosAlignedVersion() {
707726
}
708727

709728
DarwinKernelVersion GetDarwinKernelVersion() {
710-
VersStr vers;
729+
VersStr vers = {};
711730
uptr len = sizeof(VersStr);
712731
int res = internal_sysctlbyname("kern.osrelease", vers, &len, nullptr, 0);
713732
CHECK_EQ(res, 0);

0 commit comments

Comments
 (0)