我有一个 kvm 虚拟机,它似乎会随机重新启动。我在 syslog 中没有看到任何有关重新启动、关闭、错误、核心转储、恐慌等的信息。主机上的 libvirtd 日志中也没有错误,qemu 日志中也没有错误,主机上也没有任何错误。
似乎某个随机进程可能正在调用虚拟机内的重新启动系统调用?我能想到的就只有这些了...
我如何确定是什么原因造成的?操作系统是Debian。
答案1
如果您不介意接触 C 代码,那么您可以编写一个简单的内核模块来拦截重新启动/关闭调用并通过printk()
.
这个答案可能是一个好的开始。要了解谁在调用您修改后的处理程序,请查看这个。
测试代码
我尝试开发上面的提示,并提出了以下代码。
在我自己的家庭系统(Ubuntu 22.04-LTS)上,它确实编译并安装了内核模块,并且似乎可以使用一些符号: 例如__do_sys_swapon
:
Dec 15 22:38:51 mintaka kernel: [82534.879652] __do_sys_swapon called by PID 5381 (swapon)
但是 中似乎有几个类似重新启动的调用/proc/kallsyms
,所以恐怕您需要几个 kprobe,或者需要相当多的试验和错误。如果我从提示符中__do_sys_reboot
调用,似乎不会被记录。reboot
#include <linux/module.h>
#include <linux/printk.h>
#include <linux/kprobes.h>
MODULE_LICENSE("GPL");
/**
* Pre handler
* @return int unless you're a kprobe geek
*/
static noinline int handler(struct kprobe *p, struct pt_regs *regs) {
struct task_struct *task = current;
printk(KERN_EMERG "%s called by PID %d (%s)\n", p->symbol_name, (int)task->pid, task->comm);
return 0;
}
// Verify that the symbol name is present in /proc/kallsyms
static struct kprobe kp = {
.symbol_name = "__do_sys_reboot",
.pre_handler = handler
};
/**
* Module initialization
*
* @returns int
*/
int init_module(void) {
int ret;
printk(KERN_INFO "loading whistlebooter\n");
// register_kprobe ultimately returns e.g. arch_copy_kprobe() which succeeds with 0
ret = register_kprobe(&kp);
if (ret < 0) {
if (-2 == ret) {
printk(KERN_INFO "register_kprobe did not find the requested symbol\n");
} else {
printk(KERN_INFO "register_kprobe failed with code %d\n", ret);
}
} else {
printk(KERN_INFO "kprobe registered at addr=%p for '%s'\n", kp.addr, kp.symbol_name);
}
return 0;
}
/**
* @returns void
*/
void cleanup_module(void) {
printk(KERN_INFO "unloading whistlebooter\n");
unregister_kprobe(&kp);
}
生成文件
# vim: tabstop=4 sw=4 noexpandtab
obj-m += mymodule.o
PWD := $(CURDIR)
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
要编译,只需运行“ make
”。