Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1437621 > unrolled thread
| Started by | Wanpeng Li <kernellwp@gmail.com> |
|---|---|
| First post | 2016-07-06 12:40 +0200 |
| Last post | 2016-07-06 14:00 +0200 |
| Articles | 4 — 2 participants |
Back to article view | Back to linux.kernel
[PATCH v2] KVM: nVMX: Fix preemption timer kernel NULL pointer dereference Wanpeng Li <kernellwp@gmail.com> - 2016-07-06 12:40 +0200
Re: [PATCH v2] KVM: nVMX: Fix preemption timer kernel NULL pointer dereference Paolo Bonzini <pbonzini@redhat.com> - 2016-07-06 13:10 +0200
Re: [PATCH v2] KVM: nVMX: Fix preemption timer kernel NULL pointer dereference Wanpeng Li <kernellwp@gmail.com> - 2016-07-06 13:40 +0200
Re: [PATCH v2] KVM: nVMX: Fix preemption timer kernel NULL pointer dereference Wanpeng Li <kernellwp@gmail.com> - 2016-07-06 14:00 +0200
| From | Wanpeng Li <kernellwp@gmail.com> |
|---|---|
| Date | 2016-07-06 12:40 +0200 |
| Subject | [PATCH v2] KVM: nVMX: Fix preemption timer kernel NULL pointer dereference |
| Message-ID | <rRSpj-81D-7@gated-at.bofh.it> |
From: Wanpeng Li <wanpeng.li@hotmail.com> BUG: unable to handle kernel NULL pointer dereference at (null) IP: [< (null)>] (null) PGD 0 Oops: 0010 [#1] SMP Call Trace: ? kvm_lapic_expired_hv_timer+0x47/0x90 [kvm] handle_preemption_timer+0xe/0x20 [kvm_intel] vmx_handle_exit+0x169/0x15a0 [kvm_intel] ? kvm_arch_vcpu_ioctl_run+0xd5d/0x19d0 [kvm] kvm_arch_vcpu_ioctl_run+0xdee/0x19d0 [kvm] ? kvm_arch_vcpu_ioctl_run+0xd5d/0x19d0 [kvm] ? vcpu_load+0x1c/0x60 [kvm] ? kvm_arch_vcpu_load+0x57/0x260 [kvm] kvm_vcpu_ioctl+0x2d3/0x7c0 [kvm] do_vfs_ioctl+0x96/0x6a0 ? __fget_light+0x2a/0x90 SyS_ioctl+0x79/0x90 do_syscall_64+0x68/0x180 entry_SYSCALL64_slow_path+0x25/0x25 Code: Bad RIP value. RIP [< (null)>] (null) RSP <ffff8800b5263c48> CR2: 0000000000000000 ---[ end trace 9c70c48b1a2bc66e ]--- This can be reproduced readily by preemption timer enabled on L0 and disabled on L1. Preemption timer for nested VMX is emulated by hrtimer which is started on L2 entry, stopped on L2 exit and evaluated via the check_nested_events hook. However, nested_vmx_exit_handled is always return true for preemption timer vmexit, then the L1 preemption timer vmexit is captured and be treated as a L2 preemption timer vmexit, incurr a nested vmexit dereference NULL pointer. This patch fix it by depending on check_nested_events to capture L2 preemption timer(emulated hrtimer) expire and nested vmexit. Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: Radim Krčmář <rkrcmar@redhat.com> Cc: Yunhong Jiang <yunhong.jiang@intel.com> Cc: Jan Kiszka <jan.kiszka@siemens.com> Cc: Haozhong Zhang <haozhong.zhang@intel.com> Signed-off-by: Wanpeng Li <wanpeng.li@hotmail.com> --- v1 -> v2: * fix typo in patch description arch/x86/kvm/vmx.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 85e2f0a..29c16a8 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -8041,6 +8041,8 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu) return nested_cpu_has2(vmcs12, SECONDARY_EXEC_XSAVES); case EXIT_REASON_PCOMMIT: return nested_cpu_has2(vmcs12, SECONDARY_EXEC_PCOMMIT); + case EXIT_REASON_PREEMPTION_TIMER: + return false; default: return true; } -- 1.9.1
[toc] | [next] | [standalone]
| From | Paolo Bonzini <pbonzini@redhat.com> |
|---|---|
| Date | 2016-07-06 13:10 +0200 |
| Subject | Re: [PATCH v2] KVM: nVMX: Fix preemption timer kernel NULL pointer dereference |
| Message-ID | <rRSSl-8rf-13@gated-at.bofh.it> |
| In reply to | #1437621 |
On 06/07/2016 12:29, Wanpeng Li wrote:
> BUG: unable to handle kernel NULL pointer dereference at (null)
> IP: [< (null)>] (null)
> PGD 0
> Oops: 0010 [#1] SMP
> Call Trace:
> ? kvm_lapic_expired_hv_timer+0x47/0x90 [kvm]
> handle_preemption_timer+0xe/0x20 [kvm_intel]
> vmx_handle_exit+0x169/0x15a0 [kvm_intel]
> ? kvm_arch_vcpu_ioctl_run+0xd5d/0x19d0 [kvm]
> kvm_arch_vcpu_ioctl_run+0xdee/0x19d0 [kvm]
> ? kvm_arch_vcpu_ioctl_run+0xd5d/0x19d0 [kvm]
> ? vcpu_load+0x1c/0x60 [kvm]
> ? kvm_arch_vcpu_load+0x57/0x260 [kvm]
> kvm_vcpu_ioctl+0x2d3/0x7c0 [kvm]
> do_vfs_ioctl+0x96/0x6a0
> ? __fget_light+0x2a/0x90
> SyS_ioctl+0x79/0x90
> do_syscall_64+0x68/0x180
> entry_SYSCALL64_slow_path+0x25/0x25
> Code: Bad RIP value.
> RIP [< (null)>] (null)
> RSP <ffff8800b5263c48>
> CR2: 0000000000000000
> ---[ end trace 9c70c48b1a2bc66e ]---
This is happening in L2, while the patch is for L1, right? So the commit
title should be "KVM: nVMX: fix incorrect preemption timer vmexit in nested guest".
The patch looks correct, but I'm not sure how you get a preemption
timer vmexit while vmcs02 is active:
exec_control = vmcs12->pin_based_vm_exec_control;
exec_control |= vmcs_config.pin_based_exec_ctrl;
exec_control &= ~PIN_BASED_VMX_PREEMPTION_TIMER;
In other words, don't you need something like
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index f6e5cc679898..edf925a2da9d 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -1121,9 +1121,6 @@ static inline bool cpu_has_broken_vmx_preemption_timer(void)
static inline bool cpu_has_vmx_preemption_timer(void)
{
- if (cpu_has_broken_vmx_preemption_timer())
- return false;
-
return vmcs_config.pin_based_exec_ctrl &
PIN_BASED_VMX_PREEMPTION_TIMER;
}
@@ -3406,6 +3403,9 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PINBASED_CTLS,
&_pin_based_exec_control) < 0)
return -EIO;
+
+ if (cpu_has_broken_vmx_preemption_timer())
+ _pin_based_exec_control &= ~PIN_BASED_VMX_PREEMPTION_TIMER;
if (!(_cpu_based_2nd_exec_control &
SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY))
@@ -9797,8 +9796,10 @@ static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
vmcs_write64(VMCS_LINK_POINTER, -1ull);
exec_control = vmcs12->pin_based_vm_exec_control;
+ exec_control &= ~PIN_BASED_VMX_PREEMPTION_TIMER;
exec_control |= vmcs_config.pin_based_exec_ctrl;
- exec_control &= ~PIN_BASED_VMX_PREEMPTION_TIMER;
+ if (vmx->hv_deadline_tsc == -1)
+ exec_control &= ~PIN_BASED_VMX_PREEMPTION_TIMER;
if (nested_cpu_has_posted_intr(vmcs12)) {
/*
for the L1 TSC deadline timer to trigger while L2 is running? It's untested,
but this would replace the patch that Haozhong submitted earlier.
Paolo
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Cc: Radim Krčmář <rkrcmar@redhat.com>
> Cc: Yunhong Jiang <yunhong.jiang@intel.com>
> Cc: Jan Kiszka <jan.kiszka@siemens.com>
> Cc: Haozhong Zhang <haozhong.zhang@intel.com>
> Signed-off-by: Wanpeng Li <wanpeng.li@hotmail.com>
> ---
> v1 -> v2:
> * fix typo in patch description
>
> arch/x86/kvm/vmx.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
> index 85e2f0a..29c16a8 100644
> --- a/arch/x86/kvm/vmx.c
> +++ b/arch/x86/kvm/vmx.c
> @@ -8041,6 +8041,8 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu)
> return nested_cpu_has2(vmcs12, SECONDARY_EXEC_XSAVES);
> case EXIT_REASON_PCOMMIT:
> return nested_cpu_has2(vmcs12, SECONDARY_EXEC_PCOMMIT);
> + case EXIT_REASON_PREEMPTION_TIMER:
> + return false;
> default:
> return true;
> }
>
[toc] | [prev] | [next] | [standalone]
| From | Wanpeng Li <kernellwp@gmail.com> |
|---|---|
| Date | 2016-07-06 13:40 +0200 |
| Message-ID | <rRTlo-bj-37@gated-at.bofh.it> |
| In reply to | #1437640 |
2016-07-06 19:02 GMT+08:00 Paolo Bonzini <pbonzini@redhat.com>: > > > On 06/07/2016 12:29, Wanpeng Li wrote: >> BUG: unable to handle kernel NULL pointer dereference at (null) >> IP: [< (null)>] (null) >> PGD 0 >> Oops: 0010 [#1] SMP >> Call Trace: >> ? kvm_lapic_expired_hv_timer+0x47/0x90 [kvm] >> handle_preemption_timer+0xe/0x20 [kvm_intel] >> vmx_handle_exit+0x169/0x15a0 [kvm_intel] >> ? kvm_arch_vcpu_ioctl_run+0xd5d/0x19d0 [kvm] >> kvm_arch_vcpu_ioctl_run+0xdee/0x19d0 [kvm] >> ? kvm_arch_vcpu_ioctl_run+0xd5d/0x19d0 [kvm] >> ? vcpu_load+0x1c/0x60 [kvm] >> ? kvm_arch_vcpu_load+0x57/0x260 [kvm] >> kvm_vcpu_ioctl+0x2d3/0x7c0 [kvm] >> do_vfs_ioctl+0x96/0x6a0 >> ? __fget_light+0x2a/0x90 >> SyS_ioctl+0x79/0x90 >> do_syscall_64+0x68/0x180 >> entry_SYSCALL64_slow_path+0x25/0x25 >> Code: Bad RIP value. >> RIP [< (null)>] (null) >> RSP <ffff8800b5263c48> >> CR2: 0000000000000000 >> ---[ end trace 9c70c48b1a2bc66e ]--- > > This is happening in L2, while the patch is for L1, right? So the commit > title should be "KVM: nVMX: fix incorrect preemption timer vmexit in nested guest". Thanks. I will send out another version. :) > > The patch looks correct, but I'm not sure how you get a preemption > timer vmexit while vmcs02 is active: > > exec_control = vmcs12->pin_based_vm_exec_control; > exec_control |= vmcs_config.pin_based_exec_ctrl; > exec_control &= ~PIN_BASED_VMX_PREEMPTION_TIMER; > > In other words, don't you need something like After apply your patch, L0 calltrace. [ 355.840045] ------------[ cut here ]------------ [ 355.840072] WARNING: CPU: 3 PID: 4176 at /home/kernel/kvm/arch/x86/kvm/lapic.c:1362 kvm_lapic_expired_hv_timer+0x6c/0x90 [kvm] [ 355.840073] Modules linked in: kvm_intel(OE) kvm(OE) openvswitch nf_nat_ipv6 nf_nat_ipv4 libcrc32c ip6t_REJECT nf_reject_ipv6 nf_log_ipv6 xt_hl ip6t_rt nf_conntrack_ipv6 nf_defrag_ipv6 ipt_REJECT snd_hda_codec_hdmi nf_reject_ipv4 nf_log_ipv4 nf_log_common xt_LOG xt_limit xt_tcpudp intel_rapl xt_addrtype x86_pkg_temp_thermal i915 intel_powerclamp nf_conntrack_ipv4 coretemp nf_defrag_ipv4 xt_conntrack snd_hda_codec_realtek snd_hda_codec_generic ip6table_filter snd_hda_intel drm_kms_helper ip6_tables snd_hda_codec nf_conntrack_netbios_ns nf_conntrack_broadcast nf_nat_ftp nf_nat snd_hda_core nf_conntrack_ftp snd_hwdep nf_conntrack snd_pcm iptable_filter snd_seq_midi ip_tables snd_seq_midi_event x_tables snd_rawmidi irqbypass snd_seq crct10dif_pclmul crc32_pclmul ghash_clmulni_intel drm aesni_intel snd_seq_device aes_x86_64 snd_timer lrw dcdbas gf128mul snd glue_helper ablk_helper cryptd mei_me serio_raw mei i2c_algo_bit soundcore shpchp lpc_ich video mac_hid bnep rfcomm bluetooth nfsd auth_rpcgss nfs_acl nfs parport_pc ppdev lockd grace sunrpc lp fscache parport hid_generic usbhid ahci psmouse hid e1000e libahci ptp pps_core [last unloaded: kvm] [ 355.840135] CPU: 3 PID: 4176 Comm: qemu-system-x86 Tainted: G W OE 4.7.0-rc1+ #19 [ 355.840136] Hardware name: Dell Inc. OptiPlex 7020/0F5C5X, BIOS A03 01/08/2015 [ 355.840137] 0000000000000000 ffff880203bf7be8 ffffffff8143a669 0000000000000000 [ 355.840140] 0000000000000000 ffff880203bf7c28 ffffffff8108b5a1 00000552117eb580 [ 355.840142] ffff8800d9ea3c00 ffff880204ed0000 0000000000000001 ffff8802028c4280 [ 355.840145] Call Trace: [ 355.840149] [<ffffffff8143a669>] dump_stack+0x99/0xd0 [ 355.840152] [<ffffffff8108b5a1>] __warn+0xd1/0xf0 [ 355.840154] [<ffffffff8108b68d>] warn_slowpath_null+0x1d/0x20 [ 355.840166] [<ffffffffc08976fc>] kvm_lapic_expired_hv_timer+0x6c/0x90 [kvm] [ 355.840169] [<ffffffffc057061e>] handle_preemption_timer+0xe/0x20 [kvm_intel] [ 355.840172] [<ffffffffc057c329>] vmx_handle_exit+0x169/0x15a0 [kvm_intel] [ 355.840182] [<ffffffffc087c5cf>] ? kvm_arch_vcpu_ioctl_run+0xdef/0x1aa0 [kvm] [ 355.840190] [<ffffffffc087c661>] kvm_arch_vcpu_ioctl_run+0xe81/0x1aa0 [kvm] [ 355.840197] [<ffffffffc087c5cf>] ? kvm_arch_vcpu_ioctl_run+0xdef/0x1aa0 [kvm] [ 355.840206] [<ffffffffc08751a7>] ? kvm_arch_vcpu_load+0x57/0x260 [kvm] [ 355.840213] [<ffffffffc0860c13>] kvm_vcpu_ioctl+0x2d3/0x7c0 [kvm] [ 355.840216] [<ffffffff810e6794>] ? __lock_is_held+0x54/0x70 [ 355.840218] [<ffffffff8126a646>] do_vfs_ioctl+0x96/0x6a0 [ 355.840220] [<ffffffff8127734a>] ? __fget_light+0x2a/0x90 [ 355.840221] [<ffffffff8126acc9>] SyS_ioctl+0x79/0x90 [ 355.840223] [<ffffffff81003c5c>] do_syscall_64+0x7c/0x1e0 [ 355.840226] [<ffffffff818b9483>] entry_SYSCALL64_slow_path+0x25/0x25 [ 355.840227] ---[ end trace 4efbadf14355f403 ]---
[toc] | [prev] | [next] | [standalone]
| From | Wanpeng Li <kernellwp@gmail.com> |
|---|---|
| Date | 2016-07-06 14:00 +0200 |
| Message-ID | <rRTEJ-iL-1@gated-at.bofh.it> |
| In reply to | #1437651 |
2016-07-06 19:38 GMT+08:00 Wanpeng Li <kernellwp@gmail.com>: > 2016-07-06 19:02 GMT+08:00 Paolo Bonzini <pbonzini@redhat.com>: >> >> >> On 06/07/2016 12:29, Wanpeng Li wrote: >>> BUG: unable to handle kernel NULL pointer dereference at (null) >>> IP: [< (null)>] (null) >>> PGD 0 >>> Oops: 0010 [#1] SMP >>> Call Trace: >>> ? kvm_lapic_expired_hv_timer+0x47/0x90 [kvm] >>> handle_preemption_timer+0xe/0x20 [kvm_intel] >>> vmx_handle_exit+0x169/0x15a0 [kvm_intel] >>> ? kvm_arch_vcpu_ioctl_run+0xd5d/0x19d0 [kvm] >>> kvm_arch_vcpu_ioctl_run+0xdee/0x19d0 [kvm] >>> ? kvm_arch_vcpu_ioctl_run+0xd5d/0x19d0 [kvm] >>> ? vcpu_load+0x1c/0x60 [kvm] >>> ? kvm_arch_vcpu_load+0x57/0x260 [kvm] >>> kvm_vcpu_ioctl+0x2d3/0x7c0 [kvm] >>> do_vfs_ioctl+0x96/0x6a0 >>> ? __fget_light+0x2a/0x90 >>> SyS_ioctl+0x79/0x90 >>> do_syscall_64+0x68/0x180 >>> entry_SYSCALL64_slow_path+0x25/0x25 >>> Code: Bad RIP value. >>> RIP [< (null)>] (null) >>> RSP <ffff8800b5263c48> >>> CR2: 0000000000000000 >>> ---[ end trace 9c70c48b1a2bc66e ]--- >> >> This is happening in L2, while the patch is for L1, right? So the commit >> title should be "KVM: nVMX: fix incorrect preemption timer vmexit in nested guest". > > Thanks. I will send out another version. :) > >> >> The patch looks correct, but I'm not sure how you get a preemption >> timer vmexit while vmcs02 is active: >> >> exec_control = vmcs12->pin_based_vm_exec_control; >> exec_control |= vmcs_config.pin_based_exec_ctrl; >> exec_control &= ~PIN_BASED_VMX_PREEMPTION_TIMER; >> >> In other words, don't you need something like > > After apply your patch, L0 calltrace. my patch + your patch, L0 calltrace. w/o my patch + your patch, L1 the same calltrace. Regards, Wanpeng Li
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web