[next] hfsplus: fix oob in hfsplus_bnode_read_key

Message ID tencent_164AB8743976ED67863C2F375496E236B009@qq.com
State New
Headers
Series [next] hfsplus: fix oob in hfsplus_bnode_read_key |

Commit Message

Edward Adam Davis Feb. 4, 2024, 11:51 a.m. UTC
  In hfs_brec_insert(), if data has not been moved to "data_off + size", the size
should not be added when reading search_key from node->page.

Reported-and-tested-by: syzbot+57028366b9825d8e8ad0@syzkaller.appspotmail.com
Signed-off-by: Edward Adam Davis <eadavis@qq.com>
---
 fs/hfsplus/brec.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
  

Comments

Viacheslav Dubeyko Feb. 6, 2024, 12:05 p.m. UTC | #1
> On 4 Feb 2024, at 14:51, Edward Adam Davis <eadavis@qq.com> wrote:
> 
> In hfs_brec_insert(), if data has not been moved to "data_off + size", the size
> should not be added when reading search_key from node->page.
> 
> Reported-and-tested-by: syzbot+57028366b9825d8e8ad0@syzkaller.appspotmail.com
> Signed-off-by: Edward Adam Davis <eadavis@qq.com>
> ---
> fs/hfsplus/brec.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/fs/hfsplus/brec.c b/fs/hfsplus/brec.c
> index 1918544a7871..9e0e0c1f15a5 100644
> --- a/fs/hfsplus/brec.c
> +++ b/fs/hfsplus/brec.c
> @@ -138,7 +138,8 @@ int hfs_brec_insert(struct hfs_find_data *fd, void *entry, int entry_len)
> * at the start of the node and it is not the new node
> */
> if (!rec && new_node != node) {
> - hfs_bnode_read_key(node, fd->search_key, data_off + size);

As far as I can see, likewise pattern 'data_off + size’ is used multiple times in hfs_brec_insert().
It’s real source of potential bugs, for my taste. Could we introduce a special variable (like offset)
that can keep calculated value?

> + hfs_bnode_read_key(node, fd->search_key, data_off + 
> + (idx_rec_off == data_rec_off ? 0 : size));

I believe the code of hfs_brec_insert() is complicated enough.
It will be great to rework this code and to add comments with
reasonable explanation of the essence of modification. It’s not so easy
to follow how moving is related to read the key operation.

What do you think?

Thanks,
Slava.

> hfs_brec_update_parent(fd);
> }
> 
> -- 
> 2.43.0
> 
>
  
Edward Adam Davis Feb. 7, 2024, 6:23 a.m. UTC | #2
On Tue, 6 Feb 2024 15:05:23 +0300, Viacheslav Dubeyko <slava@dubeyko.com> wrote: 
> > In hfs_brec_insert(), if data has not been moved to "data_off + size", the size
> > should not be added when reading search_key from node->page.
> >
> > Reported-and-tested-by: syzbot+57028366b9825d8e8ad0@syzkaller.appspotmail.com
> > Signed-off-by: Edward Adam Davis <eadavis@qq.com>
> > ---
> > fs/hfsplus/brec.c | 3 ++-
> > 1 file changed, 2 insertions(+), 1 deletion(-)
> >
> > diff --git a/fs/hfsplus/brec.c b/fs/hfsplus/brec.c
> > index 1918544a7871..9e0e0c1f15a5 100644
> > --- a/fs/hfsplus/brec.c
> > +++ b/fs/hfsplus/brec.c
> > @@ -138,7 +138,8 @@ int hfs_brec_insert(struct hfs_find_data *fd, void *entry, int entry_len)
> > * at the start of the node and it is not the new node
> > */
> > if (!rec && new_node != node) {
> > - hfs_bnode_read_key(node, fd->search_key, data_off + size);
> 
> As far as I can see, likewise pattern 'data_off + size’ is used multiple times in hfs_brec_insert().
> It’s real source of potential bugs, for my taste. Could we introduce a special variable (like offset)
> that can keep calculated value?
The code after "skip:" only adds size at this point, so currently there is no
need to add variables for separate management.
> 
> > + hfs_bnode_read_key(node, fd->search_key, data_off +
> > + (idx_rec_off == data_rec_off ? 0 : size));
> 
> I believe the code of hfs_brec_insert() is complicated enough.
> It will be great to rework this code and to add comments with
> reasonable explanation of the essence of modification. It’s not so easy
> to follow how moving is related to read the key operation.
As the case may be, other code is just complex but no issues have been reported.
It is not recommended to make unfounded optimizations.
> 
> What do you think?
Thanks,
Edward.
  

Patch

diff --git a/fs/hfsplus/brec.c b/fs/hfsplus/brec.c
index 1918544a7871..9e0e0c1f15a5 100644
--- a/fs/hfsplus/brec.c
+++ b/fs/hfsplus/brec.c
@@ -138,7 +138,8 @@  int hfs_brec_insert(struct hfs_find_data *fd, void *entry, int entry_len)
 	 * at the start of the node and it is not the new node
 	 */
 	if (!rec && new_node != node) {
-		hfs_bnode_read_key(node, fd->search_key, data_off + size);
+		hfs_bnode_read_key(node, fd->search_key, data_off + 
+				(idx_rec_off == data_rec_off ? 0 : size));
 		hfs_brec_update_parent(fd);
 	}