在Linux内核模块中释放Filp-> private_data会导致不使用后使用

发布于 2025-02-13 17:06:13 字数 1913 浏览 0 评论 0原文

我很早就了解Linux内核模块&设备驱动程序。我已经写了一个实现小腿的基本驱动程序(遵循Linux设备驱动程序第三版)。驱动程序实际上是按预期工作的,我可以通过cp/cat以及与Direct Syscalls在A的设备文件中打开/关闭/读取/写入。用户空间程序。

这本书的下一章是关于调试的,所以我重新编译了内核,并打开了更多调试功能。我尝试将其写入与以前相同的设备,并警告过无用的错误错误。 “ 错误:Kasan:CDEV_PUT中的不使用时使用+0x4c/0x90”。查看“分配的”跟踪,我看到有问题的内存是cdev,并

cdev = kmalloc(sizeof(struct cdev), GFP_KERNEL);

在我的CLOSE> CLOSE> CLOSE函数中存储在file> file> file_operations 结构:

int my_close(struct inode *inode, struct file *filp) {
    kfree(filp->private_data);
    return 0;
}

我应该注意,private_data实际上存储的内容是指向我的设备结构的指针,其中包含struct cdev。但是,由于设备struct包含struct cdev,而不是cdev的指针,所以我想它也可以释放cdev

使用后使用的呼叫跟踪是

dump_backtrace+0x0/0x460
show_stack+0x24/0x30
dump_stack_lvl+0x9c/0xd8
print_address_description.constprop.0+0x74/0x2b8
kasan_report+0x1bc/0x2ac
__asan_load8+0xbc/0xd0
cdev_put+0x4c/0x90
__fput+0x4c4/0x750
____fput+0x1c/0x30
task_work_run+0x17c/0x26c
do_notify_resume+0x2ce4/0x3060
work_pending+0xc/0x438

这样的,因此看起来cdev_put函数在我的cdev中使用了cdev在我的my_close函数中释放之后。 。但是根据该书(第3章),关闭函数应“ deallage在菲尔普 - > private_data>”中分配的任何打开的内容。但是,本书中包含的Scaull闭合功能的剥离版本看起来

int scull_release(struct inode *inode, struct file *filp)
{
    return 0;
}

不包括我包含的免费功能。

这本书还说,关闭功能应“ 在最后一个关闭上关闭设备”,所以也许private_data在文件的“最后一个”关闭之前不应释放?驾驶员应该如何知道一个特定的接近是最后一个关闭?从我到目前为止阅读的书的其他部分中,跟踪诸如打开和关闭的内容是内核的工作,而不是驱动程序。但是也许我已经误解了。

因此,主要问题: 应该private_data被释放吗?

I'm early in learning about linux kernel modules & device drivers. I've written a basic driver that implements scull (following Linux Device Drivers 3rd ed.). The driver actually works as expected, I can open/close/read/write from the device file it creates both with things like cp/cat and also with direct syscalls in a userspace program.

The next chapter of the book is all about debugging, so I recompiled the kernel with more debugging features turned on. I try writing to the device same as before, and I'm warned about a use-after-free error. "BUG: KASAN: use-after-free in cdev_put+0x4c/0x90". Looking at the "allocated by" trace, I see the memory in question is the cdev allocated with

cdev = kmalloc(sizeof(struct cdev), GFP_KERNEL);

The free occurs in my close function stored in the file_operations struct:

int my_close(struct inode *inode, struct file *filp) {
    kfree(filp->private_data);
    return 0;
}

I should note, what is actually stored in private_data is a pointer to my device struct, which contains a struct cdev. But since the device struct contains a struct cdev and not a pointer to a cdev, I guess it would free the cdev too.

The call trace of the use-after-free is

dump_backtrace+0x0/0x460
show_stack+0x24/0x30
dump_stack_lvl+0x9c/0xd8
print_address_description.constprop.0+0x74/0x2b8
kasan_report+0x1bc/0x2ac
__asan_load8+0xbc/0xd0
cdev_put+0x4c/0x90
__fput+0x4c4/0x750
____fput+0x1c/0x30
task_work_run+0x17c/0x26c
do_notify_resume+0x2ce4/0x3060
work_pending+0xc/0x438

So it looks like this cdev_put function is using the cdev after it's freed in my my_close function. But according to the book (in chapter 3), the close function should "Deallocate anything that open allocated in filp->private_data". However, the stripped down version of scull's close function included in the book looks like

int scull_release(struct inode *inode, struct file *filp)
{
    return 0;
}

Which does not include the free I've included.

The book also does say that the close function should "Shut down the device on last close" so perhaps private_data shouldn't be freed until the "last" close of the file? How is the driver supposed to know if a particular close is the last close? From the other parts of the book I've read so far, keeping track of stuff like how many opens and closes have occurred is the kernel's job, not the driver. But maybe I've misunderstood.

So main question: when should private_data be freed?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文