Skip to content

Commit 58b6e5e

Browse files
mjkravetztorvalds
authored andcommitted
hugetlbfs: fix memory leak for resv_map
When mknod is used to create a block special file in hugetlbfs, it will allocate an inode and kmalloc a 'struct resv_map' via resv_map_alloc(). inode->i_mapping->private_data will point the newly allocated resv_map. However, when the device special file is opened bd_acquire() will set inode->i_mapping to bd_inode->i_mapping. Thus the pointer to the allocated resv_map is lost and the structure is leaked. Programs to reproduce: mount -t hugetlbfs nodev hugetlbfs mknod hugetlbfs/dev b 0 0 exec 30<> hugetlbfs/dev umount hugetlbfs/ resv_map structures are only needed for inodes which can have associated page allocations. To fix the leak, only allocate resv_map for those inodes which could possibly be associated with page allocations. Link: http://lkml.kernel.org/r/20190401213101.16476-1-mike.kravetz@oracle.com Signed-off-by: Mike Kravetz <mike.kravetz@oracle.com> Reviewed-by: Andrew Morton <akpm@linux-foundation.org> Reported-by: Yufen Yu <yuyufen@huawei.com> Suggested-by: Yufen Yu <yuyufen@huawei.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent fcae96f commit 58b6e5e

File tree

1 file changed

+14
-6
lines changed

1 file changed

+14
-6
lines changed

fs/hugetlbfs/inode.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -755,11 +755,17 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb,
755755
umode_t mode, dev_t dev)
756756
{
757757
struct inode *inode;
758-
struct resv_map *resv_map;
758+
struct resv_map *resv_map = NULL;
759759

760-
resv_map = resv_map_alloc();
761-
if (!resv_map)
762-
return NULL;
760+
/*
761+
* Reserve maps are only needed for inodes that can have associated
762+
* page allocations.
763+
*/
764+
if (S_ISREG(mode) || S_ISLNK(mode)) {
765+
resv_map = resv_map_alloc();
766+
if (!resv_map)
767+
return NULL;
768+
}
763769

764770
inode = new_inode(sb);
765771
if (inode) {
@@ -794,8 +800,10 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb,
794800
break;
795801
}
796802
lockdep_annotate_inode_mutex_key(inode);
797-
} else
798-
kref_put(&resv_map->refs, resv_map_release);
803+
} else {
804+
if (resv_map)
805+
kref_put(&resv_map->refs, resv_map_release);
806+
}
799807

800808
return inode;
801809
}

0 commit comments

Comments
 (0)