From patchwork Sun Feb 27 18:45:11 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 12762083 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 9CBBAC433EF for ; Sun, 27 Feb 2022 18:45:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231228AbiB0SqI (ORCPT ); Sun, 27 Feb 2022 13:46:08 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53006 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231197AbiB0SqE (ORCPT ); Sun, 27 Feb 2022 13:46:04 -0500 Received: from mail-pj1-x102d.google.com (mail-pj1-x102d.google.com [IPv6:2607:f8b0:4864:20::102d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B31B228E29 for ; Sun, 27 Feb 2022 10:45:22 -0800 (PST) Received: by mail-pj1-x102d.google.com with SMTP id v5-20020a17090ac90500b001bc40b548f9so12895287pjt.0 for ; Sun, 27 Feb 2022 10:45:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=rtQJ6+HWuDHNtXviDEv3CrUYrjsryDE8pWmriGiESg0=; b=m2E7Mkc5+O/hSN+7zDdRObC+NbGDn8KfETTWlSmuj/vdJqDtWt/86czuCbSuNxGYsA 1Y8x9mmgL+ELb5DPf58L2FnoGs1NDCSPpYG1XAYvTOFZMvu4Tjtd1dL3M+2Uzub2AVmJ mxFjyzhIpbnoLtl+uqKjMt1eDPuGbpgQO/92Y= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=rtQJ6+HWuDHNtXviDEv3CrUYrjsryDE8pWmriGiESg0=; b=dy1NYDMEnIxDMQcZ2hhl8428TmAUb+qw79T4mu5W8C54fwfgHKxPqPEhufJnhEnleM GFatK0Bd+qea3VtRKSWKh7O9P/0sBQjgU9sI/wHeAm5wN8t/FmqR/rd5El1zBXOAgGCP ZBBuQ/N4TNkhdxL7HeGtLIaK4xp+4KkSQeIQeCUdNazWBC4I+O5wQvNilVDXZrXf1mbI cZ/3jO67H9ov4TmoCcXGvkmHzLjrWLCpbMOlPh5lhGRiUiSARi+g71XTaekQdjPf/iS1 556LdM2jVbx7FhiLx2aeEejGqYKZx7gP584bT840+7M9buMe3C/l578fK+gb5Nzcabur y2Qg== X-Gm-Message-State: AOAM530YGKdxN4cPfgK/qpXBozqmfWd9LuT2epH6wFOI/mleNB+0ysha /JgCqvj+8EV7KrxM36vjBymumg== X-Google-Smtp-Source: ABdhPJzVRRQGxF6e1NTngPEsB3I/EvTNRmSUfuQ6v7xj8PQt1X32lE1LoqLXaWLdGVbZluSQR3Vj5w== X-Received: by 2002:a17:90b:250f:b0:1bc:e520:91e6 with SMTP id ns15-20020a17090b250f00b001bce52091e6mr13355572pjb.43.1645987521825; Sun, 27 Feb 2022 10:45:21 -0800 (PST) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id q10-20020a056a00084a00b004f26d3f5d8fsm10450378pfk.25.2022.02.27.10.45.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 27 Feb 2022 10:45:21 -0800 (PST) From: Kees Cook To: Kees Cook Cc: "Gustavo A . R . Silva" , Nathan Chancellor , Nick Desaulniers , Rasmus Villemoes , Vitor Massaru Iha , Daniel Latypov , David Gow , Anton Ivanov , Jeff Dike , Richard Weinberger , Masahiro Yamada , Arnd Bergmann , linux-kernel@vger.kernel.org, linux-um@lists.infradead.org, linux-kbuild@vger.kernel.org, kunit-dev@googlegroups.com, llvm@lists.linux.dev, x86@kernel.org, linux-hardening@vger.kernel.org Subject: [PATCH v3 1/7] overflow: Provide constant expression struct_size Date: Sun, 27 Feb 2022 10:45:11 -0800 Message-Id: <20220227184517.504931-2-keescook@chromium.org> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220227184517.504931-1-keescook@chromium.org> References: <20220227184517.504931-1-keescook@chromium.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=5098; h=from:subject; bh=2kZK8Pa8mdtDR/Nqo/3Vk6gXcxnyZeRVGJOFKK5/Dm4=; b=owEBbQKS/ZANAwAKAYly9N/cbcAmAcsmYgBiG8a7FSbvVC74wmbAmC12ksTVuBzN9xRSIPC+WKU3 EO0+lGSJAjMEAAEKAB0WIQSlw/aPIp3WD3I+bhOJcvTf3G3AJgUCYhvGuwAKCRCJcvTf3G3AJksnD/ 9jFKmi/Ux9BHhxzZ2RpxelaewUNUU1aSHv57YDOG4L43fmRoLxzBROLz9OcWcP5/ejuFFtwfP5323z DZFpA+Ts0sy9zDjBAcP06aCVrZ0D5y/C1HsAUvPpk+yS2jUe50vXwu7X4wwMS//COr8VCW+aGk4dvG B9loTCNsEklQK46RkPdt0d/WAGj0xMnzHWyztM050GcaJUl4TSBtIeN+5BKRWOt045Npdnf3eCWXq5 24GX5UE5ts6sZKHIk4ywytyDoK+uftNnd8Ufbn8iG34ZO8/fbkf7WAilUNTQH/y1cfyx8qYSIDJ7eL ZqDZejMvx4eMGypzGXA4J2L+Isq+cRIXrbnFLxtUgJt9YvTRrfQdunOtMOTC2WmHAnEKzOs9jlymHB T+Vc4UxaWsdNIBMnhRu+nSHuG/JJK2iYBNxjlNh3xcFWcODPFhCJG4S93ANnr+fKRDE8kq9rAkOYna KxjcdpjVWN/jDTmLHOI3cXBRLG3AxPuwSNAvFKvnck0F8hRGoQDfqTXM10M3TLrNXL9tKJrEJ/eIuQ TT36kiajoi0oH2nbWk9ne714xn1lJ4NoqeFFDO05bz78F70Sb5SOe7nU5RN75Gdbpw18YhvTG6ojX6 cuKk1/+pWSBz29y7CCOHSd+MakbP+FqPYa4n7OorO435P4PZiQdZPAhov3Xw== X-Developer-Key: i=keescook@chromium.org; a=openpgp; fpr=A5C3F68F229DD60F723E6E138972F4DFDC6DC026 Precedence: bulk List-ID: X-Mailing-List: linux-hardening@vger.kernel.org There have been cases where struct_size() (or flex_array_size()) needs to be calculated for an initializer, which requires it be a constant expression. This is possible when the "count" argument is a constant expression, so provide this ability for the helpers. Cc: Gustavo A. R. Silva Cc: Nathan Chancellor Cc: Nick Desaulniers Cc: Rasmus Villemoes Signed-off-by: Kees Cook Reviewed-by: Gustavo A. R. Silva Tested-by: Gustavo A. R. Silva Link: https://lore.kernel.org/lkml/20220210010407.GA701603@embeddedor --- v1: https://lore.kernel.org/linux-hardening/20220210004326.776574-1-keescook@chromium.org v2: - fix broken self-test due to CE optimization --- include/linux/overflow.h | 10 +++++++--- lib/test_overflow.c | 26 +++++++++++++++++--------- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/include/linux/overflow.h b/include/linux/overflow.h index 59d7228104d0..f1221d11f8e5 100644 --- a/include/linux/overflow.h +++ b/include/linux/overflow.h @@ -4,6 +4,7 @@ #include #include +#include /* * We need to compute the minimum and maximum values representable in a given @@ -221,8 +222,9 @@ static inline size_t __must_check size_sub(size_t minuend, size_t subtrahend) * Return: number of bytes needed or SIZE_MAX on overflow. */ #define flex_array_size(p, member, count) \ - size_mul(count, \ - sizeof(*(p)->member) + __must_be_array((p)->member)) + __builtin_choose_expr(__is_constexpr(count), \ + (count) * sizeof(*(p)->member) + __must_be_array((p)->member), \ + size_mul(count, sizeof(*(p)->member) + __must_be_array((p)->member))) /** * struct_size() - Calculate size of structure with trailing flexible array. @@ -237,6 +239,8 @@ static inline size_t __must_check size_sub(size_t minuend, size_t subtrahend) * Return: number of bytes needed or SIZE_MAX on overflow. */ #define struct_size(p, member, count) \ - size_add(sizeof(*(p)), flex_array_size(p, member, count)) + __builtin_choose_expr(__is_constexpr(count), \ + sizeof(*(p)) + flex_array_size(p, member, count), \ + size_add(sizeof(*(p)), flex_array_size(p, member, count))) #endif /* __LINUX_OVERFLOW_H */ diff --git a/lib/test_overflow.c b/lib/test_overflow.c index 712fb2351c27..f6530fce799d 100644 --- a/lib/test_overflow.c +++ b/lib/test_overflow.c @@ -602,10 +602,18 @@ struct __test_flex_array { static int __init test_overflow_size_helpers(void) { + /* Make sure struct_size() can be used in a constant expression. */ + u8 ce_array[struct_size((struct __test_flex_array *)0, data, 55)]; struct __test_flex_array *obj; int count = 0; int err = 0; int var; + volatile int unconst = 0; + + /* Verify constant expression against runtime version. */ + var = 55; + OPTIMIZER_HIDE_VAR(var); + err |= sizeof(ce_array) != struct_size(obj, data, var); #define check_one_size_helper(expected, func, args...) ({ \ bool __failure = false; \ @@ -663,28 +671,28 @@ static int __init test_overflow_size_helpers(void) flex_array_size, obj, data, var++); err |= check_one_size_helper(5 * sizeof(*obj->data), flex_array_size, obj, data, var++); - err |= check_one_size_helper(0, flex_array_size, obj, data, 0); + err |= check_one_size_helper(0, flex_array_size, obj, data, 0 + unconst); err |= check_one_size_helper(sizeof(*obj->data), - flex_array_size, obj, data, 1); + flex_array_size, obj, data, 1 + unconst); err |= check_one_size_helper(7 * sizeof(*obj->data), - flex_array_size, obj, data, 7); + flex_array_size, obj, data, 7 + unconst); err |= check_one_size_helper(SIZE_MAX, - flex_array_size, obj, data, -1); + flex_array_size, obj, data, -1 + unconst); err |= check_one_size_helper(SIZE_MAX, - flex_array_size, obj, data, SIZE_MAX - 4); + flex_array_size, obj, data, SIZE_MAX - 4 + unconst); var = 4; err |= check_one_size_helper(sizeof(*obj) + (4 * sizeof(*obj->data)), struct_size, obj, data, var++); err |= check_one_size_helper(sizeof(*obj) + (5 * sizeof(*obj->data)), struct_size, obj, data, var++); - err |= check_one_size_helper(sizeof(*obj), struct_size, obj, data, 0); + err |= check_one_size_helper(sizeof(*obj), struct_size, obj, data, 0 + unconst); err |= check_one_size_helper(sizeof(*obj) + sizeof(*obj->data), - struct_size, obj, data, 1); + struct_size, obj, data, 1 + unconst); err |= check_one_size_helper(SIZE_MAX, - struct_size, obj, data, -3); + struct_size, obj, data, -3 + unconst); err |= check_one_size_helper(SIZE_MAX, - struct_size, obj, data, SIZE_MAX - 3); + struct_size, obj, data, SIZE_MAX - 3 + unconst); pr_info("%d overflow size helper tests finished\n", count); From patchwork Sun Feb 27 18:45:12 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 12762090 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 87992C41535 for ; Sun, 27 Feb 2022 18:45:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231331AbiB0SqL (ORCPT ); Sun, 27 Feb 2022 13:46:11 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53402 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231230AbiB0SqJ (ORCPT ); Sun, 27 Feb 2022 13:46:09 -0500 Received: from mail-pg1-x52e.google.com (mail-pg1-x52e.google.com [IPv6:2607:f8b0:4864:20::52e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D57DF4F9CA for ; Sun, 27 Feb 2022 10:45:23 -0800 (PST) Received: by mail-pg1-x52e.google.com with SMTP id 12so9616467pgd.0 for ; Sun, 27 Feb 2022 10:45:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=CORTFBC46eh2Ga2s+fFB0KGQ4LMJ6ZxXrGNYQWksMqg=; b=jytEN8QTp7WhnOe0gT5W/OXrVbY0DUQY952kCReWpRh9pDUaVhNG1K0ws9pIOqfHmK adIxfisDqTjVHsRnx+V9+Hiuw3IYOO2Yrcf2t+Z7nuXFudBfIPQoYAj4V9ZZ2qZUFlGP I/PjfCexi3vGX3x11G8SN7l0KCs7oVLuCbH6I= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=CORTFBC46eh2Ga2s+fFB0KGQ4LMJ6ZxXrGNYQWksMqg=; b=oVtZLyyYkxsoAIhMVkivrwECmbg20IDyVmyuCob4/iZCV7dJfaXB9WxAFIK5KQWC0A OQ4VzGtzs0rkVRtaxlb1g1WpP+Ij40kwLooRvho/5TgqYmQLXzWAgDw9gfh0Te1TUXBe okGQkD40+O9HHM/iVG1z+X2x+9XylVPIzrED1ACm+DH1Kxy0CJOo+XJigjdP24zG9vI2 ukBYzO12vZgsj5CtBvoQOz9KP9YVuK/u22TB5g0S88stY/eMjuG0Krce9ZM7G9hJXr68 cHTJu36KGqcQHSnVbMig3dSjLlSm7lJNmrsDQ2PF+wIZ9DaIeXbZr+dAipM9YcVm3kKC hbsA== X-Gm-Message-State: AOAM533ZDuATeJIF7xf8TSgr0gv6Fm9XKAPBWLaL25gaR6d/brz1gSXr l6EoMZWICz5jZxYkYUF2J0lGnQ== X-Google-Smtp-Source: ABdhPJxomb26Bwz9HcGd5TkaawG3h2BNGxZVW5HWB81Zwt50QQjqO2wMQalut84jO4vI56mEbrWb8A== X-Received: by 2002:aa7:8882:0:b0:4df:7b9e:1ccb with SMTP id z2-20020aa78882000000b004df7b9e1ccbmr17848161pfe.41.1645987523005; Sun, 27 Feb 2022 10:45:23 -0800 (PST) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id n34-20020a056a000d6200b004e1ba1016absm10661559pfv.31.2022.02.27.10.45.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 27 Feb 2022 10:45:21 -0800 (PST) From: Kees Cook To: Kees Cook Cc: Rasmus Villemoes , Nick Desaulniers , Vitor Massaru Iha , Daniel Latypov , David Gow , "Gustavo A. R. Silva" , Nathan Chancellor , Anton Ivanov , Jeff Dike , Richard Weinberger , Masahiro Yamada , Arnd Bergmann , linux-kernel@vger.kernel.org, linux-um@lists.infradead.org, linux-kbuild@vger.kernel.org, kunit-dev@googlegroups.com, llvm@lists.linux.dev, x86@kernel.org, linux-hardening@vger.kernel.org Subject: [PATCH v3 2/7] lib: overflow: Convert to Kunit Date: Sun, 27 Feb 2022 10:45:12 -0800 Message-Id: <20220227184517.504931-3-keescook@chromium.org> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220227184517.504931-1-keescook@chromium.org> References: <20220227184517.504931-1-keescook@chromium.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=34366; h=from:subject; bh=dzw9SDJzAKsm5GcR68EenTegMSttn9bi588mTjw/bnc=; b=owEBbQKS/ZANAwAKAYly9N/cbcAmAcsmYgBiG8a7t8JK9SalujIWrFt5o3iTGFXwFh4Drbrgk5FY iGnGW3+JAjMEAAEKAB0WIQSlw/aPIp3WD3I+bhOJcvTf3G3AJgUCYhvGuwAKCRCJcvTf3G3AJgoFD/ 9D+GRjQWP3rUKgJzs9GPpa9OhEnWomxof+Oim9tM5eNiNIQ9kvU6GK50UwU5lQ+lOlH4XiH7iztUbT qZKWivb/l6dfOmhCbP6glggmU9AXEUmZZsl6Y2ceKQi4XbBkVbqreWixI6HxEGx9SofyEN9M/GgVJ5 /kdcSkF05xIirv9M4TYn+v/geFlU/0R4T1Xbpqtp4SxN4p2xMtD9PCiYkVi3HVMtf9wRdUfiVBScvJ 4B6KclzV8X8O5f3VIl0vnAPx8MMRH0ScvR0JRvyum6FJPO0WYbVQR7gngPXkxElXm58TEx+7iC/Ysm +SgXNPgPhR5XqesfyyHMdsudhteSo6ezh+dTtOJoJs1kD1gdpIim/BpPaMoBhtDsfjVMGy+AYv0mPB GhTyZGGdieNnE3PbDV7XLyt3p8oRKLJDbI0bJa9BMlV3qBa/lLVWWFzJTZEe5lXDcmQUX7IyREHMNa 6UJgcct8Aj6tsOMrKHgGeosRWKZCvZREAkmGBBj9wSonwxywMlOX9+VbThO+pj4rxzRrT5pNKk+wTz di+QIdGbgbXvNXmIZLCPSv1hOqdagRRzcctlUSHtmm60Kbn5kBwfr4oFyNcl7lfWwP70ErwU+dnVTX Qc+V5XTcQLuTXjCvVOvLOwVc9f5aTYpFcZI7FOt8gm2AXQJBH53yRSeGM6Iw== X-Developer-Key: i=keescook@chromium.org; a=openpgp; fpr=A5C3F68F229DD60F723E6E138972F4DFDC6DC026 Precedence: bulk List-ID: X-Mailing-List: linux-hardening@vger.kernel.org Convert overflow unit tests to KUnit, for better integration into the kernel self test framework. Includes a rename of test_overflow.c to overflow_kunit.c, and CONFIG_TEST_OVERFLOW to CONFIG_OVERFLOW_KUNIT_TEST. $ ./tools/testing/kunit/kunit.py run overflow ... [14:33:51] Starting KUnit Kernel (1/1)... [14:33:51] ============================================================ [14:33:51] ================== overflow (11 subtests) ================== [14:33:51] [PASSED] u8_overflow_test [14:33:51] [PASSED] s8_overflow_test [14:33:51] [PASSED] u16_overflow_test [14:33:51] [PASSED] s16_overflow_test [14:33:51] [PASSED] u32_overflow_test [14:33:51] [PASSED] s32_overflow_test [14:33:51] [PASSED] u64_overflow_test [14:33:51] [PASSED] s64_overflow_test [14:33:51] [PASSED] overflow_shift_test [14:33:51] [PASSED] overflow_allocation_test [14:33:51] [PASSED] overflow_size_helpers_test [14:33:51] ==================== [PASSED] overflow ===================== [14:33:51] ============================================================ [14:33:51] Testing complete. Passed: 11, Failed: 0, Crashed: 0, Skipped: 0, Errors: 0 [14:33:51] Elapsed time: 12.525s total, 0.001s configuring, 12.402s building, 0.101s running Cc: Rasmus Villemoes Cc: Nick Desaulniers Co-developed-by: Vitor Massaru Iha Signed-off-by: Vitor Massaru Iha Link: https://lore.kernel.org/lkml/20200720224418.200495-1-vitor@massaru.org/ Co-developed-by: Daniel Latypov Signed-off-by: Daniel Latypov Link: https://lore.kernel.org/linux-kselftest/20210503211536.1384578-1-dlatypov@google.com/ Acked-by: Nick Desaulniers Link: https://lore.kernel.org/lkml/CAKwvOdm62iA1dNiC6Q11UJ-MnTqtc4kXkm-ubPaFMK824_k0nw@mail.gmail.com Signed-off-by: Kees Cook Reviewed-by: David Gow Link: https://lore.kernel.org/lkml/CABVgOS=TWVh649_Vjo3wnMu9gZnq66gkV-LtGgsksAWMqc+MSA@mail.gmail.com --- v1: https://lore.kernel.org/lkml/20220216224153.2242451-1-keescook@chromium.org v2: https://lore.kernel.org/lkml/20220224054825.1853314-1-keescook@chromium.org v3: - tweak commit log (David) --- lib/Kconfig.debug | 16 +- lib/Makefile | 2 +- lib/{test_overflow.c => overflow_kunit.c} | 554 ++++++++++------------ 3 files changed, 263 insertions(+), 309 deletions(-) rename lib/{test_overflow.c => overflow_kunit.c} (54%) diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 14b89aa37c5c..14d90d03bc8d 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -2214,9 +2214,6 @@ config TEST_UUID config TEST_XARRAY tristate "Test the XArray code at runtime" -config TEST_OVERFLOW - tristate "Test check_*_overflow() functions at runtime" - config TEST_RHASHTABLE tristate "Perform selftest on resizable hash table" help @@ -2501,6 +2498,19 @@ config MEMCPY_KUNIT_TEST If unsure, say N. +config OVERFLOW_KUNIT_TEST + tristate "Test check_*_overflow() functions at runtime" if !KUNIT_ALL_TESTS + depends on KUNIT + default KUNIT_ALL_TESTS + help + Builds unit tests for the check_*_overflow(), size_*(), allocation, and + related functions. + + For more information on KUnit and unit tests in general please refer + to the KUnit documentation in Documentation/dev-tools/kunit/. + + If unsure, say N. + config TEST_UDELAY tristate "udelay test driver" help diff --git a/lib/Makefile b/lib/Makefile index 300f569c626b..fdfcbfaff32f 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -77,7 +77,6 @@ obj-$(CONFIG_TEST_LIST_SORT) += test_list_sort.o obj-$(CONFIG_TEST_MIN_HEAP) += test_min_heap.o obj-$(CONFIG_TEST_LKM) += test_module.o obj-$(CONFIG_TEST_VMALLOC) += test_vmalloc.o -obj-$(CONFIG_TEST_OVERFLOW) += test_overflow.o obj-$(CONFIG_TEST_RHASHTABLE) += test_rhashtable.o obj-$(CONFIG_TEST_SORT) += test_sort.o obj-$(CONFIG_TEST_USER_COPY) += test_user_copy.o @@ -363,6 +362,7 @@ obj-$(CONFIG_BITS_TEST) += test_bits.o obj-$(CONFIG_CMDLINE_KUNIT_TEST) += cmdline_kunit.o obj-$(CONFIG_SLUB_KUNIT_TEST) += slub_kunit.o obj-$(CONFIG_MEMCPY_KUNIT_TEST) += memcpy_kunit.o +obj-$(CONFIG_OVERFLOW_KUNIT_TEST) += overflow_kunit.o obj-$(CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED) += devmem_is_allowed.o diff --git a/lib/test_overflow.c b/lib/overflow_kunit.c similarity index 54% rename from lib/test_overflow.c rename to lib/overflow_kunit.c index f6530fce799d..475f0c064bf6 100644 --- a/lib/test_overflow.c +++ b/lib/overflow_kunit.c @@ -1,11 +1,13 @@ // SPDX-License-Identifier: GPL-2.0 OR MIT /* - * Test cases for arithmetic overflow checks. + * Test cases for arithmetic overflow checks. See: + * https://www.kernel.org/doc/html/latest/dev-tools/kunit/kunit-tool.html#configuring-building-and-running-tests + * ./tools/testing/kunit/kunit.py run overflow [--raw_output] */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include #include -#include #include #include #include @@ -19,7 +21,7 @@ t a, b; \ t sum, diff, prod; \ bool s_of, d_of, p_of; \ - } t ## _tests[] __initconst + } t ## _tests[] DEFINE_TEST_ARRAY(u8) = { {0, 0, 0, 0, 0, false, false, false}, @@ -220,43 +222,31 @@ DEFINE_TEST_ARRAY(s64) = { bool _of; \ \ _of = check_ ## op ## _overflow(a, b, &_r); \ - if (_of != of) { \ - pr_warn("expected "fmt" "sym" "fmt \ - " to%s overflow (type %s)\n", \ - a, b, of ? "" : " not", #t); \ - err = 1; \ - } \ - if (_r != r) { \ - pr_warn("expected "fmt" "sym" "fmt" == " \ - fmt", got "fmt" (type %s)\n", \ - a, b, r, _r, #t); \ - err = 1; \ - } \ + KUNIT_EXPECT_EQ_MSG(test, _of, of, \ + "expected "fmt" "sym" "fmt" to%s overflow (type %s)\n", \ + a, b, of ? "" : " not", #t); \ + KUNIT_EXPECT_EQ_MSG(test, _r, r, \ + "expected "fmt" "sym" "fmt" == "fmt", got "fmt" (type %s)\n", \ + a, b, r, _r, #t); \ } while (0) #define DEFINE_TEST_FUNC(t, fmt) \ -static int __init do_test_ ## t(const struct test_ ## t *p) \ +static void do_test_ ## t(struct kunit *test, const struct test_ ## t *p) \ { \ - int err = 0; \ - \ check_one_op(t, fmt, add, "+", p->a, p->b, p->sum, p->s_of); \ check_one_op(t, fmt, add, "+", p->b, p->a, p->sum, p->s_of); \ check_one_op(t, fmt, sub, "-", p->a, p->b, p->diff, p->d_of); \ check_one_op(t, fmt, mul, "*", p->a, p->b, p->prod, p->p_of); \ check_one_op(t, fmt, mul, "*", p->b, p->a, p->prod, p->p_of); \ - \ - return err; \ } \ \ -static int __init test_ ## t ## _overflow(void) { \ - int err = 0; \ +static void t ## _overflow_test(struct kunit *test) { \ unsigned i; \ \ for (i = 0; i < ARRAY_SIZE(t ## _tests); ++i) \ - err |= do_test_ ## t(&t ## _tests[i]); \ - pr_info("%zu %s arithmetic tests finished\n", \ + do_test_ ## t(test, &t ## _tests[i]); \ + kunit_info(test, "%zu %s arithmetic tests finished\n", \ ARRAY_SIZE(t ## _tests), #t); \ - return err; \ } DEFINE_TEST_FUNC(u8, "%d"); @@ -270,198 +260,176 @@ DEFINE_TEST_FUNC(u64, "%llu"); DEFINE_TEST_FUNC(s64, "%lld"); #endif -static int __init test_overflow_calculation(void) +static void overflow_shift_test(struct kunit *test) { - int err = 0; - - err |= test_u8_overflow(); - err |= test_s8_overflow(); - err |= test_u16_overflow(); - err |= test_s16_overflow(); - err |= test_u32_overflow(); - err |= test_s32_overflow(); -#if BITS_PER_LONG == 64 - err |= test_u64_overflow(); - err |= test_s64_overflow(); -#endif - - return err; -} - -static int __init test_overflow_shift(void) -{ - int err = 0; int count = 0; /* Args are: value, shift, type, expected result, overflow expected */ -#define TEST_ONE_SHIFT(a, s, t, expect, of) ({ \ - int __failed = 0; \ +#define TEST_ONE_SHIFT(a, s, t, expect, of) do { \ typeof(a) __a = (a); \ typeof(s) __s = (s); \ t __e = (expect); \ t __d; \ bool __of = check_shl_overflow(__a, __s, &__d); \ if (__of != of) { \ - pr_warn("expected (%s)(%s << %s) to%s overflow\n", \ + KUNIT_EXPECT_EQ_MSG(test, __of, of, \ + "expected (%s)(%s << %s) to%s overflow\n", \ #t, #a, #s, of ? "" : " not"); \ - __failed = 1; \ } else if (!__of && __d != __e) { \ - pr_warn("expected (%s)(%s << %s) == %s\n", \ + KUNIT_EXPECT_EQ_MSG(test, __d, __e, \ + "expected (%s)(%s << %s) == %s\n", \ #t, #a, #s, #expect); \ if ((t)-1 < 0) \ - pr_warn("got %lld\n", (s64)__d); \ + kunit_info(test, "got %lld\n", (s64)__d); \ else \ - pr_warn("got %llu\n", (u64)__d); \ - __failed = 1; \ + kunit_info(test, "got %llu\n", (u64)__d); \ } \ count++; \ - __failed; \ -}) +} while (0) /* Sane shifts. */ - err |= TEST_ONE_SHIFT(1, 0, u8, 1 << 0, false); - err |= TEST_ONE_SHIFT(1, 4, u8, 1 << 4, false); - err |= TEST_ONE_SHIFT(1, 7, u8, 1 << 7, false); - err |= TEST_ONE_SHIFT(0xF, 4, u8, 0xF << 4, false); - err |= TEST_ONE_SHIFT(1, 0, u16, 1 << 0, false); - err |= TEST_ONE_SHIFT(1, 10, u16, 1 << 10, false); - err |= TEST_ONE_SHIFT(1, 15, u16, 1 << 15, false); - err |= TEST_ONE_SHIFT(0xFF, 8, u16, 0xFF << 8, false); - err |= TEST_ONE_SHIFT(1, 0, int, 1 << 0, false); - err |= TEST_ONE_SHIFT(1, 16, int, 1 << 16, false); - err |= TEST_ONE_SHIFT(1, 30, int, 1 << 30, false); - err |= TEST_ONE_SHIFT(1, 0, s32, 1 << 0, false); - err |= TEST_ONE_SHIFT(1, 16, s32, 1 << 16, false); - err |= TEST_ONE_SHIFT(1, 30, s32, 1 << 30, false); - err |= TEST_ONE_SHIFT(1, 0, unsigned int, 1U << 0, false); - err |= TEST_ONE_SHIFT(1, 20, unsigned int, 1U << 20, false); - err |= TEST_ONE_SHIFT(1, 31, unsigned int, 1U << 31, false); - err |= TEST_ONE_SHIFT(0xFFFFU, 16, unsigned int, 0xFFFFU << 16, false); - err |= TEST_ONE_SHIFT(1, 0, u32, 1U << 0, false); - err |= TEST_ONE_SHIFT(1, 20, u32, 1U << 20, false); - err |= TEST_ONE_SHIFT(1, 31, u32, 1U << 31, false); - err |= TEST_ONE_SHIFT(0xFFFFU, 16, u32, 0xFFFFU << 16, false); - err |= TEST_ONE_SHIFT(1, 0, u64, 1ULL << 0, false); - err |= TEST_ONE_SHIFT(1, 40, u64, 1ULL << 40, false); - err |= TEST_ONE_SHIFT(1, 63, u64, 1ULL << 63, false); - err |= TEST_ONE_SHIFT(0xFFFFFFFFULL, 32, u64, - 0xFFFFFFFFULL << 32, false); + TEST_ONE_SHIFT(1, 0, u8, 1 << 0, false); + TEST_ONE_SHIFT(1, 4, u8, 1 << 4, false); + TEST_ONE_SHIFT(1, 7, u8, 1 << 7, false); + TEST_ONE_SHIFT(0xF, 4, u8, 0xF << 4, false); + TEST_ONE_SHIFT(1, 0, u16, 1 << 0, false); + TEST_ONE_SHIFT(1, 10, u16, 1 << 10, false); + TEST_ONE_SHIFT(1, 15, u16, 1 << 15, false); + TEST_ONE_SHIFT(0xFF, 8, u16, 0xFF << 8, false); + TEST_ONE_SHIFT(1, 0, int, 1 << 0, false); + TEST_ONE_SHIFT(1, 16, int, 1 << 16, false); + TEST_ONE_SHIFT(1, 30, int, 1 << 30, false); + TEST_ONE_SHIFT(1, 0, s32, 1 << 0, false); + TEST_ONE_SHIFT(1, 16, s32, 1 << 16, false); + TEST_ONE_SHIFT(1, 30, s32, 1 << 30, false); + TEST_ONE_SHIFT(1, 0, unsigned int, 1U << 0, false); + TEST_ONE_SHIFT(1, 20, unsigned int, 1U << 20, false); + TEST_ONE_SHIFT(1, 31, unsigned int, 1U << 31, false); + TEST_ONE_SHIFT(0xFFFFU, 16, unsigned int, 0xFFFFU << 16, false); + TEST_ONE_SHIFT(1, 0, u32, 1U << 0, false); + TEST_ONE_SHIFT(1, 20, u32, 1U << 20, false); + TEST_ONE_SHIFT(1, 31, u32, 1U << 31, false); + TEST_ONE_SHIFT(0xFFFFU, 16, u32, 0xFFFFU << 16, false); + TEST_ONE_SHIFT(1, 0, u64, 1ULL << 0, false); + TEST_ONE_SHIFT(1, 40, u64, 1ULL << 40, false); + TEST_ONE_SHIFT(1, 63, u64, 1ULL << 63, false); + TEST_ONE_SHIFT(0xFFFFFFFFULL, 32, u64, 0xFFFFFFFFULL << 32, false); /* Sane shift: start and end with 0, without a too-wide shift. */ - err |= TEST_ONE_SHIFT(0, 7, u8, 0, false); - err |= TEST_ONE_SHIFT(0, 15, u16, 0, false); - err |= TEST_ONE_SHIFT(0, 31, unsigned int, 0, false); - err |= TEST_ONE_SHIFT(0, 31, u32, 0, false); - err |= TEST_ONE_SHIFT(0, 63, u64, 0, false); + TEST_ONE_SHIFT(0, 7, u8, 0, false); + TEST_ONE_SHIFT(0, 15, u16, 0, false); + TEST_ONE_SHIFT(0, 31, unsigned int, 0, false); + TEST_ONE_SHIFT(0, 31, u32, 0, false); + TEST_ONE_SHIFT(0, 63, u64, 0, false); /* Sane shift: start and end with 0, without reaching signed bit. */ - err |= TEST_ONE_SHIFT(0, 6, s8, 0, false); - err |= TEST_ONE_SHIFT(0, 14, s16, 0, false); - err |= TEST_ONE_SHIFT(0, 30, int, 0, false); - err |= TEST_ONE_SHIFT(0, 30, s32, 0, false); - err |= TEST_ONE_SHIFT(0, 62, s64, 0, false); + TEST_ONE_SHIFT(0, 6, s8, 0, false); + TEST_ONE_SHIFT(0, 14, s16, 0, false); + TEST_ONE_SHIFT(0, 30, int, 0, false); + TEST_ONE_SHIFT(0, 30, s32, 0, false); + TEST_ONE_SHIFT(0, 62, s64, 0, false); /* Overflow: shifted the bit off the end. */ - err |= TEST_ONE_SHIFT(1, 8, u8, 0, true); - err |= TEST_ONE_SHIFT(1, 16, u16, 0, true); - err |= TEST_ONE_SHIFT(1, 32, unsigned int, 0, true); - err |= TEST_ONE_SHIFT(1, 32, u32, 0, true); - err |= TEST_ONE_SHIFT(1, 64, u64, 0, true); + TEST_ONE_SHIFT(1, 8, u8, 0, true); + TEST_ONE_SHIFT(1, 16, u16, 0, true); + TEST_ONE_SHIFT(1, 32, unsigned int, 0, true); + TEST_ONE_SHIFT(1, 32, u32, 0, true); + TEST_ONE_SHIFT(1, 64, u64, 0, true); /* Overflow: shifted into the signed bit. */ - err |= TEST_ONE_SHIFT(1, 7, s8, 0, true); - err |= TEST_ONE_SHIFT(1, 15, s16, 0, true); - err |= TEST_ONE_SHIFT(1, 31, int, 0, true); - err |= TEST_ONE_SHIFT(1, 31, s32, 0, true); - err |= TEST_ONE_SHIFT(1, 63, s64, 0, true); + TEST_ONE_SHIFT(1, 7, s8, 0, true); + TEST_ONE_SHIFT(1, 15, s16, 0, true); + TEST_ONE_SHIFT(1, 31, int, 0, true); + TEST_ONE_SHIFT(1, 31, s32, 0, true); + TEST_ONE_SHIFT(1, 63, s64, 0, true); /* Overflow: high bit falls off unsigned types. */ /* 10010110 */ - err |= TEST_ONE_SHIFT(150, 1, u8, 0, true); + TEST_ONE_SHIFT(150, 1, u8, 0, true); /* 1000100010010110 */ - err |= TEST_ONE_SHIFT(34966, 1, u16, 0, true); + TEST_ONE_SHIFT(34966, 1, u16, 0, true); /* 10000100000010001000100010010110 */ - err |= TEST_ONE_SHIFT(2215151766U, 1, u32, 0, true); - err |= TEST_ONE_SHIFT(2215151766U, 1, unsigned int, 0, true); + TEST_ONE_SHIFT(2215151766U, 1, u32, 0, true); + TEST_ONE_SHIFT(2215151766U, 1, unsigned int, 0, true); /* 1000001000010000010000000100000010000100000010001000100010010110 */ - err |= TEST_ONE_SHIFT(9372061470395238550ULL, 1, u64, 0, true); + TEST_ONE_SHIFT(9372061470395238550ULL, 1, u64, 0, true); /* Overflow: bit shifted into signed bit on signed types. */ /* 01001011 */ - err |= TEST_ONE_SHIFT(75, 1, s8, 0, true); + TEST_ONE_SHIFT(75, 1, s8, 0, true); /* 0100010001001011 */ - err |= TEST_ONE_SHIFT(17483, 1, s16, 0, true); + TEST_ONE_SHIFT(17483, 1, s16, 0, true); /* 01000010000001000100010001001011 */ - err |= TEST_ONE_SHIFT(1107575883, 1, s32, 0, true); - err |= TEST_ONE_SHIFT(1107575883, 1, int, 0, true); + TEST_ONE_SHIFT(1107575883, 1, s32, 0, true); + TEST_ONE_SHIFT(1107575883, 1, int, 0, true); /* 0100000100001000001000000010000001000010000001000100010001001011 */ - err |= TEST_ONE_SHIFT(4686030735197619275LL, 1, s64, 0, true); + TEST_ONE_SHIFT(4686030735197619275LL, 1, s64, 0, true); /* Overflow: bit shifted past signed bit on signed types. */ /* 01001011 */ - err |= TEST_ONE_SHIFT(75, 2, s8, 0, true); + TEST_ONE_SHIFT(75, 2, s8, 0, true); /* 0100010001001011 */ - err |= TEST_ONE_SHIFT(17483, 2, s16, 0, true); + TEST_ONE_SHIFT(17483, 2, s16, 0, true); /* 01000010000001000100010001001011 */ - err |= TEST_ONE_SHIFT(1107575883, 2, s32, 0, true); - err |= TEST_ONE_SHIFT(1107575883, 2, int, 0, true); + TEST_ONE_SHIFT(1107575883, 2, s32, 0, true); + TEST_ONE_SHIFT(1107575883, 2, int, 0, true); /* 0100000100001000001000000010000001000010000001000100010001001011 */ - err |= TEST_ONE_SHIFT(4686030735197619275LL, 2, s64, 0, true); + TEST_ONE_SHIFT(4686030735197619275LL, 2, s64, 0, true); /* Overflow: values larger than destination type. */ - err |= TEST_ONE_SHIFT(0x100, 0, u8, 0, true); - err |= TEST_ONE_SHIFT(0xFF, 0, s8, 0, true); - err |= TEST_ONE_SHIFT(0x10000U, 0, u16, 0, true); - err |= TEST_ONE_SHIFT(0xFFFFU, 0, s16, 0, true); - err |= TEST_ONE_SHIFT(0x100000000ULL, 0, u32, 0, true); - err |= TEST_ONE_SHIFT(0x100000000ULL, 0, unsigned int, 0, true); - err |= TEST_ONE_SHIFT(0xFFFFFFFFUL, 0, s32, 0, true); - err |= TEST_ONE_SHIFT(0xFFFFFFFFUL, 0, int, 0, true); - err |= TEST_ONE_SHIFT(0xFFFFFFFFFFFFFFFFULL, 0, s64, 0, true); + TEST_ONE_SHIFT(0x100, 0, u8, 0, true); + TEST_ONE_SHIFT(0xFF, 0, s8, 0, true); + TEST_ONE_SHIFT(0x10000U, 0, u16, 0, true); + TEST_ONE_SHIFT(0xFFFFU, 0, s16, 0, true); + TEST_ONE_SHIFT(0x100000000ULL, 0, u32, 0, true); + TEST_ONE_SHIFT(0x100000000ULL, 0, unsigned int, 0, true); + TEST_ONE_SHIFT(0xFFFFFFFFUL, 0, s32, 0, true); + TEST_ONE_SHIFT(0xFFFFFFFFUL, 0, int, 0, true); + TEST_ONE_SHIFT(0xFFFFFFFFFFFFFFFFULL, 0, s64, 0, true); /* Nonsense: negative initial value. */ - err |= TEST_ONE_SHIFT(-1, 0, s8, 0, true); - err |= TEST_ONE_SHIFT(-1, 0, u8, 0, true); - err |= TEST_ONE_SHIFT(-5, 0, s16, 0, true); - err |= TEST_ONE_SHIFT(-5, 0, u16, 0, true); - err |= TEST_ONE_SHIFT(-10, 0, int, 0, true); - err |= TEST_ONE_SHIFT(-10, 0, unsigned int, 0, true); - err |= TEST_ONE_SHIFT(-100, 0, s32, 0, true); - err |= TEST_ONE_SHIFT(-100, 0, u32, 0, true); - err |= TEST_ONE_SHIFT(-10000, 0, s64, 0, true); - err |= TEST_ONE_SHIFT(-10000, 0, u64, 0, true); + TEST_ONE_SHIFT(-1, 0, s8, 0, true); + TEST_ONE_SHIFT(-1, 0, u8, 0, true); + TEST_ONE_SHIFT(-5, 0, s16, 0, true); + TEST_ONE_SHIFT(-5, 0, u16, 0, true); + TEST_ONE_SHIFT(-10, 0, int, 0, true); + TEST_ONE_SHIFT(-10, 0, unsigned int, 0, true); + TEST_ONE_SHIFT(-100, 0, s32, 0, true); + TEST_ONE_SHIFT(-100, 0, u32, 0, true); + TEST_ONE_SHIFT(-10000, 0, s64, 0, true); + TEST_ONE_SHIFT(-10000, 0, u64, 0, true); /* Nonsense: negative shift values. */ - err |= TEST_ONE_SHIFT(0, -5, s8, 0, true); - err |= TEST_ONE_SHIFT(0, -5, u8, 0, true); - err |= TEST_ONE_SHIFT(0, -10, s16, 0, true); - err |= TEST_ONE_SHIFT(0, -10, u16, 0, true); - err |= TEST_ONE_SHIFT(0, -15, int, 0, true); - err |= TEST_ONE_SHIFT(0, -15, unsigned int, 0, true); - err |= TEST_ONE_SHIFT(0, -20, s32, 0, true); - err |= TEST_ONE_SHIFT(0, -20, u32, 0, true); - err |= TEST_ONE_SHIFT(0, -30, s64, 0, true); - err |= TEST_ONE_SHIFT(0, -30, u64, 0, true); + TEST_ONE_SHIFT(0, -5, s8, 0, true); + TEST_ONE_SHIFT(0, -5, u8, 0, true); + TEST_ONE_SHIFT(0, -10, s16, 0, true); + TEST_ONE_SHIFT(0, -10, u16, 0, true); + TEST_ONE_SHIFT(0, -15, int, 0, true); + TEST_ONE_SHIFT(0, -15, unsigned int, 0, true); + TEST_ONE_SHIFT(0, -20, s32, 0, true); + TEST_ONE_SHIFT(0, -20, u32, 0, true); + TEST_ONE_SHIFT(0, -30, s64, 0, true); + TEST_ONE_SHIFT(0, -30, u64, 0, true); /* Overflow: shifted at or beyond entire type's bit width. */ - err |= TEST_ONE_SHIFT(0, 8, u8, 0, true); - err |= TEST_ONE_SHIFT(0, 9, u8, 0, true); - err |= TEST_ONE_SHIFT(0, 8, s8, 0, true); - err |= TEST_ONE_SHIFT(0, 9, s8, 0, true); - err |= TEST_ONE_SHIFT(0, 16, u16, 0, true); - err |= TEST_ONE_SHIFT(0, 17, u16, 0, true); - err |= TEST_ONE_SHIFT(0, 16, s16, 0, true); - err |= TEST_ONE_SHIFT(0, 17, s16, 0, true); - err |= TEST_ONE_SHIFT(0, 32, u32, 0, true); - err |= TEST_ONE_SHIFT(0, 33, u32, 0, true); - err |= TEST_ONE_SHIFT(0, 32, int, 0, true); - err |= TEST_ONE_SHIFT(0, 33, int, 0, true); - err |= TEST_ONE_SHIFT(0, 32, s32, 0, true); - err |= TEST_ONE_SHIFT(0, 33, s32, 0, true); - err |= TEST_ONE_SHIFT(0, 64, u64, 0, true); - err |= TEST_ONE_SHIFT(0, 65, u64, 0, true); - err |= TEST_ONE_SHIFT(0, 64, s64, 0, true); - err |= TEST_ONE_SHIFT(0, 65, s64, 0, true); + TEST_ONE_SHIFT(0, 8, u8, 0, true); + TEST_ONE_SHIFT(0, 9, u8, 0, true); + TEST_ONE_SHIFT(0, 8, s8, 0, true); + TEST_ONE_SHIFT(0, 9, s8, 0, true); + TEST_ONE_SHIFT(0, 16, u16, 0, true); + TEST_ONE_SHIFT(0, 17, u16, 0, true); + TEST_ONE_SHIFT(0, 16, s16, 0, true); + TEST_ONE_SHIFT(0, 17, s16, 0, true); + TEST_ONE_SHIFT(0, 32, u32, 0, true); + TEST_ONE_SHIFT(0, 33, u32, 0, true); + TEST_ONE_SHIFT(0, 32, int, 0, true); + TEST_ONE_SHIFT(0, 33, int, 0, true); + TEST_ONE_SHIFT(0, 32, s32, 0, true); + TEST_ONE_SHIFT(0, 33, s32, 0, true); + TEST_ONE_SHIFT(0, 64, u64, 0, true); + TEST_ONE_SHIFT(0, 65, u64, 0, true); + TEST_ONE_SHIFT(0, 64, s64, 0, true); + TEST_ONE_SHIFT(0, 65, s64, 0, true); /* * Corner case: for unsigned types, we fail when we've shifted @@ -472,17 +440,14 @@ static int __init test_overflow_shift(void) * signed bit). So, for now, we will test this condition but * mark it as not expected to overflow. */ - err |= TEST_ONE_SHIFT(0, 7, s8, 0, false); - err |= TEST_ONE_SHIFT(0, 15, s16, 0, false); - err |= TEST_ONE_SHIFT(0, 31, int, 0, false); - err |= TEST_ONE_SHIFT(0, 31, s32, 0, false); - err |= TEST_ONE_SHIFT(0, 63, s64, 0, false); - - pr_info("%d shift tests finished\n", count); + TEST_ONE_SHIFT(0, 7, s8, 0, false); + TEST_ONE_SHIFT(0, 15, s16, 0, false); + TEST_ONE_SHIFT(0, 31, int, 0, false); + TEST_ONE_SHIFT(0, 31, s32, 0, false); + TEST_ONE_SHIFT(0, 63, s64, 0, false); + kunit_info(test, "%d shift tests finished\n", count); #undef TEST_ONE_SHIFT - - return err; } /* @@ -502,7 +467,7 @@ static int __init test_overflow_shift(void) #define TEST_SIZE (5 * 4096) #define DEFINE_TEST_ALLOC(func, free_func, want_arg, want_gfp, want_node)\ -static int __init test_ ## func (void *arg) \ +static void test_ ## func (struct kunit *test, void *arg) \ { \ volatile size_t a = TEST_SIZE; \ volatile size_t b = (SIZE_MAX / TEST_SIZE) + 1; \ @@ -510,30 +475,24 @@ static int __init test_ ## func (void *arg) \ \ /* Tiny allocation test. */ \ ptr = alloc ## want_arg ## want_gfp ## want_node (func, arg, 1);\ - if (!ptr) { \ - pr_warn(#func " failed regular allocation?!\n"); \ - return 1; \ - } \ + KUNIT_ASSERT_NOT_ERR_OR_NULL_MSG(test, ptr, \ + #func " failed regular allocation?!\n"); \ free ## want_arg (free_func, arg, ptr); \ \ /* Wrapped allocation test. */ \ ptr = alloc ## want_arg ## want_gfp ## want_node (func, arg, \ a * b); \ - if (!ptr) { \ - pr_warn(#func " unexpectedly failed bad wrapping?!\n"); \ - return 1; \ - } \ + KUNIT_ASSERT_NOT_ERR_OR_NULL_MSG(test, ptr, \ + #func " unexpectedly failed bad wrapping?!\n"); \ free ## want_arg (free_func, arg, ptr); \ \ /* Saturated allocation test. */ \ ptr = alloc ## want_arg ## want_gfp ## want_node (func, arg, \ array_size(a, b)); \ if (ptr) { \ - pr_warn(#func " missed saturation!\n"); \ + KUNIT_FAIL(test, #func " missed saturation!\n"); \ free ## want_arg (free_func, arg, ptr); \ - return 1; \ } \ - return 0; \ } /* @@ -554,44 +513,38 @@ DEFINE_TEST_ALLOC(kvzalloc_node, kvfree, 0, 1, 1); DEFINE_TEST_ALLOC(devm_kmalloc, devm_kfree, 1, 1, 0); DEFINE_TEST_ALLOC(devm_kzalloc, devm_kfree, 1, 1, 0); -static int __init test_overflow_allocation(void) +static void overflow_allocation_test(struct kunit *test) { const char device_name[] = "overflow-test"; struct device *dev; int count = 0; - int err = 0; -#define check_allocation_overflow(alloc) ({ \ +#define check_allocation_overflow(alloc) do { \ count++; \ - test_ ## alloc(dev); \ -}) + test_ ## alloc(test, dev); \ +} while (0) /* Create dummy device for devm_kmalloc()-family tests. */ dev = root_device_register(device_name); - if (IS_ERR(dev)) { - pr_warn("Cannot register test device\n"); - return 1; - } - - err |= check_allocation_overflow(kmalloc); - err |= check_allocation_overflow(kmalloc_node); - err |= check_allocation_overflow(kzalloc); - err |= check_allocation_overflow(kzalloc_node); - err |= check_allocation_overflow(__vmalloc); - err |= check_allocation_overflow(kvmalloc); - err |= check_allocation_overflow(kvmalloc_node); - err |= check_allocation_overflow(kvzalloc); - err |= check_allocation_overflow(kvzalloc_node); - err |= check_allocation_overflow(devm_kmalloc); - err |= check_allocation_overflow(devm_kzalloc); + KUNIT_ASSERT_FALSE_MSG(test, IS_ERR(dev), + "Cannot register test device\n"); + + check_allocation_overflow(kmalloc); + check_allocation_overflow(kmalloc_node); + check_allocation_overflow(kzalloc); + check_allocation_overflow(kzalloc_node); + check_allocation_overflow(__vmalloc); + check_allocation_overflow(kvmalloc); + check_allocation_overflow(kvmalloc_node); + check_allocation_overflow(kvzalloc); + check_allocation_overflow(kvzalloc_node); + check_allocation_overflow(devm_kmalloc); + check_allocation_overflow(devm_kzalloc); device_unregister(dev); - pr_info("%d allocation overflow tests finished\n", count); - + kunit_info(test, "%d allocation overflow tests finished\n", count); #undef check_allocation_overflow - - return err; } struct __test_flex_array { @@ -600,127 +553,118 @@ struct __test_flex_array { unsigned long data[]; }; -static int __init test_overflow_size_helpers(void) +static void overflow_size_helpers_test(struct kunit *test) { /* Make sure struct_size() can be used in a constant expression. */ u8 ce_array[struct_size((struct __test_flex_array *)0, data, 55)]; struct __test_flex_array *obj; int count = 0; - int err = 0; int var; volatile int unconst = 0; /* Verify constant expression against runtime version. */ var = 55; OPTIMIZER_HIDE_VAR(var); - err |= sizeof(ce_array) != struct_size(obj, data, var); + KUNIT_EXPECT_EQ(test, sizeof(ce_array), struct_size(obj, data, var)); -#define check_one_size_helper(expected, func, args...) ({ \ - bool __failure = false; \ - size_t _r; \ - \ - _r = func(args); \ - if (_r != (expected)) { \ - pr_warn("expected " #func "(" #args ") " \ - "to return %zu but got %zu instead\n", \ - (size_t)(expected), _r); \ - __failure = true; \ - } \ +#define check_one_size_helper(expected, func, args...) do { \ + size_t _r = func(args); \ + KUNIT_EXPECT_EQ_MSG(test, _r, expected, \ + "expected " #func "(" #args ") to return %zu but got %zu instead\n", \ + (size_t)(expected), _r); \ count++; \ - __failure; \ -}) +} while (0) var = 4; - err |= check_one_size_helper(20, size_mul, var++, 5); - err |= check_one_size_helper(20, size_mul, 4, var++); - err |= check_one_size_helper(0, size_mul, 0, 3); - err |= check_one_size_helper(0, size_mul, 3, 0); - err |= check_one_size_helper(6, size_mul, 2, 3); - err |= check_one_size_helper(SIZE_MAX, size_mul, SIZE_MAX, 1); - err |= check_one_size_helper(SIZE_MAX, size_mul, SIZE_MAX, 3); - err |= check_one_size_helper(SIZE_MAX, size_mul, SIZE_MAX, -3); + check_one_size_helper(20, size_mul, var++, 5); + check_one_size_helper(20, size_mul, 4, var++); + check_one_size_helper(0, size_mul, 0, 3); + check_one_size_helper(0, size_mul, 3, 0); + check_one_size_helper(6, size_mul, 2, 3); + check_one_size_helper(SIZE_MAX, size_mul, SIZE_MAX, 1); + check_one_size_helper(SIZE_MAX, size_mul, SIZE_MAX, 3); + check_one_size_helper(SIZE_MAX, size_mul, SIZE_MAX, -3); var = 4; - err |= check_one_size_helper(9, size_add, var++, 5); - err |= check_one_size_helper(9, size_add, 4, var++); - err |= check_one_size_helper(9, size_add, 9, 0); - err |= check_one_size_helper(9, size_add, 0, 9); - err |= check_one_size_helper(5, size_add, 2, 3); - err |= check_one_size_helper(SIZE_MAX, size_add, SIZE_MAX, 1); - err |= check_one_size_helper(SIZE_MAX, size_add, SIZE_MAX, 3); - err |= check_one_size_helper(SIZE_MAX, size_add, SIZE_MAX, -3); + check_one_size_helper(9, size_add, var++, 5); + check_one_size_helper(9, size_add, 4, var++); + check_one_size_helper(9, size_add, 9, 0); + check_one_size_helper(9, size_add, 0, 9); + check_one_size_helper(5, size_add, 2, 3); + check_one_size_helper(SIZE_MAX, size_add, SIZE_MAX, 1); + check_one_size_helper(SIZE_MAX, size_add, SIZE_MAX, 3); + check_one_size_helper(SIZE_MAX, size_add, SIZE_MAX, -3); var = 4; - err |= check_one_size_helper(1, size_sub, var--, 3); - err |= check_one_size_helper(1, size_sub, 4, var--); - err |= check_one_size_helper(1, size_sub, 3, 2); - err |= check_one_size_helper(9, size_sub, 9, 0); - err |= check_one_size_helper(SIZE_MAX, size_sub, 9, -3); - err |= check_one_size_helper(SIZE_MAX, size_sub, 0, 9); - err |= check_one_size_helper(SIZE_MAX, size_sub, 2, 3); - err |= check_one_size_helper(SIZE_MAX, size_sub, SIZE_MAX, 0); - err |= check_one_size_helper(SIZE_MAX, size_sub, SIZE_MAX, 10); - err |= check_one_size_helper(SIZE_MAX, size_sub, 0, SIZE_MAX); - err |= check_one_size_helper(SIZE_MAX, size_sub, 14, SIZE_MAX); - err |= check_one_size_helper(SIZE_MAX - 2, size_sub, SIZE_MAX - 1, 1); - err |= check_one_size_helper(SIZE_MAX - 4, size_sub, SIZE_MAX - 1, 3); - err |= check_one_size_helper(1, size_sub, SIZE_MAX - 1, -3); + check_one_size_helper(1, size_sub, var--, 3); + check_one_size_helper(1, size_sub, 4, var--); + check_one_size_helper(1, size_sub, 3, 2); + check_one_size_helper(9, size_sub, 9, 0); + check_one_size_helper(SIZE_MAX, size_sub, 9, -3); + check_one_size_helper(SIZE_MAX, size_sub, 0, 9); + check_one_size_helper(SIZE_MAX, size_sub, 2, 3); + check_one_size_helper(SIZE_MAX, size_sub, SIZE_MAX, 0); + check_one_size_helper(SIZE_MAX, size_sub, SIZE_MAX, 10); + check_one_size_helper(SIZE_MAX, size_sub, 0, SIZE_MAX); + check_one_size_helper(SIZE_MAX, size_sub, 14, SIZE_MAX); + check_one_size_helper(SIZE_MAX - 2, size_sub, SIZE_MAX - 1, 1); + check_one_size_helper(SIZE_MAX - 4, size_sub, SIZE_MAX - 1, 3); + check_one_size_helper(1, size_sub, SIZE_MAX - 1, -3); var = 4; - err |= check_one_size_helper(4 * sizeof(*obj->data), - flex_array_size, obj, data, var++); - err |= check_one_size_helper(5 * sizeof(*obj->data), - flex_array_size, obj, data, var++); - err |= check_one_size_helper(0, flex_array_size, obj, data, 0 + unconst); - err |= check_one_size_helper(sizeof(*obj->data), - flex_array_size, obj, data, 1 + unconst); - err |= check_one_size_helper(7 * sizeof(*obj->data), - flex_array_size, obj, data, 7 + unconst); - err |= check_one_size_helper(SIZE_MAX, - flex_array_size, obj, data, -1 + unconst); - err |= check_one_size_helper(SIZE_MAX, - flex_array_size, obj, data, SIZE_MAX - 4 + unconst); + check_one_size_helper(4 * sizeof(*obj->data), + flex_array_size, obj, data, var++); + check_one_size_helper(5 * sizeof(*obj->data), + flex_array_size, obj, data, var++); + check_one_size_helper(0, flex_array_size, obj, data, 0 + unconst); + check_one_size_helper(sizeof(*obj->data), + flex_array_size, obj, data, 1 + unconst); + check_one_size_helper(7 * sizeof(*obj->data), + flex_array_size, obj, data, 7 + unconst); + check_one_size_helper(SIZE_MAX, + flex_array_size, obj, data, -1 + unconst); + check_one_size_helper(SIZE_MAX, + flex_array_size, obj, data, SIZE_MAX - 4 + unconst); var = 4; - err |= check_one_size_helper(sizeof(*obj) + (4 * sizeof(*obj->data)), - struct_size, obj, data, var++); - err |= check_one_size_helper(sizeof(*obj) + (5 * sizeof(*obj->data)), - struct_size, obj, data, var++); - err |= check_one_size_helper(sizeof(*obj), struct_size, obj, data, 0 + unconst); - err |= check_one_size_helper(sizeof(*obj) + sizeof(*obj->data), - struct_size, obj, data, 1 + unconst); - err |= check_one_size_helper(SIZE_MAX, - struct_size, obj, data, -3 + unconst); - err |= check_one_size_helper(SIZE_MAX, - struct_size, obj, data, SIZE_MAX - 3 + unconst); - - pr_info("%d overflow size helper tests finished\n", count); - - return err; + check_one_size_helper(sizeof(*obj) + (4 * sizeof(*obj->data)), + struct_size, obj, data, var++); + check_one_size_helper(sizeof(*obj) + (5 * sizeof(*obj->data)), + struct_size, obj, data, var++); + check_one_size_helper(sizeof(*obj), struct_size, obj, data, 0 + unconst); + check_one_size_helper(sizeof(*obj) + sizeof(*obj->data), + struct_size, obj, data, 1 + unconst); + check_one_size_helper(SIZE_MAX, + struct_size, obj, data, -3 + unconst); + check_one_size_helper(SIZE_MAX, + struct_size, obj, data, SIZE_MAX - 3 + unconst); + + kunit_info(test, "%d overflow size helper tests finished\n", count); +#undef check_one_size_helper } -static int __init test_module_init(void) -{ - int err = 0; - - err |= test_overflow_calculation(); - err |= test_overflow_shift(); - err |= test_overflow_size_helpers(); - err |= test_overflow_allocation(); - - if (err) { - pr_warn("FAIL!\n"); - err = -EINVAL; - } else { - pr_info("all tests passed\n"); - } +static struct kunit_case overflow_test_cases[] = { + KUNIT_CASE(u8_overflow_test), + KUNIT_CASE(s8_overflow_test), + KUNIT_CASE(u16_overflow_test), + KUNIT_CASE(s16_overflow_test), + KUNIT_CASE(u32_overflow_test), + KUNIT_CASE(s32_overflow_test), +#if BITS_PER_LONG == 64 + KUNIT_CASE(u64_overflow_test), + KUNIT_CASE(s64_overflow_test), +#endif + KUNIT_CASE(overflow_shift_test), + KUNIT_CASE(overflow_allocation_test), + KUNIT_CASE(overflow_size_helpers_test), + {} +}; - return err; -} +static struct kunit_suite overflow_test_suite = { + .name = "overflow", + .test_cases = overflow_test_cases, +}; -static void __exit test_module_exit(void) -{ } +kunit_test_suite(overflow_test_suite); -module_init(test_module_init); -module_exit(test_module_exit); MODULE_LICENSE("Dual MIT/GPL"); From patchwork Sun Feb 27 18:45:13 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 12762084 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 CFCE5C433EF for ; Sun, 27 Feb 2022 18:45:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231213AbiB0SqK (ORCPT ); Sun, 27 Feb 2022 13:46:10 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53014 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231209AbiB0SqE (ORCPT ); Sun, 27 Feb 2022 13:46:04 -0500 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 D713F48E5A for ; Sun, 27 Feb 2022 10:45:22 -0800 (PST) Received: by mail-pj1-x102f.google.com with SMTP id bx5so9229407pjb.3 for ; Sun, 27 Feb 2022 10:45:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=lNerjKnrLq1mzg7meHtI9HSpdFqh8op60Xx8N1ZiLfw=; b=Jr0yJeEZIKJLj1DUJnFBO3uvzL0weaiXKeajxm9pM8JoQNy2uegYOMvaJRLuJ8Uib7 Pv0U4bOC0mzJS889tXajsXuZEDCxHLF6/3dzjCPuLL7LYMNCxjD0nF6GdeWIPWR8H9Fm clw/KWTuD8soQR8FJZpgXCYEHze59giMoUZ+Y= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=lNerjKnrLq1mzg7meHtI9HSpdFqh8op60Xx8N1ZiLfw=; b=aJWHGwlQ7/xHQOeAFimvNSpKmZiWvGn7Jc4e40hVadHkn1Dd3AA/eJSJUphMChmU6D HLPH3RWV57luyfHmcV9VAasD2Xf+Z+Z5CFSk7A7eETRV+JzsYA+K+g6ivD6AUYZBFR8f jYx1IANotscjduh2HXBbFylmzk04/vlf7EwhtuoQ385bhc6gkBDzOWIIBkD85XvBuPRd zclF4dVlHahWfnjQs2LD3xKHSEAIYujjwDORBelVerLHB6J/7pvhLKMHurQRuLVKOLA2 2W7N8B5fQUCEu2RucNOStbNn8wzpxkbSLAINSviQPficOU1cE0FXwGRshCeG9s/UF+7U 3Vew== X-Gm-Message-State: AOAM5322JaeN+TPYXdA2cakRtMZUnNDs7x5H5/2uE8xVOXf1UHAihpqG 5cN0l9fxCeoEsfcIbKPnZ6FaFA== X-Google-Smtp-Source: ABdhPJwr3yU+S9CYU72TPvCVp/pkqfJFhYcfUElEnSnBBrukweZBCVubPSK86r4KINp53JP/mq3zxw== X-Received: by 2002:a17:90a:a78c:b0:1b8:b769:62d0 with SMTP id f12-20020a17090aa78c00b001b8b76962d0mr13075887pjq.227.1645987522189; Sun, 27 Feb 2022 10:45:22 -0800 (PST) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id f6-20020a056a00238600b004e1906b3bb2sm10683826pfc.12.2022.02.27.10.45.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 27 Feb 2022 10:45:21 -0800 (PST) From: Kees Cook To: Kees Cook Cc: David Gow , "Gustavo A. R. Silva" , Nathan Chancellor , Nick Desaulniers , Rasmus Villemoes , Vitor Massaru Iha , Daniel Latypov , Anton Ivanov , Jeff Dike , Richard Weinberger , Masahiro Yamada , Arnd Bergmann , linux-kernel@vger.kernel.org, linux-um@lists.infradead.org, linux-kbuild@vger.kernel.org, kunit-dev@googlegroups.com, llvm@lists.linux.dev, x86@kernel.org, linux-hardening@vger.kernel.org Subject: [PATCH v3 3/7] um: Cleanup syscall_handler_t definition/cast, fix warning Date: Sun, 27 Feb 2022 10:45:13 -0800 Message-Id: <20220227184517.504931-4-keescook@chromium.org> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220227184517.504931-1-keescook@chromium.org> References: <20220227184517.504931-1-keescook@chromium.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=2860; i=keescook@chromium.org; h=from:subject; bh=x+dnSolAXYFL3BT0a5kvXMCMP6a5EsT3sg6+p2gJHGU=; b=owEBbQKS/ZANAwAKAYly9N/cbcAmAcsmYgBiG8a7yUYgXa1FT6iIYRcyFYXJrB5R00YlXTwQ84Dl ly57u+qJAjMEAAEKAB0WIQSlw/aPIp3WD3I+bhOJcvTf3G3AJgUCYhvGuwAKCRCJcvTf3G3AJizYEA CNb2bXcut1vDNHAoju2GPOc3OFs0G8V2WKCzzUKRK1IzqIDaSsvmZft2Zh01er3fyOo/fCw+N561JI dQ5RSNtSjGVoEb02yuUbZJRtB96/H1ByjVXwEzt3GmUh+YDqRCQh0516dzh2HKYejN2BpTZOdlSnoi HNT5GnI7w0PJW1CoarvIjIHPg8kQeXRS4LQIb0/xlPQRhr4wqrbQnmumuPRIhcdgCOeqYJYEmGJTWa XDrdOKdghbjEjNJQuwPrXMgxA0nbT5QV9kNPGe5ovoiT/MUw8jAyhmbAGfEffwgMCogtTMNQ31seeB VDr9NFJDVw/R/iIKpSmijT5XKvHnrbmYVscXr4YwhogN11OtdUBcWVcZ1oSkHmT8fnHVwHThhtlXQh r59GYhqhaWouBSz1pb/g/dcpu0530mr96aeOBz0o/ZADYRAPk59CVog0QBSVlILeLJuc2w63STCWPU HhGzGEYn9aWm+kE0jLdCpPi9VmLXZ6hRCtFkxhoujHW9W9YAAcdltYUcy1W1Hf5nSM6AdAvwsIM2cJ XiAk6mLRQydd2hnuKYvux1kouR/u+aqTKC6e384tsqmzrEh1eSZhFjgt3xgqkbOAu0j3EcRxMd6KWP p/0O+lB7e9hnEMcMyLksL0BlODvLslyBwJHpobDwFRAQPTrUdUvNGzIYIsjA== X-Developer-Key: i=keescook@chromium.org; a=openpgp; fpr=A5C3F68F229DD60F723E6E138972F4DFDC6DC026 Precedence: bulk List-ID: X-Mailing-List: linux-hardening@vger.kernel.org From: David Gow The syscall_handler_t type for x86_64 was defined as 'long (*)(void)', but always cast to 'long (*)(long, long, long, long, long, long)' before use. This now triggers a warning (see below). Define syscall_handler_t as the latter instead, and remove the cast. This simplifies the code, and fixes the warning. Warning: In file included from ../arch/um/include/asm/processor-generic.h:13 from ../arch/x86/um/asm/processor.h:41 from ../include/linux/rcupdate.h:30 from ../include/linux/rculist.h:11 from ../include/linux/pid.h:5 from ../include/linux/sched.h:14 from ../include/linux/ptrace.h:6 from ../arch/um/kernel/skas/syscall.c:7: ../arch/um/kernel/skas/syscall.c: In function ‘handle_syscall’: ../arch/x86/um/shared/sysdep/syscalls_64.h:18:11: warning: cast between incompatible function types from ‘long int (*)(void)’ to ‘long int (*)(long int, long int, long int, long int, long int, long int)’ [ -Wcast-function-type] 18 | (((long (*)(long, long, long, long, long, long)) \ | ^ ../arch/x86/um/asm/ptrace.h:36:62: note: in definition of macro ‘PT_REGS_SET_SYSCALL_RETURN’ 36 | #define PT_REGS_SET_SYSCALL_RETURN(r, res) (PT_REGS_AX(r) = (res)) | ^~~ ../arch/um/kernel/skas/syscall.c:46:33: note: in expansion of macro ‘EXECUTE_SYSCALL’ 46 | EXECUTE_SYSCALL(syscall, regs)); | ^~~~~~~~~~~~~~~ Signed-off-by: David Gow Signed-off-by: Kees Cook Link: https://lore.kernel.org/r/20220210034353.1065703-1-davidgow@google.com --- This is just a re-send of the above linked patch, collecting it into this series. --- arch/x86/um/shared/sysdep/syscalls_64.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/x86/um/shared/sysdep/syscalls_64.h b/arch/x86/um/shared/sysdep/syscalls_64.h index 48d6cd12f8a5..b6b997225841 100644 --- a/arch/x86/um/shared/sysdep/syscalls_64.h +++ b/arch/x86/um/shared/sysdep/syscalls_64.h @@ -10,13 +10,12 @@ #include #include -typedef long syscall_handler_t(void); +typedef long syscall_handler_t(long, long, long, long, long, long); extern syscall_handler_t *sys_call_table[]; #define EXECUTE_SYSCALL(syscall, regs) \ - (((long (*)(long, long, long, long, long, long)) \ - (*sys_call_table[syscall]))(UPT_SYSCALL_ARG1(®s->regs), \ + (((*sys_call_table[syscall]))(UPT_SYSCALL_ARG1(®s->regs), \ UPT_SYSCALL_ARG2(®s->regs), \ UPT_SYSCALL_ARG3(®s->regs), \ UPT_SYSCALL_ARG4(®s->regs), \ From patchwork Sun Feb 27 18:45:14 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 12762086 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 3C4CFC4321E for ; Sun, 27 Feb 2022 18:45:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231200AbiB0SqJ (ORCPT ); Sun, 27 Feb 2022 13:46:09 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53358 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231213AbiB0SqI (ORCPT ); Sun, 27 Feb 2022 13:46:08 -0500 Received: from mail-pl1-x631.google.com (mail-pl1-x631.google.com [IPv6:2607:f8b0:4864:20::631]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 03BF448E77 for ; Sun, 27 Feb 2022 10:45:22 -0800 (PST) Received: by mail-pl1-x631.google.com with SMTP id i1so8910157plr.2 for ; Sun, 27 Feb 2022 10:45:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=hguOC+xPYO0eaAtZXq+RAjwSHPM/20IFHUGj359jpG8=; b=Vt+FMmf2Lvacdy2VablByMnnRD1mjjC9+gDyfFfDq1B8f1Y4ajQPMV0pNVAwM0HZ9+ ta7G8l5pJ+K0fPQjp9rdTxZyZvDIpiK8a22ZNIYRBfHI4U0rZifX7Zi4ZWRI4jtYa0tl LPTe8NuUbL6oMV+pLKAfdbADATj8s48JOZxcE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=hguOC+xPYO0eaAtZXq+RAjwSHPM/20IFHUGj359jpG8=; b=UJPfpUgwcZV5bzlTb4C/sPgd1Zu/Z55glZdE9W006faiCrmUy8YXJ94d26/P4ULv8b w0NZiZWGlJz0RXHcuqlOGEg0iErEYa98ZZaZI8rChYNEtgbda/IQCEQ7iZ+GNQrq1Aeq MQk9DepTzb1lYRNUQPoFaZvy74CgvGojWZD+t/vIjMdMMvFQbzZpJKdjqdhun+lEPc8Q rE5ksSUHDbslRw4NH/f6G2U+dSu4KbnY9dK2zjtQhvE7L81aFG0zck6+hWV0Gg36eIW9 sEeiDpSEiUE8prLCI+xB/FhPLRWWJtM7Y8CMFIDlr0GbPPpRg3/StT4MzRsvRpSHYmjM Y66A== X-Gm-Message-State: AOAM5311kJTZkyi1Fthq1aK5jhy+XbLGlFakjfGp2v3Sq5643N7DK5Na qoujzQmRq+ToJ79UGWZFrSDVUg== X-Google-Smtp-Source: ABdhPJwyo1rMccr+9zW0ZyrPf84LJWZt8qC3wyk+XmwEvTaVBmNHap92GcCcUQYiiBcW9n/4wUYQ/g== X-Received: by 2002:a17:902:8203:b0:14f:c36f:70c with SMTP id x3-20020a170902820300b0014fc36f070cmr17209832pln.95.1645987522375; Sun, 27 Feb 2022 10:45:22 -0800 (PST) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id bg3-20020a056a001f8300b004f40e8b3133sm694802pfb.188.2022.02.27.10.45.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 27 Feb 2022 10:45:21 -0800 (PST) From: Kees Cook To: Kees Cook Cc: David Gow , Anton Ivanov , "Gustavo A. R. Silva" , Nathan Chancellor , Nick Desaulniers , Rasmus Villemoes , Vitor Massaru Iha , Daniel Latypov , Jeff Dike , Richard Weinberger , Masahiro Yamada , Arnd Bergmann , linux-kernel@vger.kernel.org, linux-um@lists.infradead.org, linux-kbuild@vger.kernel.org, kunit-dev@googlegroups.com, llvm@lists.linux.dev, x86@kernel.org, linux-hardening@vger.kernel.org Subject: [PATCH v3 4/7] um: Remove unused timeval_to_ns() function Date: Sun, 27 Feb 2022 10:45:14 -0800 Message-Id: <20220227184517.504931-5-keescook@chromium.org> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220227184517.504931-1-keescook@chromium.org> References: <20220227184517.504931-1-keescook@chromium.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=1397; i=keescook@chromium.org; h=from:subject; bh=BBY0jyLtd6SE6A0Q+0QxoOVDMufJjpQntzXWcTVbBzQ=; b=owEBbQKS/ZANAwAKAYly9N/cbcAmAcsmYgBiG8a7pgTujxq03iEogLI3HZhrantD7izHXSbMposM 3ezh8hWJAjMEAAEKAB0WIQSlw/aPIp3WD3I+bhOJcvTf3G3AJgUCYhvGuwAKCRCJcvTf3G3AJvdxD/ oCEV1wTwasGpPxS1HOVrQMyGEgZMjg1DXdqdV6HOBfnHhLIsIzbWuxSG7ROL9d+etvNu4CZ+boboMy F7ft4nDST1eKRd78RKyyQPuhjph5qsS/hk7PIadhAeAy+zBCdKfXIPzdA+NlthXEVCBTJU7MfuhaS8 WnW0AsKPv7iPGwFgFd3xCJ9Bl4aLW8KtaOhcKju3e1VCGJ/s4Yzf+P9PKpsgoHBBjRJWAxHvpISG9J yuRL+4TvhGpwioQUFq1FxLJy3blx9iD3vtnGBT+uaTxYXgjQZ8DF6m/lUsVwR43OdedREO3Gle3h2O ArZdZq0I1UZ7NysvfZOXcGFyrF1+OrxIIee/APsPXfOUeFkk12RJNnNCBBXcFdv/AtnX69OORj4hLW 4VBpLH01GaHhh9bO+Nzgzoiygx0ZURY6DOIbGd85lHROMECQedbCVjnSZWrDz9aA0L2IaOw0Neipba vifUqc5dwEZaZaQ/qpTOeLvmmTlgrFN7xOfi4oLNykNb65NlKZm9AOveVJrTprb2lcc4Q+ssTRhJ79 66chg4/PouI37iL0kA7CQLexQvpIc9aUVlvvZ5E4N7heEOMbxZ85wYGG5KSjWp5dGCbDQ6UDSbqyQD PtbBq8sZX7srMnaXmhH0C7ni5QOuy5hpeXo9lOudn2EfJOcEdpCfihoVDUtg== X-Developer-Key: i=keescook@chromium.org; a=openpgp; fpr=A5C3F68F229DD60F723E6E138972F4DFDC6DC026 Precedence: bulk List-ID: X-Mailing-List: linux-hardening@vger.kernel.org From: David Gow The timeval_to_ns() function doesn't appear to be used anywhere, as far as I (or git grep) can tell, and clang throws up a warning about it: ../arch/um/os-Linux/time.c:21:25: warning: unused function 'timeval_to_ns' [-Wunused-function] static inline long long timeval_to_ns(const struct timeval *tv) ^ 1 warning generated. Signed-off-by: David Gow Acked-By: Anton Ivanov Link: https://lore.kernel.org/lkml/78d6ac17-9492-7c41-d6dd-4c92dce8ce62@cambridgegreys.com Signed-off-by: Kees Cook Link: https://lore.kernel.org/r/20220224081233.1765788-1-davidgow@google.com --- This is a resend of the above linked patch, just included in this series. --- arch/um/os-Linux/time.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c index 6c5041c5560b..4d5591d96d8c 100644 --- a/arch/um/os-Linux/time.c +++ b/arch/um/os-Linux/time.c @@ -18,12 +18,6 @@ static timer_t event_high_res_timer = 0; -static inline long long timeval_to_ns(const struct timeval *tv) -{ - return ((long long) tv->tv_sec * UM_NSEC_PER_SEC) + - tv->tv_usec * UM_NSEC_PER_USEC; -} - static inline long long timespec_to_ns(const struct timespec *ts) { return ((long long) ts->tv_sec * UM_NSEC_PER_SEC) + ts->tv_nsec; From patchwork Sun Feb 27 18:45:15 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 12762089 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 68F74C4167D for ; Sun, 27 Feb 2022 18:45:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231218AbiB0SqL (ORCPT ); Sun, 27 Feb 2022 13:46:11 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53340 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229644AbiB0SqJ (ORCPT ); Sun, 27 Feb 2022 13:46:09 -0500 Received: from mail-pj1-x102a.google.com (mail-pj1-x102a.google.com [IPv6:2607:f8b0:4864:20::102a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0421050B30 for ; Sun, 27 Feb 2022 10:45:23 -0800 (PST) Received: by mail-pj1-x102a.google.com with SMTP id ev16-20020a17090aead000b001bc3835fea8so9464391pjb.0 for ; Sun, 27 Feb 2022 10:45:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=BMkktAsNfHIhPa1AJtPClUlYlr4FtiZE1a3GDbCXgk4=; b=eH6EZmnqMckOS9O4oCCAOQ97Gk7PWZAVrFVwAHWRPKjSCasHblw8J3H51Cto/L4Oq/ 7zqDwL6uGdZO25v6bmjZhS2MBNmqdSItLdQ8tnbuPyKYCvQsgJaqVAw1FtxJcVe83/LS Zy2H2PJDdnwp3/ziVO/JJXQqpsFMARfT5Ychk= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=BMkktAsNfHIhPa1AJtPClUlYlr4FtiZE1a3GDbCXgk4=; b=YSQgl/lz5HQoDfVAtUzQ8oPXH9c9LH5bJEiZ2yVe/z09KViFEp8+2mlVXuuQe8fuyQ XhB+JtcWp07K8krlK9JulQRkoKhAUS8mDBAD7yFt9BgUGc/ud+j9ZpBd+B6dPiSCJ9/Y qsIioL1LaydSe0zqWCdp+k/feB4fLIenNXEG/o7tBmNpnfXIMa5Dl60UyROZmteardZF IaHDPE88AusHKciuxVztbBg55KdAMiZ/OuB0I63Xg8FnSf52Ry+2tM5jeIuqYLP3bDsz //07iAMgr1FWfA2dtx7jXG51dQChwbomVJ+tnNik1HazWvZ97nfGyrTDp9CzBpHo/rhp X3NA== X-Gm-Message-State: AOAM5334X+lsaxt554YWZgSi5ts1/VGMPV9JiHBu2uo1VsVFSe/+Jijf q9K+yTkRHAdIY7troMkepx6Xrw== X-Google-Smtp-Source: ABdhPJw84+Su+R84+skE0k1lOhQUbnaFmq9xBqLDdfjXiaJKJ64Oxb/qHpmbmqqlBln5RT3beTcbVA== X-Received: by 2002:a17:902:d705:b0:14e:e5a2:1b34 with SMTP id w5-20020a170902d70500b0014ee5a21b34mr16650742ply.88.1645987523283; Sun, 27 Feb 2022 10:45:23 -0800 (PST) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id y12-20020a62ce0c000000b004ec4d8900d5sm10038318pfg.163.2022.02.27.10.45.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 27 Feb 2022 10:45:23 -0800 (PST) From: Kees Cook To: Kees Cook Cc: Jeff Dike , Richard Weinberger , Anton Ivanov , Masahiro Yamada , Nick Desaulniers , Nathan Chancellor , David Gow , linux-um@lists.infradead.org, linux-kbuild@vger.kernel.org, linux-kselftest@vger.kernel.org, kunit-dev@googlegroups.com, llvm@lists.linux.dev, "Gustavo A. R. Silva" , Rasmus Villemoes , Vitor Massaru Iha , Daniel Latypov , Arnd Bergmann , linux-kernel@vger.kernel.org, x86@kernel.org, linux-hardening@vger.kernel.org Subject: [PATCH v3 5/7] um: Allow builds with Clang Date: Sun, 27 Feb 2022 10:45:15 -0800 Message-Id: <20220227184517.504931-6-keescook@chromium.org> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220227184517.504931-1-keescook@chromium.org> References: <20220227184517.504931-1-keescook@chromium.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=3536; h=from:subject; bh=9QnH+z+rCwCFrRsn/51gPTE+pPH8ccRFsd0v6DZGBGk=; b=owEBbQKS/ZANAwAKAYly9N/cbcAmAcsmYgBiG8a8dEBk1HwrxEO2kL1Oda4tIa5yb6JeGO7Q8F+W TXMu3eKJAjMEAAEKAB0WIQSlw/aPIp3WD3I+bhOJcvTf3G3AJgUCYhvGvAAKCRCJcvTf3G3AJh5fD/ 9KuzRhMOYg8agcaXgdhk9bHElsujSJHIv4H/iYy4vhIm5y+K4au1niInCr8gbRxN8h9SSpzFeHVeOV A+xuZDPDYD0/lGfOoYtZpV2f9uQZVbCu2O4DEne9NwKDTvoIRjBem9qfJmbhHpG6gcFnEYy8IA3/oe YoJUrjDoIKakakFQ0EWS7Y3OF6mZutVETPOUUBQJJ6FTmaXehOi2JRWbE5M0Y6f1utAKkHM7GQObJl gp4Y6NzKu3MsgDQC/PitvlV7wxex2381qQKHfMjaBXLtUKLizYHyvbjWStV9XM2J6VbCt0BU/LV+yJ qDs59Ih223zt/j7TbKxTAjrwLIX+byh70A+0o9K4CJvWbyAJ9X5CnAccGvf1HCW28QwuyLrpTwSAy8 YiSKxd9UxcYUI4/CDSV+8r72iiUkt7nWG1Ygv1E416BjhxHrDuk2k7nFssdZEYfIlDIqQA8ey/QpWf d48v7LOCx1Cui2GUH/XGI/QqDM7TOISr58NfvoT02QrJ398Hk/EovB9Y1CzFA+hlUrdcmRLnfw+THt WQvvUo7T7/w80plD1UFpTjsxcPq6znVhO0NCDULvpyGKXfCqzxri43YBojcrgwA4vXNVIrRUeaC5RW nBl0txZW59SpCiVLjlI9W0bmg+VGOmyOQGYcXCJo4mdIvb2DjeBGm21cJnyA== X-Developer-Key: i=keescook@chromium.org; a=openpgp; fpr=A5C3F68F229DD60F723E6E138972F4DFDC6DC026 Precedence: bulk List-ID: X-Mailing-List: linux-hardening@vger.kernel.org Add SUBARCH target for Clang+um (which must go last, not alphabetically, so the other SUBARCHes are assigned). Remove open-coded "DEFINE" macro, instead using linux/kbuild.h's version which was updated to use Clang-friendly assembly in commit cf0c3e68aa81 ("kbuild: fix asm-offset generation to work with clang"). Redefine "DEFINE_LONGS" in terms of "COMMENT" and "DEFINE" so that the intended coment actually has useful content. Add a missed "break" to avoid implicit fall-through warnings. This lets me run KUnit tests with Clang: $ ./tools/testing/kunit/kunit.py run --make_options LLVM=1 ... Cc: Jeff Dike Cc: Richard Weinberger Cc: Anton Ivanov Cc: Masahiro Yamada Cc: Nick Desaulniers Cc: Nathan Chancellor Cc: David Gow Cc: linux-um@lists.infradead.org Cc: linux-kbuild@vger.kernel.org Cc: linux-kselftest@vger.kernel.org Cc: kunit-dev@googlegroups.com Cc: llvm@lists.linux.dev Reviewed-by: Nathan Chancellor Link: https://lore.kernel.org/lkml/Yg2YubZxvYvx7%2Fnm@dev-arch.archlinux-ax161/ Tested-by: David Gow Link: https://lore.kernel.org/lkml/CABVgOSk=oFxsbSbQE-v65VwR2+mXeGXDDjzq8t7FShwjJ3+kUg@mail.gmail.com/ Signed-off-by: Kees Cook --- v1: https://lore.kernel.org/lkml/20220217002843.2312603-1-keescook@chromium.org v2: https://lore.kernel.org/lkml/20220224055831.1854786-1-keescook@chromium.org v3: - use kbuild.h to avoid duplication (Masahiro) - fix intended comments (Masahiro) - use SUBARCH (Nathan) --- arch/um/os-Linux/execvp.c | 1 + arch/x86/um/user-offsets.c | 9 ++++----- scripts/Makefile.clang | 1 + 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/arch/um/os-Linux/execvp.c b/arch/um/os-Linux/execvp.c index 84a0777c2a45..c09a5fd5e225 100644 --- a/arch/um/os-Linux/execvp.c +++ b/arch/um/os-Linux/execvp.c @@ -93,6 +93,7 @@ int execvp_noalloc(char *buf, const char *file, char *const argv[]) up finding no executable we can use, we want to diagnose that we did find one but were denied access. */ got_eacces = 1; + break; case ENOENT: case ESTALE: case ENOTDIR: diff --git a/arch/x86/um/user-offsets.c b/arch/x86/um/user-offsets.c index bae61554abcc..e54a9814ccf1 100644 --- a/arch/x86/um/user-offsets.c +++ b/arch/x86/um/user-offsets.c @@ -8,12 +8,11 @@ #define __FRAME_OFFSETS #include #include +#include -#define DEFINE(sym, val) \ - asm volatile("\n->" #sym " %0 " #val : : "i" (val)) - -#define DEFINE_LONGS(sym, val) \ - asm volatile("\n->" #sym " %0 " #val : : "i" (val/sizeof(unsigned long))) +#define DEFINE_LONGS(sym, val) \ + COMMENT(#val " / sizeof(unsigned long)"); \ + DEFINE(sym, val / sizeof(unsigned long)) void foo(void) { diff --git a/scripts/Makefile.clang b/scripts/Makefile.clang index 51fc23e2e9e5..87285b76adb2 100644 --- a/scripts/Makefile.clang +++ b/scripts/Makefile.clang @@ -10,6 +10,7 @@ CLANG_TARGET_FLAGS_powerpc := powerpc64le-linux-gnu CLANG_TARGET_FLAGS_riscv := riscv64-linux-gnu CLANG_TARGET_FLAGS_s390 := s390x-linux-gnu CLANG_TARGET_FLAGS_x86 := x86_64-linux-gnu +CLANG_TARGET_FLAGS_um := $(CLANG_TARGET_FLAGS_$(SUBARCH)) CLANG_TARGET_FLAGS := $(CLANG_TARGET_FLAGS_$(SRCARCH)) ifeq ($(CROSS_COMPILE),) From patchwork Sun Feb 27 18:45:16 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 12762088 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 B59E9C3525A for ; Sun, 27 Feb 2022 18:45:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231244AbiB0SqM (ORCPT ); Sun, 27 Feb 2022 13:46:12 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53370 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231255AbiB0SqJ (ORCPT ); Sun, 27 Feb 2022 13:46:09 -0500 Received: from mail-pj1-x1029.google.com (mail-pj1-x1029.google.com [IPv6:2607:f8b0:4864:20::1029]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4BD2D517CE for ; Sun, 27 Feb 2022 10:45:24 -0800 (PST) Received: by mail-pj1-x1029.google.com with SMTP id m22so9273948pja.0 for ; Sun, 27 Feb 2022 10:45:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=q6m+DhiSNpp0WEg7Y2GFtce2qoilswFv9XNCymBz300=; b=adurY7lnz6k4Lj7dGkSWg3wTjUo42w1bdJZXLgnRdjA8hkoEPM7J4cvLrp/CrDlLZl Kp5lTQEv4oXe/qyvj2H1tsFXgV69fEpPRjxajXYVyMOv4OHWkZ3G6MpUWIT0wSgreplv PXCW9ylgqLq1EAmFd14NpGlzCdpa8Ed3aenmM= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=q6m+DhiSNpp0WEg7Y2GFtce2qoilswFv9XNCymBz300=; b=VqA5Mgt/zCFciBciVWj+oocp3vRvJTKpJL2AJ1gJGyjkJDAMJFwvSVzh/V9i+XMbxf OMi8JbEZyeMuKSXNfiPfQv0oma8T6Rn9hhzgt6VCZWgG8+bvqu/g5OValt4Q8JB6+Rxp jzzjXSeFgkA2k7G6NxOXF69C40Lo7aFwxYy67I2ldEwEu4Z9VAwLK5r+H3I3iYD7Qpzm Qg+B+doxcYDo4QjHY1rvc7Ty+sM09z7gPFcu43O5400KgESXq9aXRgXtxb0HtLrmQJuQ Tu7iXq7aTdi29Jnfq2TMoxnAbGgkImcS5oWdCNj3g7wSD+17SbxFDC/ZL3fOKicTakzJ b8WA== X-Gm-Message-State: AOAM530kRRuFDo+svm6LUiMG57oMTA5OU0wICds/O8cSlRux8bUxlWNd hnGojo0cI09rr5oUxkvlyaGdeA== X-Google-Smtp-Source: ABdhPJwSlhs6c8I9Lo6GGuabSIXJWoTu3k7tDJKSwX1nd4WRcf7i7kGNzdvNDJBsvRw8NeGFJP+y+Q== X-Received: by 2002:a17:902:d4d1:b0:150:1d1c:30bd with SMTP id o17-20020a170902d4d100b001501d1c30bdmr15303539plg.1.1645987523611; Sun, 27 Feb 2022 10:45:23 -0800 (PST) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id o10-20020a056a0015ca00b004e0ff94313esm11270971pfu.91.2022.02.27.10.45.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 27 Feb 2022 10:45:23 -0800 (PST) From: Kees Cook To: Kees Cook Cc: David Gow , Daniel Latypov , Arnd Bergmann , "Gustavo A. R. Silva" , Nathan Chancellor , Nick Desaulniers , Rasmus Villemoes , Vitor Massaru Iha , Anton Ivanov , Jeff Dike , Richard Weinberger , Masahiro Yamada , linux-kernel@vger.kernel.org, linux-um@lists.infradead.org, linux-kbuild@vger.kernel.org, kunit-dev@googlegroups.com, llvm@lists.linux.dev, x86@kernel.org, linux-hardening@vger.kernel.org Subject: [PATCH v3 6/7] lib: stackinit: Convert to KUnit Date: Sun, 27 Feb 2022 10:45:16 -0800 Message-Id: <20220227184517.504931-7-keescook@chromium.org> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220227184517.504931-1-keescook@chromium.org> References: <20220227184517.504931-1-keescook@chromium.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=18150; h=from:subject; bh=UP9YVxfMlY8O0+NQMLGofpK4VLIvcpYgNEp/ewL3Cy0=; b=owEBbQKS/ZANAwAKAYly9N/cbcAmAcsmYgBiG8a8zSAsXG7oEnfr4TxZoZxcd4Pag+vI1Jn94X84 /Vw1XsGJAjMEAAEKAB0WIQSlw/aPIp3WD3I+bhOJcvTf3G3AJgUCYhvGvAAKCRCJcvTf3G3AJjCiD/ 0aDe79UaDsyIhrBubBQeRFGV5QTV312hqgfejYoVW3REqLHpl78/fSarG3KikpGeFhv1YY0RcRM+LB cK57iEymCQLba9GlFso5OpTJToY/PjfR7MdxaKgNDVPwQi2NMFIA7gyqoiKZsOBXxJ5x4jYCH1Eiim /B2r2PzGMQC1gXPAlZUi9SrWk7VG9xVFtI2d35Ki7YXslzg7B5/2lwufNFNBaLpoAszcwuKKGZ0xbE njN41caNWtAz1mNT6PlY2vpI/yLkQU38Zq4CdOmmTl8FVL1N+/fpBsc9dnhQcgbuxf2Tr+56NriT1/ y39P7GrZ/F6upX1PxoAMj2Q1FMFERWjLra2zRy8a9m8cxyGcrrkDP3CuqeyusBU0pfLYyQstsNFzhr D+NTQrT2sA8Owp5qm5oHhVqLK5ffOr8T23fQlfdaXqOlzQ0OLngadBP8F1MoMsIvaOM5M1c0W30RYl AK6fvvMbQVMzXs1KYhWTIYIy7saF7GE5bkGm8ILXL/bl9DSo1qKyCk1RakqLj+Uae9gEKF2R1DWBmZ u3kSM4yxBfl3kbobot0gBrqat9yf9vdWWka4EsDWulrAykZB5rGiUXgx4Cf2S62VwtKeVy9hj++1Rp zYZWWyU1BqVm+FQrm3AitOiotMe+NuQz/twVybOPywFHWrllAtWKN6S5obvQ== X-Developer-Key: i=keescook@chromium.org; a=openpgp; fpr=A5C3F68F229DD60F723E6E138972F4DFDC6DC026 Precedence: bulk List-ID: X-Mailing-List: linux-hardening@vger.kernel.org Convert stackinit unit tests to KUnit, for better integration into the kernel self test framework. Includes a rename of test_stackinit.c to stackinit_kunit.c, and CONFIG_TEST_STACKINIT to CONFIG_STACKINIT_KUNIT_TEST. Adjust expected test results based on which stack initialization method was chosen: $ CMD="./tools/testing/kunit/kunit.py run stackinit --raw_output \ --arch=x86_64 --kconfig_add" $ $CMD | grep stackinit: # stackinit: pass:36 fail:0 skip:29 total:65 $ $CMD CONFIG_GCC_PLUGIN_STRUCTLEAK_USER=y | grep stackinit: # stackinit: pass:37 fail:0 skip:28 total:65 $ $CMD CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF=y | grep stackinit: # stackinit: pass:55 fail:0 skip:10 total:65 $ $CMD CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL=y | grep stackinit: # stackinit: pass:62 fail:0 skip:3 total:65 $ $CMD CONFIG_INIT_STACK_ALL_PATTERN=y --make_option LLVM=1 | grep stackinit: # stackinit: pass:60 fail:0 skip:5 total:65 $ $CMD CONFIG_INIT_STACK_ALL_ZERO=y --make_option LLVM=1 | grep stackinit: # stackinit: pass:60 fail:0 skip:5 total:65 Temporarily remove the userspace-build mode, which will be restored in a later patch. Expand the size of the pre-case switch variable so it doesn't get accidentally cleared. Cc: David Gow Cc: Daniel Latypov Cc: Arnd Bergmann Signed-off-by: Kees Cook --- v1: https://lore.kernel.org/lkml/20220224055145.1853657-1-keescook@chromium.org v2: - split "userspace KUnit stub" into separate header and patch (Daniel) - Improve commit log and comments (David) - Provide mapping of expected XFAIL tests to CONFIGs (David) --- lib/Kconfig.debug | 22 +- lib/Makefile | 4 +- lib/{test_stackinit.c => stackinit_kunit.c} | 269 ++++++++------------ 3 files changed, 121 insertions(+), 174 deletions(-) rename lib/{test_stackinit.c => stackinit_kunit.c} (66%) diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 14d90d03bc8d..a5556ab05240 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -2511,6 +2511,17 @@ config OVERFLOW_KUNIT_TEST If unsure, say N. +config STACKINIT_KUNIT_TEST + tristate "Test level of stack variable initialization" if !KUNIT_ALL_TESTS + depends on KUNIT + default KUNIT_ALL_TESTS + help + Test if the kernel is zero-initializing stack variables and + padding. Coverage is controlled by compiler flags, + CONFIG_INIT_STACK_ALL_PATTERN, CONFIG_INIT_STACK_ALL_ZERO, + CONFIG_GCC_PLUGIN_STRUCTLEAK, CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF, + or CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL. + config TEST_UDELAY tristate "udelay test driver" help @@ -2602,17 +2613,6 @@ config TEST_OBJAGG Enable this option to test object aggregation manager on boot (or module load). - -config TEST_STACKINIT - tristate "Test level of stack variable initialization" - help - Test if the kernel is zero-initializing stack variables and - padding. Coverage is controlled by compiler flags, - CONFIG_GCC_PLUGIN_STRUCTLEAK, CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF, - or CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL. - - If unsure, say N. - config TEST_MEMINIT tristate "Test heap/page initialization" help diff --git a/lib/Makefile b/lib/Makefile index fdfcbfaff32f..353bc09ce38d 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -93,8 +93,6 @@ obj-$(CONFIG_TEST_KMOD) += test_kmod.o obj-$(CONFIG_TEST_DEBUG_VIRTUAL) += test_debug_virtual.o obj-$(CONFIG_TEST_MEMCAT_P) += test_memcat_p.o obj-$(CONFIG_TEST_OBJAGG) += test_objagg.o -CFLAGS_test_stackinit.o += $(call cc-disable-warning, switch-unreachable) -obj-$(CONFIG_TEST_STACKINIT) += test_stackinit.o obj-$(CONFIG_TEST_BLACKHOLE_DEV) += test_blackhole_dev.o obj-$(CONFIG_TEST_MEMINIT) += test_meminit.o obj-$(CONFIG_TEST_LOCKUP) += test_lockup.o @@ -363,6 +361,8 @@ obj-$(CONFIG_CMDLINE_KUNIT_TEST) += cmdline_kunit.o obj-$(CONFIG_SLUB_KUNIT_TEST) += slub_kunit.o obj-$(CONFIG_MEMCPY_KUNIT_TEST) += memcpy_kunit.o obj-$(CONFIG_OVERFLOW_KUNIT_TEST) += overflow_kunit.o +CFLAGS_stackinit_kunit.o += $(call cc-disable-warning, switch-unreachable) +obj-$(CONFIG_STACKINIT_KUNIT_TEST) += stackinit_kunit.o obj-$(CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED) += devmem_is_allowed.o diff --git a/lib/test_stackinit.c b/lib/stackinit_kunit.c similarity index 66% rename from lib/test_stackinit.c rename to lib/stackinit_kunit.c index a3c74e6a21ff..35c69aa425b2 100644 --- a/lib/test_stackinit.c +++ b/lib/stackinit_kunit.c @@ -2,76 +2,21 @@ /* * Test cases for compiler-based stack variable zeroing via * -ftrivial-auto-var-init={zero,pattern} or CONFIG_GCC_PLUGIN_STRUCTLEAK*. + * For example, see: + * https://www.kernel.org/doc/html/latest/dev-tools/kunit/kunit-tool.html#configuring-building-and-running-tests + * ./tools/testing/kunit/kunit.py run stackinit [--raw_output] \ + * --make_option LLVM=1 \ + * --kconfig_add CONFIG_INIT_STACK_ALL_ZERO=y * - * External build example: - * clang -O2 -Wall -ftrivial-auto-var-init=pattern \ - * -o test_stackinit test_stackinit.c */ -#ifdef __KERNEL__ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include #include #include #include #include -#else - -/* Userspace headers. */ -#include -#include -#include -#include -#include -#include - -/* Linux kernel-ism stubs for stand-alone userspace build. */ -#define KBUILD_MODNAME "stackinit" -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#define pr_err(fmt, ...) fprintf(stderr, pr_fmt(fmt), ##__VA_ARGS__) -#define pr_warn(fmt, ...) fprintf(stderr, pr_fmt(fmt), ##__VA_ARGS__) -#define pr_info(fmt, ...) fprintf(stdout, pr_fmt(fmt), ##__VA_ARGS__) -#define __init /**/ -#define __exit /**/ -#define __user /**/ -#define noinline __attribute__((__noinline__)) -#define __aligned(x) __attribute__((__aligned__(x))) -#ifdef __clang__ -# define __compiletime_error(message) /**/ -#else -# define __compiletime_error(message) __attribute__((__error__(message))) -#endif -#define __compiletime_assert(condition, msg, prefix, suffix) \ - do { \ - extern void prefix ## suffix(void) __compiletime_error(msg); \ - if (!(condition)) \ - prefix ## suffix(); \ - } while (0) -#define _compiletime_assert(condition, msg, prefix, suffix) \ - __compiletime_assert(condition, msg, prefix, suffix) -#define compiletime_assert(condition, msg) \ - _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) -#define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) -#define BUILD_BUG_ON(condition) \ - BUILD_BUG_ON_MSG(condition, "BUILD_BUG_ON failed: " #condition) -typedef uint8_t u8; -typedef uint16_t u16; -typedef uint32_t u32; -typedef uint64_t u64; - -#define module_init(func) static int (*do_init)(void) = func -#define module_exit(func) static void (*do_exit)(void) = func -#define MODULE_LICENSE(str) int main(void) { \ - int rc; \ - /* License: str */ \ - rc = do_init(); \ - if (rc == 0) \ - do_exit(); \ - return rc; \ - } - -#endif /* __KERNEL__ */ - /* Exfiltration buffer. */ #define MAX_VAR_SIZE 128 static u8 check_buf[MAX_VAR_SIZE]; @@ -201,7 +146,7 @@ static bool range_contains(char *haystack_start, size_t haystack_size, */ #define DEFINE_TEST_DRIVER(name, var_type, which, xfail) \ /* Returns 0 on success, 1 on failure. */ \ -static noinline __init int test_ ## name (void) \ +static noinline void test_ ## name (struct kunit *test) \ { \ var_type zero INIT_CLONE_ ## which; \ int ignored; \ @@ -220,10 +165,8 @@ static noinline __init int test_ ## name (void) \ /* Verify all bytes overwritten with 0xFF. */ \ for (sum = 0, i = 0; i < target_size; i++) \ sum += (check_buf[i] != 0xFF); \ - if (sum) { \ - pr_err(#name ": leaf fill was not 0xFF!?\n"); \ - return 1; \ - } \ + KUNIT_ASSERT_EQ_MSG(test, sum, 0, \ + "leaf fill was not 0xFF!?\n"); \ /* Clear entire check buffer for later bit tests. */ \ memset(check_buf, 0x00, sizeof(check_buf)); \ /* Extract stack-defined variable contents. */ \ @@ -231,32 +174,29 @@ static noinline __init int test_ ## name (void) \ FETCH_ARG_ ## which(zero)); \ \ /* Validate that compiler lined up fill and target. */ \ - if (!range_contains(fill_start, fill_size, \ - target_start, target_size)) { \ - pr_err(#name ": stack fill missed target!?\n"); \ - pr_err(#name ": fill %zu wide\n", fill_size); \ - pr_err(#name ": target offset by %d\n", \ - (int)((ssize_t)(uintptr_t)fill_start - \ - (ssize_t)(uintptr_t)target_start)); \ - return 1; \ - } \ + KUNIT_ASSERT_TRUE_MSG(test, \ + range_contains(fill_start, fill_size, \ + target_start, target_size), \ + "stack fill missed target!? " \ + "(fill %zu wide, target offset by %d)\n", \ + fill_size, \ + (int)((ssize_t)(uintptr_t)fill_start - \ + (ssize_t)(uintptr_t)target_start)); \ \ /* Look for any bytes still 0xFF in check region. */ \ for (sum = 0, i = 0; i < target_size; i++) \ sum += (check_buf[i] == 0xFF); \ \ - if (sum == 0) { \ - pr_info(#name " ok\n"); \ - return 0; \ - } else { \ - pr_warn(#name " %sFAIL (uninit bytes: %d)\n", \ - (xfail) ? "X" : "", sum); \ - return (xfail) ? 0 : 1; \ - } \ + if (sum != 0 && xfail) \ + kunit_skip(test, \ + "XFAIL uninit bytes: %d\n", \ + sum); \ + KUNIT_ASSERT_EQ_MSG(test, sum, 0, \ + "uninit bytes: %d\n", sum); \ } #define DEFINE_TEST(name, var_type, which, init_level, xfail) \ /* no-op to force compiler into ignoring "uninitialized" vars */\ -static noinline __init DO_NOTHING_TYPE_ ## which(var_type) \ +static noinline DO_NOTHING_TYPE_ ## which(var_type) \ do_nothing_ ## name(var_type *ptr) \ { \ /* Will always be true, but compiler doesn't know. */ \ @@ -265,9 +205,8 @@ do_nothing_ ## name(var_type *ptr) \ else \ return DO_NOTHING_RETURN_ ## which(ptr + 1); \ } \ -static noinline __init int leaf_ ## name(unsigned long sp, \ - bool fill, \ - var_type *arg) \ +static noinline int leaf_ ## name(unsigned long sp, bool fill, \ + var_type *arg) \ { \ char buf[VAR_BUFFER]; \ var_type var \ @@ -341,6 +280,27 @@ struct test_user { unsigned long four; }; +#define ALWAYS_PASS WANT_SUCCESS +#define ALWAYS_FAIL XFAIL + +#ifdef CONFIG_INIT_STACK_NONE +# define USER_PASS XFAIL +# define BYREF_PASS XFAIL +# define STRONG_PASS XFAIL +#elif defined(CONFIG_GCC_PLUGIN_STRUCTLEAK_USER) +# define USER_PASS WANT_SUCCESS +# define BYREF_PASS XFAIL +# define STRONG_PASS XFAIL +#elif defined(CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF) +# define USER_PASS WANT_SUCCESS +# define BYREF_PASS WANT_SUCCESS +# define STRONG_PASS XFAIL +#else +# define USER_PASS WANT_SUCCESS +# define BYREF_PASS WANT_SUCCESS +# define STRONG_PASS WANT_SUCCESS +#endif + #define DEFINE_SCALAR_TEST(name, init, xfail) \ DEFINE_TEST(name ## _ ## init, name, SCALAR, \ init, xfail) @@ -364,27 +324,26 @@ struct test_user { DEFINE_STRUCT_TEST(trailing_hole, init, xfail); \ DEFINE_STRUCT_TEST(packed, init, xfail) -#define DEFINE_STRUCT_INITIALIZER_TESTS(base) \ +#define DEFINE_STRUCT_INITIALIZER_TESTS(base, xfail) \ DEFINE_STRUCT_TESTS(base ## _ ## partial, \ - WANT_SUCCESS); \ - DEFINE_STRUCT_TESTS(base ## _ ## all, \ - WANT_SUCCESS) + xfail); \ + DEFINE_STRUCT_TESTS(base ## _ ## all, xfail) /* These should be fully initialized all the time! */ -DEFINE_SCALAR_TESTS(zero, WANT_SUCCESS); -DEFINE_STRUCT_TESTS(zero, WANT_SUCCESS); +DEFINE_SCALAR_TESTS(zero, ALWAYS_PASS); +DEFINE_STRUCT_TESTS(zero, ALWAYS_PASS); /* Struct initializers: padding may be left uninitialized. */ -DEFINE_STRUCT_INITIALIZER_TESTS(static); -DEFINE_STRUCT_INITIALIZER_TESTS(dynamic); -DEFINE_STRUCT_INITIALIZER_TESTS(runtime); -DEFINE_STRUCT_INITIALIZER_TESTS(assigned_static); -DEFINE_STRUCT_INITIALIZER_TESTS(assigned_dynamic); -DEFINE_STRUCT_TESTS(assigned_copy, XFAIL); +DEFINE_STRUCT_INITIALIZER_TESTS(static, STRONG_PASS); +DEFINE_STRUCT_INITIALIZER_TESTS(dynamic, STRONG_PASS); +DEFINE_STRUCT_INITIALIZER_TESTS(runtime, STRONG_PASS); +DEFINE_STRUCT_INITIALIZER_TESTS(assigned_static, STRONG_PASS); +DEFINE_STRUCT_INITIALIZER_TESTS(assigned_dynamic, STRONG_PASS); +DEFINE_STRUCT_TESTS(assigned_copy, ALWAYS_FAIL); /* No initialization without compiler instrumentation. */ -DEFINE_SCALAR_TESTS(none, WANT_SUCCESS); -DEFINE_STRUCT_TESTS(none, WANT_SUCCESS); +DEFINE_SCALAR_TESTS(none, STRONG_PASS); +DEFINE_STRUCT_TESTS(none, BYREF_PASS); /* Initialization of members with __user attribute. */ -DEFINE_TEST(user, struct test_user, STRUCT, none, WANT_SUCCESS); +DEFINE_TEST(user, struct test_user, STRUCT, none, USER_PASS); /* * Check two uses through a variable declaration outside either path, @@ -398,7 +357,7 @@ static int noinline __leaf_switch_none(int path, bool fill) * This is intentionally unreachable. To silence the * warning, build with -Wno-switch-unreachable */ - uint64_t var; + uint64_t var[10]; case 1: target_start = &var; @@ -423,19 +382,19 @@ static int noinline __leaf_switch_none(int path, bool fill) memcpy(check_buf, target_start, target_size); break; default: - var = 5; - return var & forced_mask; + var[1] = 5; + return var[1] & forced_mask; } return 0; } -static noinline __init int leaf_switch_1_none(unsigned long sp, bool fill, +static noinline int leaf_switch_1_none(unsigned long sp, bool fill, uint64_t *arg) { return __leaf_switch_none(1, fill); } -static noinline __init int leaf_switch_2_none(unsigned long sp, bool fill, +static noinline int leaf_switch_2_none(unsigned long sp, bool fill, uint64_t *arg) { return __leaf_switch_none(2, fill); @@ -447,68 +406,56 @@ static noinline __init int leaf_switch_2_none(unsigned long sp, bool fill, * non-code areas (i.e. in a switch statement before the first "case"). * https://bugs.llvm.org/show_bug.cgi?id=44916 */ -DEFINE_TEST_DRIVER(switch_1_none, uint64_t, SCALAR, XFAIL); -DEFINE_TEST_DRIVER(switch_2_none, uint64_t, SCALAR, XFAIL); - -static int __init test_stackinit_init(void) -{ - unsigned int failures = 0; - -#define test_scalars(init) do { \ - failures += test_u8_ ## init (); \ - failures += test_u16_ ## init (); \ - failures += test_u32_ ## init (); \ - failures += test_u64_ ## init (); \ - failures += test_char_array_ ## init (); \ - } while (0) - -#define test_structs(init) do { \ - failures += test_small_hole_ ## init (); \ - failures += test_big_hole_ ## init (); \ - failures += test_trailing_hole_ ## init (); \ - failures += test_packed_ ## init (); \ - } while (0) - +DEFINE_TEST_DRIVER(switch_1_none, uint64_t, SCALAR, ALWAYS_FAIL); +DEFINE_TEST_DRIVER(switch_2_none, uint64_t, SCALAR, ALWAYS_FAIL); + +#define KUNIT_test_scalars(init) \ + KUNIT_CASE(test_u8_ ## init), \ + KUNIT_CASE(test_u16_ ## init), \ + KUNIT_CASE(test_u32_ ## init), \ + KUNIT_CASE(test_u64_ ## init), \ + KUNIT_CASE(test_char_array_ ## init) + +#define KUNIT_test_structs(init) \ + KUNIT_CASE(test_small_hole_ ## init), \ + KUNIT_CASE(test_big_hole_ ## init), \ + KUNIT_CASE(test_trailing_hole_ ## init),\ + KUNIT_CASE(test_packed_ ## init) \ + +static struct kunit_case stackinit_test_cases[] = { /* These are explicitly initialized and should always pass. */ - test_scalars(zero); - test_structs(zero); + KUNIT_test_scalars(zero), + KUNIT_test_structs(zero), /* Padding here appears to be accidentally always initialized? */ - test_structs(dynamic_partial); - test_structs(assigned_dynamic_partial); + KUNIT_test_structs(dynamic_partial), + KUNIT_test_structs(assigned_dynamic_partial), /* Padding initialization depends on compiler behaviors. */ - test_structs(static_partial); - test_structs(static_all); - test_structs(dynamic_all); - test_structs(runtime_partial); - test_structs(runtime_all); - test_structs(assigned_static_partial); - test_structs(assigned_static_all); - test_structs(assigned_dynamic_all); + KUNIT_test_structs(static_partial), + KUNIT_test_structs(static_all), + KUNIT_test_structs(dynamic_all), + KUNIT_test_structs(runtime_partial), + KUNIT_test_structs(runtime_all), + KUNIT_test_structs(assigned_static_partial), + KUNIT_test_structs(assigned_static_all), + KUNIT_test_structs(assigned_dynamic_all), /* Everything fails this since it effectively performs a memcpy(). */ - test_structs(assigned_copy); - + KUNIT_test_structs(assigned_copy), /* STRUCTLEAK_BYREF_ALL should cover everything from here down. */ - test_scalars(none); - failures += test_switch_1_none(); - failures += test_switch_2_none(); - + KUNIT_test_scalars(none), + KUNIT_CASE(test_switch_1_none), + KUNIT_CASE(test_switch_2_none), /* STRUCTLEAK_BYREF should cover from here down. */ - test_structs(none); - + KUNIT_test_structs(none), /* STRUCTLEAK will only cover this. */ - failures += test_user(); - - if (failures == 0) - pr_info("all tests passed!\n"); - else - pr_err("failures: %u\n", failures); + KUNIT_CASE(test_user), + {} +}; - return failures ? -EINVAL : 0; -} -module_init(test_stackinit_init); +static struct kunit_suite stackinit_test_suite = { + .name = "stackinit", + .test_cases = stackinit_test_cases, +}; -static void __exit test_stackinit_exit(void) -{ } -module_exit(test_stackinit_exit); +kunit_test_suites(&stackinit_test_suite); MODULE_LICENSE("GPL"); From patchwork Sun Feb 27 18:45:17 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 12762087 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 95FC4C4167E for ; Sun, 27 Feb 2022 18:45:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231347AbiB0SqL (ORCPT ); Sun, 27 Feb 2022 13:46:11 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53360 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231250AbiB0SqJ (ORCPT ); Sun, 27 Feb 2022 13:46:09 -0500 Received: from mail-pf1-x42c.google.com (mail-pf1-x42c.google.com [IPv6:2607:f8b0:4864:20::42c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 42AB45132D for ; Sun, 27 Feb 2022 10:45:24 -0800 (PST) Received: by mail-pf1-x42c.google.com with SMTP id g1so9129196pfv.1 for ; Sun, 27 Feb 2022 10:45:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=EWQuW1pZiUPIz4vJWrH7gUOgoQp6sbO55rWZ8FArGBo=; b=HLkqZFFlTh5+wey7xEt6qvB2xnXL8ejZbXQpwYg5M1Hu1M39jy+KYOCy7/GkcvyadB BI27ZEoyAs5JPMjoehKWQKvoBalf8/7INAiq3V+ogadzoquBwdpxG2sGl1D3AwUozWZe 1cb8DNTjkn+F/UQfsvc/MiKw8lt/uudrXvxGY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=EWQuW1pZiUPIz4vJWrH7gUOgoQp6sbO55rWZ8FArGBo=; b=UE5SHp3i5ALJ39dZKrAn5vfriDh0LtCAQfODO43/NrwJgoF+TGNxl2Y9mDmwP5piIu 2zDjuDUK+k+oBepBFUliZACnA1pH7LvMzQlKt9pF2EJir+O9gyJrEOHE4yoQZUvX1Axu ACyAWCzIXBkd1PKwu7q1RapiJR51D1qYkmh1AgBFcgjIklHEN2obxP6tRl/GV20Na4WD 4sjSvHNCny56DparMKKqx8paWVgEg/K9K+o6gyhY7iaxztZp7uACkS0DEwyXSUNmyaIv WwmCGOw3iU+GZd5gso35HMwHHpfNah0c5CsJNVYboLoDaUNk/rTI0Qy9cot9ey3wzYuP 7DlA== X-Gm-Message-State: AOAM531f3N1gPfx3oJqE+CeQ+vGt6gYS2lQUaU/aVVEMQT+gzT18I+2w KXThmqT4jFdxcqJkv1wGflPVqw== X-Google-Smtp-Source: ABdhPJzYJK2sbqKeWGcVXkV09fnJetSZa1jM/ltSYX5lABvFLKwJcjqTK4mm3tuldsTqkNji510KUQ== X-Received: by 2002:a05:6a00:140b:b0:4e1:2cbd:30ba with SMTP id l11-20020a056a00140b00b004e12cbd30bamr17894766pfu.46.1645987523441; Sun, 27 Feb 2022 10:45:23 -0800 (PST) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id 17-20020a056a00071100b004f0f941d1e8sm9954418pfl.24.2022.02.27.10.45.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 27 Feb 2022 10:45:23 -0800 (PST) From: Kees Cook To: Kees Cook Cc: "Gustavo A. R. Silva" , Nathan Chancellor , Nick Desaulniers , Rasmus Villemoes , Vitor Massaru Iha , Daniel Latypov , David Gow , Anton Ivanov , Jeff Dike , Richard Weinberger , Masahiro Yamada , Arnd Bergmann , linux-kernel@vger.kernel.org, linux-um@lists.infradead.org, linux-kbuild@vger.kernel.org, kunit-dev@googlegroups.com, llvm@lists.linux.dev, x86@kernel.org, linux-hardening@vger.kernel.org Subject: [PATCH v3 7/7] UAPI: Introduce KUnit userspace compatibility Date: Sun, 27 Feb 2022 10:45:17 -0800 Message-Id: <20220227184517.504931-8-keescook@chromium.org> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220227184517.504931-1-keescook@chromium.org> References: <20220227184517.504931-1-keescook@chromium.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=7184; h=from:subject; bh=mgoDk12UNa5uSTGjFwO4+2nZAO80+cbZdVwcvxPnBXo=; b=owEBbQKS/ZANAwAKAYly9N/cbcAmAcsmYgBiG8a8w5LxxpsIKgH44u9caHGgDW3ETo0Dp34N8ul1 zx4hrReJAjMEAAEKAB0WIQSlw/aPIp3WD3I+bhOJcvTf3G3AJgUCYhvGvAAKCRCJcvTf3G3AJpx8D/ 9NJbctB6I8TH57q8ZxlKFajHl++CZpRi+uCUD2clP0VMybkc6osP/9W8EKbq2NJ+lV4SD9NYZv+zg0 Gu8kfYQHAup5DPbbwwCgFA2mcjbsC9xEbShZNo0GNrioT7sceP4nUx9LmROGT8zIt5HVFl82xIZbJd bLWUxVm2pZzU+QO7kggwCOusM1upIZsy29LkhkIEyK863FjG/jQOTLGRm6sMdRa3VDGmoCrWryhVw2 XvqCvf2/wSERJSTzW3cCgmR9D2wkBWqYZiGOnuRFxJDDt3Z8Ci306XKDiBtG2RscJn982Wp0xJe928 l3nLadXMQ6czcDCUA1ebs4nr/p7CT1AZYNtQjquACs1zZkKKi7Heb8j6U3Kqnor8hobwxWFYf4MuUA iXCx3eM0g9SLpuMRiLfxyyUQM8RyAuhT/yV9HxQ8cNnK5UUaD0wZvSRu/RMC4lCYamCKA9+pD9fdNT zZrD3fgqGQR8qS5RotWk9Y7ZwXNtFTRgqoaNF+wVrgOo58Mk0xPPBRvuBIb1/HkD5rQOZKH4Q1b1uP KDf/c6lWLVbwMOoI31RoLBUwyNNrD2C0BABp4P+yclmNSYUdoebFUSbE6PHPKbBv11vlH2Y1NlCUq5 TWoMW97b0vqrT+Fg4vuna7z0fpv2BIqzYiQRHmVHlMdVvvR1eobpjMGw78bg== X-Developer-Key: i=keescook@chromium.org; a=openpgp; fpr=A5C3F68F229DD60F723E6E138972F4DFDC6DC026 Precedence: bulk List-ID: X-Mailing-List: linux-hardening@vger.kernel.org The original lib/test_stackinit.c, which exclusively tests toolchain features, was designed to also be built without the full Linux kernel sources so that compiler developers and distro maintainers had an easy way to check for toolchain behaviors. When it was ported to KUnit, this mode was removed to simplify the code. Add a small header that provides a minimally operational KUnit API that can allow unit tests that don't depend on kernel-specific behaviors to build and run strictly from userspace without kernel sources. Add userspace-build support back to the renamed lib/stackinit_kunit.c test. Signed-off-by: Kees Cook Reviewed-by: Brendan Higgins --- v1: https://lore.kernel.org/lkml/20220224055145.1853657-1-keescook@chromium.org v2: - split from stackinit_kunit.c refactoring patch - add missing returns (Daniel) - report expression mismatch in assert msg (Daniel) - emulate kunit_test_suites() (Daniel) - emit valid KTAP (David) --- include/uapi/misc/kunit.h | 181 ++++++++++++++++++++++++++++++++++++++ lib/stackinit_kunit.c | 11 +++ 2 files changed, 192 insertions(+) create mode 100644 include/uapi/misc/kunit.h diff --git a/include/uapi/misc/kunit.h b/include/uapi/misc/kunit.h new file mode 100644 index 000000000000..afdffda583ae --- /dev/null +++ b/include/uapi/misc/kunit.h @@ -0,0 +1,181 @@ +#ifndef __UAPI_MISC_KUNIT_H__ +#define __UAPI_MISC_KUNIT_H__ +/* + * This is a light-weight userspace drop-in replacement for the in-kernel + * KUnit API. It seeks to implement a minimal subset of features so that + * a concisely written KUnit test can be made to run entirely in userspace + * when it doesn't actually depend on any real kernel internals. + * + * Additionally contains many refactored kernel-isms to support building + * and running in userspace without full kernel source. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include + +#define __user /**/ +#define noinline __attribute__((__noinline__)) +#define __aligned(x) __attribute__((__aligned__(x))) +#ifdef __clang__ +# define __compiletime_error(message) /**/ +#else +# define __compiletime_error(message) __attribute__((__error__(message))) +#endif +#define __compiletime_assert(condition, msg, prefix, suffix) \ + do { \ + extern void prefix ## suffix(void) __compiletime_error(msg); \ + if (!(condition)) \ + prefix ## suffix(); \ + } while (0) +#define _compiletime_assert(condition, msg, prefix, suffix) \ + __compiletime_assert(condition, msg, prefix, suffix) +#define compiletime_assert(condition, msg) \ + _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) +#define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) +#define BUILD_BUG_ON(condition) \ + BUILD_BUG_ON_MSG(condition, "BUILD_BUG_ON failed: " #condition) + +#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) + +#define MODULE_LICENSE(str) /* str */ + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; + +#define TEST_PASS 0 +#define TEST_SKIP 1 +#define TEST_FAIL 2 +struct kunit { + int status; + char *msg; +}; +struct kunit_case { + void (*run_case)(struct kunit *test); + const char *name; +}; +struct kunit_suite { + const char *name; + const struct kunit_case *test_cases; +}; +#define KUNIT_CASE(test_name) { .run_case = test_name, .name = #test_name } + +#define KUNIT_ASSERT_TRUE_MSG(test, expr, fmt, ...) \ +do { \ + if (!(expr)) { \ + if (test->status != TEST_SKIP) \ + test->status = TEST_FAIL; \ + if (test->msg) \ + free(test->msg); \ + asprintf(&test->msg, fmt, ##__VA_ARGS__); \ + return; \ + } \ +} while (0) + +#define KUNIT_ASSERT_EQ_MSG(test, left, right, fmt, ...) \ + KUNIT_ASSERT_TRUE_MSG(test, (left) == (right), \ + #left " != " #right ": " fmt, \ + ##__VA_ARGS__) + +#define kunit_skip(test, fmt, ...) \ +do { \ + test->status = TEST_SKIP; \ + if (test->msg) \ + free(test->msg); \ + asprintf(&test->msg, fmt, ##__VA_ARGS__); \ + return; \ +} while (0) + +static int do_kunit_test_suite(struct kunit_suite *suite) +{ + const struct kunit_case *test_case; + int pass = 0, fail = 0, skip = 0; + int rc = 0; + size_t i = 0; + + printf(" TAP version 14\n"); + for (test_case = suite->test_cases; test_case->run_case; test_case++) + i++; + printf(" 1..%zu\n", i); + i = 0; + for (test_case = suite->test_cases; test_case->run_case; test_case++) { + struct kunit test = { }; + + i++; + test_case->run_case(&test); + switch (test.status) { + default: + case TEST_FAIL: + fprintf(stderr, " not ok %zu - %s%s%s", + i, test_case->name, + test.msg ? " # ERROR " : "", + test.msg ?: "\n"); + rc = 1; + fail++; + break; + case TEST_SKIP: + fprintf(stdout, " ok %zu - %s # SKIP%s%s", + i, test_case->name, + test.msg ? " " : "", + test.msg ?: "\n"); + skip++; + break; + case TEST_PASS: + fprintf(stdout, " ok %zu - %s\n", + i, test_case->name); + pass++; + break; + } + if (test.msg) + free(test.msg); + } + printf("# %s: pass:%d fail:%d skip:%d total:%zu\n", + suite->name, pass, fail, skip, i); + return rc; +} + +static int run_suites(char *name, struct kunit_suite *suites[], size_t count) +{ + int pass = 0, fail = 0, skip = 0; + int one, ret = 0; + size_t i; + + printf("TAP version 14\n"); + printf("1..%zu\n", count); + for (i = 0; i < count; ++i) { + one = do_kunit_test_suite(suites[i]); + switch (one) { + case TEST_SKIP: + skip++; + break; + case TEST_PASS: + pass++; + break; + default: + fail++; + break; + } + printf("%sok %zu - %s\n", + one == TEST_FAIL ? "not " : "", + i + 1, suites[i]->name); + ret |= one; + } + printf("# %s: pass:%d fail:%d skip:%d total:%zu\n", + name, pass, fail, skip, count); + return ret; +} + +#define kunit_test_suites(suite...) \ +int main(int argc, char *argv[]) { \ + static struct kunit_suite *suites[] = { suite }; \ + return run_suites(argv[0], suites, ARRAY_SIZE(suites)); \ +} + +#endif /* __UAPI_MISC_KUNIT_H__ */ diff --git a/lib/stackinit_kunit.c b/lib/stackinit_kunit.c index 35c69aa425b2..6d468630c90a 100644 --- a/lib/stackinit_kunit.c +++ b/lib/stackinit_kunit.c @@ -8,7 +8,13 @@ * --make_option LLVM=1 \ * --kconfig_add CONFIG_INIT_STACK_ALL_ZERO=y * + * External build example: + * clang -O2 -Wall -ftrivial-auto-var-init=pattern \ + * -o stackinit_kunit stackinit_kunit.c + * ./stackinit_kunit + * */ +#ifdef __KERNEL__ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include @@ -17,6 +23,11 @@ #include #include +#else +/* Userspace KUnit stub header. */ +#include +#endif + /* Exfiltration buffer. */ #define MAX_VAR_SIZE 128 static u8 check_buf[MAX_VAR_SIZE];