From 2279308e25af49e91431c9fbb629211ce82d23f6 Mon Sep 17 00:00:00 2001 From: vit9696 Date: Tue, 4 Jan 2022 15:33:32 +0300 Subject: [PATCH 1/4] Fixed memory corruption when mixing cs_validate_range/page routes hookMemoryAccess used a legacy API which is unable to use slotted jumping, while plugins do use slotted jumping on 10.15 and earlier. Thanks @Goshin --- Changelog.md | 1 + Lilu/Sources/kern_user.cpp | 69 ++++++++++---------------------------- 2 files changed, 18 insertions(+), 52 deletions(-) diff --git a/Changelog.md b/Changelog.md index 7cff4e14..486dc76d 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,7 @@ Lilu Changelog - Fixed kernel panic on macOS 10.15 and earlier introduced in 1.5.7 - Added Alder Lake CPU model support - Added shared patcher instance grabbing API +- Fixed memory corruption when mixing cs_validate_range/page mid/long routes (thx @Goshin) #### v1.5.7 - Added address slot support for all 64-bit macOS version diff --git a/Lilu/Sources/kern_user.cpp b/Lilu/Sources/kern_user.cpp index 808d9ed1..6827652d 100644 --- a/Lilu/Sources/kern_user.cpp +++ b/Lilu/Sources/kern_user.cpp @@ -1053,30 +1053,13 @@ vm_prot_t UserPatcher::getPageProtection(vm_map_t map, vm_map_address_t addr) { bool UserPatcher::hookMemoryAccess() { // 10.12 and newer - mach_vm_address_t kern = patcher->solveSymbol(KernelPatcher::KernelID, "_cs_validate_range"); - - if (patcher->getError() == KernelPatcher::Error::NoError) { - orgCodeSignValidateRangeWrapper = patcher->routeFunctionLong(kern, reinterpret_cast(codeSignValidateRangeWrapper), true, true); - - if (patcher->getError() != KernelPatcher::Error::NoError) { - SYSLOG("user", "failed to hook _cs_validate_range"); - patcher->clearError(); - return false; - } - } else if (static_cast(patcher->clearError()), - static_cast(kern = patcher->solveSymbol(KernelPatcher::KernelID, "_cs_validate_page")), - patcher->getError() == KernelPatcher::Error::NoError) { - orgCodeSignValidatePageWrapper = patcher->routeFunctionLong(kern, reinterpret_cast(codeSignValidatePageWrapper), true, true); - - if (patcher->getError() != KernelPatcher::Error::NoError) { - SYSLOG("user", "failed to hook _cs_validate_page"); - patcher->clearError(); + KernelPatcher::RouteRequest rangeRoute {"_cs_validate_range", codeSignValidateRangeWrapper, orgCodeSignValidateRangeWrapper}; + if (!patcher->routeMultipleLong(KernelPatcher::KernelID, &rangeRoute, 1)) { + KernelPatcher::RouteRequest pageRoute {"_cs_validate_page", codeSignValidatePageWrapper, orgCodeSignValidatePageWrapper}; + if (!patcher->routeMultipleLong(KernelPatcher::KernelID, &pageRoute, 1)) { + SYSLOG("user", "failed to resolve _cs_validate function"); return false; } - } else { - SYSLOG("user", "failed to resolve _cs_validate function"); - patcher->clearError(); - return false; } orgCurrentMap = reinterpret_cast(patcher->solveSymbol(KernelPatcher::KernelID, "_current_map")); @@ -1139,42 +1122,24 @@ bool UserPatcher::hookMemoryAccess() { } if (patchDyldSharedCache) { - kern = patcher->solveSymbol(KernelPatcher::KernelID, "_vm_shared_region_map_file"); - - if (patcher->getError() == KernelPatcher::Error::NoError) { - orgVmSharedRegionMapFile = patcher->routeFunctionLong(kern, reinterpret_cast(vmSharedRegionMapFile), true, true); - - if (patcher->getError() != KernelPatcher::Error::NoError) { - SYSLOG("user", "failed to hook _vm_shared_region_map_file"); - patcher->clearError(); - return false; - } - - } else { - SYSLOG("user", "failed to resolve _vm_shared_region_map_file"); - patcher->clearError(); + KernelPatcher::RouteRequest mapRoute {"_vm_shared_region_map_file", vmSharedRegionMapFile, orgVmSharedRegionMapFile}; + if (!patcher->routeMultipleLong(KernelPatcher::KernelID, &mapRoute, 1)) { + SYSLOG("user", "failed to hook _vm_shared_region_map_file"); return false; } - - kern = patcher->solveSymbol(KernelPatcher::KernelID, "_vm_shared_region_slide"); - - if (patcher->getError() == KernelPatcher::Error::NoError) { - // 10.14 takes an extra argument here. - if (getKernelVersion() >= KernelVersion::Mojave) - orgVmSharedRegionSlideMojave = patcher->routeFunctionLong(kern, reinterpret_cast(vmSharedRegionSlideMojave), true, true); - else - orgVmSharedRegionSlide = patcher->routeFunctionLong(kern, reinterpret_cast(vmSharedRegionSlide), true, true); - - if (patcher->getError() != KernelPatcher::Error::NoError) { + + if (getKernelVersion() >= KernelVersion::Mojave) { + KernelPatcher::RouteRequest sharedRegionRoute {"_vm_shared_region_slide", vmSharedRegionSlideMojave, orgVmSharedRegionSlideMojave}; + if (!patcher->routeMultipleLong(KernelPatcher::KernelID, &sharedRegionRoute, 1)) { SYSLOG("user", "failed to hook _vm_shared_region_slide"); - patcher->clearError(); return false; } - } else { - SYSLOG("user", "failed to resolve _vm_shared_region_slide"); - patcher->clearError(); - return false; + KernelPatcher::RouteRequest sharedRegionRoute {"_vm_shared_region_slide", vmSharedRegionSlide, orgVmSharedRegionSlide}; + if (!patcher->routeMultipleLong(KernelPatcher::KernelID, &sharedRegionRoute, 1)) { + SYSLOG("user", "failed to hook _vm_shared_region_slide"); + return false; + } } } From 6f42d139b78cf94427d20211ce4084c5a7e9d2f3 Mon Sep 17 00:00:00 2001 From: vit9696 Date: Tue, 4 Jan 2022 15:37:36 +0300 Subject: [PATCH 2/4] Enforced all routes to be slotted after one slotted route --- Changelog.md | 1 + Lilu/Sources/kern_patcher.cpp | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 486dc76d..fb1270f3 100644 --- a/Changelog.md +++ b/Changelog.md @@ -5,6 +5,7 @@ Lilu Changelog - Added Alder Lake CPU model support - Added shared patcher instance grabbing API - Fixed memory corruption when mixing cs_validate_range/page mid/long routes (thx @Goshin) +- Enforced all routes to be slotted after one slotted route #### v1.5.7 - Added address slot support for all 64-bit macOS version diff --git a/Lilu/Sources/kern_patcher.cpp b/Lilu/Sources/kern_patcher.cpp index cd3bbf25..58c55e82 100644 --- a/Lilu/Sources/kern_patcher.cpp +++ b/Lilu/Sources/kern_patcher.cpp @@ -427,7 +427,10 @@ mach_vm_address_t KernelPatcher::routeFunctionInternal(mach_vm_address_t from, m PANIC("patcher", "current plugin has short jump type on a multiroute function, this is not allowed"); // Make sure to use just 6 bytes for medium routes instead of 14. - if (prevJump == JumpType::Medium && info) { + if (prevJump == JumpType::Medium) { + // If this happens, we can corrupt memory. Force everyone use new APIs. + if (!info) + PANIC("patcher", "trying to use long jump on top of slotted jump, please use routeMultipleLong"); addressSlot = info->getAddressSlot(); DBGLOG("patcher", "using slotted jumping for previous via " PRIKADDR, CASTKADDR(addressSlot)); // If this happens, then we should allow slotted jumping only for Auto type. From 62da8e22037e284fd356be8c9b10bb54c5ccd035 Mon Sep 17 00:00:00 2001 From: vit9696 Date: Tue, 4 Jan 2022 15:41:04 +0300 Subject: [PATCH 3/4] Refactored all internal routes to use new RouteRequest API --- Changelog.md | 1 + Lilu/Sources/kern_api.cpp | 16 +++------------- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/Changelog.md b/Changelog.md index fb1270f3..f776430f 100644 --- a/Changelog.md +++ b/Changelog.md @@ -6,6 +6,7 @@ Lilu Changelog - Added shared patcher instance grabbing API - Fixed memory corruption when mixing cs_validate_range/page mid/long routes (thx @Goshin) - Enforced all routes to be slotted after one slotted route +- Refactored all internal routes to use new RouteRequest API #### v1.5.7 - Added address slot support for all 64-bit macOS version diff --git a/Lilu/Sources/kern_api.cpp b/Lilu/Sources/kern_api.cpp index 24162af2..380fe562 100644 --- a/Lilu/Sources/kern_api.cpp +++ b/Lilu/Sources/kern_api.cpp @@ -254,19 +254,9 @@ void LiluAPI::processPatcherLoadCallbacks(KernelPatcher &patcher) { } if (entitlementRequestedCallbacks.size() > 0) { - auto entitlement = patcher.solveSymbol(KernelPatcher::KernelID, "__ZN12IOUserClient21copyClientEntitlementEP4taskPKc"); - - if (entitlement) { - orgCopyClientEntitlement = reinterpret_cast(patcher.routeFunctionLong(entitlement, reinterpret_cast(copyClientEntitlement), true)); - if (patcher.getError() == KernelPatcher::Error::NoError) - DBGLOG("api", "hooked copy user entitlement"); - else - SYSLOG("api", "failed to hook copy user entitlement"); - } else { - SYSLOG("api", "failed to solve copy user entitlement"); - } - - patcher.clearError(); + KernelPatcher::RouteRequest req{"__ZN12IOUserClient21copyClientEntitlementEP4taskPKc", copyClientEntitlement, orgCopyClientEntitlement}; + if (!patcher.routeMultiple(KernelPatcher::KernelID, &req, 1)) + SYSLOG("api", "failed to hook copy user entitlement"); } #ifdef LILU_KEXTPATCH_SUPPORT From bd48fa7f4d9773bab1f6dfb7890b9a98ab08d829 Mon Sep 17 00:00:00 2001 From: vit9696 Date: Tue, 4 Jan 2022 15:45:16 +0300 Subject: [PATCH 4/4] Deprecated routeFunction APIs as they are dangerous for multiple routes --- Changelog.md | 1 + Lilu.xcodeproj/project.pbxproj | 2 +- Lilu/Headers/kern_patcher.hpp | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Changelog.md b/Changelog.md index f776430f..b7a95c33 100644 --- a/Changelog.md +++ b/Changelog.md @@ -7,6 +7,7 @@ Lilu Changelog - Fixed memory corruption when mixing cs_validate_range/page mid/long routes (thx @Goshin) - Enforced all routes to be slotted after one slotted route - Refactored all internal routes to use new RouteRequest API +- Deprecated routeFunction APIs as they are dangerous to use for multiple routes #### v1.5.7 - Added address slot support for all 64-bit macOS version diff --git a/Lilu.xcodeproj/project.pbxproj b/Lilu.xcodeproj/project.pbxproj index d82df856..1eae222f 100644 --- a/Lilu.xcodeproj/project.pbxproj +++ b/Lilu.xcodeproj/project.pbxproj @@ -570,7 +570,7 @@ 1C748C1E1C21952C0024EED2 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1250; + LastUpgradeCheck = 1320; ORGANIZATIONNAME = vit9696; TargetAttributes = { 1C748C261C21952C0024EED2 = { diff --git a/Lilu/Headers/kern_patcher.hpp b/Lilu/Headers/kern_patcher.hpp index 3e424fea..bb1bf2aa 100644 --- a/Lilu/Headers/kern_patcher.hpp +++ b/Lilu/Headers/kern_patcher.hpp @@ -384,7 +384,7 @@ class KernelPatcher { * * @return wrapper pointer or 0 on success */ - EXPORT mach_vm_address_t routeFunction(mach_vm_address_t from, mach_vm_address_t to, bool buildWrapper=false, bool kernelRoute=true, bool revertible=true); + EXPORT mach_vm_address_t routeFunction(mach_vm_address_t from, mach_vm_address_t to, bool buildWrapper=false, bool kernelRoute=true, bool revertible=true) DEPRECATE("Use routeMultiple where possible"); /** * Route function to function with long jump @@ -397,7 +397,7 @@ class KernelPatcher { * * @return wrapper pointer or 0 on success */ - EXPORT mach_vm_address_t routeFunctionLong(mach_vm_address_t from, mach_vm_address_t to, bool buildWrapper=false, bool kernelRoute=true, bool revertible=true); + EXPORT mach_vm_address_t routeFunctionLong(mach_vm_address_t from, mach_vm_address_t to, bool buildWrapper=false, bool kernelRoute=true, bool revertible=true) DEPRECATE("Use routeMultiple where possible"); /** * Route function to function with short jump @@ -410,7 +410,7 @@ class KernelPatcher { * * @return wrapper pointer or 0 on success */ - EXPORT mach_vm_address_t routeFunctionShort(mach_vm_address_t from, mach_vm_address_t to, bool buildWrapper=false, bool kernelRoute=true, bool revertible=true); + EXPORT mach_vm_address_t routeFunctionShort(mach_vm_address_t from, mach_vm_address_t to, bool buildWrapper=false, bool kernelRoute=true, bool revertible=true) DEPRECATE("Use routeMultiple where possible"); /** * Route block at assembly level