hfs/hfsplus: fix u32 overflow in check_and_correct_requested_length
Subsystems (4)
PATCH 1/3 hfs/hfsplus: fix u32 overflow in check_and_correct_requested_length
From: Tristan Madani <[email protected]>
check_and_correct_requested_length() compares (off + len) against node_size using u32 arithmetic. When the caller passes a large len value (e.g. from an underflowed subtraction in hfs_brec_remove()), off + len can wrap past 2^32 and produce a small result, causing the bounds check to pass when it should fail.
For example, with off=14 and len=0xFFFFFFF2 (underflowed from data_off - keyoffset - size in hfs_brec_remove), off + len wraps to 6, which is less than a typical node_size of 512, so the check passes and the subsequent memmove reads ~4GB past the node buffer.
Fix this by comparing len against (node_size - off) instead. Since is_bnode_offset_valid() already guarantees off < node_size before this point, the subtraction cannot underflow.
--- fs/hfs/bnode.c | 2 +- fs/hfsplus/hfsplus_fs.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
fs/hfs/bnode.c +1 -1
@@ -41,7 +41,7 @@ u32 check_and_correct_requested_length(struct hfs_bnode *node, u32 off, u32 len) node_size = node->tree->node_size; -if ((off + len) > node_size) { +if (len > node_size - off) {u32 new_len = node_size - off; pr_err("requested length has been corrected: "
fs/hfsplus/hfsplus_fs.h +1 -1
@@ -600,7 +600,7 @@ u32 check_and_correct_requested_length(struct hfs_bnode *node, u32 off, u32 len) node_size = node->tree->node_size; -if ((off + len) > node_size) { +if (len > node_size - off) {u32 new_len = node_size - off; pr_err("requested length has been corrected: "
Signature · 1 line
2.47.3
PATCH 2/3 hfs/hfsplus: initialize data buffer in hfs_bnode_read_u16 and hfs_bnode_read_u8
From: Tristan Madani <[email protected]>
hfs_bnode_read_u16() and hfs_bnode_read_u8() declare local data buffers without initialization, then pass them to hfs_bnode_read(). If is_bnode_offset_valid() fails inside hfs_bnode_read(), the function returns early without writing to the buffer, leaving it uninitialized. The caller then returns the garbage value to its caller.
This triggers KMSAN uninit-value reports when a corrupted HFS+ image has a node_size of 1, causing rec_off to underflow in hfs_bnode_find() and the subsequent hfs_bnode_read_u16() to operate on an invalid offset.
Zero-initialize both buffers so that callers get a deterministic zero value when the underlying read fails.
--- fs/hfs/bnode.c | 4 ++-- fs/hfsplus/bnode.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-)
fs/hfs/bnode.c +2 -2
@@ -97,7 +97,7 @@ void hfs_bnode_read(struct hfs_bnode *node, void *buf, u32 off, u32 len)u16 hfs_bnode_read_u16 (struct hfs_bnode *node,u32 off) { -__be16 data; +__be16 data =0 ;// optimize later... hfs_bnode_read (node, &data, off,2 );return be16_to_cpu (data);
@@ -105,7 +105,7 @@ u16 hfs_bnode_read_u16(struct hfs_bnode *node, u32 off)u8 hfs_bnode_read_u8 (struct hfs_bnode *node,u32 off) { -u8 data; +u8 data =0 ;// optimize later... hfs_bnode_read (node, &data, off,1 );return data;
fs/hfsplus/bnode.c +2 -2
@@ -55,7 +55,7 @@ void hfs_bnode_read(struct hfs_bnode *node, void *buf, u32 off, u32 len)u16 hfs_bnode_read_u16 (struct hfs_bnode *node,u32 off) { -__be16 data; +__be16 data =0 ;/* TODO: optimize later... */ hfs_bnode_read (node, &data, off,2 );return be16_to_cpu (data);
@@ -63,7 +63,7 @@ u16 hfs_bnode_read_u16(struct hfs_bnode *node, u32 off)u8 hfs_bnode_read_u8 (struct hfs_bnode *node,u32 off) { -u8 data; +u8 data =0 ;/* TODO: optimize later... */ hfs_bnode_read (node, &data, off,1 );return data;
Signature · 1 line
2.47.3
Re: [PATCH 2/3] hfs/hfsplus: initialize data buffer in hfs_bnode_read_u16 and hfs_bnode_read_u8
Quoted 62 lines · Tristan Madani
From: Tristan Madani <[email protected]>
hfs_bnode_read_u16()andhfs_bnode_read_u8()declare local data buffers without initialization, then pass them tohfs_bnode_read(). Ifis_bnode_offset_valid()fails insidehfs_bnode_read(), the function returns early without writing to the buffer, leaving it uninitialized. The caller then returns the garbage value to its caller.This triggers KMSAN uninit-value reports when a corrupted HFS+ image has a
node_sizeof 1, causingrec_offto underflow inhfs_bnode_find()and the subsequenthfs_bnode_read_u16()to operate on an invalid offset.Zero-initialize both buffers so that callers get a deterministic zero value when the underlying read fails.
Reported-by [email protected]Tested-by [email protected]Fixes a431930c9bac ("hfs: fix slab-out-of-bounds in hfs_bnode_read()")Signed-off-by Tristan Madani <[email protected]>--- fs/hfs/bnode.c | 4 ++-- fs/hfsplus/bnode.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-)fs/hfs/bnode.c +2
-2@@ -97,7 +97,7 @@ void hfs_bnode_read(struct hfs_bnode *node, void *buf, u32 off, u32 len)u16 hfs_bnode_read_u16 (struct hfs_bnode *node,u32 off) { -__be16 data; +__be16 data =0 ;// optimize later... hfs_bnode_read (node, &data, off,2 );return be16_to_cpu (data);@@ -105,7 +105,7 @@ u16 hfs_bnode_read_u16(struct hfs_bnode *node, u32 off)u8 hfs_bnode_read_u8 (struct hfs_bnode *node,u32 off) { -u8 data; +u8 data =0 ;// optimize later... hfs_bnode_read (node, &data, off,1 );return data;fs/hfsplus/bnode.c +1
-1@@ -55,7 +55,7 @@ void hfs_bnode_read(struct hfs_bnode *node, void *buf, u32 off, u32 len)u16 hfs_bnode_read_u16 (struct hfs_bnode *node,u32 off) { -__be16 data; +__be16 data =0 ;/* TODO: optimize later... */ hfs_bnode_read (node, &data, off,2 );return be16_to_cpu (data);
fs/hfsplus/bnode.c u16 hfs_bnode_read_u16(struct hfs_bnode *node, u32 off) · line 69
Quoted 8 lines
fs/hfsplus/bnode.c +1
-1@@ -63,7 +63,7 @@ u16 hfs_bnode_read_u16(struct hfs_bnode *node, u32 off)u8 hfs_bnode_read_u8 (struct hfs_bnode *node,u32 off) { -u8 data; +u8 data =0 ;/* TODO: optimize later... */ hfs_bnode_read (node, &data, off,1 );return data;
If I remember correctly, I already shared that hfs_bnode_read() is called in multiple places. So, this patch is not enough for complete fix of the issue.
Thanks,
Slava.
PATCH 3/3 hfsplus: fix null pointer dereference in hfsplus_create_attributes_file
In reply to Tristan MadaniFrom: Tristan Madani <[email protected]>
hfsplus_create_attributes_file() calls hfsplus_mark_inode_dirty() with HFSPLUS_ATTR_TREE_I(sb) before sbi->attr_tree has been set by hfs_btree_open(). HFSPLUS_ATTR_TREE_I dereferences sbi->attr_tree to reach ->inode, causing a null pointer dereference when attr_tree is still NULL.
Move the mark_dirty call to after hfs_btree_open() and guard it with a NULL check on sbi->attr_tree.
--- fs/hfsplus/xattr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/hfsplus/xattr.c +2 -1
@@ -317,12 +317,13 @@ static int hfsplus_create_attributes_file(struct super_block *sb) next_node++; } -hfsplus_mark_inode_dirty (HFSPLUS_ATTR_TREE_I (sb),HFSPLUS_I_ATTR_DIRTY );hfsplus_mark_inode_dirty (attr_file,HFSPLUS_I_ATTR_DIRTY ); sbi->attr_tree =hfs_btree_open (sb,HFSPLUS_ATTR_CNID );if (!sbi->attr_tree)pr_err ("failed to load attributes file\n" ); +else +hfsplus_mark_inode_dirty (HFSPLUS_ATTR_TREE_I (sb),HFSPLUS_I_ATTR_DIRTY ); failed_header_node_init:kfree (buf);
Signature · 1 line
2.47.3
Re: [PATCH 3/3] hfsplus: fix null pointer dereference in hfsplus_create_attributes_file
Quoted 30 lines · Tristan Madani
From: Tristan Madani <[email protected]>
hfsplus_create_attributes_file()callshfsplus_mark_inode_dirty()withHFSPLUS_ATTR_TREE_I(sb)beforesbi->attr_treehas been set byhfs_btree_open().HFSPLUS_ATTR_TREE_Idereferencessbi->attr_treeto reach ->inode, causing a null pointer dereference whenattr_treeis still NULL.Move the
mark_dirtycall to afterhfs_btree_open()and guard it with a NULL check onsbi->attr_tree.Reported-by [email protected]Tested-by [email protected]Fixes ee8422d00b7c ("hfsplus: fix potential Allocation File corruption after fsync")Signed-off-by Tristan Madani <[email protected]>--- fs/hfsplus/xattr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)fs/hfsplus/xattr.c +0
-1@@ -317,12 +317,13 @@ static int hfsplus_create_attributes_file(struct super_block *sb) next_node++; } -hfsplus_mark_inode_dirty (HFSPLUS_ATTR_TREE_I (sb),HFSPLUS_I_ATTR_DIRTY );
fs/hfsplus/xattr.c static int hfsplus_create_attributes_file(struct super_block *sb) · line 329
Quoted 10 lines
fs/hfsplus/xattr.c +2
-0hfsplus_mark_inode_dirty (attr_file,HFSPLUS_I_ATTR_DIRTY ); sbi->attr_tree =hfs_btree_open (sb,HFSPLUS_ATTR_CNID );if (!sbi->attr_tree)pr_err ("failed to load attributes file\n" ); +else +hfsplus_mark_inode_dirty (HFSPLUS_ATTR_TREE_I (sb),HFSPLUS_I_ATTR_DIRTY ); failed_header_node_init:kfree (buf);
This patch already fixes the issue:
https://lore.kernel.org/linux-fsdevel/[email protected]/
Thanks,
Slava.
Quoted 36 lines · Tristan Madani
From: Tristan Madani <[email protected]>
check_and_correct_requested_length()compares (off + len) againstnode_sizeusing u32 arithmetic. When the caller passes a large len value (e.g. from an underflowed subtraction inhfs_brec_remove()), off + len can wrap past 2^32 and produce a small result, causing the bounds check to pass when it should fail.For example, with off=14 and len=0xFFFFFFF2 (underflowed from
data_off- keyoffset - size inhfs_brec_remove), off + len wraps to 6, which is less than a typicalnode_sizeof 512, so the check passes and the subsequent memmove reads ~4GB past the node buffer.Fix this by comparing len against (
node_size- off) instead. Sinceis_bnode_offset_valid()already guarantees off <node_sizebefore this point, the subtraction cannot underflow.Reported-by [email protected]Tested-by [email protected]Reported-by [email protected]Tested-by [email protected]Fixes a431930c9bac ("hfs: fix slab-out-of-bounds in hfs_bnode_read()")Signed-off-by Tristan Madani <[email protected]>--- fs/hfs/bnode.c | 2 +- fs/hfsplus/hfsplus_fs.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)fs/hfs/bnode.c +0
-0
fs/hfs/bnode.c u32 check_and_correct_requested_length(struct hfs_bnode *node, u32 off, u32 len) · line 44
Quoted 5 lines
fs/hfs/bnode.c +1
-1@@ -41,7 +41,7 @@ u32 check_and_correct_requested_length(struct hfs_bnode *node, u32 off, u32 len) node_size = node->tree->node_size; -if ((off + len) > node_size) { +if (len > node_size - off) {
I don't agree with likewise change. Probably, we need to have:
(u64)off + len
Thanks,
Slava.
Quoted 16 lines
fs/hfs/bnode.c +0
-0u32 new_len = node_size - off; pr_err("requested length has been corrected: "fs/hfsplus/hfsplus_fs.h +1
-1@@ -600,7 +600,7 @@ u32 check_and_correct_requested_length(struct hfs_bnode *node, u32 off, u32 len) node_size = node->tree->node_size; -if ((off + len) > node_size) { +if (len > node_size - off) {u32 new_len = node_size - off; pr_err("requested length has been corrected: "
v2 cover hfs/hfsplus: fix OOB access and uninit-value in bnode operations
In reply to Tristan MadaniFrom: Tristan Madani <[email protected]>
Two fixes for long-standing syzbot reports in the HFS/HFS+ B-tree node handling code.
Changes since v1 (20260501110218.29906-{1..3}[email protected]):
- Patch 1: use (u64) widening cast per Dubeyko's feedback
- Patch 2: memset inside hfs_bnode_read() covering all callers in both fs/hfs/ and fs/hfsplus/, per Dubeyko's feedback
- Dropped patch 3 (NULL deref in hfsplus_create_attributes_file):
already fixed by Dubeyko's patch [1]
[1] https://lore.kernel.org/linux-fsdevel/[email protected]/
Tristan Madani (2):
hfs/hfsplus: fix u32 overflow in check_and_correct_requested_length hfs/hfsplus: zero-initialize buffer in hfs_bnode_read
fs/hfs/bnode.c | 4 +++- fs/hfsplus/bnode.c | 2 ++ fs/hfsplus/hfsplus_fs.h | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-)
Signature · 1 line
2.47.3
PATCH v2 1/2 hfs/hfsplus: fix u32 overflow in check_and_correct_requested_length
From: Tristan Madani <[email protected]>
check_and_correct_requested_length() compares (off + len) against node_size using u32 arithmetic. When the caller passes a large len value (e.g. from an underflowed subtraction in hfs_brec_remove()), off + len can wrap past 2^32 and produce a small result, causing the bounds check to pass when it should fail.
For example, with off=14 and len=0xFFFFFFF2 (underflowed from data_off - keyoffset - size in hfs_brec_remove), off + len wraps to 6, which is less than a typical node_size of 512, so the check passes and the subsequent memmove reads ~4GB past the node buffer.
Fix this by widening the addition to u64 before comparing against node_size. This prevents the u32 wrap while keeping the logic straightforward.
--- fs/hfs/bnode.c | 2 +- fs/hfsplus/hfsplus_fs.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
fs/hfs/bnode.c +1 -1
@@ -41,7 +41,7 @@ u32 check_and_correct_requested_length(struct hfs_bnode *node, u32 off, u32 len) node_size = node->tree->node_size; -if ((off + len) > node_size) { +if ((u64 )off + len > node_size) {u32 new_len = node_size - off; pr_err("requested length has been corrected: "
fs/hfsplus/hfsplus_fs.h +1 -1
@@ -600,7 +600,7 @@ u32 check_and_correct_requested_length(struct hfs_bnode *node, u32 off, u32 len) node_size = node->tree->node_size; -if ((off + len) > node_size) { +if ((u64 )off + len > node_size) {u32 new_len = node_size - off; pr_err("requested length has been corrected: "
Signature · 1 line
2.47.3
Quoted 49 lines · Tristan Madani
From: Tristan Madani <[email protected]>
check_and_correct_requested_length()compares (off + len) againstnode_sizeusing u32 arithmetic. When the caller passes a large len value (e.g. from an underflowed subtraction inhfs_brec_remove()), off + len can wrap past 2^32 and produce a small result, causing the bounds check to pass when it should fail.For example, with off=14 and len=0xFFFFFFF2 (underflowed from
data_off- keyoffset - size inhfs_brec_remove), off + len wraps to 6, which is less than a typicalnode_sizeof 512, so the check passes and the subsequent memmove reads ~4GB past the node buffer.Fix this by widening the addition to u64 before comparing against
node_size. This prevents the u32 wrap while keeping the logic straightforward.Reported-by [email protected]Tested-by [email protected]Reported-by [email protected]Tested-by [email protected]Fixes a431930c9bac ("hfs: fix slab-out-of-bounds in hfs_bnode_read()")Signed-off-by Tristan Madani <[email protected]>--- fs/hfs/bnode.c | 2 +- fs/hfsplus/hfsplus_fs.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)fs/hfs/bnode.c +1
-1@@ -41,7 +41,7 @@ u32 check_and_correct_requested_length(struct hfs_bnode *node, u32 off, u32 len) node_size = node->tree->node_size; -if ((off + len) > node_size) { +if ((u64 )off + len > node_size) {u32 new_len = node_size - off; pr_err("requested length has been corrected: "fs/hfsplus/hfsplus_fs.h +0
-0
fs/hfsplus/hfsplus_fs.h u32 check_and_correct_requested_length(struct hfs_bnode *node, u32 off, u32 len) · line 606
Quoted 8 lines
fs/hfsplus/hfsplus_fs.h +1
-1@@ -600,7 +600,7 @@ u32 check_and_correct_requested_length(struct hfs_bnode *node, u32 off, u32 len) node_size = node->tree->node_size; -if ((off + len) > node_size) { +if ((u64 )off + len > node_size) {u32 new_len = node_size - off; pr_err("requested length has been corrected: "
Looks good. Thanks for the fix.
Thanks,
Slava.
PATCH v2 2/2 hfs/hfsplus: zero-initialize buffer in hfs_bnode_read
In reply to Tristan MadaniFrom: Tristan Madani <[email protected]>
hfs_bnode_read() can return early without writing to the output buffer when is_bnode_offset_valid() fails or when check_and_correct_requested_ length() corrects the length to zero. Callers such as hfs_bnode_read_ u16() and hfs_bnode_read_u8() pass stack-allocated buffers and use the result unconditionally, leading to KMSAN uninit-value reports.
Rather than initializing at each individual call site, zero the buffer at the start of hfs_bnode_read() before any validation checks. This ensures all callers in both hfs and hfsplus get a deterministic zero value regardless of which early-return path is taken.
--- fs/hfs/bnode.c | 2 ++ fs/hfsplus/bnode.c | 2 ++ 2 files changed, 4 insertions(+)
fs/hfs/bnode.c +2 -0
@@ -64,6 +64,8 @@ void hfs_bnode_read(struct hfs_bnode *node, void *buf, u32 off, u32 len)u32 bytes_read;u32 bytes_to_read; +memset (buf,0 , len); +if (!is_bnode_offset_valid (node, off))return ;
fs/hfsplus/bnode.c +2 -0
@@ -25,6 +25,8 @@ void hfs_bnode_read(struct hfs_bnode *node, void *buf, u32 off, u32 len)struct page **pagep;u32 l; +memset (buf,0 , len); +if (!is_bnode_offset_valid (node, off))return ;
Signature · 1 line
2.47.3
Re: [PATCH v2 2/2] hfs/hfsplus: zero-initialize buffer in hfs_bnode_read
Quoted 42 lines · Tristan Madani
From: Tristan Madani <[email protected]>
hfs_bnode_read()can return early without writing to the output buffer whenis_bnode_offset_valid()fails or whencheck_and_correct_requested_length()corrects the length to zero. Callers such ashfs_bnode_read_u16()andhfs_bnode_read_u8()pass stack-allocated buffers and use the result unconditionally, leading to KMSAN uninit-value reports.Rather than initializing at each individual call site, zero the buffer at the start of
hfs_bnode_read()before any validation checks. This ensures all callers in both hfs and hfsplus get a deterministic zero value regardless of which early-return path is taken.Reported-by [email protected]Tested-by [email protected]Fixes a431930c9bac ("hfs: fix slab-out-of-bounds in hfs_bnode_read()")Signed-off-by Tristan Madani <[email protected]>--- fs/hfs/bnode.c | 2 ++ fs/hfsplus/bnode.c | 2 ++ 2 files changed, 4 insertions(+)fs/hfs/bnode.c +2
-0@@ -64,6 +64,8 @@ void hfs_bnode_read(struct hfs_bnode *node, void *buf, u32 off, u32 len)u32 bytes_read;u32 bytes_to_read; +memset (buf,0 , len); +if (!is_bnode_offset_valid (node, off))return ;fs/hfsplus/bnode.c +0
-0
fs/hfsplus/bnode.c void hfs_bnode_read(struct hfs_bnode *node, void *buf, u32 off, u32 len) · line 32
Quoted 8 lines
fs/hfsplus/bnode.c +2
-0@@ -25,6 +25,8 @@ void hfs_bnode_read(struct hfs_bnode *node, void *buf, u32 off, u32 len)struct page **pagep;u32 l; +memset (buf,0 , len); +if (!is_bnode_offset_valid (node, off))return ;
We are returning back to the same my question. What if the caller of hfs_bnode_read() provides the len == 0 somehow but the buffer has not zero size on the caller side? I assume that memset() will do nothing and the buffer still be not initialized. Am I correct here?
Thanks,
Slava.
Re: [PATCH v2 2/2] hfs/hfsplus: zero-initialize buffer in hfs_bnode_read
Quoted 4 lines · Viacheslav Dubeyko
We are returning back to the same my question. What if the caller of
hfs_bnode_read()provides the len == 0 somehow but the buffer has not zero size on the caller side? I assume thatmemset()will do nothing and the buffer still be not initialized. Am I correct here?
You are correct that memset(buf, 0, 0) is a no-op. But if the caller passes len == 0, it is asking to read zero bytes -- it should not expect the function to initialize anything beyond that.
The bug this fixes is different: callers pass a non-zero len (e.g. hfs_bnode_read_u16 passes 2, hfs_bnode_read_u8 passes 1), but check_and_correct_requested_length() internally reduces the effective read to 0 due to a corrupted image. The memset runs with the original caller-supplied len before any internal validation, so the buffer is already zeroed by the time the early-return happens.
No current caller passes len == 0 -- hfs_bnode_read_u16() always passes 2, hfs_bnode_read_u8() always passes 1, and hfs_bnode_read_key() passes a key_len that is validated against the btree key size.
Thanks,
Tristan
Re: [PATCH v2 2/2] hfs/hfsplus: zero-initialize buffer in hfs_bnode_read
Quoted 17 lines · Tristan Madani
Quoted 4 lines · Viacheslav Dubeyko
We are returning back to the same my question. What if the caller of
hfs_bnode_read()provides the len == 0 somehow but the buffer has not zero size on the caller side? I assume thatmemset()will do nothing and the buffer still be not initialized. Am I correct here?You are correct that
memset(buf, 0, 0)is a no-op. But if the caller passes len == 0, it is asking to read zero bytes -- it should not expect the function to initialize anything beyond that.The bug this fixes is different: callers pass a non-zero len (e.g.
hfs_bnode_read_u16passes 2,hfs_bnode_read_u8passes 1), butcheck_and_correct_requested_length()internally reduces the effective read to 0 due to a corrupted image. The memset runs with the original caller-supplied len before any internal validation, so the buffer is already zeroed by the time the early-return happens.
Quoted 4 lines
No current caller passes len == 0 --
hfs_bnode_read_u16()always passes 2,hfs_bnode_read_u8()always passes 1, andhfs_bnode_read_key()passes akey_lenthat is validated against the btree key size.
OK. I think I can agree with you. If we have len == 0 as input argument, then we have:
if (len == 0) {
<skipped>
return;
}
And if check_and_correct_requested_length() corrects the len to 0:
len = check_and_correct_requested_length(node, off, len);
then loop will do nothing because of len == 0:
for (bytes_read = 0; bytes_read < len; bytes_read += bytes_to_read) { <skipped>
}
Thanks,
Slava.
Re: [PATCH v2 2/2] hfs/hfsplus: zero-initialize buffer in hfs_bnode_read
In reply to Tristan MadaniQuoted 43 lines · Tristan Madani
From: Tristan Madani <[email protected]>
hfs_bnode_read()can return early without writing to the output buffer whenis_bnode_offset_valid()fails or whencheck_and_correct_requested_length()corrects the length to zero. Callers such ashfs_bnode_read_u16()andhfs_bnode_read_u8()pass stack-allocated buffers and use the result unconditionally, leading to KMSAN uninit-value reports.Rather than initializing at each individual call site, zero the buffer at the start of
hfs_bnode_read()before any validation checks. This ensures all callers in both hfs and hfsplus get a deterministic zero value regardless of which early-return path is taken.Reported-by [email protected]Tested-by [email protected]Fixes a431930c9bac ("hfs: fix slab-out-of-bounds in hfs_bnode_read()")Signed-off-by Tristan Madani <[email protected]>--- fs/hfs/bnode.c | 2 ++ fs/hfsplus/bnode.c | 2 ++ 2 files changed, 4 insertions(+)fs/hfs/bnode.c +2
-0@@ -64,6 +64,8 @@ void hfs_bnode_read(struct hfs_bnode *node, void *buf, u32 off, u32 len)u32 bytes_read;u32 bytes_to_read; +memset (buf,0 , len); +if (!is_bnode_offset_valid (node, off))return ;fs/hfsplus/bnode.c +0
-0
fs/hfsplus/bnode.c void hfs_bnode_read(struct hfs_bnode *node, void *buf, u32 off, u32 len) · line 32
Quoted 8 lines
fs/hfsplus/bnode.c +2
-0@@ -25,6 +25,8 @@ void hfs_bnode_read(struct hfs_bnode *node, void *buf, u32 off, u32 len)struct page **pagep;u32 l; +memset (buf,0 , len); +if (!is_bnode_offset_valid (node, off))return ;
Looks good. Thanks a lot for the fix.
Thanks,
Slava.