Disable repatching a dirty root volume (#1179)

Co-authored-by: Dhinak G <17605561+dhinakg@users.noreply.github.com>
This commit is contained in:
Eva Isabella Luna
2025-12-19 14:06:11 -07:00
committed by GitHub
parent b5da41c030
commit 806d47f413
2 changed files with 61 additions and 1 deletions

View File

@@ -89,6 +89,7 @@ class HardwarePatchsetValidation(StrEnum):
NVDA_DRV_MISSING = "Validation: nvda_drv(_vrl) variable missing"
PATCHING_NOT_POSSIBLE = "Validation: Patching not possible"
UNPATCHING_NOT_POSSIBLE = "Validation: Unpatching not possible"
REPATCHING_NOT_SUPPORTED = "Validation: Root volume dirty, unpatch to continue"
class HardwarePatchsetDetection:
@@ -184,6 +185,42 @@ class HardwarePatchsetDetection:
return "FileVault is Off" not in subprocess.run(["/usr/bin/fdesetup", "status"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.decode()
def _validation_check_repatching_is_possible(self) -> bool:
"""
Determine if repatching is not allowed
"""
oclp_patch_path = "/System/Library/CoreServices/OpenCore-Legacy-Patcher.plist"
if not Path(oclp_patch_path).exists():
return self._is_root_volume_dirty()
oclp_plist = plistlib.load(open(oclp_patch_path, "rb"))
if self._constants.computer.oclp_sys_url != self._constants.commit_info[2]:
logging.error("Installed patches are from different commit, unpatching is required")
return True
wireless_keys = {"Legacy Wireless", "Modern Wireless"}
# Keep in sync with generate_patchset_plist
metadata_keys = {
"OpenCore Legacy Patcher",
"PatcherSupportPkg",
"Time Patched",
"Commit URL",
"Kernel Debug Kit Used",
"Metal Library Used",
"OS Version",
"Custom Signature",
}
existing_patches = set(oclp_plist) - wireless_keys - metadata_keys
if existing_patches:
logging.error(f"Patch(es) already installed: {', '.join(existing_patches)}, unpatching is required")
return True
return False
def _validation_check_system_integrity_protection_enabled(self, configs: list[str]) -> bool:
"""
@@ -307,6 +344,28 @@ class HardwarePatchsetDetection:
"""
return metallib_handler.MetalLibraryObject(self._constants, self._os_build, self._os_version).metallib_already_installed
def _is_root_volume_dirty(self) -> bool:
"""
Determine if system volume is not sealed
"""
# macOS 11.0 introduced sealed system volumes
if self._xnu_major < os_data.big_sur.value:
return False
try:
content = plistlib.loads(subprocess.run(["/usr/sbin/diskutil", "info", "-plist", "/"], capture_output=True).stdout)
except plistlib.InvalidFileException:
raise RuntimeError("Failed to parse diskutil output.")
seal = content["Sealed"]
if "Broken" in seal:
logging.error(f"System volume is tainted, unpatching is required")
return True
return False
def _can_patch(self, requirements: dict, ignore_keys: list[str] = []) -> bool:
"""
@@ -500,6 +559,7 @@ class HardwarePatchsetDetection:
HardwarePatchsetValidation.SIP_ENABLED: self._validation_check_system_integrity_protection_enabled(required_sip_configs),
HardwarePatchsetValidation.SECURE_BOOT_MODEL_ENABLED: self._validation_check_secure_boot_model_enabled(),
HardwarePatchsetValidation.AMFI_ENABLED: self._validation_check_amfi_enabled(highest_amfi_level),
HardwarePatchsetValidation.REPATCHING_NOT_SUPPORTED: self._validation_check_repatching_is_possible(),
HardwarePatchsetValidation.WHATEVERGREEN_MISSING: self._validation_check_whatevergreen_missing() if has_nvidia_web_drivers is True else False,
HardwarePatchsetValidation.FORCE_OPENGL_MISSING: self._validation_check_force_opengl_missing() if has_nvidia_web_drivers is True else False,
HardwarePatchsetValidation.FORCE_COMPAT_MISSING: self._validation_check_force_compat_missing() if has_nvidia_web_drivers is True else False,

View File

@@ -229,7 +229,7 @@ class SysPatchDisplayFrame(wx.Frame):
start_button.Disable()
else:
self.available_patches = True
if patches[HardwarePatchsetValidation.PATCHING_NOT_POSSIBLE] is True:
if patches[HardwarePatchsetValidation.PATCHING_NOT_POSSIBLE] is True or no_new_patches is True:
start_button.Disable()
elif no_new_patches is False:
start_button.SetDefault()