KEXT:vnode_open() 导致内核恐慌
KEXT: vnode_open() result in Kernel Panic
抱歉,如果之前有人问过,但我真的 google 不能。
我试图读取 OSX 的 KEXT 中的文件,使用 vnode_open()
如下:
struct vnode *vp = NULL;
kern_return_t kret;
vfs_context_t ctx = vfs_context_current();
kret = vnode_open(path, FREAD, 0, 0, &vp, ctx);
if (kret != KERN_SUCCESS) {
// Error log
} else {
proc_t proc = vfs_context_proc(ctx);
kauth_cred_t vp_cred = vfs_context_ucred(ctx);
char *buf = NULL;
int resid;
int len = sizeof(struct astruct);
buf = (char *)IOMalloc(len);
kret = vn_rdwr(UIO_READ, fvp, (caddr_t)buf,
len, 0, UIO_SYSSPACE, 0, vp_cred, &resid, proc);
vnode_close(fvp, FREAD, ctx);
if (kret != KERN_SUCCESS) {
// Error log
}
// Do something with the result.
}
vfs_context_rele(ctx);
加载 kext 后,系统崩溃并重新启动。只要 vnode_open()
在那里,它就会恐慌。
我做错了吗?
一件事立即脱颖而出:
你不应该使用 vfs_context_current()
- 使用 vfs_context_create(NULL)
。更糟糕的是,您随后在返回的上下文中调用 vfs_context_rele(ctx);
。只有 vfs_context_create
保留,vfs_context_current()
不保留,因此您过度释放了 VFS 上下文。这肯定会导致内核恐慌。
一般来说,在开发 kexts 时,您实际上可以做的不仅仅是让系统在内核崩溃后重新启动:
- 紧急日志写入 NVRAM,并在下次启动时保存到文件。您可以通过 Console.app 在 "System Diagnostic Reports" 下以 "kernel".
开始检查它们
- 紧急日志包含堆栈跟踪,默认情况下是未符号化的。您可以在崩溃后对它们进行符号化,但设置
keepsyms=1
引导参数并让崩溃处理程序为您进行符号化会更方便。
- 您可以设置
debug
引导参数以使崩溃启动内核调试器或核心转储,将堆栈跟踪写入 serial/firewire 控制台等。
这些内容部分记录在 Apple 的网站上,但在网络上进行一些搜索可能会为您提供一些更详细的信息。无论如何,它们对于调试此类问题非常有用。
抱歉,如果之前有人问过,但我真的 google 不能。
我试图读取 OSX 的 KEXT 中的文件,使用 vnode_open()
如下:
struct vnode *vp = NULL;
kern_return_t kret;
vfs_context_t ctx = vfs_context_current();
kret = vnode_open(path, FREAD, 0, 0, &vp, ctx);
if (kret != KERN_SUCCESS) {
// Error log
} else {
proc_t proc = vfs_context_proc(ctx);
kauth_cred_t vp_cred = vfs_context_ucred(ctx);
char *buf = NULL;
int resid;
int len = sizeof(struct astruct);
buf = (char *)IOMalloc(len);
kret = vn_rdwr(UIO_READ, fvp, (caddr_t)buf,
len, 0, UIO_SYSSPACE, 0, vp_cred, &resid, proc);
vnode_close(fvp, FREAD, ctx);
if (kret != KERN_SUCCESS) {
// Error log
}
// Do something with the result.
}
vfs_context_rele(ctx);
加载 kext 后,系统崩溃并重新启动。只要 vnode_open()
在那里,它就会恐慌。
我做错了吗?
一件事立即脱颖而出:
你不应该使用 vfs_context_current()
- 使用 vfs_context_create(NULL)
。更糟糕的是,您随后在返回的上下文中调用 vfs_context_rele(ctx);
。只有 vfs_context_create
保留,vfs_context_current()
不保留,因此您过度释放了 VFS 上下文。这肯定会导致内核恐慌。
一般来说,在开发 kexts 时,您实际上可以做的不仅仅是让系统在内核崩溃后重新启动:
- 紧急日志写入 NVRAM,并在下次启动时保存到文件。您可以通过 Console.app 在 "System Diagnostic Reports" 下以 "kernel". 开始检查它们
- 紧急日志包含堆栈跟踪,默认情况下是未符号化的。您可以在崩溃后对它们进行符号化,但设置
keepsyms=1
引导参数并让崩溃处理程序为您进行符号化会更方便。 - 您可以设置
debug
引导参数以使崩溃启动内核调试器或核心转储,将堆栈跟踪写入 serial/firewire 控制台等。
这些内容部分记录在 Apple 的网站上,但在网络上进行一些搜索可能会为您提供一些更详细的信息。无论如何,它们对于调试此类问题非常有用。