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: 12762091 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 11816C433EF for ; Sun, 27 Feb 2022 18:45:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230194AbiB0SqA (ORCPT ); Sun, 27 Feb 2022 13:46:00 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52728 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229635AbiB0SqA (ORCPT ); Sun, 27 Feb 2022 13:46:00 -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 7193E28E1E for ; Sun, 27 Feb 2022 10:45:22 -0800 (PST) Received: by mail-pj1-x102a.google.com with SMTP id iq13-20020a17090afb4d00b001bc4437df2cso9441780pjb.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=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=EDPdX1cciNKa1bOq5FfGR4rrR6zhU4KCN+2X4jaYX0XAoNECk+045BeY4PtkpEflXo aDTRj3gjhu3O1PilOxwqjw9RP5yAjWDD1g1kzwXey/6an11nWupQqYPlcASl9Jq7fH4N fcbvJ+qLbw1yme/RthG8nGt73zkskOcSHlzv1LPysWAicviHXkruRTM7EtNHCO0ZsoKK dhgScF3KY4dmbp/JzDLT3RLzKifoIdOdc87EPVkPU8/UM55q+T/bCTqgx44/8COVvX1R Ml/fFXygh2ss1Vz3EOZfhK3hz0DPoiNVSoohNl/vDpprmLbD28MNdpegNDlNbRFzWfJs yoIw== X-Gm-Message-State: AOAM532QYeZ76V9CXaa1I2GkaXUWQ0MngKTkoQ3IIVU5qrYLkYElUQw+ p4fZuNz3238EL7+akeSTna/RMQ== 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-kbuild@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: 12762096 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 278EEC43217 for ; Sun, 27 Feb 2022 18:45:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231199AbiB0SqL (ORCPT ); Sun, 27 Feb 2022 13:46:11 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53408 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231234AbiB0SqJ (ORCPT ); Sun, 27 Feb 2022 13:46:09 -0500 Received: from mail-pf1-x42b.google.com (mail-pf1-x42b.google.com [IPv6:2607:f8b0:4864:20::42b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E23F050042 for ; Sun, 27 Feb 2022 10:45:23 -0800 (PST) Received: by mail-pf1-x42b.google.com with SMTP id g1so9129189pfv.1 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=hEyNSgDUVeePHqQbIDzfnSHd8IXezjrM/bFHHmhc2KTw4gfRO8zGUU9qw6LHPGgGSS jqw++U8l9sZ54V2yS80BHfaYbMu11SrlsWSLNnupFe8VWvUhdTK5pi8I1b7H35Jrzl0S AI099vdL/3ITpQiFgU5HixsfxLiDMJSQh89hBqvae3BLeeFvIG9sxLaY0GpEWhqTqJBJ hAWhszsUQSJJ5m/RvKiQJtE8oQ6UHvoLKmQyPtHOUU8SZPeevTpK01syrsIi9o4zUX5x +oa0LxQhLCUL1xeFuEAoz9pwLSgKRTCBEeLNpS2TgLPzRuKsEnz1jrZwzDarCow0nyhq ZQkQ== X-Gm-Message-State: AOAM5310YUuI5DjB1JkIhj23ngUUO/m0JV8tjzQX3dMxYLkM3fjnHNjd MdH3MshpaUUvYE2QUFs2KTUfjQ== 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-kbuild@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: 12762093 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 DE22FC433FE for ; Sun, 27 Feb 2022 18:45:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231285AbiB0SqJ (ORCPT ); Sun, 27 Feb 2022 13:46:09 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53346 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231211AbiB0SqI (ORCPT ); Sun, 27 Feb 2022 13:46:08 -0500 Received: from mail-pj1-x102c.google.com (mail-pj1-x102c.google.com [IPv6:2607:f8b0:4864:20::102c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CFC0446669 for ; Sun, 27 Feb 2022 10:45:22 -0800 (PST) Received: by mail-pj1-x102c.google.com with SMTP id d15so5892909pjg.1 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=QJgKuDGeQ0pu0Oh+4dxjmae8z8P8OTseBO3pTKq3WUIpsgzcjXYVIKtM0jCUhWRR4B Gwpodzu7n75qG9M1an4vPkSMO1SeYdFyiKbIpEwIPU59LPE7m4crZUzm+940BwJaBC1f Sc3Z3dJCwsIIkqSMkDod3VOFNkQCjlnxOT6rTtndXDnQaN5T9lLLhaXmLdbV0drHawTn 0ACBE6IoworHyMuBzdlRT82lWXk4h8If3csUyY+TWweS+h8dIKuDhl+QVChSYO29L+Y9 vGZHoABCT101FkRMa0GYxy+piZxegSWifbvL30kaNBEBGoRvVYxMHHDsgo6lw3R4gdzZ pQdA== X-Gm-Message-State: AOAM532ZKXHodlglZ7IUR+FJEK3jMeaSKIS39ekk/PmFdOinq4iot7Ja FNs7DQ9RDWNpY/Xrb+cvA4wiTg== 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-kbuild@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: 12762094 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 EE432C4332F for ; Sun, 27 Feb 2022 18:45:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231299AbiB0SqK (ORCPT ); Sun, 27 Feb 2022 13:46:10 -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 S231218AbiB0SqI (ORCPT ); Sun, 27 Feb 2022 13:46:08 -0500 Received: from mail-pj1-x1031.google.com (mail-pj1-x1031.google.com [IPv6:2607:f8b0:4864:20::1031]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1094549F12 for ; Sun, 27 Feb 2022 10:45:23 -0800 (PST) Received: by mail-pj1-x1031.google.com with SMTP id g7-20020a17090a708700b001bb78857ccdso12898201pjk.1 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=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=mFf5dSbekQ85mmIfG17HrASkPEQe0zSBrZdJRoRz69OqQ95Dw62pGDRTbv4DCrn6eP cbzSw9BI6zuBQwR5bBKL5FMYdeXCPPgKyFT4zAB3a0nzYsjexv3AY5+SjZLUvohj1NoB LqHB6l/HBxohSZkGTv2GR3ULaVnFKDdKW91NAymsdnos5gtKFsQHFFdL/MfFan2thVkV bKVxgjEuwfsNw/ROUm2OG78NPGA8PEPq4FDPW1w9F1RXmOGiM0TTqVdLQeEAdw4ihgJR uba8XWOGImDUpgVHIHtr1WeiBNzAaeAOGuR7QWMgVyMtGb8EijYIa6GSCgeTyz4cGLUx Ix0Q== X-Gm-Message-State: AOAM532rPg0IzCkj+S5LjYNLe5gpAh1RYc8sYxdvunHRi34jkGy9qa5U EiT6E2QoTlMTSpzxdihns34TNQ== 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-kbuild@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: 12762095 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 7707AC4167B for ; Sun, 27 Feb 2022 18:45:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231234AbiB0SqL (ORCPT ); Sun, 27 Feb 2022 13:46:11 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53410 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231235AbiB0SqJ (ORCPT ); Sun, 27 Feb 2022 13:46:09 -0500 Received: from mail-pj1-x102e.google.com (mail-pj1-x102e.google.com [IPv6:2607:f8b0:4864:20::102e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1572750B3F for ; Sun, 27 Feb 2022 10:45:24 -0800 (PST) Received: by mail-pj1-x102e.google.com with SMTP id d15so5892923pjg.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=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=YNic82avGBBptI5M845lLkEKNxvYNGNY23BlD/SfiRW4MTs6D5kpYTD1echHeH06VX D60QYsyXw87nr6KneILLKVIChq0ujFZicIVFS4gXzRmAPd0Qb6I0CA+A9XINImTTY73d KaL9hJ00Gx2g4j91wZ1cM+fbbc2XxWmRx5I9w4/vHia4eODYOG0OOK7pXrZKX9LeBtmd yJXLrHIOxfKUHaHWNPHr4HW9bjj24k32HV7DJ1+J0F75ye/41EO7sG1xFCuDA2SL0ybk GamLyXddY5AiuhT+acG2HYsATl44keGRCcGyK/M2W2WNNXxvkLJpDvOzB6lymph4NDZw mIwA== X-Gm-Message-State: AOAM530hY8k+ms8gJMybWFD+BF2/jMMidvA1gf/TmTyzLjsHKjwnY4qL F2Jt82mEQY1gKYlQBQ4VYKyUpQ== 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-kbuild@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: 12762098 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 38ACBC433F5 for ; Sun, 27 Feb 2022 18:45:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231255AbiB0SqM (ORCPT ); Sun, 27 Feb 2022 13:46:12 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53372 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231260AbiB0SqJ (ORCPT ); Sun, 27 Feb 2022 13:46:09 -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 5325B53732 for ; Sun, 27 Feb 2022 10:45:24 -0800 (PST) Received: by mail-pj1-x102d.google.com with SMTP id cp23-20020a17090afb9700b001bbfe0fbe94so9403082pjb.3 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=uWW/dia/Sqk0t36w2Sd2i21qOZaE5hDcA0sHrE4wMKoElIaHOKPCdgbXVrVX6QNjrP aPFrgASVJkag1V9ZMlX/VUxmLF/mYt66KK9U97AotUcOGc62fKKXcYbh/9xQCxSCQMeW g9L/T6MscGbXen/Ua16pZ+XX0szbhwr1/Iic1FD3X0EZU+X/ajNcSwurmLRgoBYVDRzy f1YPpnZmBVYcSqPS2intzYHsfc/MzAdA2BAxpTD0GP/0MwvY92iPj25iqeKzIZpugLBh lQrw7lQDW/eXXPDjz7QCM+PNHw/bvSf4z8N4S/i+aoYZRU326meqLbAKSckQVrWmQUw+ uMSQ== X-Gm-Message-State: AOAM532gHmmMyDJ2SFNORvwjMQ7pbDAAaEphTCLf5yoOpc2qsM89Iwfz NeL+UX0qDsW9eflCIyKi0mqA3g== 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-kbuild@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: 12762097 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 A4C0AC46467 for ; Sun, 27 Feb 2022 18:45:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231230AbiB0SqL (ORCPT ); Sun, 27 Feb 2022 13:46:11 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53346 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231244AbiB0SqJ (ORCPT ); Sun, 27 Feb 2022 13:46:09 -0500 Received: from mail-pg1-x529.google.com (mail-pg1-x529.google.com [IPv6:2607:f8b0:4864:20::529]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2F41451300 for ; Sun, 27 Feb 2022 10:45:24 -0800 (PST) Received: by mail-pg1-x529.google.com with SMTP id w37so9568602pga.7 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=X3cf6Vc+5e2KIJd+RUFItOvfsuTJz1aZmuHIvkdelTt7g5HXjU7/eZavIu7mo7oeff NycPUufYL0L0fqcPWhiDnWg0D+vnrsO1OtdzGK+roo/TuJA6JcdK0+sjkjZC8/dNQ8ZR /UiXDJ6nwoeVcFieqmXjE8gGUE8sCPD0MRRkwE7K9LlAN1m1EreFwa8wqMzBfIxeK8aJ keixyAbp1CD0hVpumKs80kw4KOcgB+NfJ9whihMFAmGSiBjG25Krc6trdXtbHAXhwZs5 RXDdKB+3akB1O3K3uTzMmjEx5DRHw/KhnwFq+z0S3iG2tDPAxVBlOrFtmNJ14Bi2jPCd 0D/Q== X-Gm-Message-State: AOAM533Y+3/Rr8GHNRJRK+qKQuAWfXxQprS8hNCNzDcmgREEMvEJ8ZOs gjgLKl2OT1reNaHqhmqDKDil2w== 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-kbuild@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];