[PATCH v3] qnx4: fix use-after-free caused by strlen

From: Tong Zhang
Date: Mon Mar 22 2021 - 16:24:21 EST


If di_fname is not terminated by '\0', it can cause buffer overrun and
trigger a user-after-free bug. This can happen in some corrupted or
malicious qnx4 image. Use strnlen to prevent buffer overrun.

[ 513.248784] qnx4_readdir: bread failed (3718095557)
[ 513.251109] BUG: KASAN: use-after-free in strlen+0x1f/0x40
[ 513.251268] Read of size 1 at addr ffff888002700000 by task find/230
[ 513.252069] Call Trace:
[ 513.252869] ? strlen+0x1f/0x40
[ 513.253237] strlen+0x1f/0x40
[ 513.253329] qnx4_lookup+0xab/0x220
[ 513.253431] __lookup_slow+0x103/0x220

Co-Developed-by: Anders Larsen <al@xxxxxxxxxxx>
Signed-off-by: Tong Zhang <ztong0001@xxxxxxxxx>
Signed-off-by: Anders Larsen <al@xxxxxxxxxxx>
---
v2: The name can grow longer than QNX4_SHORT_NAME_MAX if de is a
QNX4_FILE_LINK type and de should points to a qnx4_link_info struct, so
this is safe. We also remove redundant checks in this version.
v3: make commit log short and resend

fs/qnx4/namei.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/fs/qnx4/namei.c b/fs/qnx4/namei.c
index 8d72221735d7..2bcbbd7c772e 100644
--- a/fs/qnx4/namei.c
+++ b/fs/qnx4/namei.c
@@ -40,9 +40,7 @@ static int qnx4_match(int len, const char *name,
} else {
namelen = QNX4_SHORT_NAME_MAX;
}
- thislen = strlen( de->di_fname );
- if ( thislen > namelen )
- thislen = namelen;
+ thislen = strnlen( de->di_fname, namelen );
if (len != thislen) {
return 0;
}
--
2.25.1