Received: by 2002:a05:6a10:8c0a:0:0:0:0 with SMTP id go10csp2261650pxb; Thu, 11 Feb 2021 08:10:14 -0800 (PST) X-Google-Smtp-Source: ABdhPJxsR6c2XOV/5vjF2vprH65gbrdqfNZR1nvATsmhTczVqbI4jL5zttEcys1JK7MHUfS3PxJF X-Received: by 2002:a05:6402:105a:: with SMTP id e26mr8681302edu.60.1613059814757; Thu, 11 Feb 2021 08:10:14 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1613059814; cv=none; d=google.com; s=arc-20160816; b=t6W0Mpu1eihv80ly2XGiIyO6IKywXT2Jac3Sr42S5BX0fX5ResejGnJaC2oM3nYMpY DG3+0sYudK3NXk8zhmuUtAeqEIFXpaNY+ur/2ZrjqZQLvuCHrfb9duNvh0GUF2f5HsIv jQ6p11wZmHYTjU/Go3meeAndlMsHVYq8db6BzRrKxFkSf5ZWQMndEChMYk+cw7CHPHrb 02XCcIT76dqW3lbBR/+YQw2zefEab4EO4vCqxbe+ePDfdn6g0ZBIDI//MsAndtOXfJLc wCQKiC6bN2601QPk94pAq6K+106spwTiXPrn6zQEMjhzUYU6nyR3zF4Q1DxfpM+at3OK p0sA== 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=m0ePa472MVx0lxb3gkMMKk/xiqAQJzgrchXk4Jtf8+Y=; b=XDvk9rw41ztm9sOvmB4o2YSK3WbKaLtMsbdqK/nZCbJouQWag2c5kzKjRfu1DmM4xG +re/mKXfDs8A5Ay5SW8WjoutMMPiRQ3v7q4Leu1sQwLlWHHFNdAy+FSatEW5LUNsUdwb FbAj42m6l2gqGaaDNRv70gmkocw75b2u4Pz1WjYtYM9kInXRAFY5CXIYqc50qIp35Ry2 N3EXwLR+8BOyFBhfOFfq/pCEW4TiPurER0LEWPNjoHQtTosmqsPuHAbuWZlHlCM23Z50 QWbhLUNEes2EMTBFfaJwrfzFgSWUvm9Rd63w2pZfHZBytjeBJ6OV9VKxz9OQvEAp9CaT aE7g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=0Tqe7KVi; 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 x14si3937422eds.256.2021.02.11.08.09.39; Thu, 11 Feb 2021 08:10:14 -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=0Tqe7KVi; 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 S231808AbhBKQIE (ORCPT + 99 others); Thu, 11 Feb 2021 11:08:04 -0500 Received: from mail.kernel.org ([198.145.29.99]:52630 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229912AbhBKPUg (ORCPT ); Thu, 11 Feb 2021 10:20:36 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 77DD464F29; Thu, 11 Feb 2021 15:06:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1613056012; bh=JHDr2IOXzI89qrCUK4WjbM/xAngvlCwxSD66t9bjhFI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=0Tqe7KViKodYZBpVNvi8NQlq8E+DWuy2zu7HKdDr8SudecuE8qhDaJ3J5HSGrGFlB PNQJTj0X9wJxMA9ePfU7eyDzH3lI/vDrbvOdpQ5fb9fXhvNUo6L9wQhipN06agQJI2 aAtIzAOlR86jl2FJF5jqy1m2vCevkB9XSd4yBcdI= 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.19 16/24] lib/string: Add strscpy_pad() function Date: Thu, 11 Feb 2021 16:02:50 +0100 Message-Id: <20210211150148.467778368@linuxfoundation.org> X-Mailer: git-send-email 2.30.1 In-Reply-To: <20210211150147.743660073@linuxfoundation.org> References: <20210211150147.743660073@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 4db285b83f44e..1e0c442b941e2 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -31,6 +31,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 edf4907ec946f..f7f7770444bf5 100644 --- a/lib/string.c +++ b/lib/string.c @@ -158,11 +158,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 @@ -172,8 +170,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) { @@ -260,6 +260,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