Mode Aman Virtual

Mode Aman Virtual (VSM) adalah serangkaian kemampuan dan pencerahan hypervisor yang ditawarkan untuk menghosting dan partisi tamu yang memungkinkan pembuatan dan pengelolaan batas keamanan baru dalam perangkat lunak sistem operasi. VSM adalah fasilitas hypervisor tempat fitur keamanan Windows termasuk Device Guard, Credential Guard, TPM virtual, dan VM terlindungi didasarkan. Fitur keamanan ini diperkenalkan di Windows 10 dan Windows Server 2016.

VSM memungkinkan perangkat lunak sistem operasi di partisi root dan tamu untuk membuat wilayah memori yang terisolasi untuk penyimpanan dan pemrosesan aset keamanan sistem. Akses ke wilayah terisolasi ini dikontrol dan diberikan hanya melalui hypervisor, yang merupakan bagian yang sangat istimewa dan sangat tepercaya dari Basis Komputasi Tepercaya (TCB) sistem. Karena hypervisor berjalan pada tingkat hak istimewa yang lebih tinggi daripada perangkat lunak sistem operasi dan memiliki kontrol eksklusif atas sumber daya perangkat keras sistem utama seperti kontrol izin akses memori di CPU MMU dan IOMMU dini dalam inisialisasi sistem, hypervisor dapat melindungi wilayah terisolasi ini dari akses yang tidak sah, bahkan dari perangkat lunak sistem operasi (misalnya, kernel OS dan driver perangkat) dengan akses mode supervisor (yaitu CPL0, atau "Cincin 0").

Dengan arsitektur ini, bahkan jika perangkat lunak tingkat sistem normal yang berjalan dalam mode supervisor (misalnya kernel, driver, dll.) disusupi oleh perangkat lunak berbahaya, aset di wilayah terisolasi yang dilindungi oleh hypervisor dapat tetap aman.

Tingkat Kepercayaan Virtual (VTL)

VSM mencapai dan mempertahankan isolasi melalui Tingkat Kepercayaan Virtual (VTL). VTL diaktifkan dan dikelola berdasarkan prosesor per partisi dan per virtual.

Tingkat Kepercayaan Virtual bersifat hierarkis, dengan tingkat yang lebih tinggi lebih istimewa daripada tingkat yang lebih rendah. VTL0 adalah tingkat hak istimewa paling sedikit, dengan VTL1 lebih istimewa daripada VTL0, VTL2 lebih istimewa daripada VTL1, dll.

Secara arsitektur, hingga 16 tingkat VTL didukung; namun hypervisor dapat memilih untuk menerapkan kurang dari 16 VTL. Saat ini, hanya dua VTL yang diimplementasikan.

typedef UINT8 HV_VTL, *PHV_VTL;

#define HV_NUM_VTLS 2
#define HV_INVALID_VTL ((HV_VTL) -1)
#define HV_VTL_ALL 0xF

Setiap VTL memiliki serangkaian perlindungan akses memorinya sendiri. Perlindungan akses ini dikelola oleh hypervisor di ruang alamat fisik partisi, dan dengan demikian tidak dapat dimodifikasi oleh perangkat lunak tingkat sistem yang berjalan di partisi.

Karena VTL yang lebih istimewa dapat memberlakukan perlindungan memori mereka sendiri, VTL yang lebih tinggi dapat secara efektif melindungi area memori dari VTL yang lebih rendah. Dalam praktiknya, ini memungkinkan VTL yang lebih rendah untuk melindungi wilayah memori terisolasi dengan mengamankannya dengan VTL yang lebih tinggi. Misalnya, VTL0 dapat menyimpan rahasia di VTL1, di mana hanya VTL1 yang dapat mengaksesnya. Bahkan jika VTL0 disusupi, rahasianya akan aman.

Perlindungan VTL

Ada beberapa faset untuk mencapai isolasi antara VTL:

  • Perlindungan Akses Memori: Setiap VTL mempertahankan serangkaian perlindungan akses memori fisik tamu. Perangkat lunak yang berjalan pada VTL tertentu hanya dapat mengakses memori sesuai dengan perlindungan ini.
  • Status Prosesor Virtual: Prosesor virtual mempertahankan status per-VTL terpisah. Misalnya, setiap VTL mendefinisikan sekumpulan register VP privat. Perangkat lunak yang berjalan pada VTL yang lebih rendah tidak dapat mengakses status register prosesor virtual privat VTL yang lebih tinggi.
  • Interupsi: Bersama dengan status prosesor terpisah, setiap VTL juga memiliki subsistem interupsi sendiri (APIC lokal). Ini memungkinkan VTL yang lebih tinggi untuk memproses interupsi tanpa berisiko mengganggu dari VTL yang lebih rendah.
  • Halaman Overlay: Halaman overlay tertentu dipertahankan per-VTL sehingga VTL yang lebih tinggi memiliki akses yang andal. Misalnya, ada halaman overlay hypercall terpisah per VTL.

Deteksi dan Status VSM

Kemampuan VSM diiklankan ke partisi melalui bendera hak istimewa partisi AccessVsm. Hanya partisi dengan semua hak istimewa berikut yang dapat menggunakan VSM: AccessVsm, AccessVpRegisters, dan AccessSynicRegs.

Deteksi Kemampuan VSM

Tamu harus menggunakan register khusus model berikut untuk mengakses laporan tentang kemampuan VSM:

