From patchwork Tue Sep 20 19:21:59 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 12982521 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 64235C54EE9 for ; Tue, 20 Sep 2022 19:22:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231232AbiITTWM (ORCPT ); Tue, 20 Sep 2022 15:22:12 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37344 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230371AbiITTWK (ORCPT ); Tue, 20 Sep 2022 15:22:10 -0400 Received: from mail-pj1-x1031.google.com (mail-pj1-x1031.google.com [IPv6:2607:f8b0:4864:20::1031]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 974FE28E0E for ; Tue, 20 Sep 2022 12:22:09 -0700 (PDT) Received: by mail-pj1-x1031.google.com with SMTP id fs14so4107922pjb.5 for ; Tue, 20 Sep 2022 12:22:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date; bh=mRkb49hJ/o7sUzNJw/zHfFKhjBVcyGD1caVksculA00=; b=PCUI69eggGWeXyBeTxep9IHUaH7o4uqq9Tn6NaYKT/NYgVgrpRX6+8DhNeX3ewe9ey clzFXuBXIjdIDBwAb0H1OJggBDLLvppduw51miVUkus5CCOXfCg6GLFkPmuoAUvBdVwx pWo63368x3lb04WlSCci+u5M/slQQLEVz5BeA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date; bh=mRkb49hJ/o7sUzNJw/zHfFKhjBVcyGD1caVksculA00=; b=1r1hHXPff6qh96gJ+6FsanwE1IaWlIyiHbNP3VAJG/BQuvIJ668yX1F2hZ52AvEcjn bjdh2hrsKZCL+YA7DgsedbXRY4XVsegd0jQPTl29oVIoct2BqHXgzerHouh1N1qQMeDE LvlJ1mHpt5pWRtWcMigGzA0ug0sD81azQ5hvoKLFz2zTjYPVbM/MG5ZA9H7FWYU3UG5T 7Iob8bAbU00ZrRmo5RZffMnupVXhMhkSRgqoIvPWQ1erHvStisVDykcu2Hc3Cp0IXwuz v4lm0HQ05gTRSrn0UbFNc3O7D2jqHCzehKdK4BsDD2NPNbMNYmEpKXDYfzNP1iBbo+aw OU2w== X-Gm-Message-State: ACrzQf3yWaTnjqE8rplpJe6FkKHmS5QI6UNhd/XrZ7LS2f1tDOep1Yfl 2u+j1sYa8zOgx97ktK+a0BlojfumOYydXA== X-Google-Smtp-Source: AMsMyM761d7Fl9dtnwBzIqTJhW7NDE0KfYgW2Z3zOf5cFMrONbSUwHk2/D83vjqkbY1Tqo6olp+d4w== X-Received: by 2002:a17:903:1248:b0:172:f3c7:97a6 with SMTP id u8-20020a170903124800b00172f3c797a6mr1097776plh.128.1663701729091; Tue, 20 Sep 2022 12:22:09 -0700 (PDT) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id i62-20020a17090a3dc400b001facf455c91sm286910pjc.21.2022.09.20.12.22.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 Sep 2022 12:22:08 -0700 (PDT) From: Kees Cook To: linux-hardening@vger.kernel.org Cc: Kees Cook , Juergen Gross , Boris Ostrovsky , Nathan Chancellor , Nick Desaulniers , xen-devel@lists.xenproject.org, llvm@lists.linux.dev, Siddhesh Poyarekar , Arnd Bergmann , Tom Rix , Miguel Ojeda , linux-kernel@vger.kernel.org Subject: [PATCH 1/4] x86/entry: Work around Clang __bdos() bug Date: Tue, 20 Sep 2022 12:21:59 -0700 Message-Id: <20220920192202.190793-2-keescook@chromium.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220920192202.190793-1-keescook@chromium.org> References: <20220920192202.190793-1-keescook@chromium.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=1979; h=from:subject; bh=4MnVaPsx8mraEdez/1qUw/f+9P/3EjkrM/1wqdGlA2Y=; b=owEBbQKS/ZANAwAKAYly9N/cbcAmAcsmYgBjKhLZE7kAhe/OxfUVwh8eyd4pKAVAQvW03irD5DAW qRCvxvmJAjMEAAEKAB0WIQSlw/aPIp3WD3I+bhOJcvTf3G3AJgUCYyoS2QAKCRCJcvTf3G3AJuSWD/ 0YU5lJR6Qasvy4L3d9D2h5U5JWrfw5lBGb341IHXohJFP1UnzRH0CT/UnomvYDoLvjhR2joksvkjkn BNTSv7VoRq4RwprCdKG4kgHD8PGjx57z3qsj73lXyfUXt1MwvQB9y+YDpD/SE2IuUFQpf+4iZ2uEtn LvLw9kT0MNmAnaM2dSR5lA6wrcdt9dcqBf4C1O80RyWBKBnfJN2tT3TskZggBrAyk2Y4VxfAOg9UF2 vTENn7pVEn7EisxLJ6/wCFt835Ov9Op7ldWqez4GSVVxpyhYW3zjEzqFOZ1Jwto62iUKdM+V83O8ew rjJ/WRDJT6EN225b5IvYvTHVC742B3/OkrjefYwWsKruTy7sR4aGoXrx6gtHOCfsncloYhZnF1ayiE /BA9ncPIH958gJ01gz7eZndZ2kkOAFTm3BBIZ/Rm8ISXObKAWBd6rFb0MBYeVza2e4fbwvVJfgTG9H tv86FQuDi0OhoT1JbgJrNbf/GhLz8PegmQUKUoAhXk9LrWby/jti9NoGokj6bJKjjtuORb0ETDHUJU WM+b2N7anNSPw/Sovfcx5bkbvOrenXO1PW7ByUj5o5/nal3mnvLFtWS7g3Z17XB5ybO8nxngnjb9NG Fcmwv0P7fktHuuT0QNwTw4WG5vmaMeqDZTTYXOKsbqzpoOfwlI1qO6qXA0jQ== X-Developer-Key: i=keescook@chromium.org; a=openpgp; fpr=A5C3F68F229DD60F723E6E138972F4DFDC6DC026 Precedence: bulk List-ID: X-Mailing-List: linux-hardening@vger.kernel.org After expanding bounds checking to use __builtin_dynamic_object_size(), Clang produces a false positive when building with CONFIG_FORTIFY_SOURCE=y and CONFIG_UBSAN_BOUNDS=y when operating on an array with a dynamic offset. Work around this by using a direct assignment of an empty instance. Avoids this warning: ../include/linux/fortify-string.h:309:4: warning: call to __write_overflow_field declared with 'warn ing' attribute: detected write beyond size of field (1st parameter); maybe use struct_group()? [-Wat tribute-warning] __write_overflow_field(p_size_field, size); ^ which was isolated to the memset() call in xen_load_idt(). Note that this looks very much like another bug that was worked around: https://github.com/ClangBuiltLinux/linux/issues/1592 Cc: Juergen Gross Cc: Boris Ostrovsky Cc: Nathan Chancellor Cc: Nick Desaulniers Cc: xen-devel@lists.xenproject.org Cc: llvm@lists.linux.dev Signed-off-by: Kees Cook Reviewed-by: Boris Ostrovsky --- arch/x86/xen/enlighten_pv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c index 0ed2e487a693..9b1a58dda935 100644 --- a/arch/x86/xen/enlighten_pv.c +++ b/arch/x86/xen/enlighten_pv.c @@ -765,6 +765,7 @@ static void xen_load_idt(const struct desc_ptr *desc) { static DEFINE_SPINLOCK(lock); static struct trap_info traps[257]; + static const struct trap_info zero = { }; unsigned out; trace_xen_cpu_load_idt(desc); @@ -774,7 +775,7 @@ static void xen_load_idt(const struct desc_ptr *desc) memcpy(this_cpu_ptr(&idt_desc), desc, sizeof(idt_desc)); out = xen_convert_trap_info(desc, traps, false); - memset(&traps[out], 0, sizeof(traps[0])); + traps[out] = zero; xen_mc_flush(); if (HYPERVISOR_set_trap_table(traps)) From patchwork Tue Sep 20 19:22:00 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 12982522 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BE299C6FA82 for ; Tue, 20 Sep 2022 19:22:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231239AbiITTWN (ORCPT ); Tue, 20 Sep 2022 15:22:13 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37368 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231209AbiITTWL (ORCPT ); Tue, 20 Sep 2022 15:22:11 -0400 Received: from mail-pf1-x431.google.com (mail-pf1-x431.google.com [IPv6:2607:f8b0:4864:20::431]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3E15A2CCBB for ; Tue, 20 Sep 2022 12:22:10 -0700 (PDT) Received: by mail-pf1-x431.google.com with SMTP id d82so3638853pfd.10 for ; Tue, 20 Sep 2022 12:22:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date; bh=JX0ua+LFqhoPxmKV4FkFTEjLOIsGeEC5zMQTZ7gmmn0=; b=PWP5PK9w7OmL6GItthJmplzUuDG9moNLPk1mcXR9Camj5lYCFnho3xhjAIJ5jFVdQD BnG1hTJQPls+dKR8bJXIqGnHInIPWik0zjjmf2tJQpudCX/SrH/eQGDw6m4VoJNzKtQx hZe6UK4yikBf0kLC1TdwbX1/6fADVBSzEcVcM= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date; bh=JX0ua+LFqhoPxmKV4FkFTEjLOIsGeEC5zMQTZ7gmmn0=; b=FlDsVqG53uzEyT/a9DvOVktIVhEwWKQ1HeiPMc/CBHwJ8AOa0G4VbSW2v7noh550K6 HMAbGh5h2p/AIfwefjcJZSYOMuD5fqMWqhynUzT/DGkcUvu3HnLGYm31NFQuIulBDml6 jxeAYQmdOk1TglQX18dVQQeZvEKlcBYqYBEdhptZwqd1P44Uvp/14+2tebJMnolGBKk2 JwunrRd8JLzV4J5Ceelk3MPgu1u+kVOEP2SM0sftqza9gaNvqWC4aDqE8ThhegMnu+80 Z6UFRkjuSX/qlNDucacG4v/O2ShCfOCCDKlVYkpPiC90ddsa/8Er9Cn+MEF2/cAY6HGz bDjQ== X-Gm-Message-State: ACrzQf1qYlHeEAzFVohuGZuW8TZ8hjdRgf2TVvVKvFdjngfWMvTxIbAS EhAsnkybA0vmdyN1Q8rOo4tvzQ== X-Google-Smtp-Source: AMsMyM4hPEYquldZYsARoLf9Epv/KmSgPcBvKIvtg1QdMq9AHUvzPJ5F7JBZcSTvNKqzgwJubVJMEg== X-Received: by 2002:a63:81c1:0:b0:439:ff01:ff81 with SMTP id t184-20020a6381c1000000b00439ff01ff81mr12874505pgd.39.1663701729659; Tue, 20 Sep 2022 12:22:09 -0700 (PDT) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id s16-20020aa78bd0000000b0053e7d3b8d6dsm295543pfd.1.2022.09.20.12.22.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 Sep 2022 12:22:08 -0700 (PDT) From: Kees Cook To: linux-hardening@vger.kernel.org Cc: Kees Cook , Siddhesh Poyarekar , Nathan Chancellor , Nick Desaulniers , Arnd Bergmann , Juergen Gross , Boris Ostrovsky , Tom Rix , Miguel Ojeda , linux-kernel@vger.kernel.org, llvm@lists.linux.dev Subject: [PATCH 2/4] fortify: Explicitly check bounds are compile-time constants Date: Tue, 20 Sep 2022 12:22:00 -0700 Message-Id: <20220920192202.190793-3-keescook@chromium.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220920192202.190793-1-keescook@chromium.org> References: <20220920192202.190793-1-keescook@chromium.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=6494; h=from:subject; bh=H1LlmpBscaiEe04I7Sh+ZCZmF9ZgzimcwM4cFmtVeLs=; b=owEBbQKS/ZANAwAKAYly9N/cbcAmAcsmYgBjKhLZNwEQUjp9SkNBWAp8JMozzL5lhw11d4e0rr46 SL0SNsGJAjMEAAEKAB0WIQSlw/aPIp3WD3I+bhOJcvTf3G3AJgUCYyoS2QAKCRCJcvTf3G3AJvs7D/ 9VRJeaTb6BW+4YIzT0+1vpKMjjFvHn5Vt8YD9KVShd7IMqv89ggecT7cEPzwYqGULXFFsgBiSMF1eF RQLaTRMR5ET9DQMztatGHuYJM1WoQ9wqcGieTl0s3NfYEknwNaIxb5Do6AvLiy6WLP9YC8rDLOU6jg +9XXHTf0CPxRiD0ZSF9J/S9FG2GTo8TDLLfOv/I51htuw0jhzXDFkGuOXv4k0VpC3ajwZE32iRtsOR KmVQNVPqo/nhKEQyplpeBxIX91oCn4wQR02lg+x7Fa7aXB8oHD7LhnSUpy4wQ3Ns/yG0tmWxfvOmmv rq0ktZA6z33b+Md/dM0CBN8Hs15I3EnViOYjsOb7h3/ou6vD6qhNzYoCGHmlBrEZ2emlCGiti1rMxq 9pkNNpQbxTI/92DbtUQDd5dbji7k0hCyT7aPobMd26ucldxq9F4LiTc+vVyBieBtqNmrNSAqYR1lti L3kgrtO5jJaoS62216+2WDIkVtFsRvHFJv0iqvpdxmFY0l5IH7wlo44icmLQkTSH1w5bEjCuYSQj82 NQbcPMtFm8cWYrSSyJ1drVOW/MUsYOyUY9DUiaTq1w6pZZcWtCaE/3Zph8Zot4spfo3UUcPadycuei DoMLVZPRh0tmtX6CCEzNfHUL3OAUUR+VnrL1n3UnUSa4RSgtuxFZPRpEoSDQ== X-Developer-Key: i=keescook@chromium.org; a=openpgp; fpr=A5C3F68F229DD60F723E6E138972F4DFDC6DC026 Precedence: bulk List-ID: X-Mailing-List: linux-hardening@vger.kernel.org In preparation for replacing __builtin_object_size() with __builtin_dynamic_object_size(), all the compile-time size checks need to check that the bounds variables are, in fact, known at compile-time. Enforce what was guaranteed with __bos(). In other words, since all uses of __bos() were constant expressions, it was not required to test for this. When these change to __bdos(), they _may_ be constant expressions, and the checks are only valid when the prior condition holds. This results in no binary differences. Signed-off-by: Kees Cook --- include/linux/fortify-string.h | 50 +++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/include/linux/fortify-string.h b/include/linux/fortify-string.h index ff879efe94ed..71c0a432c638 100644 --- a/include/linux/fortify-string.h +++ b/include/linux/fortify-string.h @@ -80,6 +80,12 @@ extern char *__underlying_strncpy(char *p, const char *q, __kernel_size_t size) #define POS __pass_object_size(1) #define POS0 __pass_object_size(0) +#define __compiletime_lessthan(bounds, length) ( \ + __builtin_constant_p(length) && \ + __builtin_constant_p(bounds) && \ + bounds < length \ +) + /** * strncpy - Copy a string to memory with non-guaranteed NUL padding * @@ -117,7 +123,7 @@ char *strncpy(char * const POS p, const char *q, __kernel_size_t size) { size_t p_size = __builtin_object_size(p, 1); - if (__builtin_constant_p(size) && p_size < size) + if (__compiletime_lessthan(p_size, size)) __write_overflow(); if (p_size < size) fortify_panic(__func__); @@ -224,7 +230,7 @@ __FORTIFY_INLINE ssize_t strscpy(char * const POS p, const char * const POS q, s * 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) + if (__compiletime_lessthan(p_size, size)) __write_overflow(); /* @@ -281,15 +287,16 @@ __FORTIFY_INLINE void fortify_memset_chk(__kernel_size_t size, /* * Length argument is a constant expression, so we * can perform compile-time bounds checking where - * buffer sizes are known. + * buffer sizes are also known at compile time. */ /* Error when size is larger than enclosing struct. */ - if (p_size > p_size_field && p_size < size) + if (__compiletime_lessthan(p_size_field, p_size) && + __compiletime_lessthan(p_size, size)) __write_overflow(); /* Warn when write size is larger than dest field. */ - if (p_size_field < size) + if (__compiletime_lessthan(p_size_field, size)) __write_overflow_field(p_size_field, size); } /* @@ -365,25 +372,28 @@ __FORTIFY_INLINE bool fortify_memcpy_chk(__kernel_size_t size, /* * Length argument is a constant expression, so we * can perform compile-time bounds checking where - * buffer sizes are known. + * buffer sizes are also known at compile time. */ /* Error when size is larger than enclosing struct. */ - if (p_size > p_size_field && p_size < size) + if (__compiletime_lessthan(p_size_field, p_size) && + __compiletime_lessthan(p_size, size)) __write_overflow(); - if (q_size > q_size_field && q_size < size) + if (__compiletime_lessthan(q_size_field, q_size) && + __compiletime_lessthan(q_size, size)) __read_overflow2(); /* Warn when write size argument larger than dest field. */ - if (p_size_field < size) + if (__compiletime_lessthan(p_size_field, size)) __write_overflow_field(p_size_field, size); /* * Warn for source field over-read when building with W=1 * or when an over-write happened, so both can be fixed at * the same time. */ - if ((IS_ENABLED(KBUILD_EXTRA_WARN1) || p_size_field < size) && - q_size_field < size) + if ((IS_ENABLED(KBUILD_EXTRA_WARN1) || + __compiletime_lessthan(p_size_field, size)) && + __compiletime_lessthan(q_size_field, size)) __read_overflow2_field(q_size_field, size); } /* @@ -494,7 +504,7 @@ __FORTIFY_INLINE void *memscan(void * const POS0 p, int c, __kernel_size_t size) { size_t p_size = __builtin_object_size(p, 0); - if (__builtin_constant_p(size) && p_size < size) + if (__compiletime_lessthan(p_size, size)) __read_overflow(); if (p_size < size) fortify_panic(__func__); @@ -508,9 +518,9 @@ int memcmp(const void * const POS0 p, const void * const POS0 q, __kernel_size_t size_t q_size = __builtin_object_size(q, 0); if (__builtin_constant_p(size)) { - if (p_size < size) + if (__compiletime_lessthan(p_size, size)) __read_overflow(); - if (q_size < size) + if (__compiletime_lessthan(q_size, size)) __read_overflow2(); } if (p_size < size || q_size < size) @@ -523,7 +533,7 @@ void *memchr(const void * const POS0 p, int c, __kernel_size_t size) { size_t p_size = __builtin_object_size(p, 0); - if (__builtin_constant_p(size) && p_size < size) + if (__compiletime_lessthan(p_size, size)) __read_overflow(); if (p_size < size) fortify_panic(__func__); @@ -535,7 +545,7 @@ __FORTIFY_INLINE void *memchr_inv(const void * const POS0 p, int c, size_t size) { size_t p_size = __builtin_object_size(p, 0); - if (__builtin_constant_p(size) && p_size < size) + if (__compiletime_lessthan(p_size, size)) __read_overflow(); if (p_size < size) fortify_panic(__func__); @@ -547,7 +557,7 @@ __FORTIFY_INLINE void *kmemdup(const void * const POS0 p, size_t size, gfp_t gfp { size_t p_size = __builtin_object_size(p, 0); - if (__builtin_constant_p(size) && p_size < size) + if (__compiletime_lessthan(p_size, size)) __read_overflow(); if (p_size < size) fortify_panic(__func__); @@ -563,11 +573,13 @@ char *strcpy(char * const POS p, const char * const POS q) size_t size; /* If neither buffer size is known, immediately give up. */ - if (p_size == SIZE_MAX && q_size == SIZE_MAX) + if (__builtin_constant_p(p_size) && + __builtin_constant_p(q_size) && + p_size == SIZE_MAX && q_size == SIZE_MAX) return __underlying_strcpy(p, q); size = strlen(q) + 1; /* Compile-time check for const size overflow. */ - if (__builtin_constant_p(size) && p_size < size) + if (__compiletime_lessthan(p_size, size)) __write_overflow(); /* Run-time check for dynamic size overflow. */ if (p_size < size) From patchwork Tue Sep 20 19:22:01 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 12982525 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7CBF2C54EE9 for ; Tue, 20 Sep 2022 19:22:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231225AbiITTWP (ORCPT ); Tue, 20 Sep 2022 15:22:15 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37442 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231258AbiITTWN (ORCPT ); Tue, 20 Sep 2022 15:22:13 -0400 Received: from mail-pj1-x102f.google.com (mail-pj1-x102f.google.com [IPv6:2607:f8b0:4864:20::102f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5A5C1286E7 for ; Tue, 20 Sep 2022 12:22:12 -0700 (PDT) Received: by mail-pj1-x102f.google.com with SMTP id q9-20020a17090a178900b0020265d92ae3so11815487pja.5 for ; Tue, 20 Sep 2022 12:22:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date; bh=b7FvkRf/XameI3tAxI0qKDnPDgul0cfpqZiW5Ih+TfY=; b=G0yzd3YQmRHSm8hygGaJN23uIfHcIPVonGOjkqyNWhgM4CENWufgxK3rc2ksXWFaq5 W1pvS4BzvsxlUiZWzbHjFUgvT7hopNCjL7/IfebtaUkJyqFyjRtP+IPnqn4y0na+dKs7 J0wWa6WM4Qv2DbhPAozS3qg50xwRRqP+oeG5E= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date; bh=b7FvkRf/XameI3tAxI0qKDnPDgul0cfpqZiW5Ih+TfY=; b=GiCJ2y+FgCyT0tDBr6c/d6bKxfBwP19vu9beRy2wQ7qSBEBotAzrnlB9vt1A50Dc8l 2bcXZAxUfKOP6KyFB4a3M8DljL8FnboCCQdRdzW+U9gIkV5NqK19AT3bVREs3BX+921R w+bADSdTfFxqVvQv4b/UdBvWRyKxG1lV0+dDmB7TLRVHaxJrNd5SOZ2h29Vr6+1LV1he pub8OIbYjAd67VBXJOVxdzjgoCK7T17ehXI0iQwsXScJiYIXLfBV02bh5edkdMaL+Plq KsvrouheCMf+eTxkh9x6au5HS+xj1ZU6nEyrz/gHQ6apgNIUTUjopvfeOW4sNlPgbEJH BPqg== X-Gm-Message-State: ACrzQf1L8wp33dgBKu52fCAh0CK07F5Ed8nANhaEsIPsx1qm45R0Yo39 9YwUZWrZ5IFK/doq/BDJ+PG9xg== X-Google-Smtp-Source: AMsMyM4MlWS2VfZxaUxG/J/yjFdlpSdd1ttEqoJXydSzcYurOBNsEyN3/lJvRpJhe6BzL1xIb54Ykg== X-Received: by 2002:a17:902:dac7:b0:178:b5e0:3627 with SMTP id q7-20020a170902dac700b00178b5e03627mr1050536plx.147.1663701732000; Tue, 20 Sep 2022 12:22:12 -0700 (PDT) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id d10-20020a170902ceca00b0017732e4003bsm262226plg.141.2022.09.20.12.22.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 Sep 2022 12:22:08 -0700 (PDT) From: Kees Cook To: linux-hardening@vger.kernel.org Cc: Kees Cook , Nathan Chancellor , Nick Desaulniers , Tom Rix , llvm@lists.linux.dev, Siddhesh Poyarekar , Arnd Bergmann , Juergen Gross , Boris Ostrovsky , Miguel Ojeda , linux-kernel@vger.kernel.org Subject: [PATCH 3/4] fortify: Convert to struct vs member helpers Date: Tue, 20 Sep 2022 12:22:01 -0700 Message-Id: <20220920192202.190793-4-keescook@chromium.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220920192202.190793-1-keescook@chromium.org> References: <20220920192202.190793-1-keescook@chromium.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=9864; h=from:subject; bh=BqQbiGaquIsbcMOqf8A6fSRC6Vfu8ZKyxxnc+qe3hgU=; b=owEBbQKS/ZANAwAKAYly9N/cbcAmAcsmYgBjKhLZ0Oxez6IX/gcUwsIFv3+tMCVKvwgPQj27qPt8 VXbpHlqJAjMEAAEKAB0WIQSlw/aPIp3WD3I+bhOJcvTf3G3AJgUCYyoS2QAKCRCJcvTf3G3AJkDdD/ 4q2zvDS9l/L4s2sAzrxtBwCZUnHjkBHzcdbXLIMLWrIepT/FQAM3Kk2z7w84mjlNBeiW0infuj23MH o1u1RPvNkHf9A/+vRJfGs21mJA+0+Fav4YMboXMqbp1hpIx9YxW9JJ7dJrkRGNpfLXY8n8t3jCRi7n FEUyBKp81hcgHgWxILxQ8mIqLf75AZxwCUyrTAcu8LyNbCR9O+buVloQ8tKdiGsET+3CYTF5KbLYhb PJeWtRKVBFO8QAOIWoWwkdCTn0mgfIKMzevZ3SZd7vuIF28ExS9VX9Oh+BSrYWN5SKR2+5VFypcVyM ln6dH04dg2abuCq7Dvft9pCN2OjVZZjmMU3qoVx69WaD4hViFuGBRXfS+PUAUtWOHwNPlrHkedlukV KkHl1OLS0ueDpoNZ2MkiKtuKGyxPs3lwC06Tp/uPgdzmCJbdwQzzS2MoZx3bXLRcfvr7jhUJmtSrD0 CpwYhQzocUF7Qz0exEUjIgOZwzkx/BgRoMxGD8aftpAzOCjXb95k3wQJDgSIspogue2cLDWwg1EP28 o9opm3tYeLVcIM89XXxu1rGM0jA8ZkfQAdK3ZFmCaB93ai7/BZOAdlB+ElB/7qtXaUgLZpaKmV0XBj wSrPBqjrKEijV2hEVqi7xjlhTwUdHp9HrHTrE7G1vvC0P0Q3TTyMo/sDet/A== X-Developer-Key: i=keescook@chromium.org; a=openpgp; fpr=A5C3F68F229DD60F723E6E138972F4DFDC6DC026 Precedence: bulk List-ID: X-Mailing-List: linux-hardening@vger.kernel.org In preparation for adding support for __builtin_dynamic_object_size(), wrap each instance of __builtin_object_size(p, N) with either the new __struct_size(p) as __bos(p, 0), or __member_size(p) as __bos(p, 1). This will allow us to replace the definitions with __bdos() next. There are no binary differences from this change. Cc: Nathan Chancellor Cc: Nick Desaulniers Cc: Tom Rix Cc: linux-hardening@vger.kernel.org Cc: llvm@lists.linux.dev Signed-off-by: Kees Cook --- include/linux/fortify-string.h | 68 +++++++++++++++++----------------- 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/include/linux/fortify-string.h b/include/linux/fortify-string.h index 71c0a432c638..3f1178584d7b 100644 --- a/include/linux/fortify-string.h +++ b/include/linux/fortify-string.h @@ -20,7 +20,7 @@ void __write_overflow_field(size_t avail, size_t wanted) __compiletime_warning(" ({ \ unsigned char *__p = (unsigned char *)(p); \ size_t __ret = SIZE_MAX; \ - size_t __p_size = __builtin_object_size(p, 1); \ + size_t __p_size = __member_size(p); \ if (__p_size != SIZE_MAX && \ __builtin_constant_p(*__p)) { \ size_t __p_len = __p_size - 1; \ @@ -72,13 +72,15 @@ extern char *__underlying_strncpy(char *p, const char *q, __kernel_size_t size) __underlying_memcpy(dst, src, bytes) /* - * Clang's use of __builtin_object_size() within inlines needs hinting via - * __pass_object_size(). The preference is to only ever use type 1 (member + * Clang's use of __builtin_*object_size() within inlines needs hinting via + * __pass_*object_size(). The preference is to only ever use type 1 (member * size, rather than struct size), but there remain some stragglers using * type 0 that will be converted in the future. */ -#define POS __pass_object_size(1) -#define POS0 __pass_object_size(0) +#define POS __pass_object_size(1) +#define POS0 __pass_object_size(0) +#define __struct_size(p) __builtin_object_size(p, 0) +#define __member_size(p) __builtin_object_size(p, 1) #define __compiletime_lessthan(bounds, length) ( \ __builtin_constant_p(length) && \ @@ -121,7 +123,7 @@ extern char *__underlying_strncpy(char *p, const char *q, __kernel_size_t size) __FORTIFY_INLINE __diagnose_as(__builtin_strncpy, 1, 2, 3) char *strncpy(char * const POS p, const char *q, __kernel_size_t size) { - size_t p_size = __builtin_object_size(p, 1); + size_t p_size = __member_size(p); if (__compiletime_lessthan(p_size, size)) __write_overflow(); @@ -133,7 +135,7 @@ char *strncpy(char * const POS p, const char *q, __kernel_size_t size) __FORTIFY_INLINE __diagnose_as(__builtin_strcat, 1, 2) char *strcat(char * const POS p, const char *q) { - size_t p_size = __builtin_object_size(p, 1); + size_t p_size = __member_size(p); if (p_size == SIZE_MAX) return __underlying_strcat(p, q); @@ -145,7 +147,7 @@ char *strcat(char * const POS 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 * const POS p, __kernel_size_t maxlen) { - size_t p_size = __builtin_object_size(p, 1); + size_t p_size = __member_size(p); size_t p_len = __compiletime_strlen(p); size_t ret; @@ -175,7 +177,7 @@ __FORTIFY_INLINE __diagnose_as(__builtin_strlen, 1) __kernel_size_t __fortify_strlen(const char * const POS p) { __kernel_size_t ret; - size_t p_size = __builtin_object_size(p, 1); + size_t p_size = __member_size(p); /* Give up if we don't know how large p is. */ if (p_size == SIZE_MAX) @@ -190,8 +192,8 @@ __kernel_size_t __fortify_strlen(const char * const POS p) extern size_t __real_strlcpy(char *, const char *, size_t) __RENAME(strlcpy); __FORTIFY_INLINE size_t strlcpy(char * const POS p, const char * const POS q, size_t size) { - size_t p_size = __builtin_object_size(p, 1); - size_t q_size = __builtin_object_size(q, 1); + size_t p_size = __member_size(p); + size_t q_size = __member_size(q); size_t q_len; /* Full count of source string length. */ size_t len; /* Count of characters going into destination. */ @@ -219,8 +221,8 @@ __FORTIFY_INLINE ssize_t strscpy(char * const POS p, const char * const POS q, s { 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); + size_t p_size = __member_size(p); + size_t q_size = __member_size(q); /* If we cannot get size of p and q default to call strscpy. */ if (p_size == SIZE_MAX && q_size == SIZE_MAX) @@ -265,8 +267,8 @@ __FORTIFY_INLINE __diagnose_as(__builtin_strncat, 1, 2, 3) char *strncat(char * const POS p, const char * const POS q, __kernel_size_t count) { size_t p_len, copy_len; - size_t p_size = __builtin_object_size(p, 1); - size_t q_size = __builtin_object_size(q, 1); + size_t p_size = __member_size(p); + size_t q_size = __member_size(q); if (p_size == SIZE_MAX && q_size == SIZE_MAX) return __underlying_strncat(p, q, count); @@ -324,11 +326,11 @@ __FORTIFY_INLINE void fortify_memset_chk(__kernel_size_t size, }) /* - * __builtin_object_size() must be captured here to avoid evaluating argument - * side-effects further into the macro layers. + * __struct_size() vs __member_size() must be captured here to avoid + * evaluating argument side-effects further into the macro layers. */ #define memset(p, c, s) __fortify_memset_chk(p, c, s, \ - __builtin_object_size(p, 0), __builtin_object_size(p, 1)) + __struct_size(p), __member_size(p)) /* * To make sure the compiler can enforce protection against buffer overflows, @@ -421,7 +423,7 @@ __FORTIFY_INLINE bool fortify_memcpy_chk(__kernel_size_t size, * fake flexible arrays, until they are all converted to * proper flexible arrays. * - * The implementation of __builtin_object_size() behaves + * The implementation of __builtin_*object_size() behaves * like sizeof() when not directly referencing a flexible * array member, which means there will be many bounds checks * that will appear at run-time, without a way for them to be @@ -487,22 +489,22 @@ __FORTIFY_INLINE bool fortify_memcpy_chk(__kernel_size_t size, */ /* - * __builtin_object_size() must be captured here to avoid evaluating argument - * side-effects further into the macro layers. + * __struct_size() vs __member_size() must be captured here to avoid + * evaluating argument side-effects further into the macro layers. */ #define memcpy(p, q, s) __fortify_memcpy_chk(p, q, s, \ - __builtin_object_size(p, 0), __builtin_object_size(q, 0), \ - __builtin_object_size(p, 1), __builtin_object_size(q, 1), \ + __struct_size(p), __struct_size(q), \ + __member_size(p), __member_size(q), \ memcpy) #define memmove(p, q, s) __fortify_memcpy_chk(p, q, s, \ - __builtin_object_size(p, 0), __builtin_object_size(q, 0), \ - __builtin_object_size(p, 1), __builtin_object_size(q, 1), \ + __struct_size(p), __struct_size(q), \ + __member_size(p), __member_size(q), \ memmove) extern void *__real_memscan(void *, int, __kernel_size_t) __RENAME(memscan); __FORTIFY_INLINE void *memscan(void * const POS0 p, int c, __kernel_size_t size) { - size_t p_size = __builtin_object_size(p, 0); + size_t p_size = __struct_size(p); if (__compiletime_lessthan(p_size, size)) __read_overflow(); @@ -514,8 +516,8 @@ __FORTIFY_INLINE void *memscan(void * const POS0 p, int c, __kernel_size_t size) __FORTIFY_INLINE __diagnose_as(__builtin_memcmp, 1, 2, 3) int memcmp(const void * const POS0 p, const void * const POS0 q, __kernel_size_t size) { - size_t p_size = __builtin_object_size(p, 0); - size_t q_size = __builtin_object_size(q, 0); + size_t p_size = __struct_size(p); + size_t q_size = __struct_size(q); if (__builtin_constant_p(size)) { if (__compiletime_lessthan(p_size, size)) @@ -531,7 +533,7 @@ int memcmp(const void * const POS0 p, const void * const POS0 q, __kernel_size_t __FORTIFY_INLINE __diagnose_as(__builtin_memchr, 1, 2, 3) void *memchr(const void * const POS0 p, int c, __kernel_size_t size) { - size_t p_size = __builtin_object_size(p, 0); + size_t p_size = __struct_size(p); if (__compiletime_lessthan(p_size, size)) __read_overflow(); @@ -543,7 +545,7 @@ void *memchr(const void * const POS0 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 * const POS0 p, int c, size_t size) { - size_t p_size = __builtin_object_size(p, 0); + size_t p_size = __struct_size(p); if (__compiletime_lessthan(p_size, size)) __read_overflow(); @@ -555,7 +557,7 @@ __FORTIFY_INLINE void *memchr_inv(const void * const POS0 p, int c, size_t size) extern void *__real_kmemdup(const void *src, size_t len, gfp_t gfp) __RENAME(kmemdup); __FORTIFY_INLINE void *kmemdup(const void * const POS0 p, size_t size, gfp_t gfp) { - size_t p_size = __builtin_object_size(p, 0); + size_t p_size = __struct_size(p); if (__compiletime_lessthan(p_size, size)) __read_overflow(); @@ -568,8 +570,8 @@ __FORTIFY_INLINE void *kmemdup(const void * const POS0 p, size_t size, gfp_t gfp __FORTIFY_INLINE __diagnose_as(__builtin_strcpy, 1, 2) char *strcpy(char * const POS p, const char * const POS q) { - size_t p_size = __builtin_object_size(p, 1); - size_t q_size = __builtin_object_size(q, 1); + size_t p_size = __member_size(p); + size_t q_size = __member_size(q); size_t size; /* If neither buffer size is known, immediately give up. */ From patchwork Tue Sep 20 19:22:02 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 12982524 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E6EA8C6FA92 for ; Tue, 20 Sep 2022 19:22:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231258AbiITTWQ (ORCPT ); Tue, 20 Sep 2022 15:22:16 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37444 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231266AbiITTWN (ORCPT ); Tue, 20 Sep 2022 15:22:13 -0400 Received: from mail-pl1-x630.google.com (mail-pl1-x630.google.com [IPv6:2607:f8b0:4864:20::630]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D4D262CCBB for ; Tue, 20 Sep 2022 12:22:12 -0700 (PDT) Received: by mail-pl1-x630.google.com with SMTP id b21so3384473plz.7 for ; Tue, 20 Sep 2022 12:22:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date; bh=1o1LGpQmDlpzu7Ike/ReIwaogbPO4zuoRH4aws7NQKw=; b=FXsWBJaEckAPDyoDiTuGCNmqPBDHU8OmeUYXqYEhHzpmgSVzhU9z/lEgbkR1kaUI6B pky8QUt2XZ7fpm7bVNYPfwkdR+NnTkqxrOFMRrhG0USUZJIluHryxIkbCc5bM1a2+KcF yKvv2CblYRVdr6M/Ht3buy67ScvtSCu7ccOx4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date; bh=1o1LGpQmDlpzu7Ike/ReIwaogbPO4zuoRH4aws7NQKw=; b=borYkiA3yfX0hzCACpP/62ThRl1q4E5mlcHl+fFqW+fNak4URu8EOgORChK/5qCUAD kPHeK5rQqA+Y4xcS5eXkESDN3v7kEArSJT7mMpFlOzaF9ZrV8Zag5FFwyFoLV1j8DSTq UmbSEz9I87IkIAoZ2zGGUD6rS4f5LT1JiJ5bg4y6nyfqKmGQL5svLRUB244nyreMK5Qn mmTnCXjqJ3thgyOOgrPLsqUQYa8o3VL9g0O4IdCN19j4WZ5Yi2sCv8XHQKUXNy20pMmt ONFyBSxYBQWwTbRtY9z1kqXffmkmj/oZR6HQBmTAx6irPC/F1WMAlWHx+s9YjLyvlgK0 W6KA== X-Gm-Message-State: ACrzQf2wAACN1IL1meQJD7bbgQUcfKV7b6AFS9xklUt8wTvA2/kIis5T Foz9gPC9q9ODNDv+6lv6Uw9enw== X-Google-Smtp-Source: AMsMyM5cGE6yDYaNnkOQI2S/AY/raVeY3MQmtPRCA7w7Y1F/Hp50JUsxZyNnn8zkQ8BUw5iA6TjTdQ== X-Received: by 2002:a17:90b:1b0a:b0:203:3947:1a73 with SMTP id nu10-20020a17090b1b0a00b0020339471a73mr5502968pjb.43.1663701732553; Tue, 20 Sep 2022 12:22:12 -0700 (PDT) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id g6-20020aa79dc6000000b00540b3be3bf6sm241957pfq.196.2022.09.20.12.22.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 Sep 2022 12:22:08 -0700 (PDT) From: Kees Cook To: linux-hardening@vger.kernel.org Cc: Kees Cook , Miguel Ojeda , Siddhesh Poyarekar , Arnd Bergmann , Nick Desaulniers , Nathan Chancellor , Tom Rix , llvm@lists.linux.dev, Juergen Gross , Boris Ostrovsky , linux-kernel@vger.kernel.org Subject: [PATCH 4/4] fortify: Use __builtin_dynamic_object_size() when available Date: Tue, 20 Sep 2022 12:22:02 -0700 Message-Id: <20220920192202.190793-5-keescook@chromium.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220920192202.190793-1-keescook@chromium.org> References: <20220920192202.190793-1-keescook@chromium.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=3540; h=from:subject; bh=SuFYab5ne2I0fynfIO4bCDx/ZuEkBNyDkYK1dq1mYyM=; b=owEBbQKS/ZANAwAKAYly9N/cbcAmAcsmYgBjKhLZYIErDe7TJDRHJVXzahhQK/yb2r2Hf0BSFlIk 1TRe4CGJAjMEAAEKAB0WIQSlw/aPIp3WD3I+bhOJcvTf3G3AJgUCYyoS2QAKCRCJcvTf3G3AJv/FEA Czrw6b87vzPgCg7ACdCSxIWAVzP/trBSumyV4j+mMLwNorFE6sFmGa1LuJ6nJ9vUo8EDqahBZ9CDBv CCFp8MECNgOMcPu/f9UeJe5xWlEhzXx50YVKLlo7VRhI8qaTjuwPStnIPCMhNAq5rUTrhFgzZ6TRNj OgfUKDOAKj66fCR9ZZF5XOrZ6L6jqb+s3UKC7cRRxMly4pF5kpDIWS5rDy8HCb62zZEpRWfx5keU+c wKIblI52S1m4B92gAPSzTovz30UDFmQ4h77kqjrD8IGfuxtaLDGCXoUdVjKB1MZt6aA2TmCffYyif3 r75kl/VnrhA8BgG2hSaLao8eLp5NVSB05oeoRAtH3Ihg1oD3Prs2u+TfZlAxa/tAqS+NUbEp2tr48c zWUXBJXPA6CBD+InglqErOPIokC1bYUX4B8zrszOm04+MWWFVwHHNyAQ81LXctDwofckcu/XDFOYVg zWXa9fVrGWo3xzHFwXi6s2wmVGfwoHO82cH+ZIk/Z73l+so0GgscIkOaRUt0T7PsgStttC0CCxYBYl JDjycZUlwUA7bGRdCcsWeiMYuUuplqYkIbj4spMC7TIhgRjE13n8QTklhFlA6cfQLyq+jXqw+jstdN +767zQnvbl3Litrhx7i4I4UpuOQxMl919VqKmJrB4aFHEaFW6iZpVe7aEffQ== X-Developer-Key: i=keescook@chromium.org; a=openpgp; fpr=A5C3F68F229DD60F723E6E138972F4DFDC6DC026 Precedence: bulk List-ID: X-Mailing-List: linux-hardening@vger.kernel.org Since the commits starting with c37495d6254c ("slab: add __alloc_size attributes for better bounds checking"), the compilers have runtime allocation size hints available in some places. This was immediately available to CONFIG_UBSAN_BOUNDS, but CONFIG_FORTIFY_SOURCE needed updating to explicitly make use the hints via the associated __builtin_dynamic_object_size() helper. Detect and use the builtin when it is available, increasing the accuracy of the mitigation. When runtime sizes are not available, __builtin_dynamic_object_size() falls back to __builtin_object_size(), leaving the existing bounds checking unchanged. Additionally update the VMALLOC_LINEAR_OVERFLOW LKDTM test to make the hint invisible, otherwise the architectural defense is not exercised (the buffer overflow is detected in the memset() rather than when it crosses the edge of the allocation). Cc: Miguel Ojeda Cc: Siddhesh Poyarekar Cc: Arnd Bergmann Cc: Nick Desaulniers Cc: Nathan Chancellor Cc: Tom Rix Cc: linux-hardening@vger.kernel.org Cc: llvm@lists.linux.dev Signed-off-by: Kees Cook Reviewed-by: Miguel Ojeda Reviewed-by: Siddhesh Poyarekar Tested-by: Niklas Cassel --- drivers/misc/lkdtm/heap.c | 1 + include/linux/compiler_attributes.h | 5 +++++ include/linux/fortify-string.h | 7 +++++++ 3 files changed, 13 insertions(+) diff --git a/drivers/misc/lkdtm/heap.c b/drivers/misc/lkdtm/heap.c index 62516078a619..0ce4cbf6abda 100644 --- a/drivers/misc/lkdtm/heap.c +++ b/drivers/misc/lkdtm/heap.c @@ -31,6 +31,7 @@ static void lkdtm_VMALLOC_LINEAR_OVERFLOW(void) char *one, *two; one = vzalloc(PAGE_SIZE); + OPTIMIZER_HIDE_VAR(one); two = vzalloc(PAGE_SIZE); pr_info("Attempting vmalloc linear overflow ...\n"); diff --git a/include/linux/compiler_attributes.h b/include/linux/compiler_attributes.h index 445e80517cab..9a9907fad6fd 100644 --- a/include/linux/compiler_attributes.h +++ b/include/linux/compiler_attributes.h @@ -296,6 +296,11 @@ * * clang: https://clang.llvm.org/docs/AttributeReference.html#pass-object-size-pass-dynamic-object-size */ +#if __has_attribute(__pass_dynamic_object_size__) +# define __pass_dynamic_object_size(type) __attribute__((__pass_dynamic_object_size__(type))) +#else +# define __pass_dynamic_object_size(type) +#endif #if __has_attribute(__pass_object_size__) # define __pass_object_size(type) __attribute__((__pass_object_size__(type))) #else diff --git a/include/linux/fortify-string.h b/include/linux/fortify-string.h index 3f1178584d7b..dd7f85d74ade 100644 --- a/include/linux/fortify-string.h +++ b/include/linux/fortify-string.h @@ -77,10 +77,17 @@ extern char *__underlying_strncpy(char *p, const char *q, __kernel_size_t size) * size, rather than struct size), but there remain some stragglers using * type 0 that will be converted in the future. */ +#if __has_builtin(__builtin_dynamic_object_size) +#define POS __pass_dynamic_object_size(1) +#define POS0 __pass_dynamic_object_size(0) +#define __struct_size(p) __builtin_dynamic_object_size(p, 0) +#define __member_size(p) __builtin_dynamic_object_size(p, 1) +#else #define POS __pass_object_size(1) #define POS0 __pass_object_size(0) #define __struct_size(p) __builtin_object_size(p, 0) #define __member_size(p) __builtin_object_size(p, 1) +#endif #define __compiletime_lessthan(bounds, length) ( \ __builtin_constant_p(length) && \