linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Kees Cook <keescook@chromium.org>
To: linux-kernel@vger.kernel.org
Cc: Kees Cook <keescook@chromium.org>,
	"Gustavo A. R. Silva" <gustavoars@kernel.org>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Andrew Morton <akpm@linux-foundation.org>,
	linux-wireless@vger.kernel.org, netdev@vger.kernel.org,
	dri-devel@lists.freedesktop.org, linux-staging@lists.linux.dev,
	linux-block@vger.kernel.org, linux-kbuild@vger.kernel.org,
	clang-built-linux@googlegroups.com,
	Rasmus Villemoes <linux@rasmusvillemoes.dk>,
	linux-hardening@vger.kernel.org
Subject: [PATCH v2 63/63] fortify: Work around Clang inlining bugs
Date: Tue, 17 Aug 2021 23:05:33 -0700	[thread overview]
Message-ID: <20210818060533.3569517-64-keescook@chromium.org> (raw)
In-Reply-To: <20210818060533.3569517-1-keescook@chromium.org>

To enable FORTIFY_SOURCE support for Clang, the kernel must work around
a pair of bugs, related to Clang's inlining.

Change all the fortified APIs into macros with different inline names to
bypass Clang's broken inline-of-a-builtin detection:
https://bugs.llvm.org/show_bug.cgi?id=50322

Lift all misbehaving __builtin_object_size() calls into the macros to
bypass Clang's broken __builtin_object_size() arguments-of-an-inline
visibility:
https://github.com/ClangBuiltLinux/linux/issues/1401

Thankfully, due to how the inlining already behaves in GCC, this change
has no effect on GCC builds, but allows Clang to finally gain full
FORTIFY coverage.

However, because of a third bug which had no work-arounds, FORTIFY_SOURCE
will only work with Clang version 13 and later. Update the Kconfig to
reflect the new requirements.

Signed-off-by: Kees Cook <keescook@chromium.org>
---
 include/linux/fortify-string.h | 55 +++++++++++++++++++++-------------
 security/Kconfig               |  2 +-
 2 files changed, 36 insertions(+), 21 deletions(-)

diff --git a/include/linux/fortify-string.h b/include/linux/fortify-string.h
index 7de4673dfe2c..e62d3633a329 100644
--- a/include/linux/fortify-string.h
+++ b/include/linux/fortify-string.h
@@ -48,10 +48,10 @@ extern char *__underlying_strncpy(char *p, const char *q, __kernel_size_t size)
 #define __underlying_strncpy	__builtin_strncpy
 #endif
 
-__FORTIFY_INLINE char *strncpy(char *p, const char *q, __kernel_size_t size)
+#define strncpy(p, q, s) __fortify_strncpy(p, q, s, __builtin_object_size(p, 1))
+__FORTIFY_INLINE char *__fortify_strncpy(char *p, const char *q,
+					 __kernel_size_t size, size_t p_size)
 {
-	size_t p_size = __builtin_object_size(p, 1);
-
 	if (__builtin_constant_p(size) && p_size < size)
 		__write_overflow();
 	if (p_size < size)
@@ -71,9 +71,10 @@ __FORTIFY_INLINE char *strcat(char *p, const char *q)
 }
 
 extern __kernel_size_t __real_strnlen(const char *, __kernel_size_t) __RENAME(strnlen);