Alamat MSR Daftarkan Nama Deskripsi
0x000D0006 HV_X64_REGISTER_VSM_CAPABILITIES Laporkan kemampuan VSM.

Format Register VSM Capabilities MSR adalah sebagai berikut:

Bit Deskripsi Atribut
63 Dr6Shared Baca
62:47 MbecVtlMask Baca
46 DenyLowerVtlStartup Baca
45:0 RsvdZ Baca

Dr6Shared menunjukkan kepada tamu apakah Dr6 adalah register bersama antara VTL.

MvecVtlMask menunjukkan kepada tamu VTL tempat Mbec dapat diaktifkan.

DenyLowerVtlStartup menunjukkan kepada tamu apakah Vtl dapat menolak reset VP oleh VTL yang lebih rendah.

Daftar Status VSM

Selain bendera hak istimewa partisi, dua register virtual dapat digunakan untuk mempelajari informasi tambahan tentang status VSM: HvRegisterVsmPartitionStatus dan HvRegisterVsmVpStatus.

HvRegisterVsmPartitionStatus

HvRegisterVsmPartitionStatus adalah register baca-saja per partisi yang dibagikan di semua VTL. Register ini menyediakan informasi tentang VTL mana yang telah diaktifkan untuk partisi, VTL mana yang mengaktifkan Kontrol Eksekusi Berbasis Mode, serta VTL maksimum yang diizinkan.

typedef union
{
    UINT64 AsUINT64;
    struct
    {
        UINT64 EnabledVtlSet : 16;
        UINT64 MaximumVtl : 4;
        UINT64 MbecEnabledVtlSet: 16;
        UINT64 ReservedZ : 28;
    };
} HV_REGISTER_VSM_PARTITION_STATUS;

HvRegisterVsmVpStatus

HvRegisterVsmVpStatus adalah register baca-saja dan dibagikan di semua VTL. Ini adalah register per-VP, yang berarti setiap prosesor virtual mempertahankan instansnya sendiri. Register ini menyediakan informasi tentang VTL mana yang telah diaktifkan, yang aktif, serta mode MBEC yang aktif pada VP.

typedef union
{
    UINT64 AsUINT64;
    struct
    {
        UINT64 ActiveVtl : 4;
        UINT64 ActiveMbecEnabled : 1;
        UINT64 ReservedZ0 : 11;
        UINT64 EnabledVtlSet : 16;
        UINT64 ReservedZ1 : 32;
    };
} HV_REGISTER_VSM_VP_STATUS;

ActiveVtl adalah ID konteks VTL yang saat ini aktif pada prosesor virtual.

ActiveMbecEnabled menentukan bahwa MBEC saat ini aktif pada prosesor virtual.

EnabledVtlSet adalah bitmap dari VTL yang diaktifkan pada prosesor virtual.

Status Awal VTL Partisi

Saat partisi dimulai atau direset, partisi mulai berjalan di VTL0. Semua VTL lainnya dinonaktifkan pada pembuatan partisi.

Pengaktifan VTL

Untuk mulai menggunakan VTL, VTL yang lebih rendah harus memulai hal berikut:

  1. Aktifkan target VTL untuk partisi. Hal ini membuat VTL umumnya tersedia untuk partisi.
  2. Aktifkan VTL target pada satu atau beberapa prosesor virtual. Ini membuat VTL tersedia untuk VP, dan menetapkan konteks awalnya. Disarankan agar semua VP memiliki VTL yang diaktifkan yang sama. Mengaktifkan VTL pada beberapa VP (tetapi tidak semua) dapat menyebabkan perilaku yang tidak terduga.
  3. Setelah VTL diaktifkan untuk partisi dan VP, VP dapat mulai mengatur perlindungan akses setelah bendera EnableVtlProtection ditetapkan.

Perhatikan bahwa VTL tidak perlu berturut-turut.

Mengaktifkan Target VTL untuk Partisi

HvCallEnablePartitionVtl hypercall digunakan untuk mengaktifkan VTL untuk partisi tertentu. Perhatikan bahwa sebelum perangkat lunak benar-benar dapat dijalankan dalam VTL tertentu, VTL harus diaktifkan pada prosesor virtual di partisi.

Mengaktifkan Target VTL untuk Prosesor Virtual

Setelah VTL diaktifkan untuk partisi, VTL dapat diaktifkan pada prosesor virtual partisi. Hypercall HvCallEnableVpVtl dapat digunakan untuk mengaktifkan VTL untuk prosesor virtual, yang menetapkan konteks awalnya.

Prosesor virtual memiliki satu "konteks" per VTL. Jika VTL dialihkan, status privat VTL juga dialihkan.

Konfigurasi VTL

Setelah VTL diaktifkan, konfigurasinya dapat diubah oleh VP yang berjalan pada VTL yang sama atau lebih tinggi.

Konfigurasi Partisi

Atribut seluruh partisi dapat dikonfigurasi menggunakan register HvRegisterVsmPartitionConfig. Ada satu contoh register ini untuk setiap VTL (lebih besar dari 0) pada setiap partisi.

Setiap VTL dapat memodifikasi instans HV_REGISTER_VSM_PARTITION_CONFIG sendiri, serta instans untuk VTL yang lebih rendah. VTL mungkin tidak mengubah register ini untuk VTL yang lebih tinggi.

