Slide 1

Slide 1 text

Apple Silicon HVF K/VM Online Part3

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

作ろうとしたもの - keystone engineとHVFを組み合わせたA64アセンブリ(ARM64)のREPL - 先に言うとREPLはできていません - Linux用にptraceベースな既存のものが存在する - https://github.com/yrp604/rappel - A64命令、少し複雑なものが多々ある(UBFX, BICS, FJCVTZS) - 必要に応じて命令を実行してくれるツールがあったらいいなあ - アセンブリ書いたファイル読み込ませてレジスタダンプするところまではできた

Slide 4

Slide 4 text

← x2 = x0 & ~x1

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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による動作が必要

Slide 7

Slide 7 text

hv_vm_create

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

- 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のソースコードにはここまでしか書かれていないが…

Slide 10

Slide 10 text

- macOS 11.3のカーネル、handle_svc()に該当するDisassembly - CMN (CoMpare Negative)命令によりtrap_noを(-5)と比較 - この部分はまだオープンになっていない

Slide 11

Slide 11 text

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される

Slide 12

Slide 12 text

迂回路 (boot-args) - 迂回路はある - boot-argsに “amfi_get_out_of_my_way=1” を設定 - % sudo nvram boot-args=... - これやるとセキュリティ的によろしくない状態になる - ソフトウェアやドライバが動かなくなることもしばしば - 実験が終わったら元に戻しましょう - こうするとamfidによるチェックが行われなくなるため、先述の(2)•(3)の Entitlementsを付与可能 - (1)•(2)•(3)は具体的にどう違うのか?

Slide 13

Slide 13 text

Hidden HVF API - _hv_capability(uint64_t cap, uint64_t *out) - 引数名は適当 - Hypervisor.frameworkのヘッダファイルに存在しない API - 共有ライブラリにシンボルとして存在する - 内部ではX0レジスタに#0を設定した上でSVCをする - 先程の3種のEntitlementsをそれぞれ設定して呼び出してみる

Slide 14

Slide 14 text

No content

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

HACR_EL2 - control_hacr だけ異なっている - hacr → Hypervisor Auxiliary Control Register - 64-bitレジスタ、内容はIMPLEMENTATION DEFINED - すなわちコア実装による - (2)•(3)ではbit 0がセットされている - このビットに何か秘密がある? - カーネルを読んでみたが、まだ詳細は不明 …

Slide 17

Slide 17 text

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を設定するフィールドがあるっぽい - (時間切れ)

Slide 18

Slide 18 text

- まとまりのない話になってしまった - 将来的に(privateが外れて)vmappleのEntitlementが解放されたら嬉しい - Apple Silicon VMWareとかParallelsはこのEntitlementを使って開発されてそう - 調査継続します(REPLも作りたい)