“74bc2ecfb5ca14d22eec1b6b8d476735067fa8db”上不存在“...util/concurrent/ConcurrentLinkedQueue/RemoveLeak.java”
提交 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) ...@@ -484,11 +484,15 @@ static void hugetlbfs_evict_inode(struct inode *inode)
{ {
struct resv_map *resv_map; struct resv_map *resv_map;
struct hugetlbfs_inode_info *info = HUGETLBFS_I(inode);
remove_inode_hugepages(inode, 0, LLONG_MAX); 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 */ /* 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); resv_map_release(&resv_map->refs);
info->resv_map = NULL;
}
clear_inode(inode); clear_inode(inode);
} }
...@@ -757,7 +761,7 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb, ...@@ -757,7 +761,7 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb,
&hugetlbfs_i_mmap_rwsem_key); &hugetlbfs_i_mmap_rwsem_key);
inode->i_mapping->a_ops = &hugetlbfs_aops; inode->i_mapping->a_ops = &hugetlbfs_aops;
inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode); 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; info->seals = F_SEAL_SEAL;
switch (mode & S_IFMT) { switch (mode & S_IFMT) {
default: default:
...@@ -1025,6 +1029,7 @@ static struct inode *hugetlbfs_alloc_inode(struct super_block *sb) ...@@ -1025,6 +1029,7 @@ static struct inode *hugetlbfs_alloc_inode(struct super_block *sb)
* private inode. This simplifies hugetlbfs_destroy_inode. * private inode. This simplifies hugetlbfs_destroy_inode.
*/ */
mpol_shared_policy_init(&p->policy, NULL); mpol_shared_policy_init(&p->policy, NULL);
p->resv_map = NULL;
return &p->vfs_inode; return &p->vfs_inode;
} }
...@@ -1039,6 +1044,7 @@ static void hugetlbfs_destroy_inode(struct inode *inode) ...@@ -1039,6 +1044,7 @@ static void hugetlbfs_destroy_inode(struct inode *inode)
{ {
hugetlbfs_inc_free_inodes(HUGETLBFS_SB(inode->i_sb)); hugetlbfs_inc_free_inodes(HUGETLBFS_SB(inode->i_sb));
mpol_free_shared_policy(&HUGETLBFS_I(inode)->policy); mpol_free_shared_policy(&HUGETLBFS_I(inode)->policy);
HUGETLBFS_I(inode)->resv_map = NULL;
call_rcu(&inode->i_rcu, hugetlbfs_i_callback); call_rcu(&inode->i_rcu, hugetlbfs_i_callback);
} }
......
...@@ -291,6 +291,7 @@ struct hugetlbfs_inode_info { ...@@ -291,6 +291,7 @@ struct hugetlbfs_inode_info {
struct shared_policy policy; struct shared_policy policy;
struct inode vfs_inode; struct inode vfs_inode;
unsigned int seals; unsigned int seals;
struct resv_map *resv_map;
}; };
static inline struct hugetlbfs_inode_info *HUGETLBFS_I(struct inode *inode) static inline struct hugetlbfs_inode_info *HUGETLBFS_I(struct inode *inode)
......
...@@ -739,7 +739,7 @@ void resv_map_release(struct kref *ref) ...@@ -739,7 +739,7 @@ void resv_map_release(struct kref *ref)
static inline struct resv_map *inode_resv_map(struct inode *inode) 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) 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.
先完成此消息的编辑!
想要评论请 注册