typedef union
{
    UINT64 AsUINT64;
    struct
    {
        UINT64 EnableVtlProtection : 1;
        UINT64 DefaultVtlProtectionMask : 4;
        UINT64 ZeroMemoryOnReset : 1;
        UINT64 DenyLowerVtlStartup : 1;
        UINT64 ReservedZ : 2;
        UINT64 InterceptVpStartup : 1;
        UINT64 ReservedZ : 54; };
} HV_REGISTER_VSM_PARTITION_CONFIG;

Bidang register ini dijelaskan di bawah ini.

Aktifkan Perlindungan VTL

Setelah VTL diaktifkan, bendera EnableVtlProtection harus diatur sebelum dapat mulai menerapkan perlindungan memori. Bendera ini ditulis sekali, yang berarti bahwa setelah ditetapkan, bendera ini tidak dapat dimodifikasi.

Masker Perlindungan Default

Secara default, sistem menerapkan perlindungan RWX ke semua halaman yang saat ini dipetakan, dan halaman "hot-added" di masa mendatang. Halaman yang ditambahkan panas mengacu pada memori apa pun yang ditambahkan ke partisi selama operasi mengubah ukuran.

VTL yang lebih tinggi dapat mengatur kebijakan perlindungan memori default yang berbeda dengan menentukan DefaultVtlProtectionMask dalam HV_REGISTER_VSM_PARTITION_CONFIG. Masker ini harus diatur pada saat VTL diaktifkan. Ini tidak dapat diubah setelah diatur, dan hanya dibersihkan oleh reset partisi.

Bit Deskripsi
0 Baca
1 Tulis
2 Eksekusi Mode Kernel (KMX)
3 Eksekusi Mode Pengguna (UMX)

Memori Nol saat Reset

ZeroMemOnReset adalah bit yang mengontrol apakah memori di-nol sebelum partisi diatur ulang. Konfigurasi ini aktif secara default. Jika bit diatur, memori partisi di-nol saat direset sehingga memori VTL yang lebih tinggi tidak dapat disusupi oleh VTL yang lebih rendah. Jika bit ini dibersihkan, memori partisi tidak di-nol pada reset.

DenyLowerVtlStartup

Bendera DenyLowerVtlStartup mengontrol apakah prosesor virtual dapat dimulai atau direset dengan VTL yang lebih rendah. Ini termasuk cara arsitektur untuk mengatur ulang prosesor virtual (misalnya SIPI di X64) serta hypercall HvCallStartVirtualProcessor .

InterceptVpStartup

Jika bendera InterceptVpStartup diatur, memulai atau mengatur ulang prosesor virtual menghasilkan intersepsi ke VTL yang lebih tinggi.

Mengonfigurasi VTL Yang Lebih Rendah

Register berikut dapat digunakan oleh VTL yang lebih tinggi untuk mengonfigurasi perilaku VTL yang lebih rendah:

typedef union
{
    UINT64 AsUINT64;
    struct
    {
        UINT64 MbecEnabled : 1;
        UINT64 TlbLocked : 1;
        UINT64 ReservedZ : 62;
    };
} HV_REGISTER_VSM_VP_SECURE_VTL_CONFIG;

Setiap VTL (lebih tinggi dari 0) memiliki instans register ini untuk setiap VTL yang lebih rendah dari dirinya sendiri. Misalnya, VTL2 akan memiliki dua instans register ini – satu untuk VTL1, dan satu detik untuk VTL0.

Bidang register ini dijelaskan di bawah ini.

MbecEnabled

Bidang ini mengonfigurasi apakah MBEC diaktifkan untuk VTL yang lebih rendah.

TlbLocked

Bidang ini mengunci TLB VTL yang lebih rendah. Kemampuan ini dapat digunakan untuk mencegah VTL yang lebih rendah menyebabkan pembatalan TLB yang mungkin mengganggu VTL yang lebih tinggi. Ketika bit ini diatur, semua permintaan flush ruang alamat dari VTL yang lebih rendah diblokir sampai kunci diangkat.

Untuk membuka kunci TLB, VTL yang lebih tinggi dapat menghapus bit ini. Selain itu, setelah VP kembali ke VTL yang lebih rendah, VP akan melepaskan semua kunci TLB yang disimpannya pada saat itu.

Entri VTL

VTL "dimasukkan" ketika VP beralih dari VTL yang lebih rendah ke VTL yang lebih tinggi. Kesalahan ini dapat terjadi karena beberapa alasan berikut:

  1. Panggilan VTL: ini adalah ketika perangkat lunak secara eksplisit ingin memanggil kode di VTL yang lebih tinggi.
  2. Gangguan aman: jika gangguan diterima untuk VTL yang lebih tinggi, VP akan memasuki VTL yang lebih tinggi.
  3. Penyadapan aman: tindakan tertentu akan memicu gangguan aman (misalnya mengakses MSR tertentu).

Setelah VTL dimasukkan, VTL harus secara sukarela keluar. VTL yang lebih tinggi tidak dapat didahulukan oleh VTL yang lebih rendah.

Mengidentifikasi Alasan Entri VTL

Untuk bereaksi dengan tepat terhadap entri, VTL yang lebih tinggi mungkin perlu mengetahui alasan masuknya. Untuk membedakan antara alasan entri, entri VTL disertakan dalam struktur HV_VP_VTL_CONTROL .

Panggilan VTL

