Received: by 2002:a05:6a10:8c0a:0:0:0:0 with SMTP id go10csp1574329pxb; Mon, 22 Feb 2021 05:45:18 -0800 (PST) X-Google-Smtp-Source: ABdhPJzE8Z+2W+vXZgkWU1fMgRJHxQTonLismvCDzykRFgyatKCCI43uf6o1wLLdjs60dPdY0WGY X-Received: by 2002:a05:6402:1398:: with SMTP id b24mr21637998edv.108.1614001518291; Mon, 22 Feb 2021 05:45:18 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1614001518; cv=none; d=google.com; s=arc-20160816; b=dguTeonW1n+/F6jZxoaLye/mPxRHEwoSYOAh3/ZRYyryORi0wOdxoASQLq6FvgfnUZ 2m7KRbJCI47yctoZfDT6DK6wexw0ibvpQVkjQ5nErTlcizuhq0g/oraIbchj5WChHeEh 2RkLhrPnTLRCrfnFi7yQeklFGAPrQqH4AYtAt95AWYXGlAQ4skKlOZnpd6A+Y2pXHlcg 1/+edIszH7f4rfA/Yst1sc+CURAAW9Gu3gViKSuF3tE3UumQaiY2kCtftA5elD11Pxff Xqp3/YYYNSudZUEji8U25240gi1MZSEzj4Gv7HWI3c985s22OZJMLZPGdBsXrk2BczIp N8/g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=wi2PG/2rhb2RB+PRfj6/CPmxPq8Rk95y98Gg21Pn51g=; b=Io+ygVmomD6QZShf6bazQvrMBIrlO5szE3aKoUtPZ2+fTYNLYyldPs/p1+9SpPOVm9 zcPfcKyAbKQReWdFXReD5JG0Vhq/ets/ht7JmeXI65i1AilLa1x1AXkshubFtclDL8Ay NimpFzjE7+AYmZX2eaRizCfLvKTBxnrBRDoKRRZorRHmcuxqb1IFNCh14n1st7ew4VZK /0xsCglA8VUpW+4nPlkr3ZueZMmToWYzvhvpWvGXHmk+HMK7TgpE8L00Kb+tvi4ShJgb batvb9ELajjsQXLKvaXhJ44uModNzTDZpDT9a+yEvLxDdeKD2kNjOF2QpCRhoI4Ybva7 TSgA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=EgsOBwbJ; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id eb13si13780668edb.8.2021.02.22.05.44.55; Mon, 22 Feb 2021 05:45:18 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=EgsOBwbJ; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231861AbhBVNmL (ORCPT + 99 others); Mon, 22 Feb 2021 08:42:11 -0500 Received: from mail.kernel.org ([198.145.29.99]:53702 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231341AbhBVMnm (ORCPT ); Mon, 22 Feb 2021 07:43:42 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 5789F64F4C; Mon, 22 Feb 2021 12:41:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1613997666; bh=1j4bC7sPzvGyQFXvKx2pUeSYrd/Twrpp70EXC6RSFlE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=EgsOBwbJbx2yoCTh70oMY0XBVNAYC5KkbRSOsopxcFLIFJUMt0LMTcl+uxzGZpNld RbvMryxyRVv2W3YZYOuAgYR/Onou5kHh9OCJq3zfO65CferJ7VAaNeenp9JzF1geDQ gAOYmo1l7B54TqKvha0x/ZsN4ofpjVcdCZDOu2cY= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Kees Cook , "Tobin C. Harding" , Shuah Khan , Sasha Levin Subject: [PATCH 4.9 10/49] lib/string: Add strscpy_pad() function Date: Mon, 22 Feb 2021 13:36:08 +0100 Message-Id: <20210222121025.280261387@linuxfoundation.org> X-Mailer: git-send-email 2.30.1 In-Reply-To: <20210222121022.546148341@linuxfoundation.org> References: <20210222121022.546148341@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Tobin C. Harding [ Upstream commit 458a3bf82df4fe1f951d0f52b1e0c1e9d5a88a3b ] We have a function to copy strings safely and we have a function to copy strings and zero the tail of the destination (if source string is shorter than destination buffer) but we do not have a function to do both at once. This means developers must write this themselves if they desire this functionality. This is a chore, and also leaves us open to off by one errors unnecessarily. Add a function that calls strscpy() then memset()s the tail to zero if the source string is shorter than the destination buffer. Acked-by: Kees Cook Signed-off-by: Tobin C. Harding Signed-off-by: Shuah Khan Signed-off-by: Sasha Levin --- include/linux/string.h | 4 ++++ lib/string.c | 47 +++++++++++++++++++++++++++++++++++------- 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/include/linux/string.h b/include/linux/string.h index 42eed573ebb63..66a91f5a34499 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -29,6 +29,10 @@ size_t strlcpy(char *, const char *, size_t); #ifndef __HAVE_ARCH_STRSCPY ssize_t strscpy(char *, const char *, size_t); #endif + +/* Wraps calls to strscpy()/memset(), no arch specific code required */ +ssize_t strscpy_pad(char *dest, const char *src, size_t count); + #ifndef __HAVE_ARCH_STRCAT extern char * strcat(char *, const char *); #endif diff --git a/lib/string.c b/lib/string.c index d099762a9bd60..8fe13371aed7a 100644 --- a/lib/string.c +++ b/lib/string.c @@ -157,11 +157,9 @@ EXPORT_SYMBOL(strlcpy); * @src: Where to copy the string from * @count: Size of destination buffer * - * Copy the string, or as much of it as fits, into the dest buffer. - * The routine returns the number of characters copied (not including - * the trailing NUL) or -E2BIG if the destination buffer wasn't big enough. - * The behavior is undefined if the string buffers overlap. - * The destination buffer is always NUL terminated, unless it's zero-sized. + * Copy the string, or as much of it as fits, into the dest buffer. The + * behavior is undefined if the string buffers overlap. The destination + * buffer is always NUL terminated, unless it's zero-sized. * * Preferred to strlcpy() since the API doesn't require reading memory * from the src string beyond the specified "count" bytes, and since @@ -171,8 +169,10 @@ EXPORT_SYMBOL(strlcpy); * * Preferred to strncpy() since it always returns a valid string, and * doesn't unnecessarily force the tail of the destination buffer to be - * zeroed. If the zeroing is desired, it's likely cleaner to use strscpy() - * with an overflow test, then just memset() the tail of the dest buffer. + * zeroed. If zeroing is desired please use strscpy_pad(). + * + * Return: The number of characters copied (not including the trailing + * %NUL) or -E2BIG if the destination buffer wasn't big enough. */ ssize_t strscpy(char *dest, const char *src, size_t count) { @@ -259,6 +259,39 @@ char *stpcpy(char *__restrict__ dest, const char *__restrict__ src) } EXPORT_SYMBOL(stpcpy); +/** + * strscpy_pad() - Copy a C-string into a sized buffer + * @dest: Where to copy the string to + * @src: Where to copy the string from + * @count: Size of destination buffer + * + * Copy the string, or as much of it as fits, into the dest buffer. The + * behavior is undefined if the string buffers overlap. The destination + * buffer is always %NUL terminated, unless it's zero-sized. + * + * If the source string is shorter than the destination buffer, zeros + * the tail of the destination buffer. + * + * For full explanation of why you may want to consider using the + * 'strscpy' functions please see the function docstring for strscpy(). + * + * Return: The number of characters copied (not including the trailing + * %NUL) or -E2BIG if the destination buffer wasn't big enough. + */ +ssize_t strscpy_pad(char *dest, const char *src, size_t count) +{ + ssize_t written; + + written = strscpy(dest, src, count); + if (written < 0 || written == count - 1) + return written; + + memset(dest + written + 1, 0, count - written - 1); + + return written; +} +EXPORT_SYMBOL(strscpy_pad); + #ifndef __HAVE_ARCH_STRCAT /** * strcat - Append one %NUL-terminated string to another -- 2.27.0