| From cfda1e36725407169509879f8e4994807b9751e3 Mon Sep 17 00:00:00 2001 |
| From: Eric Biggers <ebiggers@google.com> |
| Date: Tue, 11 Aug 2020 18:35:24 -0700 |
| Subject: [PATCH] fs/minix: check return value of sb_getblk() |
| |
| commit da27e0a0e5f655f0d58d4e153c3182bb2b290f64 upstream. |
| |
| Patch series "fs/minix: fix syzbot bugs and set s_maxbytes". |
| |
| This series fixes all syzbot bugs in the minix filesystem: |
| |
| KASAN: null-ptr-deref Write in get_block |
| KASAN: use-after-free Write in get_block |
| KASAN: use-after-free Read in get_block |
| WARNING in inc_nlink |
| KMSAN: uninit-value in get_block |
| WARNING in drop_nlink |
| |
| It also fixes the minix filesystem to set s_maxbytes correctly, so that |
| userspace sees the correct behavior when exceeding the max file size. |
| |
| This patch (of 6): |
| |
| sb_getblk() can fail, so check its return value. |
| |
| This fixes a NULL pointer dereference. |
| |
| Originally from Qiujun Huang. |
| |
| Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") |
| Reported-by: syzbot+4a88b2b9dc280f47baf4@syzkaller.appspotmail.com |
| Signed-off-by: Eric Biggers <ebiggers@google.com> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Cc: Qiujun Huang <anenbupt@gmail.com> |
| Cc: Alexander Viro <viro@zeniv.linux.org.uk> |
| Cc: <stable@vger.kernel.org> |
| Link: http://lkml.kernel.org/r/20200628060846.682158-1-ebiggers@kernel.org |
| Link: http://lkml.kernel.org/r/20200628060846.682158-2-ebiggers@kernel.org |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/fs/minix/itree_common.c b/fs/minix/itree_common.c |
| index 043c3fdbc8e7..446148792f41 100644 |
| --- a/fs/minix/itree_common.c |
| +++ b/fs/minix/itree_common.c |
| @@ -75,6 +75,7 @@ static int alloc_branch(struct inode *inode, |
| int n = 0; |
| int i; |
| int parent = minix_new_block(inode); |
| + int err = -ENOSPC; |
| |
| branch[0].key = cpu_to_block(parent); |
| if (parent) for (n = 1; n < num; n++) { |
| @@ -85,6 +86,11 @@ static int alloc_branch(struct inode *inode, |
| break; |
| branch[n].key = cpu_to_block(nr); |
| bh = sb_getblk(inode->i_sb, parent); |
| + if (!bh) { |
| + minix_free_block(inode, nr); |
| + err = -ENOMEM; |
| + break; |
| + } |
| lock_buffer(bh); |
| memset(bh->b_data, 0, bh->b_size); |
| branch[n].bh = bh; |
| @@ -103,7 +109,7 @@ static int alloc_branch(struct inode *inode, |
| bforget(branch[i].bh); |
| for (i = 0; i < n; i++) |
| minix_free_block(inode, block_to_cpu(branch[i].key)); |
| - return -ENOSPC; |
| + return err; |
| } |
| |
| static inline int splice_branch(struct inode *inode, |
| -- |
| 2.27.0 |
| |