"Panggilan VTL" adalah ketika VTL yang lebih rendah memulai entri ke VTL yang lebih tinggi (misalnya, untuk melindungi wilayah memori dengan VTL yang lebih tinggi) melalui hypercall HvCallVtlCall .

Panggilan VTL mempertahankan status register bersama di seluruh sakelar VTL. Register privat dipertahankan pada tingkat per-VTL. Pengecualian untuk pembatasan ini adalah register yang diperlukan oleh urutan panggilan VTL. Register berikut diperlukan untuk panggilan VTL:

x64 x86 Deskripsi
RCX EDX:EAX Menentukan input kontrol panggilan VTL ke hypervisor
RAX ECX Dicadangkan

Semua bit dalam input kontrol panggilan VTL saat ini dicadangkan.

Pembatasan Panggilan VTL

Panggilan VTL hanya dapat dimulai dari mode prosesor yang paling istimewa. Misalnya, pada sistem x64 panggilan VTL hanya dapat berasal dari CPL0. Panggilan VTL dimulai dari mode prosesor yang apa pun kecuali yang paling istimewa pada sistem menghasilkan hypervisor yang menyuntikkan pengecualian #UD ke dalam prosesor virtual.

Panggilan VTL hanya dapat beralih ke VTL tertinggi berikutnya. Dengan kata lain, jika ada beberapa VTL yang diaktifkan, panggilan tidak dapat "melewati" VTL. Tindakan berikut menghasilkan pengecualian #UD:

  • Panggilan VTL dimulai dari mode prosesor yang tidak lain adalah yang paling istimewa pada sistem (khusus arsitektur).
  • Panggilan VTL dari mode nyata (x86/x64)
  • Panggilan VTL pada prosesor virtual tempat VTL target dinonaktifkan (atau belum diaktifkan).
  • Panggilan VTL dengan nilai input kontrol yang tidak valid

Keluar VTL

Sakelar ke VTL yang lebih rendah dikenal sebagai "return". Setelah VTL selesai diproses, VTL dapat memulai pengembalian VTL untuk beralih ke VTL yang lebih rendah. Satu-satunya cara pengembalian VTL dapat terjadi adalah jika VTL yang lebih tinggi secara sukarela memulainya. VTL yang lebih rendah tidak pernah dapat mendahului VTL yang lebih tinggi.

Pengembalian VTL

"Pengembalian VTL" adalah ketika VTL yang lebih tinggi memulai sakelar ke VTL yang lebih rendah melalui hypercall HvCallVtlReturn . Mirip dengan panggilan VTL, status prosesor privat dialihkan, dan status bersama tetap diberlakukan. Jika VTL yang lebih rendah secara eksplisit telah dipanggil ke VTL yang lebih tinggi, hypervisor meningkatkan penunjuk instruksi VTL yang lebih tinggi sebelum pengembalian selesai sehingga dapat berlanjut setelah panggilan VTL.

Urutan kode Pengembalian VTL memerlukan penggunaan register berikut:

x64 x86 Deskripsi
RCX EDX:EAX Menentukan input kontrol pengembalian VTL ke hypervisor
RAX ECX Dicadangkan

Input kontrol pengembalian VTL memiliki format berikut:

Bit Bidang Deskripsi
63:1 RsvdZ
0 Pengembalian cepat Register tidak dipulihkan

Tindakan berikut akan menghasilkan pengecualian #UD:

  • Mencoba pengembalian VTL saat VTL terendah saat ini aktif
  • Mencoba pengembalian VTL dengan nilai input kontrol yang tidak valid
  • Mencoba pengembalian VTL dari mode prosesor yang apa pun kecuali yang paling istimewa pada sistem (khusus arsitektur)

Pengembalian Cepat

Sebagai bagian dari pemrosesan pengembalian, hypervisor dapat memulihkan status register VTL yang lebih rendah dari struktur HV_VP_VTL_CONTROL . Misalnya, setelah memproses interupsi aman, VTL yang lebih tinggi mungkin ingin kembali tanpa mengganggu status VTL yang lebih rendah. Oleh karena itu, hypervisor menyediakan mekanisme untuk hanya memulihkan register VTL yang lebih rendah ke nilai pra-panggilan mereka yang disimpan dalam struktur kontrol VTL.

Jika perilaku ini tidak diperlukan, VTL yang lebih tinggi dapat menggunakan "pengembalian cepat". Pengembalian cepat adalah ketika hypervisor tidak memulihkan status register dari struktur kontrol. Ini harus digunakan jika memungkinkan untuk menghindari pemrosesan yang tidak perlu.

Bidang ini dapat diatur dengan bit 0 dari input pengembalian VTL. Jika diatur ke 0, register dipulihkan dari struktur HV_VP_VTL_CONTROL. Jika bit ini diatur ke 1, register tidak dipulihkan (pengembalian cepat).

Bantuan Halaman Hypercall

Hypervisor menyediakan mekanisme untuk membantu panggilan VTL dan kembali melalui halaman hypercall. Halaman ini mengabstraksi urutan kode tertentu yang diperlukan untuk beralih VTL.

Urutan kode untuk menjalankan panggilan dan pengembalian VTL dapat diakses dengan menjalankan instruksi tertentu di halaman hypercall. Gugus panggilan/pengembalian terletak pada offset di halaman hypercall yang ditentukan oleh register virtual HvRegisterVsmCodePageOffset. Ini adalah register baca-saja dan seluruh partisi, dengan instans terpisah per-VTL.

