From mboxrd@z Thu Jan 1 00:00:00 1970 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 E67F5ECAAD5 for ; Mon, 12 Sep 2022 09:45:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229665AbiILJp5 (ORCPT ); Mon, 12 Sep 2022 05:45:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43022 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229616AbiILJpy (ORCPT ); Mon, 12 Sep 2022 05:45:54 -0400 Received: from mail-ed1-x54a.google.com (mail-ed1-x54a.google.com [IPv6:2a00:1450:4864:20::54a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 864A633438 for ; Mon, 12 Sep 2022 02:45:52 -0700 (PDT) Received: by mail-ed1-x54a.google.com with SMTP id i17-20020a05640242d100b0044f18a5379aso5826724edc.21 for ; Mon, 12 Sep 2022 02:45:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:mime-version:date:from:to:cc:subject :date; bh=jBoH9dZtU8u1abW3Qj3aDrAs7nz5caMLzMPJv+JY2CE=; b=MR5DigsBS0/ITOnUWHz7rgazRDEBSqjosdzYJAXuVO6gDRUXtNg9chMfS+KizD1tgT 9NaYvF1m/6aPRfa8q0xlZJcT7MFNTWJt/SK7OV5dCQEJyRr1taZhhd3hLeVb7dRd+rHb UGUKoKbJFmxiV2W/B6LtSwf4iwULzTbONwflcqTnChdS03U+IxEJ/yFcZ7dVJ7NnN4Gd d1pPqhxUY0oWLOmM1K3C76rAD19FozAhJvuGY7E4b0idk28B42yT/GrEy+1W15xnFWdW 0uwCqdrVJ2BrFjX0Gypno+SDEw850aI/+OeTLYWq/BCXtDetEIgN54LDioLlIM3kfgpT MfYg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:mime-version:date:x-gm-message-state :from:to:cc:subject:date; bh=jBoH9dZtU8u1abW3Qj3aDrAs7nz5caMLzMPJv+JY2CE=; b=vQbzpaC6tXg4ZqZVd9pHDr2TMJQm8Ape3uJldZQAwNJtwLI5BJakrtTgsQgXpzPTVA ZqjC0tS9WvL0Hww23OMLL26EcjqZ4EG8sa7KTBbA6CMtRtrOIq83rguSzIsmdkZP1C0W PUz+KgpWk2h5LfnyFWGy0FmSFqwHAxlpPvBFWODtmfT8e8g7fDSRCBQgbHCBytQuJ0DR s/Q9XqXJ+5G6UFpBccw44vaCJu5ZfL1/Z2oXaE1Ucb5mU2zAYw3YAQ1vyG3Aa+wG0sxZ JXcK7nnyBq+aWtTQLaQ107p6kAVeKJADhzMxIw2dARLnw35TfRvipbEn6jTixKRYS/Sz 9bkQ== X-Gm-Message-State: ACgBeo249g/CRR6Mlmn6TqUlGro2YZo4JT6qsWhcxdEPTufxhdepoPIn 83ASPX5jfUxxgXEbFEtOH69+7OWFhQ== X-Google-Smtp-Source: AA6agR5+oeruIkBj1HE2zrvAygBUxfE3HyDxczIWzvFPZx3yXg43HU2XyG1ItaJyA72oGU8vzG5byHrq1g== X-Received: from elver.muc.corp.google.com ([2a00:79e0:9c:201:f693:9fff:fef4:2449]) (user=elver job=sendgmr) by 2002:a05:6402:5002:b0:444:26fd:d341 with SMTP id p2-20020a056402500200b0044426fdd341mr21825632eda.351.1662975950998; Mon, 12 Sep 2022 02:45:50 -0700 (PDT) Date: Mon, 12 Sep 2022 11:45:40 +0200 Mime-Version: 1.0 X-Mailer: git-send-email 2.37.2.789.g6183377224-goog Message-ID: <20220912094541.929856-1-elver@google.com> Subject: [PATCH v3 1/2] kcsan: Instrument memcpy/memset/memmove with newer Clang From: Marco Elver To: elver@google.com, "Paul E. McKenney" Cc: Mark Rutland , Dmitry Vyukov , Alexander Potapenko , Boqun Feng , kasan-dev@googlegroups.com, linux-kernel@vger.kernel.org, Nathan Chancellor , Nick Desaulniers , llvm@lists.linux.dev, Josh Poimboeuf , Peter Zijlstra , stable@vger.kernel.org Content-Type: text/plain; charset="UTF-8" Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org With Clang version 16+, -fsanitize=thread will turn memcpy/memset/memmove calls in instrumented functions into __tsan_memcpy/__tsan_memset/__tsan_memmove calls respectively. Add these functions to the core KCSAN runtime, so that we (a) catch data races with mem* functions, and (b) won't run into linker errors with such newer compilers. Cc: stable@vger.kernel.org # v5.10+ Signed-off-by: Marco Elver --- v3: * Truncate sizes larger than MAX_ENCODABLE_SIZE, so we still set up watchpoints on them. Iterating through MAX_ENCODABLE_SIZE blocks may result in pathological cases where performance would seriously suffer. So let's avoid that for now. * Just use memcpy/memset/memmove instead of __mem*() functions. Many architectures that already support KCSAN don't define them (mips, s390), and having both __mem* and mem versions of the functions provides little benefit elsewhere; and backporting would become more difficult, too. The compiler should not inline them given all parameters are non-constants here. v2: * Fix for architectures which do not provide their own memcpy/memset/memmove and instead use the generic versions in lib/string. In this case we'll just alias the __tsan_ variants. --- kernel/kcsan/core.c | 50 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/kernel/kcsan/core.c b/kernel/kcsan/core.c index fe12dfe254ec..54d077e1a2dc 100644 --- a/kernel/kcsan/core.c +++ b/kernel/kcsan/core.c @@ -14,10 +14,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include "encoding.h" @@ -1308,3 +1310,51 @@ noinline void __tsan_atomic_signal_fence(int memorder) } } EXPORT_SYMBOL(__tsan_atomic_signal_fence); + +#ifdef __HAVE_ARCH_MEMSET +void *__tsan_memset(void *s, int c, size_t count); +noinline void *__tsan_memset(void *s, int c, size_t count) +{ + /* + * Instead of not setting up watchpoints where accessed size is greater + * than MAX_ENCODABLE_SIZE, truncate checked size to MAX_ENCODABLE_SIZE. + */ + size_t check_len = min_t(size_t, count, MAX_ENCODABLE_SIZE); + + check_access(s, check_len, KCSAN_ACCESS_WRITE, _RET_IP_); + return memset(s, c, count); +} +#else +void *__tsan_memset(void *s, int c, size_t count) __alias(memset); +#endif +EXPORT_SYMBOL(__tsan_memset); + +#ifdef __HAVE_ARCH_MEMMOVE +void *__tsan_memmove(void *dst, const void *src, size_t len); +noinline void *__tsan_memmove(void *dst, const void *src, size_t len) +{ + size_t check_len = min_t(size_t, len, MAX_ENCODABLE_SIZE); + + check_access(dst, check_len, KCSAN_ACCESS_WRITE, _RET_IP_); + check_access(src, check_len, 0, _RET_IP_); + return memmove(dst, src, len); +} +#else +void *__tsan_memmove(void *dst, const void *src, size_t len) __alias(memmove); +#endif +EXPORT_SYMBOL(__tsan_memmove); + +#ifdef __HAVE_ARCH_MEMCPY +void *__tsan_memcpy(void *dst, const void *src, size_t len); +noinline void *__tsan_memcpy(void *dst, const void *src, size_t len) +{ + size_t check_len = min_t(size_t, len, MAX_ENCODABLE_SIZE); + + check_access(dst, check_len, KCSAN_ACCESS_WRITE, _RET_IP_); + check_access(src, check_len, 0, _RET_IP_); + return memcpy(dst, src, len); +} +#else +void *__tsan_memcpy(void *dst, const void *src, size_t len) __alias(memcpy); +#endif +EXPORT_SYMBOL(__tsan_memcpy); -- 2.37.2.789.g6183377224-goog