diff mbox series

[v3] fs/sysv: Null check to prevent null-ptr-deref bug

Message ID 20230528184422.596947-1-princekumarmaurya06@gmail.com (mailing list archive)
State Accepted, archived
Headers show
Series [v3] fs/sysv: Null check to prevent null-ptr-deref bug | expand

Commit Message

Prince Kumar Maurya May 28, 2023, 6:44 p.m. UTC
sb_getblk(inode->i_sb, parent) return a null ptr and taking lock on
that leads to the null-ptr-deref bug.

Reported-by: syzbot+aad58150cbc64ba41bdc@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=aad58150cbc64ba41bdc 
Signed-off-by: Prince Kumar Maurya <princekumarmaurya06@gmail.com>
---
Change since v2: Updated subject and added Reported-by and closes tags.

 fs/sysv/itree.c | 2 ++
 1 file changed, 2 insertions(+)

Comments

Christian Brauner May 30, 2023, 8:26 a.m. UTC | #1
On Sun, May 28, 2023 at 11:44:22AM -0700, Prince Kumar Maurya wrote:
> sb_getblk(inode->i_sb, parent) return a null ptr and taking lock on
> that leads to the null-ptr-deref bug.
> 
> Reported-by: syzbot+aad58150cbc64ba41bdc@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=aad58150cbc64ba41bdc 
> Signed-off-by: Prince Kumar Maurya <princekumarmaurya06@gmail.com>
> ---
> Change since v2: Updated subject and added Reported-by and closes tags.
> 
>  fs/sysv/itree.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/fs/sysv/itree.c b/fs/sysv/itree.c
> index b22764fe669c..3a6b66e719fd 100644
> --- a/fs/sysv/itree.c
> +++ b/fs/sysv/itree.c
> @@ -145,6 +145,8 @@ static int alloc_branch(struct inode *inode,
>  		 */
>  		parent = block_to_cpu(SYSV_SB(inode->i_sb), branch[n-1].key);
>  		bh = sb_getblk(inode->i_sb, parent);
> +		if (!bh)
> +			break;

When you break here you'll hit:

/* Allocation failed, free what we already allocated */
for (i = 1; i < n; i++)
        bforget(branch[i].bh);
for (i = 0; i < n; i++)
        sysv_free_block(inode->i_sb, branch[i].key);

below. The cleanup paths were coded in the assumption that sb_getblk()
can't fail. So bforget() can assume that branch[i].bh has been allocated
and set up. So that bforget(branch[i].bh) is your next pending NULL
deref afaict.
Prince Kumar Maurya May 30, 2023, 2:59 p.m. UTC | #2
On Tue, May 30, 2023 at 1:26 AM Christian Brauner <brauner@kernel.org> wrote:
>
> On Sun, May 28, 2023 at 11:44:22AM -0700, Prince Kumar Maurya wrote:
> > sb_getblk(inode->i_sb, parent) return a null ptr and taking lock on
> > that leads to the null-ptr-deref bug.
> >
> > Reported-by: syzbot+aad58150cbc64ba41bdc@syzkaller.appspotmail.com
> > Closes: https://syzkaller.appspot.com/bug?extid=aad58150cbc64ba41bdc
> > Signed-off-by: Prince Kumar Maurya <princekumarmaurya06@gmail.com>
> > ---
> > Change since v2: Updated subject and added Reported-by and closes tags.
> >
> >  fs/sysv/itree.c | 2 ++
> >  1 file changed, 2 insertions(+)
> >
> > diff --git a/fs/sysv/itree.c b/fs/sysv/itree.c
> > index b22764fe669c..3a6b66e719fd 100644
> > --- a/fs/sysv/itree.c
> > +++ b/fs/sysv/itree.c
> > @@ -145,6 +145,8 @@ static int alloc_branch(struct inode *inode,
> >                */
> >               parent = block_to_cpu(SYSV_SB(inode->i_sb), branch[n-1].key);
> >               bh = sb_getblk(inode->i_sb, parent);
> > +             if (!bh)
> > +                     break;
>
> When you break here you'll hit:
>
> /* Allocation failed, free what we already allocated */
> for (i = 1; i < n; i++)
>         bforget(branch[i].bh);
> for (i = 0; i < n; i++)
>         sysv_free_block(inode->i_sb, branch[i].key);
>
> below. The cleanup paths were coded in the assumption that sb_getblk()
> can't fail. So bforget() can assume that branch[i].bh has been allocated
> and set up. So that bforget(branch[i].bh) is your next pending NULL
> deref afaict.


I doubt that would happen. There is a break above as well, before we do
sb_getblk().

/* Allocate the next block */
branch[n].key = sysv_new_block(inode->i_sb);
if (!branch[n].key)
   break;

The clean up code path runs till i is less than n not equal to n which
would have caused the problem.
Christian Brauner May 30, 2023, 3:54 p.m. UTC | #3
On Tue, May 30, 2023 at 07:59:16AM -0700, Prince Kumar Maurya wrote:
> On Tue, May 30, 2023 at 1:26 AM Christian Brauner <brauner@kernel.org> wrote:
> >
> > On Sun, May 28, 2023 at 11:44:22AM -0700, Prince Kumar Maurya wrote:
> > > sb_getblk(inode->i_sb, parent) return a null ptr and taking lock on
> > > that leads to the null-ptr-deref bug.
> > >
> > > Reported-by: syzbot+aad58150cbc64ba41bdc@syzkaller.appspotmail.com
> > > Closes: https://syzkaller.appspot.com/bug?extid=aad58150cbc64ba41bdc
> > > Signed-off-by: Prince Kumar Maurya <princekumarmaurya06@gmail.com>
> > > ---
> > > Change since v2: Updated subject and added Reported-by and closes tags.
> > >
> > >  fs/sysv/itree.c | 2 ++
> > >  1 file changed, 2 insertions(+)
> > >
> > > diff --git a/fs/sysv/itree.c b/fs/sysv/itree.c
> > > index b22764fe669c..3a6b66e719fd 100644
> > > --- a/fs/sysv/itree.c
> > > +++ b/fs/sysv/itree.c
> > > @@ -145,6 +145,8 @@ static int alloc_branch(struct inode *inode,
> > >                */
> > >               parent = block_to_cpu(SYSV_SB(inode->i_sb), branch[n-1].key);
> > >               bh = sb_getblk(inode->i_sb, parent);
> > > +             if (!bh)
> > > +                     break;
> >
> > When you break here you'll hit:
> >
> > /* Allocation failed, free what we already allocated */
> > for (i = 1; i < n; i++)
> >         bforget(branch[i].bh);
> > for (i = 0; i < n; i++)
> >         sysv_free_block(inode->i_sb, branch[i].key);
> >
> > below. The cleanup paths were coded in the assumption that sb_getblk()
> > can't fail. So bforget() can assume that branch[i].bh has been allocated
> > and set up. So that bforget(branch[i].bh) is your next pending NULL
> > deref afaict.
> 
> 
> I doubt that would happen. There is a break above as well, before we do
> sb_getblk().
> 
> /* Allocate the next block */
> branch[n].key = sysv_new_block(inode->i_sb);
> if (!branch[n].key)
>    break;
> 
> The clean up code path runs till i is less than n not equal to n which
> would have caused the problem.

But then aren't you leaking branch[n].key if you break after failed sb_getblk()
after sysv_new_block() succeeded?
Christian Brauner June 1, 2023, 7:55 a.m. UTC | #4
On Sun, 28 May 2023 11:44:22 -0700, Prince Kumar Maurya wrote:
> sb_getblk(inode->i_sb, parent) return a null ptr and taking lock on
> that leads to the null-ptr-deref bug.
> 
> 

Applied to the vfs.misc branch of the vfs/vfs.git tree.
Patches in the vfs.misc branch should appear in linux-next soon.

Please report any outstanding bugs that were missed during review in a
new review to the original patch series allowing us to drop it.

It's encouraged to provide Acked-bys and Reviewed-bys even though the
patch has now been applied. If possible patch trailers will be updated.

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git
branch: vfs.misc

[1/1] fs/sysv: Null check to prevent null-ptr-deref bug
      https://git.kernel.org/vfs/vfs/c/47f9da4bc5e6
diff mbox series

Patch

diff --git a/fs/sysv/itree.c b/fs/sysv/itree.c
index b22764fe669c..3a6b66e719fd 100644
--- a/fs/sysv/itree.c
+++ b/fs/sysv/itree.c
@@ -145,6 +145,8 @@  static int alloc_branch(struct inode *inode,
 		 */
 		parent = block_to_cpu(SYSV_SB(inode->i_sb), branch[n-1].key);
 		bh = sb_getblk(inode->i_sb, parent);
+		if (!bh)
+			break;
 		lock_buffer(bh);
 		memset(bh->b_data, 0, blocksize);
 		branch[n].bh = bh;