]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.19.41/hugetlbfs-fix-memory-leak-for-resv_map.patch
5.1-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 4.19.41 / hugetlbfs-fix-memory-leak-for-resv_map.patch
CommitLineData
7be4ccde
SL
1From 960e849a37e5004b0aadb515457ad68ae7b2f181 Mon Sep 17 00:00:00 2001
2From: Mike Kravetz <mike.kravetz@oracle.com>
3Date: Fri, 5 Apr 2019 18:39:06 -0700
4Subject: hugetlbfs: fix memory leak for resv_map
5
6[ Upstream commit 58b6e5e8f1addd44583d61b0a03c0f5519527e35 ]
7
8When mknod is used to create a block special file in hugetlbfs, it will
9allocate an inode and kmalloc a 'struct resv_map' via resv_map_alloc().
10inode->i_mapping->private_data will point the newly allocated resv_map.
11However, when the device special file is opened bd_acquire() will set
12inode->i_mapping to bd_inode->i_mapping. Thus the pointer to the
13allocated resv_map is lost and the structure is leaked.
14
15Programs to reproduce:
16 mount -t hugetlbfs nodev hugetlbfs
17 mknod hugetlbfs/dev b 0 0
18 exec 30<> hugetlbfs/dev
19 umount hugetlbfs/
20
21resv_map structures are only needed for inodes which can have associated
22page allocations. To fix the leak, only allocate resv_map for those
23inodes which could possibly be associated with page allocations.
24
25Link: http://lkml.kernel.org/r/20190401213101.16476-1-mike.kravetz@oracle.com
26Signed-off-by: Mike Kravetz <mike.kravetz@oracle.com>
27Reviewed-by: Andrew Morton <akpm@linux-foundation.org>
28Reported-by: Yufen Yu <yuyufen@huawei.com>
29Suggested-by: Yufen Yu <yuyufen@huawei.com>
30Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
31Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
32Signed-off-by: Sasha Levin <sashal@kernel.org>
33---
34 fs/hugetlbfs/inode.c | 20 ++++++++++++++------
35 1 file changed, 14 insertions(+), 6 deletions(-)
36
37diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
38index a7fa037b876b..a3a3d256fb0e 100644
39--- a/fs/hugetlbfs/inode.c
40+++ b/fs/hugetlbfs/inode.c
41@@ -741,11 +741,17 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb,
42 umode_t mode, dev_t dev)
43 {
44 struct inode *inode;
45- struct resv_map *resv_map;
46+ struct resv_map *resv_map = NULL;
47
48- resv_map = resv_map_alloc();
49- if (!resv_map)
50- return NULL;
51+ /*
52+ * Reserve maps are only needed for inodes that can have associated
53+ * page allocations.
54+ */
55+ if (S_ISREG(mode) || S_ISLNK(mode)) {
56+ resv_map = resv_map_alloc();
57+ if (!resv_map)
58+ return NULL;
59+ }
60
61 inode = new_inode(sb);
62 if (inode) {
63@@ -780,8 +786,10 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb,
64 break;
65 }
66 lockdep_annotate_inode_mutex_key(inode);
67- } else
68- kref_put(&resv_map->refs, resv_map_release);
69+ } else {
70+ if (resv_map)
71+ kref_put(&resv_map->refs, resv_map_release);
72+ }
73
74 return inode;
75 }
76--
772.20.1
78