KVM: Prevent kvm_init from corrupting debugfs structures
I'm seeing an oops condition when kvm-intel and kvm-amd are modprobe'd during boot (say on an Intel system) and then rmmod'd: # modprobe kvm-intel kvm_init() kvm_init_debug() kvm_arch_init() <-- stores debugfs dentries internally (success, etc) # modprobe kvm-amd kvm_init() kvm_init_debug() <-- second initialization clobbers kvm's internal pointers to dentries kvm_arch_init() kvm_exit_debug() <-- and frees them # rmmod kvm-intel kvm_exit() kvm_exit_debug() <-- double free of debugfs files! *BOOM* If execution gets to the end of kvm_init(), then the calling module has been established as the kvm provider. Move the debugfs initialization to the end of the function, and remove the now-unnecessary call to kvm_exit_debug() from the error path. That way we avoid trampling on the debugfs entries and freeing them twice. Cc: stable@kernel.org Signed-off-by: Darrick J. Wong <djwong@us.ibm.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
This commit is contained in:
committed by
Marcelo Tosatti
parent
8a8365c560
commit
0ea4ed8e94
@@ -2717,8 +2717,6 @@ int kvm_init(void *opaque, unsigned int vcpu_size,
|
|||||||
int r;
|
int r;
|
||||||
int cpu;
|
int cpu;
|
||||||
|
|
||||||
kvm_init_debug();
|
|
||||||
|
|
||||||
r = kvm_arch_init(opaque);
|
r = kvm_arch_init(opaque);
|
||||||
if (r)
|
if (r)
|
||||||
goto out_fail;
|
goto out_fail;
|
||||||
@@ -2785,6 +2783,8 @@ int kvm_init(void *opaque, unsigned int vcpu_size,
|
|||||||
kvm_preempt_ops.sched_in = kvm_sched_in;
|
kvm_preempt_ops.sched_in = kvm_sched_in;
|
||||||
kvm_preempt_ops.sched_out = kvm_sched_out;
|
kvm_preempt_ops.sched_out = kvm_sched_out;
|
||||||
|
|
||||||
|
kvm_init_debug();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_free:
|
out_free:
|
||||||
@@ -2807,7 +2807,6 @@ out_free_0:
|
|||||||
out:
|
out:
|
||||||
kvm_arch_exit();
|
kvm_arch_exit();
|
||||||
out_fail:
|
out_fail:
|
||||||
kvm_exit_debug();
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(kvm_init);
|
EXPORT_SYMBOL_GPL(kvm_init);
|
||||||
@@ -2815,6 +2814,7 @@ EXPORT_SYMBOL_GPL(kvm_init);
|
|||||||
void kvm_exit(void)
|
void kvm_exit(void)
|
||||||
{
|
{
|
||||||
tracepoint_synchronize_unregister();
|
tracepoint_synchronize_unregister();
|
||||||
|
kvm_exit_debug();
|
||||||
misc_deregister(&kvm_dev);
|
misc_deregister(&kvm_dev);
|
||||||
kmem_cache_destroy(kvm_vcpu_cache);
|
kmem_cache_destroy(kvm_vcpu_cache);
|
||||||
sysdev_unregister(&kvm_sysdev);
|
sysdev_unregister(&kvm_sysdev);
|
||||||
@@ -2824,7 +2824,6 @@ void kvm_exit(void)
|
|||||||
on_each_cpu(hardware_disable, NULL, 1);
|
on_each_cpu(hardware_disable, NULL, 1);
|
||||||
kvm_arch_hardware_unsetup();
|
kvm_arch_hardware_unsetup();
|
||||||
kvm_arch_exit();
|
kvm_arch_exit();
|
||||||
kvm_exit_debug();
|
|
||||||
free_cpumask_var(cpus_hardware_enabled);
|
free_cpumask_var(cpus_hardware_enabled);
|
||||||
__free_page(bad_page);
|
__free_page(bad_page);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user