Save 37% off PRO during our Black Friday Sale! »

Apple Silicon HVF

87ff69458c87fb9b2bfdfa9574375d95?s=47 Mach0xFF
July 10, 2021
450

Apple Silicon HVF

Kernel/VM Online Part3 LT

87ff69458c87fb9b2bfdfa9574375d95?s=128

Mach0xFF

July 10, 2021
Tweet

Transcript

  1. Apple Silicon HVF K/VM Online Part3

  2. % whoami - M6Mです(Mach0xFFです) - 前回も似たようなテーマだった - ごめんなさい

  3. 作ろうとしたもの - keystone engineとHVFを組み合わせたA64アセンブリ(ARM64)のREPL - 先に言うとREPLはできていません - Linux用にptraceベースな既存のものが存在する - https://github.com/yrp604/rappel

    - A64命令、少し複雑なものが多々ある(UBFX, BICS, FJCVTZS) - 必要に応じて命令を実行してくれるツールがあったらいいなあ - アセンブリ書いたファイル読み込ませてレジスタダンプするところまではできた
  4. ← x2 = x0 & ~x1

  5. ここからは - ここからはHVFの実装について調査した結果を書きます - REPLもどきは一度忘れてください

  6. Apple A14/M1チップ - μArchは基本同じ - Firestorm (big/p-core) / Icestorm (LITTLE/e-core)

    - A14 for iOS devices、M1 for macOS/iPadOS devices - A14/M1チップ上ではEL2によるXNU(カーネル)の動作モードが存在する - これは以下のことからわかる - XNUで(実質的に)最初に実行される関数 start_first_cpuで、HCR_EL2レジスタに E2H (EL2 Host, bit 34)が設定される - その裏付けとして、EL2動作時に*_EL1システムレジスタに( re-routeされずに)アクセスするための *_EL12レジスタが実装され、読み書き( MRS/MSR)されている - Hypervisorが実装されている以上、どこかしらで EL2による動作が必要
  7. hv_vm_create

  8. hv_trap - X16レジスタに(-5)を入れてSVC - カーネルではどうなるか

  9. - SVC命令によるExc発生→Synchronous exception from Lower EL using AArch64 - ESR_EL1(Exception

    Syndrome Register EL1)の値からExcの要因を取得 - EL2で動作している場合、ESR_EL2にre-routingされる(はず) - SVC命令によるものだとKernelが判定→handle_svc()関数へ - UserがX16に入れたSyscall numberをint trap_noとして取得 - 基本的に正ならUnix、負ならMach - 例外として (osfmk/mach/arm/traps.h) - MACH_ARM_TRAP_ABSTIME (-3) - MACH_ARM_TRAP_CONTTIME (-4) - xnuのソースコードにはここまでしか書かれていないが…
  10. - macOS 11.3のカーネル、handle_svc()に該当するDisassembly - CMN (CoMpare Negative)命令によりtrap_noを(-5)と比較 - この部分はまだオープンになっていない

  11. Entitlements - ところでApple Silicon HVFを使うには実行ファイルを署名した上で、必要な Entitlementsを付与する必要がある - Entitlements: 実行ファイルが「何か権限の必要なこと」を行う際に必要となる、Plist形式のデータ -

    PlistはとりあえずXMLと考えて構わない - XNUが認識するVM作成に関するEntitlementsは以下の3つ - (1) com.apple.security.hypervisor - (2) com.apple.private.hypervisor.vmapple - (3) com.apple.private.hypervisor - 公式には(1)のみ存在することになっている( VM作成ならこれで事足りる) - https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_hypervisor - カーネル内部では(2)・(3)のEntitlementsの有無も確認する - 許可される最大のISAのレベルが変化する - HVF経由だと(1)しか作れない(hv_vm_create()に適切な引数を渡す必要あり) - ただしcom.apple.privateで始まるため、通常起動時はこの権限を付与したバイナリは実行を拒否される - 具体的には、amfidというデーモンにSIGKILLされる
  12. 迂回路 (boot-args) - 迂回路はある - boot-argsに “amfi_get_out_of_my_way=1” を設定 - %

    sudo nvram boot-args=... - これやるとセキュリティ的によろしくない状態になる - ソフトウェアやドライバが動かなくなることもしばしば - 実験が終わったら元に戻しましょう - こうするとamfidによるチェックが行われなくなるため、先述の(2)•(3)の Entitlementsを付与可能 - (1)•(2)•(3)は具体的にどう違うのか?
  13. Hidden HVF API - _hv_capability(uint64_t cap, uint64_t *out) - 引数名は適当

    - Hypervisor.frameworkのヘッダファイルに存在しない API - 共有ライブラリにシンボルとして存在する - 内部ではX0レジスタに#0を設定した上でSVCをする - 先程の3種のEntitlementsをそれぞれ設定して呼び出してみる
  14. None
  15. None
  16. HACR_EL2 - control_hacr だけ異なっている - hacr → Hypervisor Auxiliary Control

    Register - 64-bitレジスタ、内容はIMPLEMENTATION DEFINED - すなわちコア実装による - (2)•(3)ではbit 0がセットされている - このビットに何か秘密がある? - カーネルを読んでみたが、まだ詳細は不明 …
  17. vmapple - ...vmappleのEntitlementを付与するとAppleのIMPLEMENTATION DEFINEDなシステム レジスタが使える…? - https://blog.svenpeter.dev/posts/m1_sprr_gxf/#open-questions - https://twitter.com/never_released/status/1390394188395597831 -

    システムレジスタの値を取得するには - hv_vcpu_get_sys_reg(hv_vcpu_t vcpu, hv_sys_reg_t reg, uint64_t *value) - ただし、ヘッダファイルには reg (uint16_t) としてIMPLEMENTATION DEFINEDレジスタはない - 各種Entitlementsを付与しても、エラー発生せずに取得できるシステムレジスタに変化はなかった - 内部で呼ばれるSyscallを使って取得できる? - 該当Syscallの引数が固定されている - カーネル内部の構造体に、r/wが許可されるsysregを設定するフィールドがあるっぽい - (時間切れ)
  18. - まとまりのない話になってしまった - 将来的に(privateが外れて)vmappleのEntitlementが解放されたら嬉しい - Apple Silicon VMWareとかParallelsはこのEntitlementを使って開発されてそう - 調査継続します(REPLも作りたい)