From b105a73a103e2e349c5d2aff2b09b7f1e6c169f9 Mon Sep 17 00:00:00 2001 From: Mykola Grymalyuk Date: Sat, 27 Aug 2022 09:29:38 -0600 Subject: [PATCH 1/2] sys_patch: Add KDK-less support Only Applicable for Kepler and Intel iGPUs at this time --- data/sys_patch_dict.py | 2 +- resources/main.py | 4 ++ resources/sys_patch.py | 79 +++++++++++++++++++++++++++++------ resources/sys_patch_detect.py | 27 ++++++++---- 4 files changed, 89 insertions(+), 23 deletions(-) diff --git a/data/sys_patch_dict.py b/data/sys_patch_dict.py index 02669d5193..2199c5a449 100644 --- a/data/sys_patch_dict.py +++ b/data/sys_patch_dict.py @@ -196,7 +196,7 @@ def SystemPatchDictionary(os_major, os_minor, non_metal_os_support): }, }, - "Metal 1 Common": { + "Metal 3802 Common": { "Display Name": "", "OS Support": { "Minimum OS Support": { diff --git a/resources/main.py b/resources/main.py index 7020ebb6aa..c228391155 100644 --- a/resources/main.py +++ b/resources/main.py @@ -47,6 +47,10 @@ def generate_base_data(self): self.constants.unpack_thread.start() self.constants.commit_info = commit_info.commit_info(self.constants.launcher_binary).generate_commit_info() + # Now that we have commit info, update nightly link + if self.constants.commit_info[0] != "Running from source": + self.constants.installer_pkg_url_nightly = self.constants.installer_pkg_url_nightly.replace("main", self.constants.commit_info[0]) + defaults.generate_defaults.probe(self.computer.real_model, True, self.constants) if utilities.check_cli_args() is not None: diff --git a/resources/sys_patch.py b/resources/sys_patch.py index 88fc43c01a..5562d73e0e 100644 --- a/resources/sys_patch.py +++ b/resources/sys_patch.py @@ -32,6 +32,7 @@ # This is because Apple removed on-disk binaries (ref: https://github.com/dortania/OpenCore-Legacy-Patcher/issues/998) # 'sudo ditto /Library/Developer/KDKs//System /System/Volumes/Update/mnt1/System' +import plistlib import shutil import subprocess from pathlib import Path @@ -60,6 +61,8 @@ def __init__(self, model, versions, hardware_details=None): self.hardware_details = hardware_details self.init_pathing(custom_root_mount_path=None, custom_data_mount_path=None) + self.skip_root_kmutil_requirement = self.hardware_details["Settings: Supports Auxiliary Cache"] + def __del__(self): # Ensures that each time we're patching, we're using a clean repository if Path(self.constants.payload_local_binaries_root_path).exists(): @@ -106,6 +109,8 @@ def mount_root_vol(self): return False def merge_kdk_with_root(self): + if self.skip_root_kmutil_requirement is True: + return if self.constants.detected_os < os_data.os_data.ventura: return if (Path(self.mount_location) / Path("System/Library/Extensions/System.kext/PlugIns/Libkern.kext/Libkern")).exists(): @@ -149,8 +154,23 @@ def unpatch_root_vol(self): print("\nPlease reboot the machine for patches to take effect") def rebuild_snapshot(self): - print("- Rebuilding Kernel Cache (This may take some time)") + if self.rebuild_kernel_collection() is True: + self.update_preboot_kernel_cache() + self.rebuild_dyld_shared_cache() + if self.create_new_apfs_snapshot() is True: + print("- Patching complete") + print("\nPlease reboot the machine for patches to take effect") + if self.needs_kmutil_exemptions is True: + print("Note: Apple will require you to open System Preferences -> Security to allow the new kernel extensions to be loaded") + self.constants.root_patcher_succeeded = True + if self.constants.gui_mode is False: + input("\nPress [ENTER] to continue") + def rebuild_kernel_collection(self): + if self.skip_root_kmutil_requirement is True: + return True + + print("- Rebuilding Kernel Cache (This may take some time)") if self.constants.detected_os > os_data.os_data.catalina: args = [ "kmutil", @@ -206,18 +226,10 @@ def rebuild_snapshot(self): print("\nPlease reboot the machine to avoid potential issues rerunning the patcher") if self.constants.gui_mode is False: input("Press [ENTER] to continue") - else: - print("- Successfully built new kernel cache") - self.update_preboot_kernel_cache() - self.rebuild_dyld_shared_cache() - if self.create_new_apfs_snapshot() is True: - print("- Patching complete") - print("\nPlease reboot the machine for patches to take effect") - if self.needs_kmutil_exemptions is True: - print("Note: Apple will require you to open System Preferences -> Security to allow the new kernel extensions to be loaded") - self.constants.root_patcher_succeeded = True - if self.constants.gui_mode is False: - input("\nPress [ENTER] to continue") + return False + + print("- Successfully built new kernel cache") + return True def create_new_apfs_snapshot(self): if self.root_supports_snapshot is True: @@ -279,6 +291,46 @@ def write_patchset(self, patchset): utilities.process_status(utilities.elevated(["rm", destination_path_file], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) utilities.process_status(utilities.elevated(["cp", f"{self.constants.payload_path}/{file_name}", destination_path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) + def add_auxkc_support(self, install_file, source_folder_path, install_patch_directory, destination_folder_path): + # In macOS Ventura, KDKs are required to build new Boot and System KCs + # However for some patch sets, we're able to use the Auxiliary KCs with '/Library/Extensions' + + # kernelmanagerd determines which kext is installed by their 'OSBundleRequired' entry + # If a kext is labeled as 'OSBundleRequired: Root' or 'OSBundleRequired: Safe Boot', + # kernelmanagerd will require the kext to be installed in the Boot/SysKC + + # Additionally, kexts starting with 'com.apple.' are not natively allowed to be installed + # in the AuxKC. So we need to explicitly set our 'OSBundleRequired' to 'Auxiliary' + + if self.skip_root_kmutil_requirement is False: + return destination_folder_path + if not install_file.endswith(".kext"): + return destination_folder_path + if install_patch_directory != "/System/Library/Extensions": + return destination_folder_path + if self.constants.detected_os < os_data.os_data.ventura: + return destination_folder_path + + updated_install_location = str(self.mount_location_data) + "/Library/Extensions" + + print(f"- Adding AuxKC support to {install_file}") + plist_path = Path(Path(source_folder_path) / Path(install_file) / Path("Contents/Info.plist")) + plist_data = plistlib.load((plist_path).open("rb")) + + # Check if we need to update the 'OSBundleRequired' entry + if not plist_data["CFBundleIdentifier"].startswith("com.apple."): + return updated_install_location + if "OSBundleRequired" in plist_data: + if plist_data["OSBundleRequired"] == "Auxiliary": + return updated_install_location + + plist_data["OSBundleRequired"] = "Auxiliary" + plistlib.dump(plist_data, plist_path.open("wb")) + + self.constants.needs_to_open_preferences = True + + return updated_install_location + def patch_root_vol(self): print(f"- Running patches for {self.model}") if self.patch_set_dictionary != {}: @@ -316,6 +368,7 @@ def execute_patchset(self, required_patches): if install_patch_directory == "/Library/Extensions": self.needs_kmutil_exemptions = True destination_folder_path = str(self.mount_location_data) + install_patch_directory + destination_folder_path = self.add_auxkc_support(install_file, source_folder_path, install_patch_directory, destination_folder_path) self.install_new_file(source_folder_path, destination_folder_path, install_file) if "Processes" in required_patches[patch]: diff --git a/resources/sys_patch_detect.py b/resources/sys_patch_detect.py index a1184b6d7d..ea5362cbb0 100644 --- a/resources/sys_patch_detect.py +++ b/resources/sys_patch_detect.py @@ -38,6 +38,7 @@ def __init__(self, model, versions): self.amfi_must_disable = False self.supports_metal = False self.needs_nv_web_checks = False + self.requires_root_kc = False # Validation Checks self.sip_enabled = False @@ -63,6 +64,7 @@ def detect_gpus(self): self.nvidia_tesla = True self.amfi_must_disable = True self.legacy_keyboard_backlight = self.check_legacy_keyboard_backlight() + self.requires_root_kc = True elif gpu.arch == device_probe.NVIDIA.Archs.Kepler and self.constants.force_nv_web is False: if self.constants.detected_os > os_data.os_data.big_sur: # Kepler drivers were dropped with Beta 7 @@ -86,14 +88,17 @@ def detect_gpus(self): self.nvidia_web = True self.amfi_must_disable = True self.needs_nv_web_checks = True + self.requires_root_kc = True elif gpu.arch == device_probe.AMD.Archs.TeraScale_1: if self.constants.detected_os > non_metal_os: self.amd_ts1 = True self.amfi_must_disable = True + self.requires_root_kc = True elif gpu.arch == device_probe.AMD.Archs.TeraScale_2: if self.constants.detected_os > non_metal_os: self.amd_ts2 = True self.amfi_must_disable = True + self.requires_root_kc = True elif gpu.arch in [ device_probe.AMD.Archs.Legacy_GCN_7000, device_probe.AMD.Archs.Legacy_GCN_8000, @@ -105,16 +110,19 @@ def detect_gpus(self): continue self.legacy_gcn = True self.supports_metal = True + self.requires_root_kc = True elif gpu.arch == device_probe.Intel.Archs.Iron_Lake: if self.constants.detected_os > non_metal_os: self.iron_gpu = True self.amfi_must_disable = True self.legacy_keyboard_backlight = self.check_legacy_keyboard_backlight() + self.requires_root_kc = True elif gpu.arch == device_probe.Intel.Archs.Sandy_Bridge: if self.constants.detected_os > non_metal_os: self.sandy_gpu = True self.amfi_must_disable = True self.legacy_keyboard_backlight = self.check_legacy_keyboard_backlight() + self.requires_root_kc = True elif gpu.arch == device_probe.Intel.Archs.Ivy_Bridge: if self.constants.detected_os > os_data.os_data.big_sur: self.ivy_gpu = True @@ -287,6 +295,7 @@ def detect_patch_set(self): "Miscellaneous: Legacy GMUX": self.legacy_gmux, "Miscellaneous: Legacy Keyboard Backlight": self.legacy_keyboard_backlight, "Settings: Requires AMFI exemption": self.amfi_must_disable, + "Settings: Supports Auxiliary Cache": not self.requires_root_kc, "Validation: Patching Possible": self.verify_patch_allowed(), f"Validation: SIP is enabled (Required: {self.check_sip()[2]} or higher)": self.sip_enabled, f"Validation: Currently Booted SIP: ({hex(utilities.csr_dump())})": self.sip_enabled, @@ -309,7 +318,8 @@ def verify_patch_allowed(self, print_errors=False): sip_value = sip_dict[1] self.sip_enabled, self.sbm_enabled, self.amfi_enabled, self.fv_enabled, self.dosdude_patched = utilities.patching_status(sip, self.constants.detected_os) - self.missing_kdk = not self.check_kdk() + if self.requires_root_kc is True: + self.missing_kdk = not self.check_kdk() if self.nvidia_web is True: self.missing_nv_web_nvram = not self.check_nv_web_nvram() @@ -360,10 +370,9 @@ def verify_patch_allowed(self, print_errors=False): print("\nCannot patch! WhateverGreen.kext missing") print("Please ensure WhateverGreen.kext is installed") - if self.amfi_must_disable is True: - if self.missing_kdk is True: - print("\nCannot patch! Kernel Debug Kit missing") - print(f"Please ensure the correct KDK is installed (required: {self.constants.detected_os_build})") + if self.missing_kdk is True: + print("\nCannot patch! Kernel Debug Kit missing") + print(f"Please ensure the correct KDK is installed (required: {self.constants.detected_os_build})") if any( [ @@ -399,17 +408,17 @@ def generate_patchset(self, hardware_details): required_patches.update({"Intel Sandy Bridge": all_hardware_patchset["Graphics"]["Intel Sandy Bridge"]}) if hardware_details["Graphics: Intel Ivy Bridge"] is True: required_patches.update({"Metal Common": all_hardware_patchset["Graphics"]["Metal Common"]}) - required_patches.update({"Metal 1 Common": all_hardware_patchset["Graphics"]["Metal 1 Common"]}) + required_patches.update({"Metal 3802 Common": all_hardware_patchset["Graphics"]["Metal 3802 Common"]}) required_patches.update({"Catalina GVA": all_hardware_patchset["Graphics"]["Catalina GVA"]}) required_patches.update({"Intel Ivy Bridge": all_hardware_patchset["Graphics"]["Intel Ivy Bridge"]}) if hardware_details["Graphics: Intel Haswell"] is True: required_patches.update({"Metal Common": all_hardware_patchset["Graphics"]["Metal Common"]}) - required_patches.update({"Metal 1 Common": all_hardware_patchset["Graphics"]["Metal 1 Common"]}) + required_patches.update({"Metal 3802 Common": all_hardware_patchset["Graphics"]["Metal 3802 Common"]}) required_patches.update({"Monterey GVA": all_hardware_patchset["Graphics"]["Monterey GVA"]}) required_patches.update({"Intel Haswell": all_hardware_patchset["Graphics"]["Intel Haswell"]}) if hardware_details["Graphics: Intel Broadwell"] is True: required_patches.update({"Metal Common": all_hardware_patchset["Graphics"]["Metal Common"]}) - required_patches.update({"Metal 1 Common": all_hardware_patchset["Graphics"]["Metal 1 Common"]}) + required_patches.update({"Metal 3802 Common": all_hardware_patchset["Graphics"]["Metal 3802 Common"]}) required_patches.update({"Monterey GVA": all_hardware_patchset["Graphics"]["Monterey GVA"]}) required_patches.update({"Intel Broadwell": all_hardware_patchset["Graphics"]["Intel Broadwell"]}) if hardware_details["Graphics: Intel Skylake"] is True: @@ -427,7 +436,7 @@ def generate_patchset(self, hardware_details): required_patches.update({"Non-Metal Enforcement": all_hardware_patchset["Graphics"]["Non-Metal Enforcement"]}) if hardware_details["Graphics: Nvidia Kepler"] is True: required_patches.update({"Metal Common": all_hardware_patchset["Graphics"]["Metal Common"]}) - required_patches.update({"Metal 1 Common": all_hardware_patchset["Graphics"]["Metal 1 Common"]}) + required_patches.update({"Metal 3802 Common": all_hardware_patchset["Graphics"]["Metal 3802 Common"]}) required_patches.update({"Catalina GVA": all_hardware_patchset["Graphics"]["Catalina GVA"]}) required_patches.update({"Nvidia Kepler": all_hardware_patchset["Graphics"]["Nvidia Kepler"]}) for gpu in self.constants.computer.gpus: From 237b086e17f29477a8c63593eaa69f70d0ad0e7b Mon Sep 17 00:00:00 2001 From: Mykola Grymalyuk Date: Sat, 27 Aug 2022 12:57:45 -0600 Subject: [PATCH 2/2] sys_patch.py: Avoid prompts if kext has already been accepted --- resources/main.py | 4 +++- resources/sys_patch.py | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/resources/main.py b/resources/main.py index c228391155..7b140d060f 100644 --- a/resources/main.py +++ b/resources/main.py @@ -49,7 +49,9 @@ def generate_base_data(self): # Now that we have commit info, update nightly link if self.constants.commit_info[0] != "Running from source": - self.constants.installer_pkg_url_nightly = self.constants.installer_pkg_url_nightly.replace("main", self.constants.commit_info[0]) + branch = self.constants.commit_info[0] + branch = branch.replace("refs/heads/", "") + self.constants.installer_pkg_url_nightly = self.constants.installer_pkg_url_nightly.replace("main", branch) defaults.generate_defaults.probe(self.computer.real_model, True, self.constants) diff --git a/resources/sys_patch.py b/resources/sys_patch.py index 5562d73e0e..4138711d32 100644 --- a/resources/sys_patch.py +++ b/resources/sys_patch.py @@ -327,6 +327,24 @@ def add_auxkc_support(self, install_file, source_folder_path, install_patch_dire plist_data["OSBundleRequired"] = "Auxiliary" plistlib.dump(plist_data, plist_path.open("wb")) + # Verify whether the user needs to authenticate in System Preferences + # Specifically under 'private/var/db/KernelManagement/AuxKC/CurrentAuxKC/com.apple.kcgen.instructions.plist' + # ["kextsToBuild"][i]: + # ["bundlePathMainOS"] = /Library/Extensions/Test.kext + # ["cdHash"] = Bundle's CDHash (random on ad-hoc signed, static on dev signed) + # ["teamID"] = Team ID (blank on ad-hoc signed) + # To grab the CDHash of a kext, run 'codesign -dvvv ' + try: + aux_cache_path = Path(self.mount_location_data) / Path("private/var/db/KernelManagement/AuxKC/CurrentAuxKC/com.apple.kcgen.instructions.plist") + if Path(aux_cache_path).exists(): + aux_cache_data = plistlib.load((aux_cache_path).open("rb")) + for kext in aux_cache_data["kextsToBuild"]: + if "bundlePathMainOS" in kext: + if kext["bundlePathMainOS"] == f"/Library/Extensions/{install_file}": + return updated_install_location + except PermissionError: + pass + self.constants.needs_to_open_preferences = True return updated_install_location