Linux内核可能存在内存泄漏问题?

3

在对Linux内核进行静态分析以查找内存泄漏时,我遇到了一个有趣的场景,即我无法找到变量的释放。分配是在以下函数中(使用kmalloc调用)进行的:

static int mounts_open_common(struct inode *inode, struct file *file,
              int (*show)(struct seq_file *, struct vfsmount *)){
  struct proc_mounts *p;

  //some code//
  *p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL);**
  file->private_data = &p->m;//the allocated variable is escaped to file structure
  //some code

}

我希望这块内存能够被固定在以下位置:
static int mounts_release(struct inode *inode, struct file *file)
{
    struct proc_mounts *p = proc_mounts(file->private_data);
    path_put(&p->root);
    put_mnt_ns(p->ns);
    return seq_release(inode, file);
}

但是看起来这个函数正在访问已分配的变量以释放其内部成员,但不是变量“p”本身。 那么这个变量的内存被释放了吗?如果应该在mounts_release函数中释放它,那么这可能会导致内存泄漏。


seq_release(inode, file); 调用是做什么的? - Cristiano Araujo
mounts_release() 函数据我所知应该释放与已挂载设备关联的内存! - dsingh
1个回答

7
如果您查看seq_release:
int seq_release(struct inode *inode, struct file *file)
{
        struct seq_file *m = file->private_data;
        kvfree(m->buf);
        kfree(m);
        return 0;
}

它有效地执行 kfree(file->private_data)

现在,在mounts_open_common中设置了file->private_data作为

file->private_data = &p->m;

这是你问题中使用的p,在kmalloc中分配空间。成员m不是指针,因此不能被释放。但是,它是struct proc_mounts的第一个成员。
struct proc_mounts {
        struct seq_file m;
        struct mnt_namespace *ns;
        struct path root;
        int (*show)(struct seq_file *, struct vfsmount *);
        void *cached_mount;
        u64 cached_event;
        loff_t cached_index;
};

所以seq_release()m成员的地址上执行kfree(),这与p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL);获取的地址相同。
我猜对于静态分析器来说不太友好。但是没有内存泄漏。

在seq_release()函数中,明确指出m是seq_file类型的指针,因此kfree(m)将释放由该指针分配的内存(我认为这应该是由我们的原始mounts_open_common()函数调用的seq_open()函数分配的),而不是由变量p指向的父结构proc_point。 - dsingh
另外,Linux 使用 container_of 宏从其子成员中提取父指针。您可以在 generic_create_cred() / generic_free_cred 函数中进行检查。 - dsingh
你不能使用一个类型与结构体第一个成员相同且指向结构体第一个成员地址的变量来释放整个父结构体。 - dsingh
PurofHy,不是像你所说的在seq_open()中分配的,请看一下struct proc_mounts的第一个成员,它不是指针。看看第257行中分配proc_mounts的位置。看看第261行中设置file->private_data的位置,这就是关键。查看seq_open()并查看当file->private_data不为NULL时它会做什么(它不会分配任何东西)。注意seq_release()中释放的是file->private_data - nos
@PurofHy 所以最终传递给 kfree() 的是 file->private,这与第257行获取的地址相同。请注意,C语言保证结构体的第一个成员具有与结构体本身相同的地址(即始终具有偏移量为0)。由于此处不需要提取任何包含结构体,因此未在代码中使用 container_of 宏。这仅适用于 struct seq_file mstruct proc_mounts 的第一个成员的情况,因此 kfree(p) 与执行 kfree(&p->m) 相同。 - nos
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接