Procházet zdrojové kódy

use kexec userclient to call kernel functions (for iPhone 12/iOS 14.1)

See https://github.com/zhuowei/Fugu14/tree/wip-connect6
Zhuowei Zhang před 3 roky
rodič
revize
d368b281e4
6 změnil soubory, kde provedl 111 přidání a 7 odebrání
  1. 4 0
      .gitignore
  2. 17 7
      hv.m
  3. 7 0
      ios_build.sh
  4. 8 0
      ios_hv.entitlements
  5. 10 0
      make_fixed_headers.sh
  6. 65 0
      userclient_hv_trap.m

+ 4 - 0
.gitignore

@@ -0,0 +1,4 @@
+hv
+ios_hv
+*.dSYM
+fixed_hv_headers

+ 17 - 7
hv.m

@@ -51,11 +51,15 @@ static_assert(sizeof(hv_vcpu_exit_t) == 0x20, "hv_vcpu_exit");
 #define HV_CALL_VM_ADDRESS_SPACE_CREATE 12
 #define HV_CALL_VM_INVALIDATE_TLB 13
 
+#ifdef USE_EXTERNAL_HV_TRAP
+uint64_t hv_trap(unsigned int hv_call, void* hv_arg);
+#else
 __attribute__((naked)) uint64_t hv_trap(unsigned int hv_call, void* hv_arg) {
   asm volatile("mov x16, #-0x5\n"
                "svc 0x80\n"
                "ret\n");
 }
