提交 bd575e60 编写于 作者: Y Yufen Yu 提交者: Xie XiuQi

hugetlbfs: fix memory leak for resv_map

euler inclusion
category: bugfix
bugzilla: 10984
CVE: NA
---------------------------

When .mknod create a block device file in hugetlbfs, it will
allocate an inode, and kmalloc a 'struct resv_map' in resv_map_alloc().
For now, inode->i_mapping->private_data is used to point the resv_map.
However, when open the device, bd_acquire() will set i_mapping as
bd_inode->imapping, result in resv_map memory leak.

We fix the leak by adding a new entry resv_map in hugetlbfs_inode_info.
It can store resv_map pointer.

Programs to reproduce:
	mount -t hugetlbfs nodev hugetlbfs
	mknod hugetlbfs/dev b 0 0
	exec 30<> hugetlbfs/dev
	umount hugetlbfs/

Fixes: 9119a41e ("mm, hugetlb: unify region structure handling")
Signed-off-by: NYufen Yu <yuyufen@huawei.com>
Reviewed-by: NMiao Xie <miaoxie@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 d95806c9
......@@ -484,11 +484,15 @@ static void hugetlbfs_evict_inode(struct inode *inode)
{
struct resv_map *resv_map;
struct hugetlbfs_inode_info *info = HUGETLBFS_I(inode);
remove_inode_hugepages(inode, 0, LLONG_MAX);
resv_map = (struct resv_map *)inode->i_mapping->private_data;
resv_map = info->resv_map;
/* root inode doesn't have the resv_map, so we should check it */
if (resv_map)
if (resv_map) {
resv_map_release(&resv_map->refs);
info->resv_map = NULL;
}
clear_inode(inode);
}
......@@ -757,7 +761,7 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb,
&hugetlbfs_i_mmap_rwsem_key);
inode->i_mapping->a_ops = &hugetlbfs_aops;
inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
inode->i_mapping->private_data = resv_map;
info->resv_map = resv_map;
info->seals = F_SEAL_SEAL;
switch (mode & S_IFMT) {
default:
......@@ -1025,6 +1029,7 @@ static struct inode *hugetlbfs_alloc_inode(struct super_block *sb)
* private inode. This simplifies hugetlbfs_destroy_inode.
*/
mpol_shared_policy_init(&p->policy, NULL);
p->resv_map = NULL;
return &p->vfs_inode;
}
......@@ -1039,6 +1044,7 @@ static void hugetlbfs_destroy_inode(struct inode *inode)
{
hugetlbfs_inc_free_inodes(HUGETLBFS_SB(inode->i_sb));
mpol_free_shared_policy(&HUGETLBFS_I(inode)->policy);
HUGETLBFS_I(inode)->resv_map = NULL;
call_rcu(&inode->i_rcu, hugetlbfs_i_callback);
}
......
......@@ -291,6 +291,7 @@ struct hugetlbfs_inode_info {
struct shared_policy policy;
struct inode vfs_inode;
unsigned int seals;
struct resv_map *resv_map;
};
static inline struct hugetlbfs_inode_info *HUGETLBFS_I(struct inode *inode)
......
......@@ -739,7 +739,7 @@ void resv_map_release(struct kref *ref)
static inline struct resv_map *inode_resv_map(struct inode *inode)
{
return inode->i_mapping->private_data;
return HUGETLBFS_I(inode)->resv_map;
}
static struct resv_map *vma_resv_map(struct vm_area_struct *vma)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册