首页
社区
课程
招聘
未解决 [求助] 将Windows端的 x64 vt-x框架迁移至Linux时,出现Triple fault 50雪币
发表于: 2天前 1895

未解决 [求助] 将Windows端的 x64 vt-x框架迁移至Linux时,出现Triple fault 50雪币

2天前
1895

vmcs的填充源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
struct page *vmcs_page, *msr_bitmap_page;
void *vmcs, *vmcs_phys, *host_stack, *msr_bitmap_phys, *msr_bitmap;
unsigned short cs, ds, es, fs, gs, ss, tr, ldtr;
unsigned int cr0, cr3, cr4;
 
/* vm-control */
VmxPinBasedControls pin_base;
VmxProcessorBasedControls process_base;
VmxSecondaryProcessorBasedControls secondary_process_base;
VmxVmEntryControls entry;
VmxVmExitControls exit;
VmxExceptionBitmap exception_bitmap = {0};
 
// 1.申请内存
vmcs_page = alloc_pages(GFP_KERNEL, 0);
vmcs_phys = (void *)page_to_phys(vmcs_page);
vmcs = page_address(vmcs_page);
memset(vmcs, 0, 0x1000);
*(char *)vmcs = 1;
vmx_config.vmcs_region_page = vmcs_page;
 
// 2. vmclear&vmptrld
// asm_vmclear(vmcs_phys);
asm_vmptrld(vmcs_phys);
 
// 3.初始化VMCS
 
//
// 3.1 Guest State Area
//
cr0 = asm_read_cr0();
cr3 = asm_read_cr3();
cr4 = asm_read_cr4();
 
asm_vmwrite(GUEST_CR0, cr0);
asm_vmwrite(GUEST_CR3, cr3);
asm_vmwrite(GUEST_CR4, cr4);
asm_vmwrite(CR0_READ_SHADOW, cr0);
asm_vmwrite(CR4_READ_SHADOW, cr4);
 
asm_vmwrite(GUEST_DR7, 0x400);
 
/*段寄存器*/
es = asm_read_es();
cs = asm_read_cs();
ds = asm_read_ds();
fs = asm_read_fs();
gs = asm_read_gs();
ss = asm_read_ss();
tr = asm_read_tr();
ldtr = asm_read_ldtr();
 
asm_vmwrite(GUEST_ES_SELECTOR, es);
asm_vmwrite(GUEST_ES_BASE, get_segment_base(es));
asm_vmwrite(GUEST_ES_LIMIT, get_segment_limit(es));
asm_vmwrite(GUEST_ES_AR_BYTES, get_segment_access_rights(es));
printk(KERN_INFO "[*] es: %#llx %#llx %#llx %#llx\n", (__u64)es, (__u64)get_segment_base(es), (__u64)get_segment_limit(es), (__u64)(get_segment_access_rights(es) & 0xffffffff));
 
asm_vmwrite(GUEST_CS_SELECTOR, cs);
asm_vmwrite(GUEST_CS_BASE, get_segment_base(cs));
asm_vmwrite(GUEST_CS_LIMIT, get_segment_limit(cs));
asm_vmwrite(GUEST_CS_AR_BYTES, get_segment_access_rights(cs));
printk(KERN_INFO "[*] cs: %#llx %#llx %#llx %#llx\n", (__u64)cs, (__u64)get_segment_base(cs), (__u64)get_segment_limit(cs), (__u64)(get_segment_access_rights(cs) & 0xffffffff));
 
asm_vmwrite(GUEST_DS_SELECTOR, ds);
asm_vmwrite(GUEST_DS_BASE, get_segment_base(ds));
asm_vmwrite(GUEST_DS_LIMIT, get_segment_limit(ds));
asm_vmwrite(GUEST_DS_AR_BYTES, get_segment_access_rights(ds));
printk(KERN_INFO "[*] ds: %#llx %#llx %#llx %#llx\n", (__u64)ds, (__u64)get_segment_base(ds), (__u64)get_segment_limit(ds), (__u64)(get_segment_access_rights(ds) & 0xffffffff));
 
asm_vmwrite(GUEST_FS_SELECTOR, fs);
asm_vmwrite(GUEST_FS_BASE, asm_rdmsr2(IA32_FS_BASE));
asm_vmwrite(GUEST_FS_LIMIT, get_segment_limit(fs));
asm_vmwrite(GUEST_FS_AR_BYTES, get_segment_access_rights(fs));
printk(KERN_INFO "[*] fs: %#llx %#llx %#llx %#llx\n", (__u64)fs, (__u64)get_segment_base(fs), (__u64)get_segment_limit(fs), (__u64)(get_segment_access_rights(fs) & 0xffffffff));
 