VTL dapat menjalankan panggilan/pengembalian VTL menggunakan instruksi PANGGILAN. PANGGILAN ke lokasi yang benar di halaman hypercall akan memulai panggilan/pengembalian VTL.

typedef union
{
    UINT64 AsUINT64;
    struct
    {
        UINT64 VtlCallOffset : 12;
        UINT64 VtlReturnOffset : 12;
        UINT64 ReservedZ : 40;
    };
} HV_REGISTER_VSM_CODE_PAGE_OFFSETS;

Untuk meringkas, langkah-langkah untuk memanggil urutan kode menggunakan halaman hypercall adalah sebagai berikut:

  1. Memetakan halaman hypercall ke ruang GPA VTL
  2. Tentukan offset yang benar untuk urutan kode (panggilan atau pengembalian VTL).
  3. Jalankan urutan kode menggunakan CALL.

Perlindungan Akses Memori

Salah satu perlindungan yang diperlukan yang disediakan oleh VSM adalah kemampuan untuk mengisolasi akses memori.

VTL yang lebih tinggi memiliki kontrol tingkat tinggi atas jenis akses memori yang diizinkan oleh VTL yang lebih rendah. Ada tiga jenis perlindungan dasar yang dapat ditentukan oleh VTL yang lebih tinggi untuk halaman IPK tertentu: Baca, Tulis, dan eXecute. Ini didefinisikan dalam tabel berikut:

Nama Deskripsi
Baca Mengontrol apakah akses baca diizinkan ke halaman memori
Tulis Mengontrol apakah akses tulis diizinkan ke halaman memori
Jalankan Mengontrol apakah pengambilan instruksi diperbolehkan untuk halaman memori.

Ketiga gabungan ini untuk jenis perlindungan memori berikut:

  1. Tidak ada akses
  2. Baca-saja, tidak ada eksekusi
  3. Baca-saja, jalankan
  4. Baca/tulis, tidak ada eksekusi
  5. Baca/tulis, jalankan

Jika "kontrol eksekusi berbasis mode (MBEC)" diaktifkan, perlindungan eksekusi mode pengguna dan kernel dapat diatur secara terpisah.

VTL yang lebih tinggi dapat mengatur perlindungan memori untuk IPK melalui hypercall HvCallModifyVtlProtectionMask .

Hierarki Perlindungan Memori

Izin akses memori dapat diatur oleh sejumlah sumber untuk VTL tertentu. Setiap izin VTL berpotensi dibatasi oleh sejumlah VTL lainnya, serta oleh partisi host. Urutan penerapan perlindungan adalah sebagai berikut:

  1. Perlindungan memori yang ditetapkan oleh host
  2. Perlindungan memori diatur oleh VTL yang lebih tinggi

Dengan kata lain, perlindungan VTL menggantikan perlindungan host. VTL tingkat lebih tinggi menggantikan VTL tingkat bawah. Perhatikan bahwa VTL mungkin tidak mengatur izin akses memori untuk dirinya sendiri.

Antarmuka yang sesuai diharapkan tidak melapisi jenis non-RAM apa pun melalui RAM.

Pelanggaran Akses Memori

Jika VP yang berjalan pada VTL yang lebih rendah mencoba melanggar perlindungan memori yang ditetapkan oleh VTL yang lebih tinggi, intersepsi dihasilkan. Intersepsi ini diterima oleh VTL yang lebih tinggi yang menetapkan perlindungan. Ini memungkinkan VTL yang lebih tinggi untuk menangani pelanggaran berdasarkan kasus per kasus. Misalnya, VTL yang lebih tinggi dapat memilih untuk mengembalikan kesalahan, atau meniru akses.

Kontrol Eksekusi Berbasis Mode (MBEC)

Ketika VTL menempatkan pembatasan memori pada VTL yang lebih rendah, VTL mungkin ingin membuat perbedaan antara mode pengguna dan kernel saat memberikan hak istimewa "jalankan". Misalnya, jika pemeriksaan integritas kode dilakukan di VTL yang lebih tinggi, kemampuan untuk membedakan antara mode pengguna dan mode kernel berarti bahwa VTL dapat memberlakukan integritas kode hanya untuk aplikasi mode kernel.

Terlepas dari tiga perlindungan memori tradisional (baca, tulis, eksekusi), MBEC memperkenalkan perbedaan antara mode pengguna dan mode kernel untuk menjalankan perlindungan. Dengan demikian, jika MBEC diaktifkan, VTL memiliki kesempatan untuk mengatur empat jenis perlindungan memori:

Nama Deskripsi
Baca Mengontrol apakah akses baca diizinkan ke halaman memori
Tulis Mengontrol apakah akses tulis diizinkan ke halaman memori
Eksekusi Mode Pengguna (UMX) Mengontrol apakah pengambilan instruksi yang dihasilkan dalam mode pengguna diizinkan untuk halaman memori. CATATAN: Jika MBEC dinonaktifkan, pengaturan ini diabaikan.
Eksekusi Mode Kernel (UMX) Mengontrol apakah pengambilan instruksi yang dihasilkan dalam mode kernel diizinkan untuk halaman memori. CATATAN: Jika MBEC dinonaktifkan, pengaturan ini mengontrol akses eksekusi mode pengguna dan mode kernel.

