Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753175AbdLGLeO (ORCPT ); Thu, 7 Dec 2017 06:34:14 -0500 Received: from mx1.redhat.com ([209.132.183.28]:38110 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753066AbdLGLeN (ORCPT ); Thu, 7 Dec 2017 06:34:13 -0500 From: Eryu Guan To: linux-kernel@vger.kernel.org Cc: Eryu Guan , Andrew Morton , Chris Metcalf , Kees Cook Subject: [PATCH] lib/string: avoid reading beyond src buffer in strscpy Date: Thu, 7 Dec 2017 19:33:24 +0800 Message-Id: <20171207113324.24388-1-eguan@redhat.com> X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Thu, 07 Dec 2017 11:34:13 +0000 (UTC) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 1538 Lines: 51 strscpy() tries to copy sizeof(unsigned long) bytes a time from src to dest when possible, and stops the loop when 'max' is less than sizeof(unsigned long). But it doesn't check if (src+res) goes beyond src buffer and does out-of-bound access to the underlying memory. KASAN reported global-out-of-bound bug when reading seccomp actions_logged file in procfs: cat /proc/sys/kernel/seccomp/actions_logged Because seccomp_names_from_actions_logged() is copying short strings (less than sizeof(unsigned long)) to buffer 'names'. e.g. ret = strscpy(names, " ", size); Fixed by capping the 'max' value according to the src buffer size, to make sure we won't go beyond src buffer. Cc: Andrew Morton Cc: Chris Metcalf Cc: Kees Cook Signed-off-by: Eryu Guan --- lib/string.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/string.c b/lib/string.c index 64a9e33f1daa..13a0147eea00 100644 --- a/lib/string.c +++ b/lib/string.c @@ -179,6 +179,7 @@ ssize_t strscpy(char *dest, const char *src, size_t count) { const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS; size_t max = count; + size_t src_sz = strlen(src) + 1; long res = 0; if (count == 0) @@ -200,6 +201,10 @@ ssize_t strscpy(char *dest, const char *src, size_t count) max = 0; #endif + /* avoid reading beyond src buffer */ + if (max > src_sz) + max = src_sz; + while (max >= sizeof(unsigned long)) { unsigned long c, data; -- 2.14.3