asm_vmwrite(GUEST_GS_SELECTOR, gs);
asm_vmwrite(GUEST_GS_BASE, asm_rdmsr2(IA32_GS_BASE));
asm_vmwrite(GUEST_GS_LIMIT, get_segment_limit(gs));
asm_vmwrite(GUEST_GS_AR_BYTES, get_segment_access_rights(gs));
printk(KERN_INFO "[*] gs: %#llx %#llx %#llx %#llx\n", (__u64)gs, (__u64)get_segment_base(gs), (__u64)get_segment_limit(gs), (__u64)(get_segment_access_rights(gs) & 0xffffffff));
 
asm_vmwrite(GUEST_SS_SELECTOR, ss);
asm_vmwrite(GUEST_SS_BASE, get_segment_base(ss));
asm_vmwrite(GUEST_SS_LIMIT, get_segment_limit(ss));
asm_vmwrite(GUEST_SS_AR_BYTES, get_segment_access_rights(ss));
printk(KERN_INFO "[*] ss: %#llx %#llx %#llx %#llx\n", (__u64)ss, (__u64)get_segment_base(ss), (__u64)get_segment_limit(ss), (__u64)(get_segment_access_rights(ss) & 0xffffffff));
 
asm_vmwrite(GUEST_TR_SELECTOR, tr);
asm_vmwrite(GUEST_TR_BASE, get_segment_base(tr));
asm_vmwrite(GUEST_TR_LIMIT, get_segment_limit(tr));
asm_vmwrite(GUEST_TR_AR_BYTES, get_segment_access_rights(tr));
printk(KERN_INFO "[*] tr: %#llx %#llx %#llx %#llx\n", (__u64)tr, (__u64)get_segment_base(tr), (__u64)get_segment_limit(tr), (__u64)(get_segment_access_rights(tr) & 0xffffffff));
 
asm_vmwrite(GUEST_LDTR_SELECTOR, ldtr); // 必填项
asm_vmwrite(GUEST_LDTR_BASE, get_segment_base(ldtr));
asm_vmwrite(GUEST_LDTR_LIMIT, get_segment_limit(ldtr));
asm_vmwrite(GUEST_LDTR_AR_BYTES, get_segment_access_rights(ldtr));
printk(KERN_INFO "[*] ldtr: %#llx %#llx %#llx %#llx\n", (__u64)ldtr, (__u64)get_segment_base(ldtr), (__u64)get_segment_limit(ldtr), (__u64)(get_segment_access_rights(ldtr) & 0xffffffff));
 
asm_vmwrite(GUEST_GDTR_BASE, (__u64)asm_get_gdtr_base());
asm_vmwrite(GUEST_GDTR_LIMIT, asm_get_gdtr_limit());
printk(KERN_INFO "[*] gdtr: %#llx %#llx\n", (__u64)asm_get_gdtr_base(), (__u64)asm_get_gdtr_limit());
 
asm_vmwrite(GUEST_IDTR_BASE, (__u64)asm_get_idtr_base());
asm_vmwrite(GUEST_IDTR_LIMIT, asm_get_idtr_limit());
printk(KERN_INFO "[*] idtr: %#llx %#llx\n", (__u64)asm_get_idtr_base(), (__u64)asm_get_idtr_limit());
 
/*MSR寄存器组*/
asm_vmwrite(GUEST_IA32_DEBUGCTL, asm_rdmsr2(IA32_DEBUGCTL)); // 分支跟踪或性能监控
 
asm_vmwrite(GUEST_SYSENTER_CS, asm_rdmsr2(IA32_SYSENTER_CS));
asm_vmwrite(GUEST_SYSENTER_ESP, asm_rdmsr2(IA32_SYSENTER_ESP));
asm_vmwrite(GUEST_SYSENTER_EIP, asm_rdmsr2(IA32_SYSENTER_EIP)); // KiFastCallEntry
 
asm_vmwrite(GUEST_IA32_EFER, asm_rdmsr2(IA32_EFER));
 
/* 设置guest.rip/rsp/rfalgs */
asm_vmwrite(GUEST_RSP, guest_regs.rsp);
asm_vmwrite(GUEST_RIP, (__u64)&__guest_entry);
asm_vmwrite(GUEST_RFLAGS, guest_regs.rflags);
// printk(KERN_INFO "[+] guest rip: %pK, rsp: %pK, rflags: %pK\n", (void *)&__guest_entry, (void *)guest_regs.rsp, (void *)guest_regs.rflags);
 