Memori yang ditandai dengan perlindungan "Eksekusi Mode Pengguna" hanya akan dapat dieksekusi ketika prosesor virtual berjalan dalam mode pengguna. Demikian juga, memori "Kernel-Mode Execute" hanya akan dapat dieksekusi ketika prosesor virtual berjalan dalam mode kernel.

KMX dan UMX dapat diatur secara independen sehingga izin eksekusi diberlakukan secara berbeda antara mode pengguna dan kernel. Semua kombinasi UMX dan KMX didukung, kecuali untuk KMX=1, UMX=0. Perilaku kombinasi ini tidak ditentukan.

MBEC dinonaktifkan secara default untuk semua VTL dan prosesor virtual. Ketika MBEC dinonaktifkan, bit eksekusi mode kernel menentukan pembatasan akses memori. Dengan demikian, jika MBEC dinonaktifkan, kode KMX=1 dapat dieksekusi dalam mode kernel dan pengguna.

Tabel Deskriptor

Kode mode pengguna apa pun yang mengakses tabel deskriptor harus berada di halaman IPK yang ditandai sebagai KMX=UMX=1. Perangkat lunak mode pengguna yang mengakses tabel deskriptor dari halaman IPK bertanda KMX=0 tidak didukung dan mengakibatkan kesalahan perlindungan umum.

Konfigurasi MBEC

Untuk menggunakan kontrol eksekusi berbasis Mode, kontrol harus diaktifkan pada dua tingkat:

  1. Ketika VTL diaktifkan untuk partisi, MBEC harus diaktifkan menggunakan HvCallEnablePartitionVtl
  2. MBEC harus dikonfigurasi berdasarkan per-VP dan per-VTL, menggunakan HvRegisterVsmVpSecureVtlConfig.

Interaksi MBEC dengan Supervisor Mode Execution Prevention (SMEP)

Supervisor-Mode Execution Prevention (SMEP) adalah fitur prosesor yang didukung pada beberapa platform. SMEP dapat berdampak pada pengoperasian MBEC karena pembatasan akses supervisor ke halaman memori. Hypervisor mematuhi kebijakan berikut yang terkait dengan SMEP:

  • Jika SMEP tidak tersedia untuk OS tamu (baik karena kemampuan perangkat keras atau mode kompatibilitas prosesor), MBEC beroperasi tidak terpengaruh.
  • Jika SMEP tersedia, dan diaktifkan, MBEC beroperasi tidak terpengaruh.
  • Jika SMEP tersedia, dan dinonaktifkan, semua pembatasan eksekusi diatur oleh kontrol KMX. Dengan demikian, hanya kode yang ditandai KMX=1 yang akan diizinkan untuk dieksekusi.

Isolasi Status Prosesor Virtual

Prosesor virtual mempertahankan status terpisah untuk setiap VTL aktif. Namun, beberapa status ini bersifat privat untuk VTL tertentu, dan status yang tersisa dibagikan di antara semua VTL.

Status yang dipertahankan per VTL (alias status privat) disimpan oleh hypervisor di seluruh transisi VTL. Jika sakelar VTL dimulai, hypervisor menyimpan status privat saat ini untuk VTL aktif, lalu beralih ke status privat VTL target. Status bersama tetap aktif terlepas dari sakelar VTL.

Status Privat

Secara umum, setiap VTL memiliki register kontrol sendiri, rip register, RSP register, dan MSR. Di bawah ini adalah daftar register dan MSR tertentu yang bersifat privat untuk setiap VTL.

MSR Privat:

  • SYSENTER_CS, SYSENTER_ESP, SYSENTER_EIP, STAR, LSTAR, CSTAR, SFMASK, EFER, PAT, KERNEL_GSBASE, FS. BASE, GS. BASE, TSC_AUX
  • HV_X64_MSR_HYPERCALL
  • HV_X64_MSR_GUEST_OS_ID
  • HV_X64_MSR_REFERENCE_TSC
  • HV_X64_MSR_APIC_FREQUENCY
  • HV_X64_MSR_EOI
  • HV_X64_MSR_ICR
  • HV_X64_MSR_TPR
  • HV_X64_MSR_APIC_ASSIST_PAGE
  • HV_X64_MSR_NPIEP_CONFIG
  • HV_X64_MSR_SIRBP
  • HV_X64_MSR_SCONTROL
  • HV_X64_MSR_SVERSION
  • HV_X64_MSR_SIEFP
  • HV_X64_MSR_SIMP
  • HV_X64_MSR_EOM
  • HV_X64_MSR_SINT0 – HV_X64_MSR_SINT15
  • HV_X64_MSR_STIMER0_CONFIG – HV_X64_MSR_STIMER3_CONFIG
  • HV_X64_MSR_STIMER0_COUNT – HV_X64_MSR_STIMER3_COUNT
  • Register APIC lokal (termasuk CR8/TPR)

Register privat:

  • RIP, RSP
  • RFLAGS
  • CR0, CR3, CR4
  • DR7
  • IDTR, GDTR
  • CS, DS, ES, FS, GS, SS, TR, LDTR
  • TSC
  • DR6 (*tergantung pada jenis prosesor. Membaca register virtual HvRegisterVsmCapabilities untuk menentukan status bersama/privat)

Status Bersama

Status berbagi VTL untuk mengurangi overhead konteks pengalihan. Status berbagi juga memungkinkan beberapa komunikasi yang diperlukan antara VTL. Sebagian besar tujuan umum dan register floating point dibagikan, seperti halnya sebagian besar MSR arsitektur. Di bawah ini adalah daftar MSR dan register tertentu yang dibagikan di antara semua VTL:

