@@ -1005,6 +1005,48 @@ bool sb_ops_callback(struct xnu_pf_patch* patch, uint64_t* sbops_stream) {
10051005 return true;
10061006}
10071007
1008+ bool found_apfs_root_hash_new = false;
1009+ bool kpf_apfs_root_hash_new (struct xnu_pf_patch * patch , uint32_t * opcode_stream ) {
1010+ uint32_t * b = find_prev_insn (opcode_stream , 3 , 0x14000000 , 0xfc000000 );
1011+
1012+ if (!b ) return false;
1013+
1014+ uint32_t * cbz = find_next_insn (opcode_stream , 10 , 0x34000000 , 0xff00001f ); // cbz w0, Lvalidated_root_hash
1015+
1016+ if (!cbz ) return false;
1017+
1018+ if ((cbz [-1 ] & 0xfc000000 ) != 0x94000000 ) return false; // bl
1019+
1020+ if (found_apfs_root_hash_new )
1021+ panic ("kpf_apfs_root_hash_new: found twice!" );
1022+
1023+ cbz [-1 ] = 0x52800000 ; // mov w0, #0
1024+
1025+ found_apfs_root_hash_new = true;
1026+
1027+ printf ("KPF: found apfs_root_hash_new\n" );
1028+ return true;
1029+ }
1030+
1031+ void * found_apfs_handle_fsioc_graft = NULL ;
1032+ bool kpf_apfs_handle_fsioc_graft_new (struct xnu_pf_patch * patch , uint32_t * opcode_stream ) {
1033+ uint32_t * cbz = find_prev_insn (opcode_stream , 20 , 0x34000000 , 0xff00001f ); // cbz w0, Lvalidated_payload_and_manifest
1034+
1035+ if (!cbz ) return false;
1036+
1037+ if ((cbz [-1 ] & 0xfc000000 ) != 0x94000000 ) return false; // bl
1038+
1039+ if (found_apfs_handle_fsioc_graft && found_apfs_handle_fsioc_graft != cbz )
1040+ panic ("kpf_apfs_handle_fsioc_graft_new: found twice!" );
1041+
1042+ cbz [-1 ] = 0x52800000 ; // mov w0, #0
1043+
1044+ found_apfs_handle_fsioc_graft = cbz ;
1045+
1046+ printf ("KPF: found apfs_handle_fsioc_graft_new\n" );
1047+ return true;
1048+ }
1049+
10081050bool found_apfs_rename = false;
10091051bool kpf_apfs_patches_rename (struct xnu_pf_patch * patch , uint32_t * opcode_stream ) {
10101052 if (
@@ -1121,7 +1163,7 @@ bool kpf_apfs_root_snapshot_name(struct xnu_pf_patch *patch, uint32_t *opcode_st
11211163 return true;
11221164}
11231165
1124- void kpf_apfs_patches (xnu_pf_patchset_t * patchset , bool have_ssv , bool apfs_vfsop_mount_string_match ) {
1166+ void kpf_apfs_patches (xnu_pf_patchset_t * patchset , bool have_ssv , bool apfs_vfsop_mount_string_match , bool ipad6_ipados18 ) {
11251167 // there is a check in the apfs mount function that makes sure that the kernel task is calling this function (current_task() == kernel_task)
11261168 // we also want to call it so we patch that check out
11271169 // example from i7 13.3:
@@ -1273,6 +1315,46 @@ void kpf_apfs_patches(xnu_pf_patchset_t* patchset, bool have_ssv, bool apfs_vfso
12731315 xnu_pf_maskmatch (patchset ,
12741316 "apfs_root_snapshot_name" , root_snapshot_matches , root_snapshot_masks , sizeof (root_snapshot_matches ) / sizeof (uint64_t ), true ,(void * )kpf_apfs_root_snapshot_name );
12751317 }
1318+
1319+ if (ipad6_ipados18 ) {
1320+ // Patch root hash verification
1321+
1322+ uint64_t root_hash_new_matches [] = {
1323+ 0xd3430c02 // ubfx x2, xN, #3, #1
1324+ };
1325+
1326+ uint64_t root_hash_new_masks [] = {
1327+ 0xfffffc1f
1328+ };
1329+
1330+ xnu_pf_maskmatch (patchset ,
1331+ "apfs_graft_new" , root_hash_new_matches , root_hash_new_masks , sizeof (root_hash_new_matches ) / sizeof (uint64_t ), true ,(void * )kpf_apfs_root_hash_new );
1332+
1333+ // Patch root hash image4 verification
1334+
1335+ uint64_t handle_fsioc_graft_matches [] = {
1336+ 0xaa1003e0 , // mov x0, x{16-31}
1337+ 0xaa1003e1 , // mov x1, x{16-31}
1338+ 0xaa1003e3 , // mov x3, x{16-31}
1339+ 0xd2800004 , // mov x4, #0
1340+ 0xd2800005 , // mov x5, #0
1341+ 0xaa1003e6 , // mov x6, x{16-31}
1342+ 0x14000000 // b
1343+ };
1344+
1345+ uint64_t handle_fsioc_graft_masks [] = {
1346+ 0xfff0ffff ,
1347+ 0xfff0ffff ,
1348+ 0xfff0ffff ,
1349+ 0xffffffff ,
1350+ 0xffffffff ,
1351+ 0xfff0ffff ,
1352+ 0xfc000000
1353+ };
1354+
1355+ xnu_pf_maskmatch (patchset ,
1356+ "handle_fsioc_graft_new" , handle_fsioc_graft_matches , handle_fsioc_graft_masks , sizeof (handle_fsioc_graft_matches ) / sizeof (uint64_t ), false ,(void * )kpf_apfs_handle_fsioc_graft_new );
1357+ }
12761358}
12771359static uint32_t * amfi_ret ;
12781360bool kpf_amfi_execve_tail (struct xnu_pf_patch * patch , uint32_t * opcode_stream ) {
@@ -2347,6 +2429,19 @@ static void kpf_cmd(void)
23472429 if (!apfs_vfsop_mount_string_match )
23482430 strlcat ((char * )((int64_t )gBootArgs -> iOS13 .CommandLine - 0x800000000 + kCacheableView ), " rootdev=md0" , 0x270 );
23492431
2432+ const char root_hash_string [] = "%s:%d: %s Failed to authenticate root hash (volume type %d): %d\n" ;
2433+ const char * root_hash_string_match = apfs_text_cstring_range ? memmem (apfs_text_cstring_range -> cacheable_base , apfs_text_cstring_range -> size , root_hash_string , sizeof (root_hash_string )) : NULL ;
2434+ if (!root_hash_string_match ) root_hash_string_match = memmem (text_cstring_range -> cacheable_base , text_cstring_range -> size , root_hash_string , sizeof (root_hash_string ));
2435+
2436+ const char graft_image4_string [] = "%s:%d: %s Failed to validate image4 payload and manifest for grafting: %d\n" ;
2437+ const char * graft_image4_string_match = apfs_text_cstring_range ? memmem (apfs_text_cstring_range -> cacheable_base , apfs_text_cstring_range -> size , graft_image4_string , sizeof (graft_image4_string )) : NULL ;
2438+ if (!graft_image4_string_match ) graft_image4_string_match = memmem (text_cstring_range -> cacheable_base , text_cstring_range -> size , graft_image4_string , sizeof (graft_image4_string ));
2439+
2440+ if (gKernelVersion .darwinMajor < 24 || xnu_platform () != PLATFORM_IOS ) {
2441+ graft_image4_string_match = NULL ;
2442+ root_hash_string_match = NULL ;
2443+ }
2444+
23502445 xnu_pf_range_t * bootdata_range = xnu_pf_section (hdr , "__BOOTDATA" , "__init" );
23512446 xnu_pf_range_t * const_klddata_range = xnu_pf_section (hdr , "__KLDDATA" , "__const" );
23522447
@@ -2393,6 +2488,51 @@ static void kpf_cmd(void)
23932488
23942489 bool protobox_used = (protobox_string_match != NULL && gKernelVersion .xnuMajor >= 8792 );
23952490
2491+ bool ipad6_ipados18 = false;
2492+ #if !defined(KPF_TEST )
2493+ char * model = dt_prop (gDeviceTree , "model" , NULL );
2494+ if (gKernelVersion .darwinMajor >= 24 &&
2495+ (strcmp (model , "iPad7,5" ) == 0 || strcmp (model , "iPad7,6" ) == 0 )) {
2496+ ipad6_ipados18 = true;
2497+ }
2498+
2499+ if (ipad6_ipados18 ) {
2500+ puts ("Fixing up bootargs" );
2501+
2502+ dt_node_t * memory_map = dt_node (gDeviceTree , "/chosen/memory-map" );
2503+ struct memmap * map = dt_alloc_memmap (memory_map , "FunnyBootArgs" );
2504+ if (!map )
2505+ {
2506+ panic ("Failed to allocate FunnyBootArgs memory map" );
2507+ }
2508+
2509+ struct boot_args * cBootArgs = (struct boot_args * )((uint64_t )gBootArgs - 0x800000000 + kCacheableView );
2510+ struct boot_args * new_BootArgs = alloc_static (0x4000 );
2511+ bzero (new_BootArgs , sizeof (struct boot_args ));
2512+ new_BootArgs -> Revision = 3 ;
2513+ new_BootArgs -> Version = 2 ;
2514+ new_BootArgs -> virtBase = cBootArgs -> virtBase ;
2515+ new_BootArgs -> physBase = cBootArgs -> physBase ;
2516+ new_BootArgs -> memSize = cBootArgs -> memSize ;
2517+ new_BootArgs -> topOfKernelData = cBootArgs -> topOfKernelData ;
2518+ memcpy (& new_BootArgs -> Video , & cBootArgs -> Video , sizeof (struct Boot_Video ));
2519+ new_BootArgs -> machineType = cBootArgs -> machineType ;
2520+ new_BootArgs -> deviceTreeLength = cBootArgs -> deviceTreeLength ;
2521+ new_BootArgs -> deviceTreeP = cBootArgs -> deviceTreeP ;
2522+ memcpy (new_BootArgs -> iOS18 .CommandLine , cBootArgs -> iOS13 .CommandLine , BOOT_LINE_LENGTH_iOS13 );
2523+ new_BootArgs -> iOS18 .bootFlags = cBootArgs -> iOS13 .bootFlags ;
2524+ new_BootArgs -> iOS18 .memSizeActual = cBootArgs -> iOS13 .memSizeActual ;
2525+ gBootArgs = (void * )(((uint64_t )new_BootArgs ) + 0x800000000 - kCacheableView );
2526+ map -> addr = ((uint64_t )new_BootArgs ) + 0x800000000 - kCacheableView ;
2527+ map -> size = 0x4000 ;
2528+
2529+ * (uint32_t * )dt_prop (dt_find (gDeviceTree , "/chosen" ), "debug-enabled" , NULL ) = 1 ;
2530+ }
2531+ #else
2532+ if (gKernelVersion .darwinMajor >= 24 && xnu_platform () == PLATFORM_IOS )
2533+ ipad6_ipados18 = true;
2534+ #endif
2535+
23962536 for (size_t i = 0 ; i < sizeof (kpf_components )/sizeof (kpf_components [0 ]); ++ i )
23972537 {
23982538 kpf_component_t * component = kpf_components [i ];
@@ -2460,7 +2600,7 @@ static void kpf_cmd(void)
24602600 }
24612601 }
24622602
2463- kpf_apfs_patches (apfs_patchset , livefs_string_match != NULL , apfs_vfsop_mount_string_match != NULL );
2603+ kpf_apfs_patches (apfs_patchset , livefs_string_match != NULL , apfs_vfsop_mount_string_match != NULL , ipad6_ipados18 );
24642604#if 0
24652605 if (livefs_string_match )
24662606 {
0 commit comments