From nobody Fri Jul 24 23:31:27 2026 Received: from mxct.zte.com.cn (mxct.zte.com.cn [183.62.165.209]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3D3563ACEEC for ; Wed, 22 Jul 2026 06:43:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=183.62.165.209 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784702616; cv=none; b=puc7YaAtDaXZkTnb9Z1xTF/kHExtKCSfh7xYwrz1UAfdBmVZ2H7R5PKWu0wX73btujZZjhzXg6x92zuNNxvtB4AR1qTCc3Ae/rewNwbOCFOwroFlXXYoI4Px9HbdOUNJhIRaNKAdjCw3XBdQPvFXir0du9SmI6mjUzqtgKeMOa4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784702616; c=relaxed/simple; bh=EYzL6ZoMMR7dQEJEN0N8MFTJJUY7brzuHR08NG2nEf0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=IvrDEFSPJiLcKMOPlXUwmGSJK0d0xIqKG1xwfFOJHT/TufpxI64PglI8p90fVAdalTiB/ASmG6yMDJpyIlTytCx9JHhSeM8G2QvxXJLzNMe1p7a0LOylomq5zx2YwWCvb18FWFPcvkmiEA9Rvh9GAB2I+3WGZvlQEQ3gZCE5NQ0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=zte.com.cn; spf=pass smtp.mailfrom=zte.com.cn; arc=none smtp.client-ip=183.62.165.209 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=zte.com.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=zte.com.cn Received: from mse-fl2.zte.com.cn (unknown [10.5.228.133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mxct.zte.com.cn (FangMail) with ESMTPS id 4h4l8002hbz5B14y; Wed, 22 Jul 2026 14:43:28 +0800 (CST) Received: from szxl2zmapp07.zte.com.cn ([10.1.32.52]) by mse-fl2.zte.com.cn with SMTP id 66M6hMBr024367; Wed, 22 Jul 2026 14:43:22 +0800 (+08) (envelope-from gao.rui@zte.com.cn) Received: from localhost.localdomain (unknown [10.234.74.162]) by smtp (Zmail) with SMTP; Wed, 22 Jul 2026 14:43:24 +0800 X-Zmail-TransId: 3e816a60668b00d-a0a85 X-Zmail-LocalSMTP: 1 X-ZMAIL-USEORIGINALEMLTOOUTBOUND: 1 X-Zmail-RealSender: gao.rui@zte.com.cn From: Gao Rui To: Paul Walmsley , Palmer Dabbelt , Albert Ou , Alexandre Ghiti , Feng Jiang Cc: linux-riscv@lists.infradead.org, linux-kernel@vger.kernel.org, Gao Rui Subject: [PATCH 1/2] riscv: strnlen: fix ZBB path overflow and SIZE_MAX fallback Date: Wed, 22 Jul 2026 14:40:26 +0800 Message-ID: <20260722064037.1111467-2-gao.rui@zte.com.cn> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20260722064037.1111467-1-gao.rui@zte.com.cn> References: <20260722064037.1111467-1-gao.rui@zte.com.cn> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-MAIL: mse-fl2.zte.com.cn 66M6hMBr024367 X-TLS: YES X-ENVELOPE-SENDER: gao.rui@zte.com.cn X-SOURCE-IP: 10.5.228.133 unknown Wed, 22 Jul 2026 14:43:28 +0800 X-CLEAN: YES X-Fangmail-Anti-Spam-Filtered: true X-Fangmail-MID-QID: 6A60668F.000/4h4l8002hbz5B14y Content-Type: text/plain; charset="utf-8" This patch improves the RISC-V strnlen implementation: - Add explicit fallback to generic path when count =3D=3D SIZE_MAX, avoiding minu instruction misbehavior. - Add overflow check for (s + count), ensuring safe fallback when address addition wraps around. - Refactor aligned boundary calculation to use (s + count - 1), preventing word loads beyond the valid range. - Add fast exit when all remaining bytes are within the first word. - Simplify generic path loop with clearer pointer/count handling. These changes fix potential off-by-one, overflow, and extreme input bugs, while keeping ZBB optimization for normal cases. Fixes: 5ba15d419fab ("riscv: lib: add strnlen() implementation") Signed-off-by: Gao Rui --- arch/riscv/lib/strnlen.S | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/arch/riscv/lib/strnlen.S b/arch/riscv/lib/strnlen.S index 53afa7b5b314..fc5d578bbffe 100644 --- a/arch/riscv/lib/strnlen.S +++ b/arch/riscv/lib/strnlen.S @@ -17,6 +17,7 @@ SYM_FUNC_START(strnlen) __ALTERNATIVE_CFG("nop", "j strnlen_zbb", 0, RISCV_ISA_EXT_ZBB, IS_ENABLED(CONFIG_RISCV_ISA_ZBB) && IS_ENABLED(CONFIG_TOOLCHAIN_HAS_ZBB)) =20 +strnlen_generic: =20 /* * Returns @@ -27,20 +28,24 @@ SYM_FUNC_START(strnlen) * a1 - Max length of string * * Clobbers - * t0, t1, t2 + * t0, t1 */ - addi t1, a0, -1 - add t2, a0, a1 + mv t1, a0 + 1: - addi t1, t1, 1 - beq t1, t2, 2f + beqz a1, 2f + addi a1, a1, -1 + lbu t0, 0(t1) - bnez t0, 1b + beqz t0, 2f + + addi t1, t1, 1 + j 1b + 2: sub a0, t1, a0 ret =20 - /* * Variant of strnlen using the ZBB extension if available */ @@ -73,6 +78,16 @@ strnlen_zbb: /* If maxlen is 0, return 0. */ beqz a1, 3f =20 + /* + * Fallback to generic implementation when count is large enough to + * cause address overflow in the ZBB optimized path, or when count + * equals SIZE_MAX where the minu instruction misbehaves. + */ + li t5, -1 + beq a1, t5, strnlen_generic /* count =3D=3D SIZE_MAX */ + add t4, a0, a1 + bltu t4, a0, strnlen_generic /* a0 + a1 overflow */ + /* Number of irrelevant bytes in the first word. */ andi t2, a0, SZREG-1 =20 @@ -83,8 +98,12 @@ strnlen_zbb: sub t3, t3, t2 slli t2, t2, 3 =20 - /* Aligned boundary. */ - add t4, a0, a1 + /* + * Aligned boundary. Use the address of the last valid byte + * (s + count - 1) to avoid loading a word past the count + * boundary in the loop below. count =3D=3D 0 is handled above. + */ + addi t4, t4, -1 andi t4, t4, -SZREG =20 /* Get the first word. */ @@ -120,6 +139,9 @@ strnlen_zbb: =20 bgtu t3, a0, 2f =20 + /* All remaining bytes are in the first word, no loop needed. */ + bgeu t0, t4, 2f + /* Prepare for the word comparison loop. */ addi t2, t0, SZREG li t3, -1 --=20 2.27.0 From nobody Fri Jul 24 23:31:27 2026 Received: from mxhk.zte.com.cn (mxhk.zte.com.cn [160.30.148.34]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BC7B434B437; Wed, 22 Jul 2026 06:43:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=160.30.148.34 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784702618; cv=none; b=JbC6KDeYAl8qa5EaIvrYKPGBa4/yYIcnwUUY7yA5CMJbk59hBnV60knuypoPj2mUxeHIA1PL3led2XV19YN6pZA39mSDIPSBzB/esicLZvpc+pd2YoKAdvqHMwfxIyV0hHqp+Q9tgMOWdmGb1hoa9m2C3DlH9Bk07axlfS7e51Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784702618; c=relaxed/simple; bh=tSkfKA3vHyfoeHiWXwZIgl+mspI0/YAEiQfKW4Dh4o4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=aTb5ChaMZy/qR+PIVyTDU5RBWPkm/UTGQV/JnQ1HL9b+NpMH6NxwWpyi8zevryZwj8gSsOISLRjonNy4tMQzMeay1WHPJs6RLcHbCo7J5WgvV4v21i+94muI2E2VkUC7V5GZ/dmRJkGgRHCvKOxw7T/ws44DSeVGPsILmavMxCY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=zte.com.cn; spf=pass smtp.mailfrom=zte.com.cn; arc=none smtp.client-ip=160.30.148.34 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=zte.com.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=zte.com.cn Received: from mse-fl1.zte.com.cn (unknown [10.5.228.132]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mxhk.zte.com.cn (FangMail) with ESMTPS id 4h4l871gggz5B10G; Wed, 22 Jul 2026 14:43:35 +0800 (CST) Received: from szxlzmapp04.zte.com.cn ([10.5.231.166]) by mse-fl1.zte.com.cn with SMTP id 66M6hPBW061860; Wed, 22 Jul 2026 14:43:25 +0800 (+08) (envelope-from gao.rui@zte.com.cn) Received: from localhost.localdomain (unknown [10.234.74.162]) by smtp (Zmail) with SMTP; Wed, 22 Jul 2026 14:43:27 +0800 X-Zmail-TransId: 3e816a60668f00d-a0abd X-Zmail-LocalSMTP: 1 X-ZMAIL-USEORIGINALEMLTOOUTBOUND: 1 X-Zmail-RealSender: gao.rui@zte.com.cn From: Gao Rui To: Paul Walmsley , Palmer Dabbelt , Albert Ou , Alexandre Ghiti , Feng Jiang Cc: linux-riscv@lists.infradead.org, linux-kernel@vger.kernel.org, Gao Rui , Kees Cook , Andy Shevchenko , linux-hardening@vger.kernel.org Subject: [PATCH 2/2] kunit: string: add strnlen SIZE_MAX test coverage Date: Wed, 22 Jul 2026 14:40:27 +0800 Message-ID: <20260722064037.1111467-3-gao.rui@zte.com.cn> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20260722064037.1111467-1-gao.rui@zte.com.cn> References: <20260722064037.1111467-1-gao.rui@zte.com.cn> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-MAIL: mse-fl1.zte.com.cn 66M6hPBW061860 X-TLS: YES X-ENVELOPE-SENDER: gao.rui@zte.com.cn X-SOURCE-IP: 10.5.228.132 unknown Wed, 22 Jul 2026 14:43:35 +0800 X-CLEAN: YES X-Fangmail-Anti-Spam-Filtered: true X-Fangmail-MID-QID: 6A606697.000/4h4l871gggz5B10G Content-Type: text/plain; charset="utf-8" Extend string_test_strnlen to validate strnlen behavior with SIZE_MAX input: - Add explicit test case for strnlen(s, SIZE_MAX). - Ensure fallback to generic path returns correct length when string has no NUL terminator. - Complements existing tests for non-terminated strings and boundary conditions. This improves KUnit coverage for extreme inputs and verifies the correctness of the new fallback logic in strnlen.S. Signed-off-by: Gao Rui --- lib/tests/string_kunit.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/tests/string_kunit.c b/lib/tests/string_kunit.c index 0819ace5b027..8e2e8980aa75 100644 --- a/lib/tests/string_kunit.c +++ b/lib/tests/string_kunit.c @@ -155,6 +155,16 @@ static void string_test_strnlen(struct kunit *test) =20 for (size_t offset =3D 0; offset < STRING_TEST_MAX_OFFSET; offset++) { for (size_t len =3D 0; len <=3D STRING_TEST_MAX_LEN; len++) { + /* Test strings without NUL terminator */ + s =3D buf + buf_size - offset - len; + if (len > 0) + KUNIT_EXPECT_EQ(test, strnlen(s, len - 1), len - 1); + if (len > 1) + KUNIT_EXPECT_EQ(test, strnlen(s, len - 2), len - 2); + + KUNIT_EXPECT_EQ(test, strnlen(s, len), len); + + /* Test strings with NUL terminator */ s =3D buf + buf_size - 1 - offset - len; s[len] =3D '\0'; =20 @@ -169,6 +179,9 @@ static void string_test_strnlen(struct kunit *test) KUNIT_EXPECT_EQ(test, strnlen(s, len + 2), len); KUNIT_EXPECT_EQ(test, strnlen(s, len + 10), len); =20 + /* Test Count overflow fallback */ + KUNIT_EXPECT_EQ(test, strnlen(s, SSIZE_MAX), len); + s[len] =3D 'A'; } } --=20 2.27.0