MSR bersama:

  • HV_X64_MSR_TSC_FREQUENCY
  • HV_X64_MSR_VP_INDEX
  • HV_X64_MSR_VP_RUNTIME
  • HV_X64_MSR_RESET
  • HV_X64_MSR_TIME_REF_COUNT
  • HV_X64_MSR_GUEST_IDLE
  • HV_X64_MSR_DEBUG_DEVICE_OPTIONS
  • MTRR
  • MCG_CAP
  • MCG_STATUS

Daftar bersama:

  • Rax, Rbx, Rcx, Rdx, Rsi, Rdi, Rbp
  • CR2
  • R8 – R15
  • DR0 – DR5
  • Status titik mengambang X87
  • Status XMM
  • Status AVX
  • XCR0 (XFEM)
  • DR6 (*tergantung pada jenis prosesor. Membaca register virtual HvRegisterVsmCapabilities untuk menentukan status bersama/privat)

Mode Nyata

Mode nyata tidak didukung untuk VTL apa pun yang lebih besar dari 0. VTL yang lebih besar dari 0 dapat berjalan dalam mode 32-bit atau 64-bit.

Manajemen Gangguan VTL

Untuk mencapai tingkat isolasi yang tinggi antara Tingkat Kepercayaan Virtual, Mode Aman Virtual menyediakan subsistem interupsi terpisah untuk setiap VTL yang diaktifkan pada prosesor virtual. Ini memastikan bahwa VTL dapat mengirim dan menerima gangguan tanpa gangguan dari VTL yang kurang aman.

Setiap VTL memiliki pengontrol interupsi sendiri, yang hanya aktif jika prosesor virtual berjalan di VTL tertentu. Jika prosesor virtual mengalihkan status VTL, pengontrol interupsi yang aktif pada prosesor juga dialihkan.

Gangguan yang ditargetkan pada VTL yang lebih tinggi dari VTL aktif akan menyebabkan sakelar VTL langsung. VTL yang lebih tinggi kemudian dapat menerima interupsi. Jika VTL yang lebih tinggi tidak dapat menerima interupsi karena nilai TPR/CR8-nya, interupsi ditahan sebagai "tertunda" dan VTL tidak beralih. Jika ada beberapa VTL dengan interupsi tertunda, VTL tertinggi lebih diutamakan (tanpa pemberitahuan ke VTL yang lebih rendah).

Ketika interupsi ditargetkan pada VTL yang lebih rendah, interupsi tidak dikirimkan sampai lain kali prosesor virtual beralih ke VTL yang ditargetkan. INIT dan IPI startup yang ditargetkan pada VTL yang lebih rendah dihilangkan pada prosesor virtual dengan VTL yang lebih tinggi diaktifkan. Karena INIT/SIPI diblokir, hypercall HvCallStartVirtualProcessor harus digunakan untuk memulai prosesor.

RFLAGS. JIKA

Untuk tujuan beralih VTL, RFLAGS. IF tidak memengaruhi apakah gangguan aman memicu sakelar VTL. Jika RFLAGS. JIKA dibersihkan untuk menutupi gangguan, gangguan ke VTL yang lebih tinggi masih akan menyebabkan sakelar VTL ke VTL yang lebih tinggi. Hanya nilai TPR/CR8 VTL yang lebih tinggi yang diperhitungkan saat memutuskan apakah akan segera mengganggu.

Perilaku ini juga memengaruhi gangguan yang tertunda setelah pengembalian VTL. Jika RFLAGS. Bit IF dibersihkan untuk menutupi gangguan dalam VTL tertentu, dan VTL kembali (ke VTL yang lebih rendah), hypervisor akan mengevaluasi kembali gangguan yang tertunda. Ini akan menyebabkan panggilan segera kembali ke VTL yang lebih tinggi.

Bantuan Pemberitahuan Gangguan Virtual

VTL yang lebih tinggi dapat mendaftar untuk menerima pemberitahuan jika mereka memblokir pengiriman langsung interupsi ke VTL yang lebih rendah dari prosesor virtual yang sama. VTL yang lebih tinggi dapat mengaktifkan Virtual Interrupt Notification Assist (VINA) melalui register virtual HvRegisterVsmVina:

typedef union
{
    UINT64 AsUINT64;
    struct
    {
        UINT64 Vector : 8;
        UINT64 Enabled : 1;
        UINT64 AutoReset : 1;
        UINT64 AutoEoi : 1;
        UINT64 ReservedP : 53;
    };
} HV_REGISTER_VSM_VINA;

Setiap VTL pada setiap VP memiliki instans VINA sendiri, serta versi HvRegisterVsmVina sendiri. Fasilitas VINA akan menghasilkan interupsi tepi yang dipicu pada VTL yang saat ini lebih tinggi ketika gangguan untuk VTL yang lebih rendah siap untuk pengiriman segera.

Untuk mencegah banjir gangguan terjadi ketika fasilitas ini diaktifkan, fasilitas VINA mencakup beberapa keadaan terbatas. Ketika gangguan VINA dihasilkan, status fasilitas VINA diubah menjadi "Ditegaskan." Mengirim akhir gangguan ke SINT yang terkait dengan fasilitas VINA tidak akan menghapus status "Ditegaskan". Status yang ditegaskan hanya dapat dibersihkan dengan salah satu dari dua cara:

  1. Status dapat dihapus secara manual dengan menulis ke bidang VinaAsserted dari struktur HV_VP_VTL_CONTROL .
  2. Status secara otomatis dihapus pada entri berikutnya ke VTL jika opsi "reset otomatis pada entri VTL" diaktifkan di register HvRegisterVsmVina.