+#endif
 
 // type lookup hv_vm_create_t
 struct hv_vm_create_kernel_args {
@@ -153,9 +157,14 @@ hv_return_t hv_vcpu_create(hv_vcpu_t* vcpu, hv_vcpu_exit_t** exit, hv_vcpu_confi
   }
   printf("vcpu_zone = %p\n", args.output_vcpu_zone);
   if (args.output_vcpu_zone->ro.ver != kHvVcpuMagic) {
-    hv_trap(HV_CALL_VCPU_DESTROY, nil);
-    pthread_mutex_unlock(&vcpus_mutex);
-    return HV_UNSUPPORTED;
+    printf("Invalid magic! expected %lx, got %lx\n", kHvVcpuMagic, args.output_vcpu_zone->ro.ver);
+    const bool yolo = true;
+    if (!yolo) {
+      hv_trap(HV_CALL_VCPU_DESTROY, nil);
+      pthread_mutex_unlock(&vcpus_mutex);
+      return HV_UNSUPPORTED;
+    }
+    printf("yoloing\n");
   }
   vcpu_data->vcpu_zone = args.output_vcpu_zone;
   *vcpu = cpuid;  // TODO(zhuowei)
@@ -172,7 +181,8 @@ hv_return_t hv_vcpu_run(hv_vcpu_t vcpu) {
   if (err) {
     return err;
   }
-  printf("exit = %d\n", vcpu_data->vcpu_zone->ro.exit.vmexit_reason);
+  printf("exit = %d (esr = %x)\n", vcpu_data->vcpu_zone->ro.exit.vmexit_reason,
+         vcpu_data->vcpu_zone->ro.exit.vmexit_esr);
   return 0;
 }
 
@@ -283,11 +293,11 @@ hv_return_t hv_vcpus_exit(hv_vcpu_t* vcpus, uint32_t vcpu_count) {
 
 int main() {
   hv_return_t err = hv_vm_create(nil);
-  printf("%x\n", err);
+  printf("vm create %x\n", err);
   hv_vcpu_t cpu = 0;
   hv_vcpu_exit_t* exit = nil;
   err = hv_vcpu_create(&cpu, &exit, nil);
-  printf("%x\n", err);
+  printf("vcpu create %x\n", err);
   err = hv_vcpu_run(cpu);
-  printf("%x\n", err);
+  printf("run %x\n", err);
 }

+ 7 - 0
ios_build.sh

@@ -0,0 +1,7 @@
+#!/bin/sh
+set -e
+macospath="$(xcrun --sdk macosx --show-sdk-path)"
+xcrun -sdk iphoneos clang -fmodules -Os -g -target arm64-apple-ios14 -o ios_hv \
+	-DUSE_EXTERNAL_HV_TRAP -Ifixed_hv_headers -framework IOKit \
+	hv.m userclient_hv_trap.m 
+codesign --sign - --force --entitlements ios_hv.entitlements ios_hv

+ 8 - 0
ios_hv.entitlements

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+  <key>com.apple.private.hypervisor</key>
+  <true/>
+</dict>
+</plist>

+ 10 - 0
make_fixed_headers.sh

@@ -0,0 +1,10 @@
+#!/bin/sh
+set -e
+macospath="$(xcrun --sdk macosx --show-sdk-path)"
+rm -r fixed_hv_headers || true
+mkdir -p fixed_hv_headers/Hypervisor
+for i in "$macospath/System/Library/Frameworks/Hypervisor.framework/Headers/"*
+do
+	echo $i
+	sed -e "s/API_UNAVAILABLE(ios)/API_AVAILABLE(ios(14.0))/g" "$i" >fixed_hv_headers/Hypervisor/$(basename "$i")
+done

+ 65 - 0
userclient_hv_trap.m

@@ -0,0 +1,65 @@
+@import Darwin;
+@import Foundation;
+
+typedef io_object_t io_connect_t;
+
+kern_return_t IOConnectTrap6(io_connect_t connect, uint32_t index, uintptr_t p1, uintptr_t p2,
+                             uintptr_t p3, uintptr_t p4, uintptr_t p5, uintptr_t p6);
+
+static mach_port_t gUserClient;
+static uint64_t gCodePtrs[14];
+static uint64_t gDiscriminant;
+
+static int init_hv_trap() {
+  NSError* nserror = nil;
+  NSString* inStr = [NSString stringWithContentsOfFile:@"/tmp/zhuowei_portinfo"
+                                              encoding:NSUTF8StringEncoding
+                                                 error:&nserror];
+  if (!inStr) {
+    NSLog(@"Error opening portinfo: %@", nserror);
+    return 1;
+  }
+  NSArray<NSString*>* parts = [inStr componentsSeparatedByString:@"\n"];
+  int target_pid = parts[0].intValue;
+  mach_port_t target_task = 0;
+  kern_return_t err;
+  err = task_for_pid(mach_task_self_, target_pid, &target_task);
+  if (err) {
+    fprintf(stderr, "Failed to get task port: %s\n", mach_error_string(err));
+    return 1;
+  }
+  if (target_task == MACH_PORT_NULL) {
+    fprintf(stderr, "Can't get task port for pid %d\n", target_pid);
+    return 1;
+  }
+  mach_port_name_t remote_port_id = parts[1].intValue;
+  mach_port_t user_client = 0;
+  mach_msg_type_name_t user_client_type = 0;
+  err = mach_port_extract_right(target_task, remote_port_id, MACH_MSG_TYPE_COPY_SEND, &user_client,
+                                &user_client_type);
+  if (err) {
+    fprintf(stderr, "Failed to extract user client port: %s\n", mach_error_string(err));
+    return 1;
+  }
+  NSLog(@"ok port = %u", user_client);
+  gDiscriminant = strtoull(parts[2].UTF8String, nil, 0x10);
+  for (int i = 0; i < 14; i++) {
+    gCodePtrs[i] = strtoull(parts[3 + i].UTF8String, nil, 0x10);
+  }
+  gUserClient = user_client;
+  return 0;
+}
+
+kern_return_t hv_trap(unsigned int hv_call, void* hv_arg) {
+  static dispatch_once_t init_token;
+  dispatch_once(&init_token, ^{
+    init_hv_trap();
+  });
+  if (gUserClient == 0) {
+    // TODO(zhuowei): make an error code??
+    return 0x1337;
+  }
+  uint64_t signed_code_ptr = gCodePtrs[hv_call];
+  return IOConnectTrap6(gUserClient, /*index=*/0, /*arg1*/ hv_arg, /*arg2*/ 0, signed_code_ptr,
+                        gDiscriminant, 0, 0);
+}