Received: by 2002:a05:6a10:16a7:0:0:0:0 with SMTP id gp39csp240101pxb; Wed, 18 Nov 2020 03:21:33 -0800 (PST) X-Google-Smtp-Source: ABdhPJw6LkWQS0ucihiSxi4ecgBH6BanEYYnp8u30EavDJOjmIZpEZp/4LnxieOMYw8nQzvTg4Z1 X-Received: by 2002:aa7:cb4a:: with SMTP id w10mr25505821edt.343.1605698493581; Wed, 18 Nov 2020 03:21:33 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1605698493; cv=none; d=google.com; s=arc-20160816; b=JGPA2LFdTw57bD+oYIgY0MdQUd+g2OiByx48v/6eF2WXtozfoDMt0Fl/JqRbiAX96y fuy61ASxoAP+1kw35vCGCm4Rx6dT6HKVKA5itG8Hd7HqRba2EbegfijbEen6P5KqlP7/ HySPEAqAehVm0DOdq812z53wewYHjb6tiNdmRiWlti2B6nBH65KDyPhvJLeLvuofh4FN OWb5NuyySZV3c/rx0xOo3P1B8c3H4eYQaoPP2zqiCT+zsTunNMV1I8qNh1Bf4jeo0BSq InZJSCp5fZ2bwErnUxukwKxyuUA2kXAGeg6ZVtlao4N3Y4Ib44g/TMRVGHDVzZxS3h1p GfOg== 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 :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=d3Gb/r8juyYmXty1Zs6cAP1wvNQs32vfeMBtqK0HsG0=; b=jH7/ay3LudX17HsSc1QsplROGVVXOVyJlqTmxyE3SiNsqiS9vCGa2NM+IBlHkLrujB +vXVpJLJjTqZ6WH+Jb3P75bbnFnGSkZfs/dbEMirHcLNeurb+dTaUf4L5Uukbw8lnUSQ 2qPjJROBHIgApie5eiYoJ0f0Maf6/KEkxrMoumwe73Sb12BdvEEEABiCrec/IWge/zY5 orqHe55E3bMlslaqf+rYcvn894F+f/+ohB9uteDDuowQAYp76/4xhBVhDxs0it8Y34Gv Xsn8SC3g6hv/5hH8PEEG5bQvQExAkTebjnRv9tWZcHv1OrBNqkX72wba0deDsbfglzTC 4AfQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@privacyrequired.com header.s=stigmate header.b=cla1VaLF; 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id j13si15009177ejy.399.2020.11.18.03.21.11; Wed, 18 Nov 2020 03:21:33 -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=@privacyrequired.com header.s=stigmate header.b=cla1VaLF; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727840AbgKRLRL (ORCPT + 99 others); Wed, 18 Nov 2020 06:17:11 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37532 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726505AbgKRLRI (ORCPT ); Wed, 18 Nov 2020 06:17:08 -0500 Received: from latitanza.investici.org (latitanza.investici.org [IPv6:2001:888:2000:56::19]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3A9F0C0613D6 for ; Wed, 18 Nov 2020 03:17:08 -0800 (PST) Received: from mx3.investici.org (unknown [127.0.0.1]) by latitanza.investici.org (Postfix) with ESMTP id 4Cbg5P1Wm9z8sh9; Wed, 18 Nov 2020 11:07:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=privacyrequired.com; s=stigmate; t=1605697673; bh=d3Gb/r8juyYmXty1Zs6cAP1wvNQs32vfeMBtqK0HsG0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=cla1VaLF9A8iQ8uspyGt56+2EzHEPkzE4zr1K1yIKTZvmdonUt7adO43QyOHcgxQP gZCAAtJGimTbrpujiIyia+xajD57Uf4NudbV1LFpk1JFmqSMGpOy6OuLBlUDMi5v64 tjwzx5CKAo0X3tPMmGmOaKFhjcHII7Wf3nonRh30= Received: from [82.94.249.234] (mx3.investici.org [82.94.249.234]) (Authenticated sender: laniel_francis@privacyrequired.com) by localhost (Postfix) with ESMTPSA id 4Cbg5N1X4rz8sgF; Wed, 18 Nov 2020 11:07:52 +0000 (UTC) From: laniel_francis@privacyrequired.com To: akpm@linux-foundation.org Cc: linux-hardening@vger.kernel.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org, dja@axtens.net, keescook@chromium.org, Francis Laniel Subject: [PATCH v5 3/5] string.h: Add FORTIFY coverage for strscpy() Date: Wed, 18 Nov 2020 12:07:29 +0100 Message-Id: <20201118110731.15833-4-laniel_francis@privacyrequired.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20201118110731.15833-1-laniel_francis@privacyrequired.com> References: <20201118110731.15833-1-laniel_francis@privacyrequired.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Francis Laniel The fortified version of strscpy ensures the following before vanilla strscpy is called: 1. There is no read overflow because we either size is smaller than src length or we shrink size to src length by calling fortified strnlen. 2. There is no write overflow because we either failed during compilation or at runtime by checking that size is smaller than dest size. Signed-off-by: Francis Laniel Acked-by: Kees Cook --- include/linux/string.h | 48 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/include/linux/string.h b/include/linux/string.h index 46e91d684c47..1cd63a8a23ab 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -6,6 +6,7 @@ #include /* for inline */ #include /* for size_t */ #include /* for NULL */ +#include /* for E2BIG */ #include #include @@ -357,6 +358,53 @@ __FORTIFY_INLINE size_t strlcpy(char *p, const char *q, size_t size) return ret; } +/* defined after fortified strnlen to reuse it */ +extern ssize_t __real_strscpy(char *, const char *, size_t) __RENAME(strscpy); +__FORTIFY_INLINE ssize_t strscpy(char *p, const char *q, size_t size) +{ + size_t len; + /* Use string size rather than possible enclosing struct size. */ + size_t p_size = __builtin_object_size(p, 1); + size_t q_size = __builtin_object_size(q, 1); + + /* If we cannot get size of p and q default to call strscpy. */ + if (p_size == (size_t) -1 && q_size == (size_t) -1) + return __real_strscpy(p, q, size); + + /* + * If size can be known at compile time and is greater than + * p_size, generate a compile time write overflow error. + */ + if (__builtin_constant_p(size) && size > p_size) + __write_overflow(); + + /* + * This call protects from read overflow, because len will default to q + * length if it smaller than size. + */ + len = strnlen(q, size); + /* + * If len equals size, we will copy only size bytes which leads to + * -E2BIG being returned. + * Otherwise we will copy len + 1 because of the final '\O'. + */ + len = len == size ? size : len + 1; + + /* + * Generate a runtime write overflow error if len is greater than + * p_size. + */ + if (len > p_size) + fortify_panic(__func__); + + /* + * We can now safely call vanilla strscpy because we are protected from: + * 1. Read overflow thanks to call to strnlen(). + * 2. Write overflow thanks to above ifs. + */ + return __real_strscpy(p, q, len); +} + /* defined after fortified strlen and strnlen to reuse them */ __FORTIFY_INLINE char *strncat(char *p, const char *q, __kernel_size_t count) { -- 2.20.1