// VMCS link pointer, 嵌套虚拟化
asm_vmwrite(VMCS_LINK_POINTER, -1);
 
//
// 3.2 Host State Area
//
asm_vmwrite(HOST_CR0, cr0);
asm_vmwrite(HOST_CR3, cr3);
asm_vmwrite(HOST_CR4, cr4);
 
asm_vmwrite(HOST_ES_SELECTOR, es);
asm_vmwrite(HOST_CS_SELECTOR, cs);
asm_vmwrite(HOST_SS_SELECTOR, ss);
asm_vmwrite(HOST_DS_SELECTOR, ds);
asm_vmwrite(HOST_FS_SELECTOR, fs);
asm_vmwrite(HOST_GS_SELECTOR, gs);
asm_vmwrite(HOST_TR_SELECTOR, tr);
 
asm_vmwrite(HOST_FS_BASE, asm_rdmsr2(IA32_FS_BASE));
asm_vmwrite(HOST_GS_BASE, asm_rdmsr2(IA32_GS_BASE));
asm_vmwrite(HOST_TR_BASE, get_segment_base(tr));
asm_vmwrite(HOST_GDTR_BASE, (__u64)asm_get_gdtr_base());
asm_vmwrite(HOST_IDTR_BASE, (__u64)asm_get_idtr_base());
 
/*MSR寄存器组*/
asm_vmwrite(HOST_IA32_SYSENTER_CS, asm_rdmsr2(IA32_SYSENTER_CS));
asm_vmwrite(HOST_IA32_SYSENTER_ESP, asm_rdmsr2(IA32_SYSENTER_ESP));
asm_vmwrite(HOST_IA32_SYSENTER_EIP, asm_rdmsr2(IA32_SYSENTER_EIP)); // KiFastCallEntry
// asm_vmwrite(HOST_IA32_PAT, asm_rdmsr2(IA32_PAT));
asm_vmwrite(HOST_IA32_EFER, asm_rdmsr2(IA32_EFER));
 
/*申请VMX栈空间*/
host_stack = vmalloc(0x2000);
memset(host_stack, 0, 0x2000);
vmx_config.host_stack = host_stack;
asm_vmwrite(HOST_RSP, (__u64)host_stack + 0x2000);
asm_vmwrite(HOST_RIP, (__u64)&__host_entry);
// printk(KERN_INFO "[+] host ==> rip: %pK, rsp: %pK\n", &__host_entry, host_stack + 0x2000);
 
//
// 3.3 vm-control
//
 
/*检查IA32_VMX_BASIC[55]是否置位, 填充保留位*/
if (asm_rdmsr2(IA32_VMX_BASIC) & 0x0080000000000000)
{
    /*vm execution controls*/
    pin_base.all = asm_rdmsr2(IA32_VMX_TRUE_PINBASED_CTLS) & 0xffffffff;
    process_base.all = asm_rdmsr2(IA32_VMX_TRUE_PROCBASED_CTLS) & 0xffffffff;
 
    /*vm entry control*/
    entry.all = asm_rdmsr2(IA32_VMX_TRUE_ENTRY_CTLS) & 0xffffffff;
 
    /*vm exit control*/
    exit.all = asm_rdmsr2(IA32_VMX_TRUE_EXIT_CTLS) & 0xffffffff;
}
else
{
    /*vm execution controls*/
    pin_base.all = asm_rdmsr2(IA32_VMX_PINBASED_CTLS) & 0xffffffff;
    process_base.all = asm_rdmsr2(IA32_VMX_PROCBASED_CTLS) & 0xffffffff;
 
    /*vm entry control*/
    entry.all = asm_rdmsr2(IA32_VMX_ENTRY_CTLS) & 0xffffffff;
 
    /*vm exit control*/
    exit.all = asm_rdmsr2(IA32_VMX_EXIT_CTLS) & 0xffffffff;
}
 
/*检查是否启用Secondary Processor-Based VM-Execution Controls*/
if (asm_rdmsr2(IA32_VMX_PROCBASED_CTLS) & 0x8000000000000000)
{
    printk(KERN_INFO "[+] 启用Secondary Processor-Based VM-Execution Controls\n");
    secondary_process_base.all = asm_rdmsr2(IA32_VMX_PROCBASED_CTLS2);
}
 