Ini memungkinkan kode yang berjalan pada VTL aman untuk hanya diberi tahu tentang gangguan pertama yang diterima untuk VTL yang lebih rendah. Jika VTL aman ingin diberi tahu tentang gangguan tambahan, VTL dapat menghapus bidang VinaAsserted dari halaman bantuan VP, dan akan diberi tahu tentang gangguan baru berikutnya.

Intersepsi Aman

Hypervisor memungkinkan VTL yang lebih tinggi untuk menginstal intersepsi untuk peristiwa yang terjadi dalam konteks VTL yang lebih rendah. Ini memberi VTL yang lebih tinggi tingkat kontrol yang ditinggikan atas sumber daya VTL yang lebih rendah. Intersepsi aman dapat digunakan untuk melindungi sumber daya penting sistem, dan mencegah serangan dari VTL yang lebih rendah.

Intersepsi aman diantrekan ke VTL yang lebih tinggi, dan VTL dibuat dapat dijalankan pada VP.

Jenis Intersepsi Aman

Jenis Intersepsi Intersepsi Berlaku Untuk
Akses memori Mencoba mengakses perlindungan GPA yang ditetapkan oleh VTL yang lebih tinggi.
Mengontrol akses register Mencoba mengakses sekumpulan register kontrol yang ditentukan oleh VTL yang lebih tinggi.

Intersepsi Berlapis

Beberapa VTL dapat menginstal intersepsi aman untuk peristiwa yang sama di VTL yang lebih rendah. Dengan demikian, hierarki ditetapkan untuk memutuskan di mana penyadapan berlapis diberi tahu. Daftar berikut adalah urutan di mana intersepsi diberi tahu:

  1. VTL yang lebih rendah
  2. VTL yang lebih tinggi

Menangani Intersepsi Aman

Setelah VTL diberi tahu tentang intersepsi aman, VTL yang lebih rendah harus mengambil tindakan sehingga VTL yang lebih rendah dapat dilanjutkan. VTL yang lebih tinggi dapat menangani intersepsi dengan sejumlah cara, termasuk: menyuntikkan pengecualian, meniru akses, atau memberikan proksi ke akses. Bagaimanapun, jika status privat VP VTL yang lebih rendah perlu dimodifikasi, HvCallSetVpRegisters harus digunakan.

Intersepsi Register Aman

VTL yang lebih tinggi dapat mencegat akses ke register kontrol tertentu. Hal ini dicapai dengan mengatur HvX64RegisterCrInterceptControl menggunakan hypercall HvCallSetVpRegisters . Mengatur bit kontrol di HvX64RegisterCrInterceptControl akan memicu intersepsi untuk setiap akses register kontrol yang sesuai.

typedef union
{
    UINT64 AsUINT64;
    struct
    {
        UINT64 Cr0Write : 1;
        UINT64 Cr4Write : 1;
        UINT64 XCr0Write : 1;
        UINT64 IA32MiscEnableRead : 1;
        UINT64 IA32MiscEnableWrite : 1;
        UINT64 MsrLstarRead : 1;
        UINT64 MsrLstarWrite : 1;
        UINT64 MsrStarRead : 1;
        UINT64 MsrStarWrite : 1;
        UINT64 MsrCstarRead : 1;
        UINT64 MsrCstarWrite : 1;
        UINT64 ApicBaseMsrRead : 1;
        UINT64 ApicBaseMsrWrite : 1;
        UINT64 MsrEferRead : 1;
        UINT64 MsrEferWrite : 1;
        UINT64 GdtrWrite : 1;
        UINT64 IdtrWrite : 1;
        UINT64 LdtrWrite : 1;
        UINT64 TrWrite : 1;
        UINT64 MsrSysenterCsWrite : 1;
        UINT64 MsrSysenterEipWrite : 1;
        UINT64 MsrSysenterEspWrite : 1;
        UINT64 MsrSfmaskWrite : 1;
        UINT64 MsrTscAuxWrite : 1;
        UINT64 MsrSgxLaunchControlWrite : 1;
        UINT64 RsvdZ : 39;
    };
} HV_REGISTER_CR_INTERCEPT_CONTROL;

Daftar Masker

Untuk memungkinkan kontrol yang lebih baik, subset register kontrol juga memiliki register masker yang sesuai. Register masker dapat digunakan untuk memasang intersepsi pada subset dari register kontrol yang sesuai. Jika register mask tidak didefinisikan, akses apa pun (seperti yang didefinisikan oleh HvX64RegisterCrInterceptControl) akan memicu intersepsi.

Hypervisor mendukung register mask berikut: HvX64RegisterCrInterceptCr0Mask, HvX64RegisterCrInterceptCr4Mask dan HvX64RegisterCrInterceptIa32MiscEnableMask.

DMA dan Perangkat

Perangkat secara efektif memiliki tingkat hak istimewa yang sama dengan VTL0. Saat VSM diaktifkan, semua memori yang dialokasikan perangkat ditandai sebagai VTL0. Setiap akses DMA memiliki hak istimewa yang sama dengan VTL0.