-__FORTIFY_INLINE __kernel_size_t strnlen(const char *p, __kernel_size_t maxlen)
+#define strnlen(p, s) __fortify_strnlen(p, s, __builtin_object_size(p, 1))
+__FORTIFY_INLINE __kernel_size_t __fortify_strnlen(const char *p, size_t maxlen,
+						   size_t p_size)
 {
-	size_t p_size = __builtin_object_size(p, 1);
 	size_t p_len = __compiletime_strlen(p);
 	size_t ret;
 
@@ -108,10 +109,14 @@ __FORTIFY_INLINE __kernel_size_t strlen(const char *p)
 
 /* defined after fortified strlen to reuse it */
 extern size_t __real_strlcpy(char *, const char *, size_t) __RENAME(strlcpy);
-__FORTIFY_INLINE size_t strlcpy(char *p, const char *q, size_t size)
+#define strlcpy(p, q, s) __fortify_strlcpy(p, q, s,			\
+					   __builtin_object_size(p, 1),	\
+					   __builtin_object_size(q, 1))
+__FORTIFY_INLINE size_t __fortify_strlcpy(char *p, const char *q,
+					  size_t size,
+					  const size_t p_size,
+					  const size_t q_size)
 {
-	size_t p_size = __builtin_object_size(p, 1);
-	size_t q_size = __builtin_object_size(q, 1);
 	size_t q_len;	/* Full count of source string length. */
 	size_t len;	/* Count of characters going into destination. */
 
@@ -135,12 +140,15 @@ __FORTIFY_INLINE size_t strlcpy(char *p, const char *q, size_t size)
 
 /* 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)
+#define strscpy(p, q, s) __fortify_strscpy(p, q, s,			\
+					   __builtin_object_size(p, 1),	\
+					   __builtin_object_size(q, 1))
+__FORTIFY_INLINE ssize_t __fortify_strscpy(char *p, const char *q,
+					   size_t size,
+					   const size_t p_size,
+					   const size_t q_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)
@@ -181,11 +189,13 @@ __FORTIFY_INLINE ssize_t strscpy(char *p, const char *q, size_t size)
 }
 
 /* defined after fortified strlen and strnlen to reuse them */
-__FORTIFY_INLINE char *strncat(char *p, const char *q, __kernel_size_t count)
+#define strncat(p, q, count)	__fortify_strncat(p, q, count, \
+						  __builtin_object_size(p, 1), \
+						  __builtin_object_size(q, 1))
+__FORTIFY_INLINE char *__fortify_strncat(char *p, const char *q, size_t count,
+					 size_t p_size, size_t q_size)
 {
 	size_t p_len, copy_len;
-	size_t p_size = __builtin_object_size(p, 1);
-	size_t q_size = __builtin_object_size(q, 1);
 
 	if (p_size == (size_t)-1 && q_size == (size_t)-1)
 		return __underlying_strncat(p, q, count);
@@ -352,7 +362,8 @@ __FORTIFY_INLINE void fortify_memcpy_chk(__kernel_size_t size,
 		memmove)
 
 extern void *__real_memscan(void *, int, __kernel_size_t) __RENAME(memscan);
-__FORTIFY_INLINE void *memscan(void *p, int c, __kernel_size_t size)
+#define memscan(p, c, s) __fortify_memscan(p, c, s)
+__FORTIFY_INLINE void *__fortify_memscan(void *p, int c, __kernel_size_t size)
 {
 	size_t p_size = __builtin_object_size(p, 0);
 
@@ -363,7 +374,8 @@ __FORTIFY_INLINE void *memscan(void *p, int c, __kernel_size_t size)
 	return __real_memscan(p, c, size);
 }
 
-__FORTIFY_INLINE int memcmp(const void *p, const void *q, __kernel_size_t size)
+#define memcmp(p, q, s) __fortify_memcmp(p, q, s)
+__FORTIFY_INLINE int __fortify_memcmp(const void *p, const void *q, __kernel_size_t size)
 {
 	size_t p_size = __builtin_object_size(p, 0);
 	size_t q_size = __builtin_object_size(q, 0);
@@ -379,7 +391,8 @@ __FORTIFY_INLINE int memcmp(const void *p, const void *q, __kernel_size_t size)
 	return __underlying_memcmp(p, q, size);
 }
 
-__FORTIFY_INLINE void *memchr(const void *p, int c, __kernel_size_t size)
+#define memchr(p, c, s) __fortify_memchr(p, c, s)
+__FORTIFY_INLINE void *__fortify_memchr(const void *p, int c, __kernel_size_t size)
 {
 	size_t p_size = __builtin_object_size(p, 0);
 
@@ -391,7 +404,8 @@ __FORTIFY_INLINE void *memchr(const void *p, int c, __kernel_size_t size)
 }
 
 void *__real_memchr_inv(const void *s, int c, size_t n) __RENAME(memchr_inv);
-__FORTIFY_INLINE void *memchr_inv(const void *p, int c, size_t size)
+#define memchr_inv(p, c, s) __fortify_memchr_inv(p, c, s)
+__FORTIFY_INLINE void *__fortify_memchr_inv(const void *p, int c, size_t size)
 {
 	size_t p_size = __builtin_object_size(p, 0);
 
@@ -415,7 +429,8 @@ __FORTIFY_INLINE void *kmemdup(const void *p, size_t size, gfp_t gfp)
 }
 
 /* Defined after fortified strlen to reuse it. */
-__FORTIFY_INLINE char *strcpy(char *p, const char *q)
+#define strcpy(p, q) __fortify_strcpy(p, q)
+__FORTIFY_INLINE char *__fortify_strcpy(char *p, const char *q)
 {
 	size_t p_size = __builtin_object_size(p, 1);
 	size_t q_size = __builtin_object_size(q, 1);
diff --git a/security/Kconfig b/security/Kconfig
index fe6c0395fa02..530a15566b1d 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -193,7 +193,7 @@ config FORTIFY_SOURCE
 	depends on ARCH_HAS_FORTIFY_SOURCE
 	# https://bugs.llvm.org/show_bug.cgi?id=50322
 	# https://bugs.llvm.org/show_bug.cgi?id=41459
-	depends on !CC_IS_CLANG
+	depends on !CC_IS_CLANG || CLANG_VERSION >= 130000
 	help
 	  Detect overflows of buffers in common string and memory functions
 	  where the compiler can determine and validate the buffer sizes.
-- 
2.30.2


      parent reply	other threads:[~2021-08-18  6:13 UTC|newest]

Thread overview: 116+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-08-18  6:04 [PATCH v2 00/63] Introduce strict memcpy() bounds checking Kees Cook
2021-08-18  6:04 ` [PATCH v2 01/63] ipw2x00: Avoid field-overflowing memcpy() Kees Cook
2021-08-18  6:04 ` [PATCH v2 02/63] net/mlx5e: " Kees Cook
2021-08-18  6:04 ` [PATCH v2 03/63] rpmsg: glink: Replace strncpy() with strscpy_pad() Kees Cook
2021-08-18  6:04 ` [PATCH v2 04/63] pcmcia: ray_cs: Split memcpy() to avoid bounds check warning Kees Cook
2021-08-18  6:04 ` [PATCH v2 05/63] stddef: Introduce struct_group() helper macro Kees Cook
2021-08-18 22:35   ` Dan Williams
2021-08-18  6:04 ` [PATCH v2 06/63] cxl/core: Replace unions with struct_group() Kees Cook
2021-08-18 22:36   ` Dan Williams
2021-08-18  6:04 ` [PATCH v2 07/63] skbuff: Switch structure bounds to struct_group() Kees Cook
2021-09-01 13:46   ` Jason A. Donenfeld
2021-08-18  6:04 ` [PATCH v2 08/63] bnxt_en: Use struct_group_attr() for memcpy() region Kees Cook
2021-08-18  6:04 ` [PATCH v2 09/63] mwl8k: Use struct_group() " Kees Cook
2021-08-18  6:04 ` [PATCH v2 10/63] libertas: " Kees Cook
2021-08-18  6:04 ` [PATCH v2 11/63] libertas_tf: " Kees Cook
2021-08-18  6:04 ` [PATCH v2 12/63] thermal: intel: int340x_thermal: " Kees Cook
2021-11-23 13:19   ` Rafael J. Wysocki
2021-11-23 23:53     ` Srinivas Pandruvada
2021-11-24 13:33       ` Rafael J. Wysocki
2021-08-18  6:04 ` [PATCH v2 13/63] iommu/amd: " Kees Cook
2021-08-18 11:34   ` Joerg Roedel
2021-08-18  6:04 ` [PATCH v2 14/63] cxgb3: " Kees Cook
2021-08-18  6:04 ` [PATCH v2 15/63] intersil: " Kees Cook
2021-08-18  6:04 ` [PATCH v2 16/63] cxgb4: " Kees Cook
2021-08-18  6:04 ` [PATCH v2 17/63] bnx2x: " Kees Cook
2021-08-18  6:04 ` [PATCH v2 18/63] drm/amd/pm: " Kees Cook
2021-08-18 11:42   ` Lazar, Lijo
2021-08-18 23:59     ` Kees Cook
2021-08-19  5:03       ` Lazar, Lijo
2021-08-19 19:58         ` Kees Cook
2021-08-18  6:04 ` [PATCH v2 19/63] staging: wlan-ng: " Kees Cook
2021-08-18  6:04 ` [PATCH v2 20/63] drm/mga/mga_ioc32: " Kees Cook
2021-08-18  6:04 ` [PATCH v2 21/63] net/mlx5e: " Kees Cook
2021-08-18  6:04 ` [PATCH v2 22/63] HID: cp2112: " Kees Cook
2021-08-20 13:01   ` Jiri Kosina
2021-08-20 15:48     ` Kees Cook
2021-08-18  6:04 ` [PATCH v2 23/63] media: omap3isp: " Kees Cook
2021-08-18  6:04 ` [PATCH v2 24/63] sata_fsl: " Kees Cook
2021-08-18  6:04 ` [PATCH v2 25/63] compiler_types.h: Remove __compiletime_object_size() Kees Cook
2021-08-18 13:02   ` Miguel Ojeda
2021-08-18  6:04 ` [PATCH v2 26/63] lib/string: Move helper functions out of string.c Kees Cook
2021-08-18  9:35   ` Andy Shevchenko
2021-08-18  6:04 ` [PATCH v2 27/63] fortify: Move remaining fortify helpers into fortify-string.h Kees Cook
2021-08-18 19:05   ` Francis Laniel
2021-08-18  6:04 ` [PATCH v2 28/63] fortify: Explicitly disable Clang support Kees Cook
2021-08-18  6:04 ` [PATCH v2 29/63] fortify: Fix dropped strcpy() compile-time write overflow check Kees Cook
2021-08-18  6:05 ` [PATCH v2 30/63] fortify: Prepare to improve strnlen() and strlen() warnings Kees Cook
2021-08-18  6:05 ` [PATCH v2 31/63] fortify: Allow strlen() and strnlen() to pass compile-time known lengths Kees Cook
2021-08-18  6:05 ` [PATCH v2 32/63] fortify: Add compile-time FORTIFY_SOURCE tests Kees Cook
2021-08-18  6:05 ` [PATCH v2 33/63] lib: Introduce CONFIG_TEST_MEMCPY Kees Cook
2021-08-18  6:05 ` [PATCH v2 34/63] fortify: Detect struct member overflows in memcpy() at compile-time Kees Cook
2021-08-18  6:05 ` [PATCH v2 35/63] fortify: Detect struct member overflows in memmove() " Kees Cook
2021-08-18  6:05 ` [PATCH v2 36/63] scsi: ibmvscsi: Avoid multi-field memset() overflow by aiming at srp Kees Cook
2021-08-18  6:05 ` [PATCH v2 37/63] string.h: Introduce memset_after() for wiping trailing members/padding Kees Cook
2021-08-18  6:05 ` [PATCH v2 38/63] xfrm: Use memset_after() to clear padding Kees Cook
2021-08-18  6:05 ` [PATCH v2 39/63] ipv6: Use memset_after() to zero rt6_info Kees Cook
2021-08-18  6:05 ` [PATCH v2 40/63] netfilter: conntrack: Use memset_startat() to zero struct nf_conn Kees Cook
2021-08-18  6:05 ` [PATCH v2 41/63] net: 802: Use memset_startat() to clear struct fields Kees Cook
2021-08-18  6:05 ` [PATCH v2 42/63] net: dccp: Use memset_startat() for TP zeroing Kees Cook
2021-08-18  6:05 ` [PATCH v2 43/63] net: qede: Use memset_startat() for counters Kees Cook
2021-08-18  6:05 ` [PATCH v2 44/63] mac80211: Use memset_after() to clear tx status Kees Cook
2021-08-18  7:08   ` Johannes Berg
2021-08-18  8:06     ` Johannes Berg
2021-08-18  9:05       ` Kees Cook
2021-08-18  6:05 ` [PATCH v2 45/63] ath11k: Use memset_startat() for clearing queue descriptors Kees Cook
2021-08-19 13:19   ` Kalle Valo
2021-08-19 16:25     ` Kees Cook
2021-08-21 10:17       ` Kalle Valo
2021-08-22  8:11         ` Kees Cook
2021-08-18  6:05 ` [PATCH v2 46/63] iw_cxgb4: Use memset_startat() for cpl_t5_pass_accept_rpl Kees Cook
2021-08-18  6:05 ` [PATCH v2 47/63] intel_th: msu: Use memset_startat() for clearing hw header Kees Cook
2021-08-24  7:38   ` Alexander Shishkin
2021-08-18  6:05 ` [PATCH v2 48/63] IB/mthca: Use memset_startat() for clearing mpt_entry Kees Cook
2021-08-18  6:05 ` [PATCH v2 49/63] btrfs: Use memset_startat() to clear end of struct Kees Cook
2021-08-18  6:35   ` Nikolay Borisov
2021-08-18  9:28   ` David Sterba
2021-08-18  6:05 ` [PATCH v2 50/63] tracing: Use memset_startat() to zero struct trace_iterator Kees Cook
2021-08-18 13:33   ` Steven Rostedt
2021-08-18 16:21     ` Kees Cook
2021-08-18  6:05 ` [PATCH v2 51/63] drbd: Use struct_group() to zero algs Kees Cook
2021-08-18  6:05 ` [PATCH v2 52/63] cm4000_cs: Use struct_group() to zero struct cm4000_dev region Kees Cook
2021-08-18  6:05 ` [PATCH v2 53/63] KVM: x86: Use struct_group() to zero decode cache Kees Cook
2021-08-18 15:11   ` Sean Christopherson
2021-08-18 16:23     ` Kees Cook
2021-08-18 22:53       ` Sean Christopherson
2021-08-18 23:06         ` Kees Cook
2021-08-18  6:05 ` [PATCH v2 54/63] dm integrity: Use struct_group() to zero struct journal_sector Kees Cook
2021-08-18  6:05 ` [PATCH v2 55/63] HID: roccat: Use struct_group() to zero kone_mouse_event Kees Cook
2021-08-20 13:02   ` Jiri Kosina
     [not found]     ` <CAJr-aD=6-g7VRw2Hw0dhs+RrtA=Tago5r6Dukfw_gGPB0YYKOQ@mail.gmail.com>
2021-08-20 15:27       ` Jiri Kosina
2021-08-20 15:49         ` Kees Cook
2021-08-20 15:57         ` Kees Cook
2021-08-20 16:11           ` Jiri Kosina
2021-08-18  6:05 ` [PATCH v2 56/63] RDMA/mlx5: Use struct_group() to zero struct mlx5_ib_mr Kees Cook
2021-08-19 12:27   ` Jason Gunthorpe
2021-08-19 16:19     ` Kees Cook
2021-08-19 16:47       ` Jason Gunthorpe
2021-08-19 18:14         ` Kees Cook
2021-08-20 12:34           ` Jason Gunthorpe
2021-08-20 15:56             ` Kees Cook
2021-08-18  6:05 ` [PATCH v2 57/63] powerpc/signal32: Use struct_group() to zero spe regs Kees Cook
2021-08-20  7:49   ` Michael Ellerman
2021-08-20  7:53     ` Christophe Leroy
2021-08-20 12:13       ` Michael Ellerman
2021-08-20 15:55     ` Kees Cook
2021-08-23  4:55       ` Michael Ellerman
2021-08-18  6:05 ` [PATCH v2 58/63] ethtool: stats: Use struct_group() to clear all stats at once Kees Cook
2021-08-18  6:05 ` [PATCH v2 59/63] can: flexcan: Use struct_group() to zero struct flexcan_regs regions Kees Cook
2021-08-18  6:26   ` Marc Kleine-Budde
2021-08-18  6:05 ` [PATCH v2 60/63] net/af_iucv: Use struct_group() to zero struct iucv_sock region Kees Cook
2021-09-09  6:14   ` Karsten Graul
2021-08-18  6:05 ` [PATCH v2 61/63] powerpc: Split memset() to avoid multi-field overflow Kees Cook
2021-08-18  6:42   ` Christophe Leroy
2021-08-18 22:30     ` Kees Cook
2021-08-18  6:05 ` [PATCH v2 62/63] fortify: Detect struct member overflows in memset() at compile-time Kees Cook
2021-08-18  6:05 ` Kees Cook [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210818060533.3569517-64-keescook@chromium.org \
    --to=keescook@chromium.org \
    --cc=akpm@linux-foundation.org \
    --cc=clang-built-linux@googlegroups.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=gustavoars@kernel.org \
    --cc=linux-block@vger.kernel.org \
    --cc=linux-hardening@vger.kernel.org \
    --cc=linux-kbuild@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-staging@lists.linux.dev \
    --cc=linux-wireless@vger.kernel.org \
    --cc=linux@rasmusvillemoes.dk \
    --cc=netdev@vger.kernel.org \
    --subject='Re: [PATCH v2 63/63] fortify: Work around Clang inlining bugs' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).