/*
 *   VMCS controls域属性添加
 */
// process_base.Bits.interrupt_window_exiting = true;
process_base.Bits.activate_secondary_control = true;
 
/* msr bitmap */
if (vmx_config.vmcs_controls.enable_msr_bitmap)
{
    process_base.Bits.use_msr_bitmaps = true;
    msr_bitmap_page = alloc_pages(GFP_KERNEL, 0);
    msr_bitmap = page_address(msr_bitmap_page);
    memset(msr_bitmap, 0, 0x1000);
    msr_bitmap_phys = (void *)page_to_phys(msr_bitmap_page);
    asm_vmwrite(MSR_BITMAP_ADDRESS, (__u64)msr_bitmap_phys);
    vmx_config.msr_bitmap_page = msr_bitmap_page;
}
 
secondary_process_base.Bits.enable_rdtscp = true;
secondary_process_base.Bits.enable_invpcid = true;
secondary_process_base.Bits.enable_xsaves_xstors = true;
 
entry.Bits.ia32e_mode_guest = true; // x64必填【重要】
entry.Bits.load_ia32_efer = true;   // 启用 EFER 寄存器
// entry.Bits.load_ia32_pat = true;    // 页面管理相关【可选】
entry.Bits.load_debug_controls = true;
 
exit.Bits.host_address_space_size = true; // x64必填【重要】, 进入IA-32e模式
exit.Bits.load_ia32_efer = true;
exit.Bits.save_ia32_efer = true;
exit.Bits.acknowledge_interrupt_on_exit = true;
exit.Bits.save_debug_controls = true;
 
/*
    VMCS controls域写入
*/
asm_vmwrite(PIN_BASED_VM_EXEC_CONTROL, pin_base.all);
asm_vmwrite(CPU_BASED_VM_EXEC_CONTROL, process_base.all);
asm_vmwrite(SECONDARY_VM_EXEC_CONTROL, secondary_process_base.all);
asm_vmwrite(VM_ENTRY_CONTROLS, entry.all);
asm_vmwrite(VM_EXIT_CONTROLS, exit.all);

当执行流返回后,很快就会触发三重中断(VMware的log日志),但是我无法确定具体错误发生在哪里?vmcs的设置存在问题吗?vm-exit部分屏蔽了msr的读写触发的退出,此外只处理了cpuid指令,其余通过default进行打印。但是,在cpu进入关闭状态前,并未有任何的日志输出。

图片描述
寄存器的属性值如上图示,以此为(selector, base, limit, rights)。


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (6)
雪    币: 30
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
2
Triple Fault 只能根据Guest Rip 和Rsp 来猜了。三次错误发生在Double Fault 之后。慢慢找。终究能找有用的东东。
2天前
0
雪    币: 903
活跃值: (4970)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
NoHeart Triple Fault 只能根据Guest Rip 和Rsp 来猜了。三次错误发生在Double Fault 之后。慢慢找。终究能找有用的东东。
guest.rip返回后,系统实现虚拟化。关键是,发生错误时似乎并没有进入vm-exit,无法捕捉异常。
2天前
0
雪    币: 903
活跃值: (4970)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
NoHeart Triple Fault 只能根据Guest Rip 和Rsp 来猜了。三次错误发生在Double Fault 之后。慢慢找。终究能找有用的东东。
我在host的处理例程中设置了int3断点,正常情况下,gdb可以在断点处断下来。但是在发生三重错误时,host并没有任何输出日志或者捕捉到中断
2天前
0
雪    币: 903
活跃值: (4970)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
5


虽然2号exit-reason对应于Triple fault,但是似乎无法捕获而陷入vm-exit。

1天前
0
雪    币: 903
活跃值: (4970)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
6
ALwalker 虽然2号exit-reason对应于Triple fault,但是似乎无法捕获而陷入vm-exit。
我设置了exception-bitmap的double fault的拦截,但是似乎无法触发(kprint没有任何输出消息)...
1天前
0
雪    币: 30
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
7
ALwalker 我设置了exception-bitmap的double fault的拦截,但是似乎无法触发(kprint没有任何输出消息)...
Double Fault 一般是OS处理,不是你的Vmm处理。所以你需要找到First Fault的RIP来猜测哪里出了问题,因此你需要在内存中保存Dbg数据,这样出了问题你才能好调试,在某些条件下Int 3会卡死或者hung住。所以在确定int 3不会影响正常执行流程的情况下在使用。
6小时前
0
游客
登录 | 注册 方可回帖
返回
//