Skip to content

Commit b7989bb

Browse files
dubeykoSherryYang1
authored andcommitted
hfs: fix slab-out-of-bounds in hfs_bnode_read()
[ Upstream commit a431930 ] This patch introduces is_bnode_offset_valid() method that checks the requested offset value. Also, it introduces check_and_correct_requested_length() method that checks and correct the requested length (if it is necessary). These methods are used in hfs_bnode_read(), hfs_bnode_write(), hfs_bnode_clear(), hfs_bnode_copy(), and hfs_bnode_move() with the goal to prevent the access out of allocated memory and triggering the crash. Signed-off-by: Viacheslav Dubeyko <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Viacheslav Dubeyko <[email protected]> Signed-off-by: Sasha Levin <[email protected]> (cherry picked from commit e7d2dc2421e821e4045775e6dc226378328de6f6) Signed-off-by: Sherry Yang <[email protected]>
1 parent b4c8c56 commit b7989bb

File tree

1 file changed

+92
-0
lines changed

1 file changed

+92
-0
lines changed

fs/hfs/bnode.c

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,48 @@
1515

1616
#include "btree.h"
1717

18+
static inline
19+
bool is_bnode_offset_valid(struct hfs_bnode *node, int off)
20+
{
21+
bool is_valid = off < node->tree->node_size;
22+
23+
if (!is_valid) {
24+
pr_err("requested invalid offset: "
25+
"NODE: id %u, type %#x, height %u, "
26+
"node_size %u, offset %d\n",
27+
node->this, node->type, node->height,
28+
node->tree->node_size, off);
29+
}
30+
31+
return is_valid;
32+
}
33+
34+
static inline
35+
int check_and_correct_requested_length(struct hfs_bnode *node, int off, int len)
36+
{
37+
unsigned int node_size;
38+
39+
if (!is_bnode_offset_valid(node, off))
40+
return 0;
41+
42+
node_size = node->tree->node_size;
43+
44+
if ((off + len) > node_size) {
45+
int new_len = (int)node_size - off;
46+
47+
pr_err("requested length has been corrected: "
48+
"NODE: id %u, type %#x, height %u, "
49+
"node_size %u, offset %d, "
50+
"requested_len %d, corrected_len %d\n",
51+
node->this, node->type, node->height,
52+
node->tree->node_size, off, len, new_len);
53+
54+
return new_len;
55+
}
56+
57+
return len;
58+
}
59+
1860
void hfs_bnode_read(struct hfs_bnode *node, void *buf, int off, int len)
1961
{
2062
struct page *page;
@@ -23,6 +65,20 @@ void hfs_bnode_read(struct hfs_bnode *node, void *buf, int off, int len)
2365
int bytes_to_read;
2466
void *vaddr;
2567

68+
if (!is_bnode_offset_valid(node, off))
69+
return;
70+
71+
if (len == 0) {
72+
pr_err("requested zero length: "
73+
"NODE: id %u, type %#x, height %u, "
74+
"node_size %u, offset %d, len %d\n",
75+
node->this, node->type, node->height,
76+
node->tree->node_size, off, len);
77+
return;
78+
}
79+
80+
len = check_and_correct_requested_length(node, off, len);
81+
2682
off += node->page_offset;
2783
pagenum = off >> PAGE_SHIFT;
2884
off &= ~PAGE_MASK; /* compute page offset for the first page */
@@ -83,6 +139,20 @@ void hfs_bnode_write(struct hfs_bnode *node, void *buf, int off, int len)
83139
{
84140
struct page *page;
85141

142+
if (!is_bnode_offset_valid(node, off))
143+
return;
144+
145+
if (len == 0) {
146+
pr_err("requested zero length: "
147+
"NODE: id %u, type %#x, height %u, "
148+
"node_size %u, offset %d, len %d\n",
149+
node->this, node->type, node->height,
150+
node->tree->node_size, off, len);
151+
return;
152+
}
153+
154+
len = check_and_correct_requested_length(node, off, len);
155+
86156
off += node->page_offset;
87157
page = node->page[0];
88158

@@ -108,6 +178,20 @@ void hfs_bnode_clear(struct hfs_bnode *node, int off, int len)
108178
{
109179
struct page *page;
110180

181+
if (!is_bnode_offset_valid(node, off))
182+
return;
183+
184+
if (len == 0) {
185+
pr_err("requested zero length: "
186+
"NODE: id %u, type %#x, height %u, "
187+
"node_size %u, offset %d, len %d\n",
188+
node->this, node->type, node->height,
189+
node->tree->node_size, off, len);
190+
return;
191+
}
192+
193+
len = check_and_correct_requested_length(node, off, len);
194+
111195
off += node->page_offset;
112196
page = node->page[0];
113197

@@ -124,6 +208,10 @@ void hfs_bnode_copy(struct hfs_bnode *dst_node, int dst,
124208
hfs_dbg(BNODE_MOD, "copybytes: %u,%u,%u\n", dst, src, len);
125209
if (!len)
126210
return;
211+
212+
len = check_and_correct_requested_length(src_node, src, len);
213+
len = check_and_correct_requested_length(dst_node, dst, len);
214+
127215
src += src_node->page_offset;
128216
dst += dst_node->page_offset;
129217
src_page = src_node->page[0];
@@ -143,6 +231,10 @@ void hfs_bnode_move(struct hfs_bnode *node, int dst, int src, int len)
143231
hfs_dbg(BNODE_MOD, "movebytes: %u,%u,%u\n", dst, src, len);
144232
if (!len)
145233
return;
234+
235+
len = check_and_correct_requested_length(node, src, len);
236+
len = check_and_correct_requested_length(node, dst, len);
237+
146238
src += node->page_offset;
147239
dst += node->page_offset;
148240
page = node->page[0];

0 commit comments

Comments
 (0)