X-Git-Url: https://git.saurik.com/apple/libc.git/blobdiff_plain/4c63d2152434d7a24cd627ef559f93b096274076..fc56b708803d28b949a9181528bb0da4d25b3b7b:/secure/chk_fail.c diff --git a/secure/chk_fail.c b/secure/chk_fail.c index 29401b8..9dc6c00 100644 --- a/secure/chk_fail.c +++ b/secure/chk_fail.c @@ -21,10 +21,91 @@ * @APPLE_LICENSE_HEADER_END@ */ -#include -#include -#include -#include -#include +#include +#include #include +#include "crt_externs.h" +#ifndef PR_13085474_CHECK +#define PR_13085474_CHECK TARGET_OS_OSX +#endif + +#if PR_13085474_CHECK +/* Some shipped applications fail this check and were tested against + * versions of these functions that supported overlapping buffers. + * + * We would rather let such applications run, using the old memmove + * implementation, than abort() because they can't use the new + * implementation. + */ + +#include +#include +#include +#if TARGET_OS_OSX +#define START_VERSION dyld_platform_version_macOS_10_9 +#else +#error "This platform should not build with PR_13085474_CHECK=1" +#endif +#endif /* !PR_13085474_CHECK */ + +/* For PR_13085474_CHECK set, we initialize __chk_assert_no_overlap to + * 1 initially and then reset it to 0 if the main image of the process + * was linked earlier than 10.9. + * + * If PR_13085474_CHECK is zero, then we never do any sdk version checking + * and always do overlap checks. + */ +__attribute__ ((visibility ("hidden"))) +uint32_t __chk_assert_no_overlap = 1; + +#if PR_13085474_CHECK +static bool +__chk_assert_sdk_pre_start(const struct mach_header *mh) { + return (dyld_get_active_platform() == PLATFORM_MACOS && + !dyld_sdk_at_least(mh, START_VERSION)); +} +#endif + +__attribute__ ((visibility ("hidden"))) +void __chk_init(void) { +#if PR_13085474_CHECK + if (__chk_assert_sdk_pre_start((const struct mach_header *) + _NSGetMachExecuteHeader())) { + __chk_assert_no_overlap = 0; + } +#endif +} + +__attribute__ ((visibility ("hidden"))) +__attribute__ ((noreturn)) +void +__chk_fail_overflow (void) { + os_crash("detected buffer overflow"); +} + +__attribute__ ((visibility ("hidden"))) +__attribute__ ((noreturn)) +void +__chk_fail_overlap (void) { + os_crash("detected source and destination buffer overlap"); +} + +__attribute__ ((visibility ("hidden"))) +void +__chk_overlap (const void *_a, size_t an, const void *_b, size_t bn) { + uintptr_t a = (uintptr_t)_a; + uintptr_t b = (uintptr_t)_b; + + if (__builtin_expect(an == 0 || bn == 0, 0)) { + return; + } else if (__builtin_expect(a == b, 0)) { + __chk_fail_overlap(); + } else if (a < b) { + if (__builtin_expect(a + an > b, 0)) + __chk_fail_overlap(); + } else { // b < a + if (__builtin_expect(b + bn > a, 0)) + __chk_fail_overlap(); + } +}