From patchwork Fri Apr 7 19:27:07 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 81000 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp496340vqo; Fri, 7 Apr 2023 12:49:56 -0700 (PDT) X-Google-Smtp-Source: AKy350ZEx/XROTVcl2XvSfKl7cxT5ljORJjlQQwXo2uMSAICIb93BqCc3HfhUvPYcA+l1E4Vi796 X-Received: by 2002:a17:906:cc4d:b0:944:308f:b977 with SMTP id mm13-20020a170906cc4d00b00944308fb977mr399915ejb.16.1680896996390; Fri, 07 Apr 2023 12:49:56 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680896996; cv=none; d=google.com; s=arc-20160816; b=rkPAxoO5ZoptVRl4CrKssVYCA/8taneFeT+SCDK5Zd4QB4V5uflxjI0QdS01+t6T3V zcuVoRs3PeedTPkctSjTfFAJc7rqr2HbjpLqXBOOc1g4gC8IIuDQtaWjAKJBpts5pEwr EZhKW9YaSi9EMpianzUhLdI2HwVBuUZ0vjSShAExSF/5O/9A+lhV8QEBdNagBcYjq4hF TEeHvC3Q3bozuhaKqaNGq3urmwtLofSMwWa/yAlXXXhetiiD8Tciw3uQTOGE3SQqx4P1 aO2lsLJEi0C+x+eNkVr3GstMyLE16c4zbzmTfLDe6y2qbynAcReY1+9lwJ+oHa2tlMVK cITQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=Xyby/EazxIHU080H4IjdTfHbXYv3ut7QI/UHzeQm/pk=; b=GObH/rB/99RS208AndiyiXR5MFa7LPhUA1ui4ZXoHkFefl6XvJdM5pNRUNpe8vWSoP 9+yzk3lDn+yjc+W6mR0meW+axFeL7t5Mi1HA2TPF6aAjNhtUyxhCefttdltlBRm9C9n6 jvuGCROF/uOGBu4jG5JsEYhrnCoNqy/LC71M8AP8sgskf+JGSKWf1MIOg7V92jR79rRQ GxWFrc97Ahvkd+FuJ6aFlsyR/n7FHbc6Fv7Pd2ueT6Z9d2pWoewz7VjVpc81DU9yNEnB 5xG3mwCNZOT8e6J8Sv8/Wh2t8K2W3diTUxgVL1k2qCaD7MolrKU1gKwalnSovWa+OrJx QcJA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=J0oQIAcv; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id lx24-20020a170906af1800b0093959594e50si3648002ejb.248.2023.04.07.12.49.29; Fri, 07 Apr 2023 12:49:56 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=J0oQIAcv; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231153AbjDGT1b (ORCPT + 99 others); Fri, 7 Apr 2023 15:27:31 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53382 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229804AbjDGT1W (ORCPT ); Fri, 7 Apr 2023 15:27:22 -0400 Received: from mail-pl1-x629.google.com (mail-pl1-x629.google.com [IPv6:2607:f8b0:4864:20::629]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0730DBB98 for ; Fri, 7 Apr 2023 12:27:21 -0700 (PDT) Received: by mail-pl1-x629.google.com with SMTP id o11so40758555ple.1 for ; Fri, 07 Apr 2023 12:27:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1680895640; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Xyby/EazxIHU080H4IjdTfHbXYv3ut7QI/UHzeQm/pk=; b=J0oQIAcvJHQmNqjl+kzQKyzPrvC17RrlUPVkWtcyilcpofI3iWccvIsy1FWzpsd3Ce 1QCSb08qko1aBpAWce/V41Fs4NGzufTLEc8nf2sd9lnX5LXXKOixq3cKr5Xx59xQC4PL aRXEexQ6aX/UVxWtKcwLYDjLscto/MVfKav/c= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680895640; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Xyby/EazxIHU080H4IjdTfHbXYv3ut7QI/UHzeQm/pk=; b=ilDfI/UFVsaAOxx0B8dbNWE6u9wdSvaRKpW3RkDpqvInXlDtswSGAe+9Ks+jkHkkKv aqutgnBbDfnQT7cqyhOBy/SyRcqlsLb0arcdJYVL0/5My9FrAMBWpsb7YdY1wiQrlS/l ulCMfFJa58EDzHrRvP9rLDTLMW4dNNUwHU7i/3vb6WLsIULE/m9de2cIHQdlbQFfV+cF 6s7OWbWQF63UsJmoxY8928hk3JBuqiDixOgWOnlz1Hcny3SwoFa9FZRjzBn1+R/OINgt uoWOfyIeqkfUIwNVy3b1MYjfDY+hiCJSesp8gavl5ObCtS7wsz92PCcFTovr79Idz3aD WV/g== X-Gm-Message-State: AAQBX9foAq+2d5CftEB+XNfOoY64gdGTojzq6/38DlZUBplB6Yz4efQu Id7X1EahEWvx4BH9yYC/SampUA== X-Received: by 2002:a17:903:22d0:b0:19a:7217:32a9 with SMTP id y16-20020a17090322d000b0019a721732a9mr3607916plg.26.1680895640475; Fri, 07 Apr 2023 12:27:20 -0700 (PDT) Received: from www.outflux.net (198-0-35-241-static.hfc.comcastbusiness.net. [198.0.35.241]) by smtp.gmail.com with ESMTPSA id iy18-20020a170903131200b0019e60c645b1sm3251818plb.305.2023.04.07.12.27.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Apr 2023 12:27:18 -0700 (PDT) From: Kees Cook To: linux-hardening@vger.kernel.org Cc: Kees Cook , "Andy Shevchenko" , "Cezary Rojewski" , "Puyou Lu" , "Mark Brown" , "Josh Poimboeuf" , "Peter Zijlstra" , "Brendan Higgins" , "David Gow" , Andrew Morton , "Nathan Chancellor" , "Alexander Potapenko" , "Zhaoyang Huang" , "Randy Dunlap" , "Geert Uytterhoeven" , "Miguel Ojeda" , Alexander Lobakin , "Nick Desaulniers" , "Liam Howlett" , "Vlastimil Babka" , "Dan Williams" , "Rasmus Villemoes" , "Yury Norov" , "Jason A. Donenfeld" , "Sander Vanheule" , "Eric Biggers" , "Masami Hiramatsu (Google)" , "Andrey Konovalov" , "Linus Walleij" , "Daniel Latypov" , =?utf-8?b?Sm9zw6kgRXhww7NzaXRv?= , linux-kernel@vger.kernel.org, kunit-dev@googlegroups.com Subject: [PATCH v2 01/10] kunit: tool: Enable CONFIG_FORTIFY_SOURCE under UML Date: Fri, 7 Apr 2023 12:27:07 -0700 Message-Id: <20230407192717.636137-1-keescook@chromium.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230407191904.gonna.522-kees@kernel.org> References: <20230407191904.gonna.522-kees@kernel.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=1293; h=from:subject; bh=jhb9iocAv4NeEPNMASy77h08PjA+GBj0a1PxPk1ekXM=; b=owEBbQKS/ZANAwAKAYly9N/cbcAmAcsmYgBkMG6Tf4DfnuEbF/92pn95HJXNG0utK73GQacwi+o+ knpv6+aJAjMEAAEKAB0WIQSlw/aPIp3WD3I+bhOJcvTf3G3AJgUCZDBukwAKCRCJcvTf3G3AJm7zEA CBADePyPGdPcFChk93D6qSpqsV5C/AypwKmWlOgxjmalDZ0Ui+lcVeKab4Sblq73Wc4/gXo2ODgUMR xSGUd509Gr44zaB2slorlcXT8oVgp5p7FwaBwCb6YcOWyjFs2Dg9vSxvvaY+V6vZ4IeT+Kq5Fwb6hN cb7+liB/BbS0EEoAefqwVVTTYPn8tGQY0srxskJgejh/UwdYxutTizydw6qRgoO6AUxjdZabnHvVce +AVi9mmWzzwonDy5CvTOO4UlJ3/nNCt9WFCH1uuqSR2jNIdLjcw6eRn3GGCoJs1Fhu82CbHZ/po7m/ q7Grb+HX1BsJgXhh5pM4GNTpgTlykR/c4vCpr+hMNXHjkXqbYx2Vsx4wTLl5qKjU7ob9JLKV25dTOI LNwBv/n/RGM+LbthEgfdL6KpHQiBIEUZDNy/9FDGxpXoyx5mDs5x83vadC+MWP+IVSE7USdi3W5hzw viO8QD5I+E8YyrrB+BR+4wngCVAbMUDZ1CwJZdgSyNx3ls3goI9Vn8m9WuYz0JIuNF3GOHjSRj7m28 fdJAddrJvnt0NCSEfzuXqMUhR4ALlWfmd3lujiJekI14B/g9lJKw56pl109ixcrZcVtmjmHBUbU3q8 xrgqRnk3DKO9D9d2Q40cdw/yWrZhZ747tgv3pLLY8ibSF+YxPWvobWp9dEPg== X-Developer-Key: i=keescook@chromium.org; a=openpgp; fpr=A5C3F68F229DD60F723E6E138972F4DFDC6DC026 X-Spam-Status: No, score=-0.2 required=5.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1762548249344539654?= X-GMAIL-MSGID: =?utf-8?q?1762548249344539654?= Since commit ba38961a069b ("um: Enable FORTIFY_SOURCE"), it's possible to run the FORTIFY tests under UML. Enable CONFIG_FORTIFY_SOURCE when running with --altests to gain additional coverage, and by default under UML. Signed-off-by: Kees Cook --- tools/testing/kunit/configs/all_tests.config | 2 ++ tools/testing/kunit/configs/arch_uml.config | 3 +++ 2 files changed, 5 insertions(+) diff --git a/tools/testing/kunit/configs/all_tests.config b/tools/testing/kunit/configs/all_tests.config index f990cbb73250..0393940c706a 100644 --- a/tools/testing/kunit/configs/all_tests.config +++ b/tools/testing/kunit/configs/all_tests.config @@ -9,6 +9,8 @@ CONFIG_KUNIT=y CONFIG_KUNIT_EXAMPLE_TEST=y CONFIG_KUNIT_ALL_TESTS=y +CONFIG_FORTIFY_SOURCE=y + CONFIG_IIO=y CONFIG_EXT4_FS=y diff --git a/tools/testing/kunit/configs/arch_uml.config b/tools/testing/kunit/configs/arch_uml.config index e824ce43b05a..54ad8972681a 100644 --- a/tools/testing/kunit/configs/arch_uml.config +++ b/tools/testing/kunit/configs/arch_uml.config @@ -3,3 +3,6 @@ # Enable virtio/pci, as a lot of tests require it. CONFIG_VIRTIO_UML=y CONFIG_UML_PCI_OVER_VIRTIO=y + +# Enable FORTIFY_SOURCE for wider checking. +CONFIG_FORTIFY_SOURCE=y From patchwork Fri Apr 7 19:27:08 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 81005 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp496502vqo; Fri, 7 Apr 2023 12:50:26 -0700 (PDT) X-Google-Smtp-Source: AKy350YWtsisUMsjr849OVqGIOLwBionhj9HEULsHS6SC9F08NJHs0CKqR4HAb21HnBaew0Jk3EV X-Received: by 2002:a17:906:cedd:b0:921:d539:1a3a with SMTP id si29-20020a170906cedd00b00921d5391a3amr468196ejb.58.1680897026114; Fri, 07 Apr 2023 12:50:26 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680897026; cv=none; d=google.com; s=arc-20160816; b=Tig/KvISQgHFwhbLvxAAxcXdmPKWgX75D/nvps4qfhhIcTqPmSoytiQUtVpmPXFzU6 G7oVuuos8E+6RZfBgJAoKefifH8Q6hkC2VOKklRPI2hMm3g2JIzF3Mx9+Y7l7R/vDc7U PTwx5DBQwxx/1/OLbOHZhREjbM1+kAoC0+upTiqvo+euBpDQyxUQwIdx6jfrWaBRWUG1 epr76nzHa229mrZIM1XADItV64gd3JGPMO8Ztj85jJgKT/BwGoE9hVP3yZMwFAC6c1dw sSrkNh5A7OIgM24xlREQx/U2IjwekwZYXbgwgikmxpds8YnF9Oe/ItSasqyDDkkdZ+Gi Y+cw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=8iceky2qZBmmPvb+84ZhVCagAV37KBLs6ikPPwI/vVU=; b=Jo+SrSYR9Xpzi8WKKwM59rQMPanYHLEOIXTrmP28NsA8R5GZDcjBjY/1I66FwakATz 7lwhsi73QCOsbdaLdEoxT6frOr9ufSYUVUW0ew3y8lZUsEFOKLA2WKXGL6KSLvbw1GjU AQxq2Q1yvZG8Z5joC1pDTgKqylwHUtd3XZ8dP8UuoX7SKt7ctIydurxP7i6ElOiVRdXk vyVh7OSTjI2q1URgXdF97jhsdqkObf63c+s57xa9e8AokduUh5MLidi7rOW/3sHH6Mzv tjwiGR4l2ImvjsjVBAS9L3GQZinI+KoHFSa0ZtlquBCdzH04CMC8sqKF6XgDdmhR5q8c UNFQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=LPbqMcG9; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id z20-20020aa7d414000000b00501d48232ecsi3836357edq.404.2023.04.07.12.50.02; Fri, 07 Apr 2023 12:50:26 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=LPbqMcG9; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230458AbjDGT1Z (ORCPT + 99 others); Fri, 7 Apr 2023 15:27:25 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53344 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229889AbjDGT1V (ORCPT ); Fri, 7 Apr 2023 15:27:21 -0400 Received: from mail-pl1-x636.google.com (mail-pl1-x636.google.com [IPv6:2607:f8b0:4864:20::636]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3807DB47D for ; Fri, 7 Apr 2023 12:27:20 -0700 (PDT) Received: by mail-pl1-x636.google.com with SMTP id o11so40758531ple.1 for ; Fri, 07 Apr 2023 12:27:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1680895639; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=8iceky2qZBmmPvb+84ZhVCagAV37KBLs6ikPPwI/vVU=; b=LPbqMcG9W63inybkR1IO+JjW/8sCJ47LPwDmEyXhUpWSy1fntw5h/1h7xZsPDgdd70 mFP3DM413LFcwH9H7Ql3Ey8aU6Dgk3sZuG3MLwLccmbH6W5NANpZrUqjzeUr30SNkTWC YRVicFBycx5jr5GjrNes2ZqBKlQnP6T++wYlc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680895639; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=8iceky2qZBmmPvb+84ZhVCagAV37KBLs6ikPPwI/vVU=; b=XubG8B2E4rX5PT0uIukIvWBmcgwd3+KZPLVbeKILakWD/DMFcthDAS/5e9b7VCgdUG 6TOMAbqZRDagmV7W7ii5bKBHjadX+FFgQZC7dFPNtu3uTVhDuDkvSmd01IPPkZbmjeMz atykRbK8KrgHbIMmx2sJehQwfH7IoS6zHHnyTNDnA/ZEDLg7PGdD6bKzL7psVu9GEqw+ oq9ar9xRfbDNX/qFqvV00GN0PnA2NYHWuUSZmhqKfZnFc1KmHiiPmM+eLdgdt8hNkiJc ICvasVjDT6yAXpcMTakT9XPcRVi1STtP5kYHLswlex2DBqctpZB31Zm4ZqIT/PlH2W6S 8XIQ== X-Gm-Message-State: AAQBX9eUXOsyI13FIwnZp82hQshDRa5ntmUFr0ZJUheIgtVh1WJaAW3N 7hTSl9XTc6gOo1GDtgcXeREicA== X-Received: by 2002:a05:6a20:b98:b0:e8:fe82:583a with SMTP id i24-20020a056a200b9800b000e8fe82583amr1487041pzh.26.1680895639635; Fri, 07 Apr 2023 12:27:19 -0700 (PDT) Received: from www.outflux.net (198-0-35-241-static.hfc.comcastbusiness.net. [198.0.35.241]) by smtp.gmail.com with ESMTPSA id g5-20020aa78745000000b0061949fe3beasm3411886pfo.22.2023.04.07.12.27.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Apr 2023 12:27:18 -0700 (PDT) From: Kees Cook To: linux-hardening@vger.kernel.org Cc: Kees Cook , "Andy Shevchenko" , "Cezary Rojewski" , "Puyou Lu" , "Mark Brown" , "Josh Poimboeuf" , "Peter Zijlstra" , "Brendan Higgins" , "David Gow" , Andrew Morton , "Nathan Chancellor" , "Alexander Potapenko" , "Zhaoyang Huang" , "Randy Dunlap" , "Geert Uytterhoeven" , "Miguel Ojeda" , Alexander Lobakin , "Nick Desaulniers" , "Liam Howlett" , "Vlastimil Babka" , "Dan Williams" , "Rasmus Villemoes" , "Yury Norov" , "Jason A. Donenfeld" , "Sander Vanheule" , "Eric Biggers" , "Masami Hiramatsu (Google)" , "Andrey Konovalov" , "Linus Walleij" , "Daniel Latypov" , =?utf-8?b?Sm9zw6kgRXhww7NzaXRv?= , linux-kernel@vger.kernel.org, kunit-dev@googlegroups.com Subject: [PATCH v2 02/10] fortify: Allow KUnit test to build without FORTIFY Date: Fri, 7 Apr 2023 12:27:08 -0700 Message-Id: <20230407192717.636137-2-keescook@chromium.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230407191904.gonna.522-kees@kernel.org> References: <20230407191904.gonna.522-kees@kernel.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=2116; h=from:subject; bh=ccG2bNY7K5BZtbleuqiKVnIVFX8WC48jOVbBodSXYXk=; b=owEBbQKS/ZANAwAKAYly9N/cbcAmAcsmYgBkMG6TM2zrha7Ipa7uDmzoHRpb9RWuePb2XGcS7CJv en17kyyJAjMEAAEKAB0WIQSlw/aPIp3WD3I+bhOJcvTf3G3AJgUCZDBukwAKCRCJcvTf3G3AJn7YEA CER3124RngLsuvZqHAvpzkO00CzkPYu9RLFpI3cKRivKzkUkR5wxM/NC00ecF5sxvG6Sw9DWeJkVeN MNAKx38AC1EyPN5nmnhxbVnhwcU/PJJleVj1Bw2t+U/rE3Xara/ECkj6yX3aysw+2xJJYT8XpQch+t TwZ4XmilZ9le6Rfj+YioA9Jmiu0dEVO79l+reOQ+9/NTEiy6t3hYxx9cfE8iX841bZvCuo9ziloHeU 3uUHoE7RxPec0fqA6a/n72NL/aHNWTE3GthVRhAqFnK6jgRLgecdcVo6tCqFJJ2Pus2z+hbqaHbPlQ u45gFLyO+AfC9lFZLk7N6sNhThbzDS4Bbz5cRlT7SQBBlX9XVJYaY9pY2+NZTX6dumTtEM7Qf9h0DB VMdagi6uXGY6TOH9j2kTlVN+mbWiNJO2TL1i8hAWHTEe3iNqFyIQQ2bNRmCMoK4mr2jaSwsg3IwS2V okMgL1acUel87FDPsB8puAJleQ2eavuclaC5L+GwcD5jjK1mV9LKyLHBZkTMFA8vnVJaUiMWQKchEB gc7bmlmT1U3USfTbreSenFr4OqEa5mIZf5TTZEDibWczL9S5mgdhNUjRKasbVlvYz81KO7TsBLVi40 w9bldPkvRyN/Nl0lag1fccQ2jP219rdmt2y+n8cwtBr7dRkvTm+GGl90Tdbg== X-Developer-Key: i=keescook@chromium.org; a=openpgp; fpr=A5C3F68F229DD60F723E6E138972F4DFDC6DC026 X-Spam-Status: No, score=-0.2 required=5.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1762548280182728126?= X-GMAIL-MSGID: =?utf-8?q?1762548280182728126?= In order for CI systems to notice all the skipped tests related to CONFIG_FORTIFY_SOURCE, allow the FORTIFY_SOURCE KUnit tests to build with or without CONFIG_FORTIFY_SOURCE. Signed-off-by: Kees Cook --- lib/Kconfig.debug | 2 +- lib/fortify_kunit.c | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index c8b379e2e9ad..d48a5f4b471e 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -2614,7 +2614,7 @@ config STACKINIT_KUNIT_TEST config FORTIFY_KUNIT_TEST tristate "Test fortified str*() and mem*() function internals at runtime" if !KUNIT_ALL_TESTS - depends on KUNIT && FORTIFY_SOURCE + depends on KUNIT default KUNIT_ALL_TESTS help Builds unit tests for checking internals of FORTIFY_SOURCE as used diff --git a/lib/fortify_kunit.c b/lib/fortify_kunit.c index c8c33cbaae9e..524132f33cf0 100644 --- a/lib/fortify_kunit.c +++ b/lib/fortify_kunit.c @@ -25,6 +25,11 @@ static const char array_of_10[] = "this is 10"; static const char *ptr_of_11 = "this is 11!"; static char array_unknown[] = "compiler thinks I might change"; +/* Handle being built without CONFIG_FORTIFY_SOURCE */ +#ifndef __compiletime_strlen +# define __compiletime_strlen __builtin_strlen +#endif + static void known_sizes_test(struct kunit *test) { KUNIT_EXPECT_EQ(test, __compiletime_strlen("88888888"), 8); @@ -307,6 +312,14 @@ DEFINE_ALLOC_SIZE_TEST_PAIR(kvmalloc) } while (0) DEFINE_ALLOC_SIZE_TEST_PAIR(devm_kmalloc) +static int fortify_test_init(struct kunit *test) +{ + if (!IS_ENABLED(CONFIG_FORTIFY_SOURCE)) + kunit_skip(test, "Not built with CONFIG_FORTIFY_SOURCE=y"); + + return 0; +} + static struct kunit_case fortify_test_cases[] = { KUNIT_CASE(known_sizes_test), KUNIT_CASE(control_flow_split_test), @@ -323,6 +336,7 @@ static struct kunit_case fortify_test_cases[] = { static struct kunit_suite fortify_test_suite = { .name = "fortify", + .init = fortify_test_init, .test_cases = fortify_test_cases, }; From patchwork Fri Apr 7 19:27:09 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 80993 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp488186vqo; Fri, 7 Apr 2023 12:29:38 -0700 (PDT) X-Google-Smtp-Source: AKy350Ysudwf1lrpp42qONl9ybY3b1WHAsqSnX8bQkCBcveBk3bABgzsAe5AqXxJKjYrSP2ppj/l X-Received: by 2002:a17:906:7ce:b0:922:78e2:7680 with SMTP id m14-20020a17090607ce00b0092278e27680mr484467ejc.52.1680895778224; Fri, 07 Apr 2023 12:29:38 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680895778; cv=none; d=google.com; s=arc-20160816; b=Y+xjFBSbfpgVjc2BMt3RW0jHiG2MbvvGWz+kaHFbyzh5AOYPbY7xwA3gcQ80OT1k+Q u+bZNWvDFiFim6VmJRsRfulsKSKifS3YlI7clhKTD3DyPLfn3K48yPo2YiSBvCGAj10r 13WK5pOG2LO8rn8zihJ+cAWeBRRA88ILYzWxPlbvaMkZ8S84Ip/OQSRwL9H2WIwv/5ak lPW3+YuKao/QNpl34ywX3BaVpOHfVocoUEwsd2z95hgWs8g6z9iJoU0ovTADL12m8hNt SrUd8XjFfShcE34JGZMqPAC8qsrdifOni2FLEcOqt5hck4Jk/CILHBXv5Bkhhfr8zwAl FcaQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=LCqEfE4fF+BMO3eztdtksvLApA4/hcoAiL2AO2Jx8jE=; b=EtMfMUD3vdNjpCclLbHLkqYBoet1mVoTVdKaRcM5S3jRCjLisgcBHMje0tgPuB7/Xl hhIyflzeOXzAqcAbPZF5F5FsiiLnZxjCiY1+ZWvpb96yljbNBLwIKSzRjk0bsc1NkS95 61vcbGI/iaTrtGX7YDEKXnr6zqYh471HSiaR/tj1NpSQZMomtR5kTLYp7VyujH2PE410 gH3eCnJtXClNa6ceXGautyWf317Ko3rUYhUy4lYZmNKCCpC23bgukvGBJh8Fcz4qv9GK chKysZiwjfrYWWkLpYrfROGLPeFgmXh1yJJAXBv0KMuDifoARPeIJ6OmUagcrSXXHbFK rwBw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b="OX3M/cgf"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id gs38-20020a1709072d2600b0093048a8bd2esi5049397ejc.43.2023.04.07.12.29.14; Fri, 07 Apr 2023 12:29:38 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b="OX3M/cgf"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231236AbjDGT1f (ORCPT + 99 others); Fri, 7 Apr 2023 15:27:35 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53394 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230234AbjDGT1X (ORCPT ); Fri, 7 Apr 2023 15:27:23 -0400 Received: from mail-pl1-x635.google.com (mail-pl1-x635.google.com [IPv6:2607:f8b0:4864:20::635]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BD91B7D9B for ; Fri, 7 Apr 2023 12:27:21 -0700 (PDT) Received: by mail-pl1-x635.google.com with SMTP id z19so40744891plo.2 for ; Fri, 07 Apr 2023 12:27:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1680895641; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=LCqEfE4fF+BMO3eztdtksvLApA4/hcoAiL2AO2Jx8jE=; b=OX3M/cgfb49p9aUt+RUI68YYZOAp9CkoHt47Dmbxx98uIvKmfGf3dBaA8pp8pq2ITO lzjjSLnPNEb/pjy4QNBnWJ92X3qsc9lX+L0+eakeysaXYjxi7WE8OfFHzIM2XyxCtach N5uDxmje1iFdHde3TXNXWRjbku4Bt3uqCfQ7M= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680895641; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=LCqEfE4fF+BMO3eztdtksvLApA4/hcoAiL2AO2Jx8jE=; b=Nhj5nvAeKYLJqJAk8+dijXQwLEi943EfnNBQob8MLT50J7yl337WGU4oqZSS8+S+/R lL4xEPvP0+Fs/ELGIYEuDltAyMiyWcYzUHArRjFxpcFdglrdr+WNsnf93J+UvWmeTybN CPzuiOly73kSXoezW2ab8NrSUsfMzh8e57R++H9xyYV5fsUtvap+hDHBmDFzTmQID/n7 kOk6qq9r6+KRhZzCjBUhr9OWqeXv8QAz0MkcQkWNKQktU2qRv1U8wRSiy5/1Fa4vAgCc LDvn5ZoUkjAMkrUmKNZEUnpWMah34qhtqeTw4ZrjD98IrQyyeKWujQI9H87w4IKkwxTV Metg== X-Gm-Message-State: AAQBX9c0yv7uDNgA6ncsHQ8tQPKQXSxmLxHIW2OAbQ/tBltLNywl13xB 6dIfP62WNxlUbsrGM/kkHlw9uw== X-Received: by 2002:a05:6a20:be04:b0:d8:a1c9:c9bc with SMTP id ge4-20020a056a20be0400b000d8a1c9c9bcmr4044320pzb.25.1680895641278; Fri, 07 Apr 2023 12:27:21 -0700 (PDT) Received: from www.outflux.net (198-0-35-241-static.hfc.comcastbusiness.net. [198.0.35.241]) by smtp.gmail.com with ESMTPSA id f5-20020aa78b05000000b0062d8c855ee9sm3498171pfd.149.2023.04.07.12.27.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Apr 2023 12:27:18 -0700 (PDT) From: Kees Cook To: linux-hardening@vger.kernel.org Cc: Kees Cook , "Andy Shevchenko" , "Cezary Rojewski" , "Puyou Lu" , "Mark Brown" , "Josh Poimboeuf" , "Peter Zijlstra" , "Brendan Higgins" , "David Gow" , Andrew Morton , "Nathan Chancellor" , "Alexander Potapenko" , "Zhaoyang Huang" , "Randy Dunlap" , "Geert Uytterhoeven" , "Miguel Ojeda" , Alexander Lobakin , "Nick Desaulniers" , "Liam Howlett" , "Vlastimil Babka" , "Dan Williams" , "Rasmus Villemoes" , "Yury Norov" , "Jason A. Donenfeld" , "Sander Vanheule" , "Eric Biggers" , "Masami Hiramatsu (Google)" , "Andrey Konovalov" , "Linus Walleij" , "Daniel Latypov" , =?utf-8?b?Sm9zw6kgRXhww7NzaXRv?= , linux-kernel@vger.kernel.org, kunit-dev@googlegroups.com Subject: [PATCH v2 03/10] string: Add Kunit tests for strcat() family Date: Fri, 7 Apr 2023 12:27:09 -0700 Message-Id: <20230407192717.636137-3-keescook@chromium.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230407191904.gonna.522-kees@kernel.org> References: <20230407191904.gonna.522-kees@kernel.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=5622; h=from:subject; bh=d0/+ooOvDGbjHMvg1I4tGXInlU+netRGkDw9mqAzd+o=; b=owEBbQKS/ZANAwAKAYly9N/cbcAmAcsmYgBkMG6TM3Sr8YBDzEUgHpm9Qr7os7WBitixulj8nyjt 4IeCxByJAjMEAAEKAB0WIQSlw/aPIp3WD3I+bhOJcvTf3G3AJgUCZDBukwAKCRCJcvTf3G3AJpXDD/ 9UN2Ut16jFY359dFCbJjLXQb706yyaKLP/jKphDrnKusXpsMKZtx7ddsCcggAGrsFG8P8Mw97dEgOK KrKDzpv6YrAOd0BVd8olFxWKJehE1xiHdKxF3AYFaGm6nI/1iN9CTtHsKDhOE0WOovrB6TaTld5WXU KmrUJYC8cVxXI+f5SODkl7+1GC2zhlP8oQlTAwnHxT6eTUAj8omY2igdi7t3Wmwesl2hrNXBG6TkCY HsgcYW5reqdSl6TFYO/ftLyFNh/uoki30fnkB5FKopLtThS3kRapKJVVcibBEvHV61YLNauvCxF9yD M0dvpw9BSJhchgp9SrlVXtbkdq6MMUuPbhOZWKBpkqebN8Lc5zF8+xg91vKx36ehiuOmlYSL7O0hke cBtEdg9JwgUp/jnWx6+Z/Ut75zSbIrwE4HrX1vHeQ/CHSxxoCMcRexL0RXlxTJVHDUyf7HmaBPvfwQ SOiJ66o2n8RtaLnlKQpa/B0+THyl1bhcGg3Gc8Fc3I97QAeAcIvNpgNcU23B+R1lf+eqr91Odo+wkX 1pKBjP3ui1+Fnin30M836PZ0E/dY7utp3JrnqWI7YrtNgRbcZyoD/9Dv44/+YLxqjG6xkY5symZcBa IlfNB+lCBxYGxpvbYa2w/fpcL0nLMJ6QVrZiRZyDYnAAfKE+zGFXyW2Uetgg== X-Developer-Key: i=keescook@chromium.org; a=openpgp; fpr=A5C3F68F229DD60F723E6E138972F4DFDC6DC026 X-Spam-Status: No, score=-0.2 required=5.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1762546971576929140?= X-GMAIL-MSGID: =?utf-8?q?1762546971576929140?= Add tests to make sure the strcat() family of functions behave correctly. Signed-off-by: Kees Cook --- MAINTAINERS | 1 + lib/Kconfig.debug | 5 +++ lib/Makefile | 1 + lib/strcat_kunit.c | 104 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 111 insertions(+) create mode 100644 lib/strcat_kunit.c diff --git a/MAINTAINERS b/MAINTAINERS index ec57c42ed544..86c0012b5130 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8021,6 +8021,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/har F: include/linux/fortify-string.h F: lib/fortify_kunit.c F: lib/memcpy_kunit.c +F: lib/strcat_kunit.c F: lib/strscpy_kunit.c F: lib/test_fortify/* F: scripts/test_fortify.sh diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index d48a5f4b471e..86157aa5e979 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -2631,6 +2631,11 @@ config HW_BREAKPOINT_KUNIT_TEST If unsure, say N. +config STRCAT_KUNIT_TEST + tristate "Test strcat() family of functions at runtime" if !KUNIT_ALL_TESTS + depends on KUNIT + default KUNIT_ALL_TESTS + config STRSCPY_KUNIT_TEST tristate "Test strscpy*() family of functions at runtime" if !KUNIT_ALL_TESTS depends on KUNIT diff --git a/lib/Makefile b/lib/Makefile index baf2821f7a00..6582d8fe1a77 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -389,6 +389,7 @@ obj-$(CONFIG_STACKINIT_KUNIT_TEST) += stackinit_kunit.o CFLAGS_fortify_kunit.o += $(call cc-disable-warning, unsequenced) CFLAGS_fortify_kunit.o += $(DISABLE_STRUCTLEAK_PLUGIN) obj-$(CONFIG_FORTIFY_KUNIT_TEST) += fortify_kunit.o +obj-$(CONFIG_STRCAT_KUNIT_TEST) += strcat_kunit.o obj-$(CONFIG_STRSCPY_KUNIT_TEST) += strscpy_kunit.o obj-$(CONFIG_SIPHASH_KUNIT_TEST) += siphash_kunit.o diff --git a/lib/strcat_kunit.c b/lib/strcat_kunit.c new file mode 100644 index 000000000000..e21be95514af --- /dev/null +++ b/lib/strcat_kunit.c @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Kernel module for testing 'strcat' family of functions. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include + +static volatile int unconst; + +static void strcat_test(struct kunit *test) +{ + char dest[8]; + + /* Destination is terminated. */ + memset(dest, 0, sizeof(dest)); + KUNIT_EXPECT_EQ(test, strlen(dest), 0); + /* Empty copy does nothing. */ + KUNIT_EXPECT_TRUE(test, strcat(dest, "") == dest); + KUNIT_EXPECT_STREQ(test, dest, ""); + /* 4 characters copied in, stops at %NUL. */ + KUNIT_EXPECT_TRUE(test, strcat(dest, "four\000123") == dest); + KUNIT_EXPECT_STREQ(test, dest, "four"); + KUNIT_EXPECT_EQ(test, dest[5], '\0'); + /* 2 more characters copied in okay. */ + KUNIT_EXPECT_TRUE(test, strcat(dest, "AB") == dest); + KUNIT_EXPECT_STREQ(test, dest, "fourAB"); +} + +static void strncat_test(struct kunit *test) +{ + char dest[8]; + + /* Destination is terminated. */ + memset(dest, 0, sizeof(dest)); + KUNIT_EXPECT_EQ(test, strlen(dest), 0); + /* Empty copy of size 0 does nothing. */ + KUNIT_EXPECT_TRUE(test, strncat(dest, "", 0 + unconst) == dest); + KUNIT_EXPECT_STREQ(test, dest, ""); + /* Empty copy of size 1 does nothing too. */ + KUNIT_EXPECT_TRUE(test, strncat(dest, "", 1 + unconst) == dest); + KUNIT_EXPECT_STREQ(test, dest, ""); + /* Copy of max 0 characters should do nothing. */ + KUNIT_EXPECT_TRUE(test, strncat(dest, "asdf", 0 + unconst) == dest); + KUNIT_EXPECT_STREQ(test, dest, ""); + + /* 4 characters copied in, even if max is 8. */ + KUNIT_EXPECT_TRUE(test, strncat(dest, "four\000123", 8 + unconst) == dest); + KUNIT_EXPECT_STREQ(test, dest, "four"); + KUNIT_EXPECT_EQ(test, dest[5], '\0'); + KUNIT_EXPECT_EQ(test, dest[6], '\0'); + /* 2 characters copied in okay, 2 ignored. */ + KUNIT_EXPECT_TRUE(test, strncat(dest, "ABCD", 2 + unconst) == dest); + KUNIT_EXPECT_STREQ(test, dest, "fourAB"); +} + +static void strlcat_test(struct kunit *test) +{ + char dest[8] = ""; + int len = sizeof(dest) + unconst; + + /* Destination is terminated. */ + KUNIT_EXPECT_EQ(test, strlen(dest), 0); + /* Empty copy is size 0. */ + KUNIT_EXPECT_EQ(test, strlcat(dest, "", len), 0); + KUNIT_EXPECT_STREQ(test, dest, ""); + /* Size 1 should keep buffer terminated, report size of source only. */ + KUNIT_EXPECT_EQ(test, strlcat(dest, "four", 1 + unconst), 4); + KUNIT_EXPECT_STREQ(test, dest, ""); + + /* 4 characters copied in. */ + KUNIT_EXPECT_EQ(test, strlcat(dest, "four", len), 4); + KUNIT_EXPECT_STREQ(test, dest, "four"); + /* 2 characters copied in okay, gets to 6 total. */ + KUNIT_EXPECT_EQ(test, strlcat(dest, "AB", len), 6); + KUNIT_EXPECT_STREQ(test, dest, "fourAB"); + /* 2 characters ignored if max size (7) reached. */ + KUNIT_EXPECT_EQ(test, strlcat(dest, "CD", 7 + unconst), 8); + KUNIT_EXPECT_STREQ(test, dest, "fourAB"); + /* 1 of 2 characters skipped, now at true max size. */ + KUNIT_EXPECT_EQ(test, strlcat(dest, "EFG", len), 9); + KUNIT_EXPECT_STREQ(test, dest, "fourABE"); + /* Everything else ignored, now at full size. */ + KUNIT_EXPECT_EQ(test, strlcat(dest, "1234", len), 11); + KUNIT_EXPECT_STREQ(test, dest, "fourABE"); +} + +static struct kunit_case strcat_test_cases[] = { + KUNIT_CASE(strcat_test), + KUNIT_CASE(strncat_test), + KUNIT_CASE(strlcat_test), + {} +}; + +static struct kunit_suite strcat_test_suite = { + .name = "strcat", + .test_cases = strcat_test_cases, +}; + +kunit_test_suite(strcat_test_suite); + +MODULE_LICENSE("GPL"); From patchwork Fri Apr 7 19:27:10 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 81001 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp496339vqo; Fri, 7 Apr 2023 12:49:56 -0700 (PDT) X-Google-Smtp-Source: AKy350YTb0tDl/9eBGHHUDJWHELdy0G6i9fRRYYD8uzcQxK+Ann3A1piJTSTgPLFebwaW3R+i6Jh X-Received: by 2002:aa7:d290:0:b0:502:928d:4c93 with SMTP id w16-20020aa7d290000000b00502928d4c93mr3334935edq.14.1680896996390; Fri, 07 Apr 2023 12:49:56 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680896996; cv=none; d=google.com; s=arc-20160816; b=T6TVAeEFoJKiKfirYBlcTnfC/j9V53QPjBGJum/7sNIyp7VIH1xX7tVUP+3zMamQjl /Y9Y/pyVJo5DUr1Igts/Z63/0KG6zRxTF5uMev+x0HGkqFsX5yk7NBybfZznzxClLVWV Eu8BbEBtweDt8dVCpf3sUR9du7bnOSpnRpe49oB6XR5wZnZFIaMXXfh9B9iOQmlc8ATH 8NrvyWk8MYSwezY0tW28dfI04ggGIizxYixSH7+hQ2szQ9kc4HUOrCnyl15Y4IXLmoss 4hpaeYR5/IuVjM6X/D9M7YIBUU1GqnxJb3rCr5YHOYLHbT8kXeNrMzhCddLPDpgkc9cn UQ2w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=MpmYIoKSG+bC/EWBdXHIYxWKV0IWyEKuI3ZQc6us+A8=; b=nO02xDj1XDQjCvnPJygxcucJWbWgv/R3HnY/gKPsRyDjuPrwaUEKKcLew6zk1W+KgX bKroYNE7RwbL9UWUFcHya0VWA3bpqRfr5SW8Im3F1EcT2GQqcQvHeJfgGTXPC9WlCftG C5SiN5yUxKl6t6DlWeLH2IREvvwgTcmj+kMtVSw+LewG0YQuiEZcLLJm/1kQbuY1WJGz nDchBwiXAUyGIMgPTGX+P+wNsCZNuftQiSMjdkLkpszwqkF39crtXiBpFYRN55V+Thnd gIJntkjkqSFYDI657SQLATX2RVdcq9Vrh09g6p2imXw9FvtxfLzs5GUp7tuZRg11P3TZ kJYQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=EG9iRnU7; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id gs30-20020a1709072d1e00b00932fc24b601si1977926ejc.743.2023.04.07.12.49.31; Fri, 07 Apr 2023 12:49:56 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=EG9iRnU7; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230336AbjDGT1W (ORCPT + 99 others); Fri, 7 Apr 2023 15:27:22 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53308 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229500AbjDGT1U (ORCPT ); Fri, 7 Apr 2023 15:27:20 -0400 Received: from mail-pj1-x1032.google.com (mail-pj1-x1032.google.com [IPv6:2607:f8b0:4864:20::1032]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3B97FAD02 for ; Fri, 7 Apr 2023 12:27:19 -0700 (PDT) Received: by mail-pj1-x1032.google.com with SMTP id lr16-20020a17090b4b9000b0023f187954acso44071364pjb.2 for ; Fri, 07 Apr 2023 12:27:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1680895639; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=MpmYIoKSG+bC/EWBdXHIYxWKV0IWyEKuI3ZQc6us+A8=; b=EG9iRnU7Cgrw6zghD4WbG4bsmLUrUN8RbVmyA55kMuN3YzSFFODqvZA7qYGcJCqct2 3noRujL7Cmi3RPuLbYsuFZL86HiJXnbmrMptWTZ8ndqI5RXHPfJ+AdCKssv3C5wJQVpA AMM3qoO8K7hr7V+gN1+oG5y0BrLIhbx6FRn1M= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680895639; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=MpmYIoKSG+bC/EWBdXHIYxWKV0IWyEKuI3ZQc6us+A8=; b=UZ1+oG2kOKZVz+16QiAsCi7GfRGYjxh0+UGj8BP8NudtcdKMRLWIu1ru6YsUC/FFUK 0Geqxpdzx681FqYdTnswRtCltKM+DKh/gDHBEt0K3zIrU7XbPWOReWfJAcOAGGE5uguT 0u6DF2Nxl9GFaZ9c0v+5v8EshZB99dTK+d9+RcdJvjFqlCUS1ipjgnKHCat1Ona+86tH qCItqKSvZ0xU9/tpVfD8Rxa3biaQuPfmym+Y+ygPtVLg+nbmpAiVtaUb6GKeY8w61IT4 CWH2eZvcrfHzchybgbXNPBldyHIbA47qd/QzOmYtiiui+dkk6K8FAm9+U4YgslCF2hR7 pNxA== X-Gm-Message-State: AAQBX9cC3O4QZBUfMcKrHyC0Cecnz7S+HKbQFr2QvPQg6l4Pl5bkY7t0 MuzCabsZoSF55Kep4zp2UVAyQg== X-Received: by 2002:a17:903:41c5:b0:1a1:ad5e:bdb2 with SMTP id u5-20020a17090341c500b001a1ad5ebdb2mr4468616ple.57.1680895638680; Fri, 07 Apr 2023 12:27:18 -0700 (PDT) Received: from www.outflux.net (198-0-35-241-static.hfc.comcastbusiness.net. [198.0.35.241]) by smtp.gmail.com with ESMTPSA id c5-20020a170902d90500b0019a70a42b0asm3279520plz.169.2023.04.07.12.27.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Apr 2023 12:27:18 -0700 (PDT) From: Kees Cook To: linux-hardening@vger.kernel.org Cc: Kees Cook , Miguel Ojeda , "Andy Shevchenko" , "Cezary Rojewski" , "Puyou Lu" , "Mark Brown" , "Josh Poimboeuf" , "Peter Zijlstra" , "Brendan Higgins" , "David Gow" , Andrew Morton , "Nathan Chancellor" , "Alexander Potapenko" , "Zhaoyang Huang" , "Randy Dunlap" , "Geert Uytterhoeven" , "Miguel Ojeda" , Alexander Lobakin , "Nick Desaulniers" , "Liam Howlett" , "Vlastimil Babka" , "Dan Williams" , "Rasmus Villemoes" , "Yury Norov" , "Jason A. Donenfeld" , "Sander Vanheule" , "Eric Biggers" , "Masami Hiramatsu (Google)" , "Andrey Konovalov" , "Linus Walleij" , "Daniel Latypov" , =?utf-8?b?Sm9zw6kgRXhww7NzaXRv?= , linux-kernel@vger.kernel.org, kunit-dev@googlegroups.com Subject: [PATCH v2 04/10] fortify: Use const variables for __member_size tracking Date: Fri, 7 Apr 2023 12:27:10 -0700 Message-Id: <20230407192717.636137-4-keescook@chromium.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230407191904.gonna.522-kees@kernel.org> References: <20230407191904.gonna.522-kees@kernel.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=6730; h=from:subject; bh=SSZfz6yUPPV5wd89ZA5b2ejqzcpRfr59G2a0gR0Awhw=; b=owEBbQKS/ZANAwAKAYly9N/cbcAmAcsmYgBkMG6TIJi+gaVbi3MpQAYBKFCYpjiec9gLXN093SAh NZNzo76JAjMEAAEKAB0WIQSlw/aPIp3WD3I+bhOJcvTf3G3AJgUCZDBukwAKCRCJcvTf3G3AJmYPD/ wLsXYH/G8E6yYT5G2XKnEeJaXuRuok+IQ+uVR2+VumKXcCutZWabgwgw/6hYBoly4cip5xKsGSOolj siFfb3wiVIgk+ATU+amRGI6rCB++1V0AOZEhSdzLWT/8LZWeMSmQd2D0oKBEij5nJmGG7oVuLqbTaz r/g9tnF1+VpROXnU2cVYlCUrekjyn/2sJTkSlP+8prTTHrlY79R/aSpT7urQ+ijpbrhWq5GuI+48fz Spzcpn0EGqIMAT0qPsGU+vsxWbGGc1ccw3bKM5nAzUcDDyHLL/lZGMUg8VVl27LWtJcKN4XN0XDYYZ I/LAxugDV/x8LgmoL8sIoadF5m6+Csx7hpDckIrMBlMC+cC06oVVP5UmapYfvc51DtZp3YiwPezA+v 03dbcaHFspcvmi2pt8HkRFMRArS8FlHmmucaG97ovKX4875xq4ti/jDYIE5+fD75tHTUESBxQzF4NR qbNqSz6DpJfW68i12chqpf1StvIhjTzLKKnbQPomUQdhxW/1E4Mz8DFSCYxvSHCz0ez9GhB01FYCzf cDbQQCTxIP4xa2wxnh2p2nmEb3t7jTxap/4mLOdlteAe8ETCfms841Tv1OkYbhblfUvbCtEpCbUgDa 4TrUjqTqWxIh6ObdwKjOUqepHrYQUJRgYKXLUs901D199gogI/jI/npD6kdw== X-Developer-Key: i=keescook@chromium.org; a=openpgp; fpr=A5C3F68F229DD60F723E6E138972F4DFDC6DC026 X-Spam-Status: No, score=-0.2 required=5.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1762548249251615573?= X-GMAIL-MSGID: =?utf-8?q?1762548249251615573?= The sizes reported by __member_size should never change in a given function. Mark them as such. Suggested-by: Miguel Ojeda Cc: linux-hardening@vger.kernel.org Signed-off-by: Kees Cook Reviewed-by: Nick Desaulniers --- include/linux/fortify-string.h | 42 +++++++++++++++++----------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/include/linux/fortify-string.h b/include/linux/fortify-string.h index c9de1f59ee80..fae1bf4bd543 100644 --- a/include/linux/fortify-string.h +++ b/include/linux/fortify-string.h @@ -20,7 +20,7 @@ void __write_overflow_field(size_t avail, size_t wanted) __compiletime_warning(" ({ \ char *__p = (char *)(p); \ size_t __ret = SIZE_MAX; \ - size_t __p_size = __member_size(p); \ + const size_t __p_size = __member_size(p); \ if (__p_size != SIZE_MAX && \ __builtin_constant_p(*__p)) { \ size_t __p_len = __p_size - 1; \ @@ -142,7 +142,7 @@ extern char *__underlying_strncpy(char *p, const char *q, __kernel_size_t size) __FORTIFY_INLINE __diagnose_as(__builtin_strncpy, 1, 2, 3) char *strncpy(char * const POS p, const char *q, __kernel_size_t size) { - size_t p_size = __member_size(p); + const size_t p_size = __member_size(p); if (__compiletime_lessthan(p_size, size)) __write_overflow(); @@ -169,7 +169,7 @@ char *strncpy(char * const POS p, const char *q, __kernel_size_t size) __FORTIFY_INLINE __diagnose_as(__builtin_strcat, 1, 2) char *strcat(char * const POS p, const char *q) { - size_t p_size = __member_size(p); + const size_t p_size = __member_size(p); if (p_size == SIZE_MAX) return __underlying_strcat(p, q); @@ -191,8 +191,8 @@ extern __kernel_size_t __real_strnlen(const char *, __kernel_size_t) __RENAME(st */ __FORTIFY_INLINE __kernel_size_t strnlen(const char * const POS p, __kernel_size_t maxlen) { - size_t p_size = __member_size(p); - size_t p_len = __compiletime_strlen(p); + const size_t p_size = __member_size(p); + const size_t p_len = __compiletime_strlen(p); size_t ret; /* We can take compile-time actions when maxlen is const. */ @@ -233,8 +233,8 @@ __FORTIFY_INLINE __kernel_size_t strnlen(const char * const POS p, __kernel_size __FORTIFY_INLINE __diagnose_as(__builtin_strlen, 1) __kernel_size_t __fortify_strlen(const char * const POS p) { + const size_t p_size = __member_size(p); __kernel_size_t ret; - size_t p_size = __member_size(p); /* Give up if we don't know how large p is. */ if (p_size == SIZE_MAX) @@ -267,8 +267,8 @@ extern size_t __real_strlcpy(char *, const char *, size_t) __RENAME(strlcpy); */ __FORTIFY_INLINE size_t strlcpy(char * const POS p, const char * const POS q, size_t size) { - size_t p_size = __member_size(p); - size_t q_size = __member_size(q); + const size_t p_size = __member_size(p); + const size_t q_size = __member_size(q); size_t q_len; /* Full count of source string length. */ size_t len; /* Count of characters going into destination. */ @@ -318,10 +318,10 @@ extern ssize_t __real_strscpy(char *, const char *, size_t) __RENAME(strscpy); */ __FORTIFY_INLINE ssize_t strscpy(char * const POS p, const char * const POS q, size_t size) { - size_t len; /* Use string size rather than possible enclosing struct size. */ - size_t p_size = __member_size(p); - size_t q_size = __member_size(q); + const size_t p_size = __member_size(p); + const size_t q_size = __member_size(q); + size_t len; /* If we cannot get size of p and q default to call strscpy. */ if (p_size == SIZE_MAX && q_size == SIZE_MAX) @@ -394,9 +394,9 @@ __FORTIFY_INLINE ssize_t strscpy(char * const POS p, const char * const POS q, s __FORTIFY_INLINE __diagnose_as(__builtin_strncat, 1, 2, 3) char *strncat(char * const POS p, const char * const POS q, __kernel_size_t count) { + const size_t p_size = __member_size(p); + const size_t q_size = __member_size(q); size_t p_len, copy_len; - size_t p_size = __member_size(p); - size_t q_size = __member_size(q); if (p_size == SIZE_MAX && q_size == SIZE_MAX) return __underlying_strncat(p, q, count); @@ -639,7 +639,7 @@ __FORTIFY_INLINE bool fortify_memcpy_chk(__kernel_size_t size, extern void *__real_memscan(void *, int, __kernel_size_t) __RENAME(memscan); __FORTIFY_INLINE void *memscan(void * const POS0 p, int c, __kernel_size_t size) { - size_t p_size = __struct_size(p); + const size_t p_size = __struct_size(p); if (__compiletime_lessthan(p_size, size)) __read_overflow(); @@ -651,8 +651,8 @@ __FORTIFY_INLINE void *memscan(void * const POS0 p, int c, __kernel_size_t size) __FORTIFY_INLINE __diagnose_as(__builtin_memcmp, 1, 2, 3) int memcmp(const void * const POS0 p, const void * const POS0 q, __kernel_size_t size) { - size_t p_size = __struct_size(p); - size_t q_size = __struct_size(q); + const size_t p_size = __struct_size(p); + const size_t q_size = __struct_size(q); if (__builtin_constant_p(size)) { if (__compiletime_lessthan(p_size, size)) @@ -668,7 +668,7 @@ int memcmp(const void * const POS0 p, const void * const POS0 q, __kernel_size_t __FORTIFY_INLINE __diagnose_as(__builtin_memchr, 1, 2, 3) void *memchr(const void * const POS0 p, int c, __kernel_size_t size) { - size_t p_size = __struct_size(p); + const size_t p_size = __struct_size(p); if (__compiletime_lessthan(p_size, size)) __read_overflow(); @@ -680,7 +680,7 @@ void *memchr(const void * const POS0 p, int c, __kernel_size_t size) void *__real_memchr_inv(const void *s, int c, size_t n) __RENAME(memchr_inv); __FORTIFY_INLINE void *memchr_inv(const void * const POS0 p, int c, size_t size) { - size_t p_size = __struct_size(p); + const size_t p_size = __struct_size(p); if (__compiletime_lessthan(p_size, size)) __read_overflow(); @@ -693,7 +693,7 @@ extern void *__real_kmemdup(const void *src, size_t len, gfp_t gfp) __RENAME(kme __realloc_size(2); __FORTIFY_INLINE void *kmemdup(const void * const POS0 p, size_t size, gfp_t gfp) { - size_t p_size = __struct_size(p); + const size_t p_size = __struct_size(p); if (__compiletime_lessthan(p_size, size)) __read_overflow(); @@ -720,8 +720,8 @@ __FORTIFY_INLINE void *kmemdup(const void * const POS0 p, size_t size, gfp_t gfp __FORTIFY_INLINE __diagnose_as(__builtin_strcpy, 1, 2) char *strcpy(char * const POS p, const char * const POS q) { - size_t p_size = __member_size(p); - size_t q_size = __member_size(q); + const size_t p_size = __member_size(p); + const size_t q_size = __member_size(q); size_t size; /* If neither buffer size is known, immediately give up. */ From patchwork Fri Apr 7 19:27:11 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 80998 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp489513vqo; Fri, 7 Apr 2023 12:32:16 -0700 (PDT) X-Google-Smtp-Source: AKy350a9Tb0vilzKGujdLEAj6VW5PNwdH8oDycrQbN8CoFYIKM7oP/5v5IZ5NlK5Q/DLpJqocUA4 X-Received: by 2002:a05:6402:6ce:b0:4af:6c5e:225c with SMTP id n14-20020a05640206ce00b004af6c5e225cmr3174326edy.33.1680895935853; Fri, 07 Apr 2023 12:32:15 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680895935; cv=none; d=google.com; s=arc-20160816; b=p6HxOZNqu9/OLpFBVC0UvwCHB6601mGdum/Kk+KqF6n8ryPNbyS7jGrf9UZY9qaQTd N4gKRNLyZgFnk8wqSq8IUYU0IEEVYE29P3r4QwSF5w2iM6aRyk0ABZQ3cqVpzzGAOpUA o5Xhhx6068PEjxpeRqaHVne+ib34lnUJDwCx04zhxJLl+3yBX+10SsIo/qRLcKlHJV/R ruRXabFbm/vD0AgZTdw3JOOcf7hMx1iWbHyFl0t8Y++1DijVhGmYdX83xW9zZR5LqqrJ YyhTUPGE9yzUXC5q0R9UUxvIRa6O0hrT2V8KMBX7YXxzD47h6ja6pNs6YlPQZXdHsFOj rUBw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=MPcuT70JKssQ2aI2lYpWBDS/i3DDpoTMqsAdxV4Teow=; b=g6X7tIBQBrZSLLrzuUAXJKZIv5esNBQx3jdgRHXepCf/uyxUMIkUnNDpl4EPY6EVlZ dhA5Q3OYNnMfER+f8/og0ygBvZeTHzqt66r+SQqy9H9CjYnhFPhELkIVbKoEvI61iixv g0Y6Nz7i+vyX4BC3Fvl4+6ubZd4ox6zFf+BfDzkw3v6LJAx39QKHRr4GUrGTJNzPnZac EBDcBlGfV7DVdpiA3SWuBuHZqaI/Zs6gjNw/+28TckMf1s2RMD8xWOaxEihEizBl7fGe sKkqFa4/Qqns/m3l9f/ItskTf8oU2zgNwdmuqa2JGq+exoV/krgaYnImTJ33YsU+t6Nx VMIQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=cN16vjyv; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id l13-20020aa7cacd000000b0050477cb61ecsi2308315edt.82.2023.04.07.12.31.52; Fri, 07 Apr 2023 12:32:15 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=cN16vjyv; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229957AbjDGT2S (ORCPT + 99 others); Fri, 7 Apr 2023 15:28:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55178 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231523AbjDGT15 (ORCPT ); Fri, 7 Apr 2023 15:27:57 -0400 Received: from mail-pj1-x1033.google.com (mail-pj1-x1033.google.com [IPv6:2607:f8b0:4864:20::1033]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C23F7CA38 for ; Fri, 7 Apr 2023 12:27:34 -0700 (PDT) Received: by mail-pj1-x1033.google.com with SMTP id c3so73751pjg.1 for ; Fri, 07 Apr 2023 12:27:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1680895654; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=MPcuT70JKssQ2aI2lYpWBDS/i3DDpoTMqsAdxV4Teow=; b=cN16vjyvLAfvNO0jjCGHhI00oaqTmFSmnidjbBiLrBf0B/08a6qkleOl92BlOs6E1T /6iKx63ap9Uw3aFi03oADHv+RsE6oreIelPn3k+fIjdn9XIKttRJEVqbab0lIEjfC++j qpfaABtpH9kdeOaODI3LoufOzR9px+qtG2YXI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680895654; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=MPcuT70JKssQ2aI2lYpWBDS/i3DDpoTMqsAdxV4Teow=; b=LJSBmVC1RXqUZH2ZnUIqtxZt6SfZD1V7gVEz/rtreau/1rsbzskMoKUJh1xBEfm4Az mplOuQVDAY8Y7lhK8L3GgiSIEfSMTh/CcW5D7lx0bKjq0k2jBddN2rMRu4Z+VprW9Ucr jkuNqWP3D9UHAJOPtu3sFZ4O/3DMBt+55XbhsAMUgtzd9Homz9OzkbPDvffFBKKEpTqa nWa3PcAtktPJog/fzbtOQDpAnxA88j28tJu6HRVhSudFCGt/+tzCG73WGTyvcBXtclR3 vIwkLWg3lOOyEbC1M/3arnhV2MG6+Q4f0l1J8TZqKpWS5wIMsbIx66M9XkKr8H7aCjXq 0NEA== X-Gm-Message-State: AAQBX9eLwQpPyxx4qbVrNBPBYigza+hT/77+NwAzUHRfnFkGqPy+l3bk TyEXG2iMurJUdjt/IGFXXwI/HQ== X-Received: by 2002:a17:902:d2c9:b0:1a2:6f9f:de16 with SMTP id n9-20020a170902d2c900b001a26f9fde16mr2976801plc.11.1680895641785; Fri, 07 Apr 2023 12:27:21 -0700 (PDT) Received: from www.outflux.net (198-0-35-241-static.hfc.comcastbusiness.net. [198.0.35.241]) by smtp.gmail.com with ESMTPSA id v6-20020a1709028d8600b001a1faed8707sm3258805plo.63.2023.04.07.12.27.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Apr 2023 12:27:21 -0700 (PDT) From: Kees Cook To: linux-hardening@vger.kernel.org Cc: Kees Cook , "Andy Shevchenko" , "Cezary Rojewski" , "Puyou Lu" , "Mark Brown" , "Josh Poimboeuf" , "Peter Zijlstra" , "Brendan Higgins" , "David Gow" , Andrew Morton , "Nathan Chancellor" , "Alexander Potapenko" , "Zhaoyang Huang" , "Randy Dunlap" , "Geert Uytterhoeven" , "Miguel Ojeda" , Alexander Lobakin , "Nick Desaulniers" , "Liam Howlett" , "Vlastimil Babka" , "Dan Williams" , "Rasmus Villemoes" , "Yury Norov" , "Jason A. Donenfeld" , "Sander Vanheule" , "Eric Biggers" , "Masami Hiramatsu (Google)" , "Andrey Konovalov" , "Linus Walleij" , "Daniel Latypov" , =?utf-8?b?Sm9zw6kgRXhww7NzaXRv?= , linux-kernel@vger.kernel.org, kunit-dev@googlegroups.com Subject: [PATCH v2 05/10] fortify: Add protection for strlcat() Date: Fri, 7 Apr 2023 12:27:11 -0700 Message-Id: <20230407192717.636137-5-keescook@chromium.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230407191904.gonna.522-kees@kernel.org> References: <20230407191904.gonna.522-kees@kernel.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=3263; h=from:subject; bh=r+rAeBjXdjpzUns0umU+5al0iGfCgvAONvhR7EI8+Y8=; b=owEBbQKS/ZANAwAKAYly9N/cbcAmAcsmYgBkMG6TN8iuOguCB+qcsKhhHeavng+JIsd1jx5bn/I2 ZyUXTNCJAjMEAAEKAB0WIQSlw/aPIp3WD3I+bhOJcvTf3G3AJgUCZDBukwAKCRCJcvTf3G3AJqv8EA CNmv9W7JWKVOk91zfZbymKklNoRoEq6PHkPAoXZmBQ9prANIl8A0PpUcG7Tg44HCVln1YpbioI2e6c N1z+l4w9MTicUNShiQXV3p/u3aio9GZgdrwZFTXs598tWlR6bd7C7PcmhMWiVb2mEsSfoL5xw1BB+Q 7VtTxOJpRkfivCBExUzwOqJFlhEcCiLxtULImFD2OdxKvI+24zwzeL77iyDlyxyW4kVMHvPp8XBNfQ R1uJkWX/bdzxPwvnzvjgo3YUFXfU+fm1fEUrsGt4O1DjrnkiTbnymoQfmnVLtZ0SjEZ8EkJ95X/oNI dnHmjM5tm33rcPlI3v08Kr/ITAjaTQ/vQAihwmpPHuqL9QStWFVbUzt0fXcOYpoh6OdqHrtIM7Pe7s XxJb+0Dg0sDiFC/Fqx2XNWGB3lQgrWHwq1JtulFPMif5ONEyXuFZDorIv4Mu8765lshHXfdgZ92x/s vaWh4umoMxB6J94dGeKG7XGLUEFF7otfKfo5+RZXrOf/IuFrq0skfZJ24apxIverbThOXEgCqpi2ep WR8dag2pABvmetuTrKlax4AHHTN6XnZJiZfXwkyLyYpmNfS5kP4LGoIshqwA8PZ78E4UpiVwS1l/NG g9Q9TBNDFzNq+iQ60xfv0dSwA+z1t+6GXFy3ejgT/kWDK2xIDYJoqPppxYow== X-Developer-Key: i=keescook@chromium.org; a=openpgp; fpr=A5C3F68F229DD60F723E6E138972F4DFDC6DC026 X-Spam-Status: No, score=-0.2 required=5.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1762547136872223324?= X-GMAIL-MSGID: =?utf-8?q?1762547136872223324?= The definition of strcat() was defined in terms of unfortified strlcat(), but that meant there was no bounds checking done on the internal strlen() calls, and the (bounded) copy would be performed before reporting a failure. Additionally, pathological cases (i.e. unterminated destination buffer) did not make calls to fortify_panic(), which will make future unit testing more difficult. Instead, explicitly define a fortified strlcat() wrapper for strcat() to use. Signed-off-by: Kees Cook --- include/linux/fortify-string.h | 64 ++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/include/linux/fortify-string.h b/include/linux/fortify-string.h index fae1bf4bd543..8cf17ef81905 100644 --- a/include/linux/fortify-string.h +++ b/include/linux/fortify-string.h @@ -371,6 +371,70 @@ __FORTIFY_INLINE ssize_t strscpy(char * const POS p, const char * const POS q, s return __real_strscpy(p, q, len); } +/* Defined after fortified strlen() to reuse it. */ +extern size_t __real_strlcat(char *p, const char *q, size_t avail) __RENAME(strlcat); +/** + * strlcat - Append a string to an existing string + * + * @p: pointer to %NUL-terminated string to append to + * @q: pointer to %NUL-terminated string to append from + * @avail: Maximum bytes available in @p + * + * Appends %NUL-terminated string @q after the %NUL-terminated + * string at @p, but will not write beyond @avail bytes total, + * potentially truncating the copy from @q. @p will stay + * %NUL-terminated only if a %NUL already existed within + * the @avail bytes of @p. If so, the resulting number of + * bytes copied from @q will be at most "@avail - strlen(@p) - 1". + * + * Do not use this function. While FORTIFY_SOURCE tries to avoid + * read and write overflows, this is only possible when the sizes + * of @p and @q are known to the compiler. Prefer building the + * string with formatting, via scnprintf(), seq_buf, or similar. + * + * Returns total bytes that _would_ have been contained by @p + * regardless of truncation, similar to snprintf(). If return + * value is >= @avail, the string has been truncated. + * + */ +__FORTIFY_INLINE +size_t strlcat(char * const POS p, const char * const POS q, size_t avail) +{ + const size_t p_size = __member_size(p); + const size_t q_size = __member_size(q); + size_t p_len, copy_len; + size_t actual, wanted; + + /* Give up immediately if both buffer sizes are unknown. */ + if (p_size == SIZE_MAX && q_size == SIZE_MAX) + return __real_strlcat(p, q, avail); + + p_len = strnlen(p, avail); + copy_len = strlen(q); + wanted = actual = p_len + copy_len; + + /* Cannot append any more: report truncation. */ + if (avail <= p_len) + return wanted; + + /* Give up if string is already overflowed. */ + if (p_size <= p_len) + fortify_panic(__func__); + + if (actual >= avail) { + copy_len = avail - p_len - 1; + actual = p_len + copy_len; + } + + /* Give up if copy will overflow. */ + if (p_size <= actual) + fortify_panic(__func__); + __underlying_memcpy(p + p_len, q, copy_len); + p[actual] = '\0'; + + return wanted; +} + /** * strncat - Append a string to an existing string * From patchwork Fri Apr 7 19:27:12 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 80994 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp488189vqo; Fri, 7 Apr 2023 12:29:39 -0700 (PDT) X-Google-Smtp-Source: AKy350bcHtCXjRdUCCau1nfeor5IHwMLMrXDWJ/BICPx6XzdiHwjBCanBTEx78sf54XQXMKbTF6u X-Received: by 2002:aa7:d053:0:b0:501:d43e:d1dd with SMTP id n19-20020aa7d053000000b00501d43ed1ddmr3424205edo.33.1680895779481; Fri, 07 Apr 2023 12:29:39 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680895779; cv=none; d=google.com; s=arc-20160816; b=tjvnFfKbK2Hnp0RUbhQgBCwkP6hbY1NqctapUx8tE777EgZo1CELKK9vYlF6aGmO5s PklQD5zDao1BlcqpbASUBEjJlcATlPUeTPsXFiFv2lUU7qDQ5Nqn5ZxUs3+Q/8fmRGJt cbnA3u39WpEAbkwFNxFWol/TsC/V3/jKX/aQjQEoxy1d3h56+z709QMyvR1gEMTAYNWC TtWs2fWuQFmR7QUyobdB9+9KinFJWNNmdJJzKuht5WSgb0kiZY+37PxdldrsZPniiDID k/S2qKLrlUk9Zz+xfcf2/QOJdgnP+pk/tIpKdy67Iwl+nqIVcMjTdSrIY0Mqf/VmwU9p D5Uw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=lH3dZcNrJEcXdI6gLg/VVjSGY3YcGh7oSZMfJQoWlZk=; b=uafqoOc3Sp/g5JFva6m7qpPrI+SClSGPqCynZF3jgqwmBeZAuGe/eFLgTzrEQJ0gkn i7/Vzx06mmWmG2m449nN0ljdFhluvpQASCN4WU8Kdav6QGyeGBxYAqhExQEvQ2pPzspy GiJhMLHeGtJ8iC6/f5p7yPmmop5eIeHs3wmnOKsc2ahryV/dXG9Pa5xG3wcnShoOE51K zJaH1l1YfjQ/IzKu46cwUe93VBGqHEBvoUSXzbM8z85qWZuXGVkxvjIEqoT/MZ+Gb4dh NF5E6HRxEB8KOzIj8XNmycG+pXtwJ2fLh/pGyN3RgcjH2N7b+fTMAVTb7i3xcFkYs/re si7Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=Y6dsI+xa; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id w8-20020a50fa88000000b0050477dfb22bsi2627839edr.565.2023.04.07.12.29.15; Fri, 07 Apr 2023 12:29:39 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=Y6dsI+xa; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231279AbjDGT1h (ORCPT + 99 others); Fri, 7 Apr 2023 15:27:37 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53444 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230401AbjDGT1Y (ORCPT ); Fri, 7 Apr 2023 15:27:24 -0400 Received: from mail-pg1-x534.google.com (mail-pg1-x534.google.com [IPv6:2607:f8b0:4864:20::534]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D5E1BBB8E for ; Fri, 7 Apr 2023 12:27:22 -0700 (PDT) Received: by mail-pg1-x534.google.com with SMTP id 41be03b00d2f7-503e712502fso142338a12.0 for ; Fri, 07 Apr 2023 12:27:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1680895642; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=lH3dZcNrJEcXdI6gLg/VVjSGY3YcGh7oSZMfJQoWlZk=; b=Y6dsI+xaLywGjLzrDUE4NPsihTXJPkDDqEy1KlHDQJOljbqAf23LYpKKnxZGCY0Ix3 K/gQTNK5PGOrBxMnW/S3DxxG+G6DKJyIazDTG0sBOwTQS9/4TXOJZdzGlYJCaumE75eB exf7mrC7xy3XNiZXspsAYimbRc6Quu/lXQjwU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680895642; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=lH3dZcNrJEcXdI6gLg/VVjSGY3YcGh7oSZMfJQoWlZk=; b=i+HaIAI5lYTrx9pOXdmUdi+rWS8kVosUBIO66xHQOfS449IMQkBTfXXPe5eFqUp3dq ySJcPdPOmP83++JCeXXghxkc+Xyar4eIDjm0/AE0wMumiWXB1KFyfVnt9DwsD/kvlafw pm58fOCidz9+ChpDGY2PYhUqHMwjmOymS7IEjCWN0nxjMrTtoNFd8uU4leabXxVsVHQo 0nNQg114bdkSgn3kOB2IYzmfWxtPuqpvFZz6Jv/FJ2vjJARvuaBr7EjwLFJgcVI7qlW1 f16CGdIh+7gq8gpxvj2+wrPFyW4ARSzKWOMuRJjX7jNHYDeDWnAMeYyC1sDxzAUZC41x 1ZLg== X-Gm-Message-State: AAQBX9duKqs4q401Nsw8kX1ys9Ax0cWGrUbeditnkARMYnnIRtbsDyIo +Gv+6zc9oRmytkkehPnUSBWBag== X-Received: by 2002:aa7:9793:0:b0:628:650:4835 with SMTP id o19-20020aa79793000000b0062806504835mr3238044pfp.13.1680895642266; Fri, 07 Apr 2023 12:27:22 -0700 (PDT) Received: from www.outflux.net (198-0-35-241-static.hfc.comcastbusiness.net. [198.0.35.241]) by smtp.gmail.com with ESMTPSA id v12-20020aa7850c000000b005da23d8cbffsm3369357pfn.158.2023.04.07.12.27.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Apr 2023 12:27:21 -0700 (PDT) From: Kees Cook To: linux-hardening@vger.kernel.org Cc: Kees Cook , "Andy Shevchenko" , "Cezary Rojewski" , "Puyou Lu" , "Mark Brown" , "Josh Poimboeuf" , "Peter Zijlstra" , "Brendan Higgins" , "David Gow" , Andrew Morton , "Nathan Chancellor" , "Alexander Potapenko" , "Zhaoyang Huang" , "Randy Dunlap" , "Geert Uytterhoeven" , "Miguel Ojeda" , Alexander Lobakin , "Nick Desaulniers" , "Liam Howlett" , "Vlastimil Babka" , "Dan Williams" , "Rasmus Villemoes" , "Yury Norov" , "Jason A. Donenfeld" , "Sander Vanheule" , "Eric Biggers" , "Masami Hiramatsu (Google)" , "Andrey Konovalov" , "Linus Walleij" , "Daniel Latypov" , =?utf-8?b?Sm9zw6kgRXhww7NzaXRv?= , linux-kernel@vger.kernel.org, kunit-dev@googlegroups.com Subject: [PATCH v2 06/10] fortify: strcat: Move definition to use fortified strlcat() Date: Fri, 7 Apr 2023 12:27:12 -0700 Message-Id: <20230407192717.636137-6-keescook@chromium.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230407191904.gonna.522-kees@kernel.org> References: <20230407191904.gonna.522-kees@kernel.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=2641; h=from:subject; bh=fgN4hsz1FdWUIQbkd6Iy2KfoErfwaK/Oc+dmURYf7Mo=; b=owEBbAKT/ZANAwAKAYly9N/cbcAmAcsmYgBkMG6TtMTKotZ5UuZ6/J+WNgqbctlvvaLeCtSAKQ0/ hLnjmgWJAjIEAAEKAB0WIQSlw/aPIp3WD3I+bhOJcvTf3G3AJgUCZDBukwAKCRCJcvTf3G3AJoL6D/ i7HpHWgvMyI90z6CVCbQynb9o1brHw6iGmsTfNl0mrHayNgEnN50mQihqYfKpauwm1bEwTokrzBAsx oM8LLACRlDZrdzx2H8I/ZADgDIrMDceD20KpRp7hxjYibuGhlg3bOcp3BX/FLPDaQWo0CaEeTwuzvy 7wXxB2ekUV2JLQY8bjkx7KfHHoQ3n6R6LTLyaiTOEQCKnJFoteC5j32zzaWZNbZ/jbetpJOzeswFSY cOPj+VOVPvUdubTMKyKx4EjbOrb4qZEHA7hQ5SHpoCw60vpIs4jDY9VtqBMp0/sbYmdXg82YkxAqOI BUecXs5caWAfp8qvMjo739H86eS0piU2I7f8j0+IjOiL7LF08P3XJqjsoipz+xPJYmEJulwauWDKoi 1VuuVZjK2Kemw0oucpfWyWa8ghBipwF+fy7vQ0hZb/3z+Lqc07Ps17aTr4aYqI98eV/r9YLbIQzS5A 61h8Yz8PcbFc240wOdvLPxomh0tLyslgSobvWE9fqyA6YjoQZBBGSi59olM7JLn2a3Fy6+oJzPzjvq 3zU0TwLzoT8SCqJke00Ud27ZWAyT33To+3WeB2LrYN0P5cRSyrIV4DS1Nq2u43BidS5K/ej0G7YGzJ vZaR1hhi6sJmdX00dgIYTeBA49t3CTFHxhkyWHMFoQOSKzFLIJlmJyUYYM X-Developer-Key: i=keescook@chromium.org; a=openpgp; fpr=A5C3F68F229DD60F723E6E138972F4DFDC6DC026 X-Spam-Status: No, score=-0.2 required=5.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1762546973240831804?= X-GMAIL-MSGID: =?utf-8?q?1762546973240831804?= Move the definition of fortified strcat() to after strlcat() to use it for bounds checking. Signed-off-by: Kees Cook --- include/linux/fortify-string.h | 53 +++++++++++++++++----------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/include/linux/fortify-string.h b/include/linux/fortify-string.h index 8cf17ef81905..ab058d092817 100644 --- a/include/linux/fortify-string.h +++ b/include/linux/fortify-string.h @@ -151,33 +151,6 @@ char *strncpy(char * const POS p, const char *q, __kernel_size_t size) return __underlying_strncpy(p, q, size); } -/** - * strcat - Append a string to an existing string - * - * @p: pointer to NUL-terminated string to append to - * @q: pointer to NUL-terminated source string to append from - * - * Do not use this function. While FORTIFY_SOURCE tries to avoid - * read and write overflows, this is only possible when the - * destination buffer size is known to the compiler. Prefer - * building the string with formatting, via scnprintf() or similar. - * At the very least, use strncat(). - * - * Returns @p. - * - */ -__FORTIFY_INLINE __diagnose_as(__builtin_strcat, 1, 2) -char *strcat(char * const POS p, const char *q) -{ - const size_t p_size = __member_size(p); - - if (p_size == SIZE_MAX) - return __underlying_strcat(p, q); - if (strlcat(p, q, p_size) >= p_size) - fortify_panic(__func__); - return p; -} - extern __kernel_size_t __real_strnlen(const char *, __kernel_size_t) __RENAME(strnlen); /** * strnlen - Return bounded count of characters in a NUL-terminated string @@ -435,6 +408,32 @@ size_t strlcat(char * const POS p, const char * const POS q, size_t avail) return wanted; } +/* Defined after fortified strlcat() to reuse it. */ +/** + * strcat - Append a string to an existing string + * + * @p: pointer to NUL-terminated string to append to + * @q: pointer to NUL-terminated source string to append from + * + * Do not use this function. While FORTIFY_SOURCE tries to avoid + * read and write overflows, this is only possible when the + * destination buffer size is known to the compiler. Prefer + * building the string with formatting, via scnprintf() or similar. + * At the very least, use strncat(). + * + * Returns @p. + * + */ +__FORTIFY_INLINE __diagnose_as(__builtin_strcat, 1, 2) +char *strcat(char * const POS p, const char *q) +{ + const size_t p_size = __member_size(p); + + if (strlcat(p, q, p_size) >= p_size) + fortify_panic(__func__); + return p; +} + /** * strncat - Append a string to an existing string * From patchwork Fri Apr 7 19:27:13 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 80996 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp488307vqo; Fri, 7 Apr 2023 12:29:56 -0700 (PDT) X-Google-Smtp-Source: AKy350Yg2kQ0P8NmME6VUV/Snm4KPISLKEdqztKHpPAEkVZvRskQEzZjk8XRi/a9hugQcx8gM4d5 X-Received: by 2002:a17:906:1288:b0:931:19f8:d89c with SMTP id k8-20020a170906128800b0093119f8d89cmr404665ejb.73.1680895796547; Fri, 07 Apr 2023 12:29:56 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680895796; cv=none; d=google.com; s=arc-20160816; b=UMiu47uj/ia/hmQmN6XCF6Ghe0Hie0Rg1XUCUCGJ+2bkRgoaGV7VSoOlxlIgiisgOT dK8zyKFdLTYguOkuu9v1ZYAxOjgHdzeshPtbGLT3hWliMGAidcGeUyWRIcLtM9kbwsOl M6Ig2BosTY7CU00hGApM+WdAvrQfGN1SxklM3gZpcjhhb9XLNPUSWlBdlbzpEAy+Q40Y KkzF+O6XqyJV5LLfh2nKg3ev+li33RTza8zj7PWymLOcFuXfeTEwr8zd4/jMvFhM8Wj4 nRjJXDJ4zHxVjo6bjjyp3d+Z661aXTjIFQs9fYX4lMfebw4F6ncqpt4/cfbS/T6VVclD qI+A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=IE1lV//2EfqWsi9rLXlIKGjTg7Y0JuJqreF8rxNmIp4=; b=bZAQOFZGMbWC8emkSlv4PQ73sFg5uO+SKTJ2HdMHdhRA0rAIOTX2buYq8s1N8WoGle g6G6+ROqE8G6/4u/uJ1LaPjqNjrY8zOe83ig1nBMaTvVZkC86Dr16tJONWbXlzoBJfcj AFB0RYeMBug/8DT1MW0EmTxPgPA8opjVIobgnQPjJdEcqobkMpMANa87do/um8E8Qhr1 jUb1aTax6c8VSi4sCciCTzUtuZeHH3dNXMGxCrAcGGRv9+/Z88/q5yAFFlMadjFU/3/7 N/6qP30zE3eKbBeYN3Fxp4CkSZkKiPWwWapwqno85zQgEWp5WoNCHEtixHf3cpyxXC1/ TtDg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=OOfNhwt6; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id u3-20020a170906c40300b0093f9b68a0ffsi3811872ejz.319.2023.04.07.12.29.32; Fri, 07 Apr 2023 12:29:56 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=OOfNhwt6; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231352AbjDGT1q (ORCPT + 99 others); Fri, 7 Apr 2023 15:27:46 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53756 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230010AbjDGT1a (ORCPT ); Fri, 7 Apr 2023 15:27:30 -0400 Received: from mail-pl1-x62a.google.com (mail-pl1-x62a.google.com [IPv6:2607:f8b0:4864:20::62a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D75E8BDE6 for ; Fri, 7 Apr 2023 12:27:23 -0700 (PDT) Received: by mail-pl1-x62a.google.com with SMTP id o2so40742592plg.4 for ; Fri, 07 Apr 2023 12:27:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1680895643; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=IE1lV//2EfqWsi9rLXlIKGjTg7Y0JuJqreF8rxNmIp4=; b=OOfNhwt6AsOblyX4fTnJE+f4Xyodt1R+TLbdPGarUv8okjXb48BsDQyUk5d1Gcztz2 ewYv2DoGs5wuUfeWktV9+Xy4iQ8LncTDCAb/OgecOs00yI0YhnmX3rvBJpqZKHmSehxz kdnMnsN73C+olRzp00BkITWcSF8d51iFqQmEY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680895643; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=IE1lV//2EfqWsi9rLXlIKGjTg7Y0JuJqreF8rxNmIp4=; b=pn0xUV8ajUE6nR1DSABQLgn23veA3CM4R5fdW5I40Red5DLBRnY1MUWK8w8/akidsx TTOmBO4NR3+vAi4Ip/oVRHj2djUBFt8VcNPWCicZBQ1BiFPnLPCH0EZyRNO/YZJHv/M+ 5mUQy3zEhwDzFU4zfoAtTo4v6nCZTbuLh2HCjAasoNZUyWtuHhJj9FaVfYEDSCQytuLa 6QmozbX9ms0lT82u90xe97qA7Wjo14sIBvcfpbbtgn+lSYO36A0LHarXvMdl7i3t0Pkn mF35gssUrL7ostv8u0PZFqTMwkVGf7rLOnBp1ngXCkKiTtqhYVfm3JhDD+KuUSLAyOrC PTdg== X-Gm-Message-State: AAQBX9fbfjae6We70RFJFzt2CS7ZPJ+DhDufVpcKH9lPoZLYYgmJiygd DDir1QshIFNZSfX+3mw6UTHi3w== X-Received: by 2002:a17:902:d4d1:b0:19b:dbf7:f9ca with SMTP id o17-20020a170902d4d100b0019bdbf7f9camr4797649plg.0.1680895643303; Fri, 07 Apr 2023 12:27:23 -0700 (PDT) Received: from www.outflux.net (198-0-35-241-static.hfc.comcastbusiness.net. [198.0.35.241]) by smtp.gmail.com with ESMTPSA id g2-20020a1709026b4200b0019719f752c5sm3263818plt.59.2023.04.07.12.27.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Apr 2023 12:27:21 -0700 (PDT) From: Kees Cook To: linux-hardening@vger.kernel.org Cc: Kees Cook , Andy Shevchenko , Cezary Rojewski , Puyou Lu , Mark Brown , "Josh Poimboeuf" , "Peter Zijlstra" , "Brendan Higgins" , "David Gow" , Andrew Morton , "Nathan Chancellor" , "Alexander Potapenko" , "Zhaoyang Huang" , "Randy Dunlap" , "Geert Uytterhoeven" , "Miguel Ojeda" , Alexander Lobakin , "Nick Desaulniers" , "Liam Howlett" , "Vlastimil Babka" , "Dan Williams" , "Rasmus Villemoes" , "Yury Norov" , "Jason A. Donenfeld" , "Sander Vanheule" , "Eric Biggers" , "Masami Hiramatsu (Google)" , "Andrey Konovalov" , "Linus Walleij" , "Daniel Latypov" , =?utf-8?b?Sm9zw6kgRXhww7NzaXRv?= , linux-kernel@vger.kernel.org, kunit-dev@googlegroups.com Subject: [PATCH v2 07/10] fortify: Split reporting and avoid passing string pointer Date: Fri, 7 Apr 2023 12:27:13 -0700 Message-Id: <20230407192717.636137-7-keescook@chromium.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230407191904.gonna.522-kees@kernel.org> References: <20230407191904.gonna.522-kees@kernel.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=12362; h=from:subject; bh=sIh1INkht7p4hil8+5qOLn0KsawQtkhw8ZTi8OxES9I=; b=owEBbQKS/ZANAwAKAYly9N/cbcAmAcsmYgBkMG6TvuhHN7ddESKLwQhLG234Xp2FKpVi6+bCo4HY hNdQXhyJAjMEAAEKAB0WIQSlw/aPIp3WD3I+bhOJcvTf3G3AJgUCZDBukwAKCRCJcvTf3G3AJqMsD/ 4mrCtL556ZnBnBU+YpwWR4tdcwrFVN9VBaaHQ3ysRpnNzhcIKrirTf8F+bKgVXz7VdnQPQP4kPptqW oqgNJ8gLU8++PL4Jk+ztEKkKNbtSJi4D8wEK5kuFO70FcRsAjdNZlA9JMXpNEcRJtqRQlW1VU/61bX jhQ8yorXFzUYWduR/ZCRf2JlkgxzbtTWRHl0SD1dKWVr0cttG9i6ebNtGV/S6Fi8JhcT3j3nbFbWym 5xH+Q5Lu8vMc9QMdyNXP0wlTqvyUjPV8E2Ti4ZQYeY1W0HKAr/CBZcvD0/jU0u2yQcyuNZaHRE7wpS bicH4vXHlMb2SOZ9kUxh3EZU6RKJYDJLPM+t1pkBoKSI3mtpAJZn+b+2bgCdF0bRhQUTJH5xIGS4Yb lY70PRnz8ikHpcPJxt0azyFIolFkxx1dy7AvNVjdVdCgHG8O/7qKy3pan7EUy0G4/fADU534RwiCM1 XxzZ+UJwZ3BWPKVusr7jaThCQK+hQt7tYVVPLrXiExuqhRnTiHDNKHaSnpz7pXPlkNj+GaH6XQa1rE mkZC3kIyBDj3aV2k0F6gitpHkeB5RCwuRsMWDxSUcxcKCehcK50fziE5z7/13caNJaY+F11x7Ce8dy zdkF70ln9BtrthYbWI1G3YuX1DsUdE0SZd+5FbcoIRusX2h4vkNlZfBQ0YDQ== X-Developer-Key: i=keescook@chromium.org; a=openpgp; fpr=A5C3F68F229DD60F723E6E138972F4DFDC6DC026 X-Spam-Status: No, score=-0.2 required=5.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1762546990496565268?= X-GMAIL-MSGID: =?utf-8?q?1762546990496565268?= In preparation for KUnit testing and further improvements in fortify failure reporting, split out the report and encode the function and access failure (read or write overflow) into a single u8 argument. This mainly ends up saving some space in the data segment. For a defconfig with FORTIFY_SOURCE enabled: $ size gcc/vmlinux.before gcc/vmlinux.after text data bss dec hex filename 26132309 9760658 2195460 38088427 2452eeb gcc/vmlinux.before 26132386 9748382 2195460 38076228 244ff44 gcc/vmlinux.after Cc: Andy Shevchenko Cc: Cezary Rojewski Cc: Puyou Lu Cc: Mark Brown Cc: linux-hardening@vger.kernel.org Signed-off-by: Kees Cook Reviewed-by: Alexander Lobakin --- arch/arm/boot/compressed/misc.c | 2 +- arch/x86/boot/compressed/misc.c | 2 +- include/linux/fortify-string.h | 84 ++++++++++++++++++++++++--------- lib/string_helpers.c | 23 +++++++-- tools/objtool/check.c | 2 +- 5 files changed, 85 insertions(+), 28 deletions(-) diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c index abfed1aa2baa..f31e2c949089 100644 --- a/arch/arm/boot/compressed/misc.c +++ b/arch/arm/boot/compressed/misc.c @@ -160,7 +160,7 @@ decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p, putstr(" done, booting the kernel.\n"); } -void fortify_panic(const char *name) +void __fortify_panic(const u8 reason) { error("detected buffer overflow"); } diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index 014ff222bf4b..aa45e7529a40 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -470,7 +470,7 @@ asmlinkage __visible void *extract_kernel(void *rmode, memptr heap, return output + entry_offset; } -void fortify_panic(const char *name) +void __fortify_panic(const u8 reason) { error("detected buffer overflow"); } diff --git a/include/linux/fortify-string.h b/include/linux/fortify-string.h index ab058d092817..19906b45fb98 100644 --- a/include/linux/fortify-string.h +++ b/include/linux/fortify-string.h @@ -2,6 +2,7 @@ #ifndef _LINUX_FORTIFY_STRING_H_ #define _LINUX_FORTIFY_STRING_H_ +#include #include #include #include @@ -9,7 +10,45 @@ #define __FORTIFY_INLINE extern __always_inline __gnu_inline __overloadable #define __RENAME(x) __asm__(#x) -void fortify_panic(const char *name) __noreturn __cold; +#define FORTIFY_REASON_DIR(r) FIELD_GET(BIT(0), r) +#define FORTIFY_REASON_FUNC(r) FIELD_GET(GENMASK(7, 1), r) +#define FORTIFY_REASON(func, write) (FIELD_PREP(BIT(0), write) | \ + FIELD_PREP(GENMASK(7, 1), func)) + +#define fortify_panic(func, write) \ + __fortify_panic(FORTIFY_REASON(func, write)) + +#define FORTIFY_READ 0 +#define FORTIFY_WRITE 1 + +#define EACH_FORTIFY_FUNC(macro) \ + macro(strncpy), \ + macro(strnlen), \ + macro(strlen), \ + macro(strlcpy), \ + macro(strscpy), \ + macro(strlcat), \ + macro(strcat), \ + macro(strncat), \ + macro(memset), \ + macro(memcpy), \ + macro(memmove), \ + macro(memscan), \ + macro(memcmp), \ + macro(memchr), \ + macro(memchr_inv), \ + macro(kmemdup), \ + macro(strcpy), \ + macro(UNKNOWN), + +#define MAKE_FORTIFY_FUNC(func) FORTIFY_FUNC_##func + +enum fortify_func { + EACH_FORTIFY_FUNC(MAKE_FORTIFY_FUNC) +}; + +void __fortify_report(const u8 reason); +void __fortify_panic(const u8 reason) __cold __noreturn; void __read_overflow(void) __compiletime_error("detected read beyond size of object (1st parameter)"); void __read_overflow2(void) __compiletime_error("detected read beyond size of object (2nd parameter)"); void __read_overflow2_field(size_t avail, size_t wanted) __compiletime_warning("detected read beyond size of field (2nd parameter); maybe use struct_group()?"); @@ -147,7 +186,7 @@ char *strncpy(char * const POS p, const char *q, __kernel_size_t size) if (__compiletime_lessthan(p_size, size)) __write_overflow(); if (p_size < size) - fortify_panic(__func__); + fortify_panic(FORTIFY_FUNC_strncpy, FORTIFY_WRITE); return __underlying_strncpy(p, q, size); } @@ -178,7 +217,7 @@ __FORTIFY_INLINE __kernel_size_t strnlen(const char * const POS p, __kernel_size /* Do not check characters beyond the end of p. */ ret = __real_strnlen(p, maxlen < p_size ? maxlen : p_size); if (p_size <= ret && maxlen != ret) - fortify_panic(__func__); + fortify_panic(FORTIFY_FUNC_strnlen, FORTIFY_READ); return ret; } @@ -214,7 +253,7 @@ __kernel_size_t __fortify_strlen(const char * const POS p) return __underlying_strlen(p); ret = strnlen(p, p_size); if (p_size <= ret) - fortify_panic(__func__); + fortify_panic(FORTIFY_FUNC_strlen, FORTIFY_READ); return ret; } @@ -256,7 +295,7 @@ __FORTIFY_INLINE size_t strlcpy(char * const POS p, const char * const POS q, si } if (size) { if (len >= p_size) - fortify_panic(__func__); + fortify_panic(FORTIFY_FUNC_strlcpy, FORTIFY_WRITE); __underlying_memcpy(p, q, len); p[len] = '\0'; } @@ -334,7 +373,7 @@ __FORTIFY_INLINE ssize_t strscpy(char * const POS p, const char * const POS q, s * p_size. */ if (len > p_size) - fortify_panic(__func__); + fortify_panic(FORTIFY_FUNC_strscpy, FORTIFY_WRITE); /* * We can now safely call vanilla strscpy because we are protected from: @@ -392,7 +431,7 @@ size_t strlcat(char * const POS p, const char * const POS q, size_t avail) /* Give up if string is already overflowed. */ if (p_size <= p_len) - fortify_panic(__func__); + fortify_panic(FORTIFY_FUNC_strlcat, FORTIFY_READ); if (actual >= avail) { copy_len = avail - p_len - 1; @@ -401,7 +440,7 @@ size_t strlcat(char * const POS p, const char * const POS q, size_t avail) /* Give up if copy will overflow. */ if (p_size <= actual) - fortify_panic(__func__); + fortify_panic(FORTIFY_FUNC_strlcat, FORTIFY_WRITE); __underlying_memcpy(p + p_len, q, copy_len); p[actual] = '\0'; @@ -430,7 +469,7 @@ char *strcat(char * const POS p, const char *q) const size_t p_size = __member_size(p); if (strlcat(p, q, p_size) >= p_size) - fortify_panic(__func__); + fortify_panic(FORTIFY_FUNC_strcat, FORTIFY_WRITE); return p; } @@ -466,7 +505,7 @@ char *strncat(char * const POS p, const char * const POS q, __kernel_size_t coun p_len = strlen(p); copy_len = strnlen(q, count); if (p_size < p_len + copy_len + 1) - fortify_panic(__func__); + fortify_panic(FORTIFY_FUNC_strncat, FORTIFY_WRITE); __underlying_memcpy(p + p_len, q, copy_len); p[p_len + copy_len] = '\0'; return p; @@ -507,7 +546,7 @@ __FORTIFY_INLINE void fortify_memset_chk(__kernel_size_t size, * lengths are unknown.) */ if (p_size != SIZE_MAX && p_size < size) - fortify_panic("memset"); + fortify_panic(FORTIFY_FUNC_memset, FORTIFY_WRITE); } #define __fortify_memset_chk(p, c, size, p_size, p_size_field) ({ \ @@ -561,7 +600,7 @@ __FORTIFY_INLINE bool fortify_memcpy_chk(__kernel_size_t size, const size_t q_size, const size_t p_size_field, const size_t q_size_field, - const char *func) + const u8 func) { if (__builtin_constant_p(size)) { /* @@ -605,9 +644,10 @@ __FORTIFY_INLINE bool fortify_memcpy_chk(__kernel_size_t size, * (The SIZE_MAX test is to optimize away checks where the buffer * lengths are unknown.) */ - if ((p_size != SIZE_MAX && p_size < size) || - (q_size != SIZE_MAX && q_size < size)) - fortify_panic(func); + if (p_size != SIZE_MAX && p_size < size) + fortify_panic(func, FORTIFY_WRITE); + else if (q_size != SIZE_MAX && q_size < size) + fortify_panic(func, FORTIFY_READ); /* * Warn when writing beyond destination field size. @@ -640,7 +680,7 @@ __FORTIFY_INLINE bool fortify_memcpy_chk(__kernel_size_t size, const size_t __q_size_field = (q_size_field); \ WARN_ONCE(fortify_memcpy_chk(__fortify_size, __p_size, \ __q_size, __p_size_field, \ - __q_size_field, #op), \ + __q_size_field, FORTIFY_FUNC_ ##op), \ #op ": detected field-spanning write (size %zu) of single %s (size %zu)\n", \ __fortify_size, \ "field \"" #p "\" at " __FILE__ ":" __stringify(__LINE__), \ @@ -707,7 +747,7 @@ __FORTIFY_INLINE void *memscan(void * const POS0 p, int c, __kernel_size_t size) if (__compiletime_lessthan(p_size, size)) __read_overflow(); if (p_size < size) - fortify_panic(__func__); + fortify_panic(FORTIFY_FUNC_memscan, FORTIFY_READ); return __real_memscan(p, c, size); } @@ -724,7 +764,7 @@ int memcmp(const void * const POS0 p, const void * const POS0 q, __kernel_size_t __read_overflow2(); } if (p_size < size || q_size < size) - fortify_panic(__func__); + fortify_panic(FORTIFY_FUNC_memcmp, FORTIFY_READ); return __underlying_memcmp(p, q, size); } @@ -736,7 +776,7 @@ void *memchr(const void * const POS0 p, int c, __kernel_size_t size) if (__compiletime_lessthan(p_size, size)) __read_overflow(); if (p_size < size) - fortify_panic(__func__); + fortify_panic(FORTIFY_FUNC_memchr, FORTIFY_READ); return __underlying_memchr(p, c, size); } @@ -748,7 +788,7 @@ __FORTIFY_INLINE void *memchr_inv(const void * const POS0 p, int c, size_t size) if (__compiletime_lessthan(p_size, size)) __read_overflow(); if (p_size < size) - fortify_panic(__func__); + fortify_panic(FORTIFY_FUNC_memchr_inv, FORTIFY_READ); return __real_memchr_inv(p, c, size); } @@ -761,7 +801,7 @@ __FORTIFY_INLINE void *kmemdup(const void * const POS0 p, size_t size, gfp_t gfp if (__compiletime_lessthan(p_size, size)) __read_overflow(); if (p_size < size) - fortify_panic(__func__); + fortify_panic(FORTIFY_FUNC_kmemdup, FORTIFY_READ); return __real_kmemdup(p, size, gfp); } @@ -798,7 +838,7 @@ char *strcpy(char * const POS p, const char * const POS q) __write_overflow(); /* Run-time check for dynamic size overflow. */ if (p_size < size) - fortify_panic(__func__); + fortify_panic(FORTIFY_FUNC_strcpy, FORTIFY_WRITE); __underlying_memcpy(p, q, size); return p; } diff --git a/lib/string_helpers.c b/lib/string_helpers.c index 230020a2e076..96d502e1e578 100644 --- a/lib/string_helpers.c +++ b/lib/string_helpers.c @@ -1021,10 +1021,27 @@ EXPORT_SYMBOL(__read_overflow2_field); void __write_overflow_field(size_t avail, size_t wanted) { } EXPORT_SYMBOL(__write_overflow_field); -void fortify_panic(const char *name) +#define MAKE_FORTIFY_FUNC_NAME(func) [MAKE_FORTIFY_FUNC(func)] = #func + +static const char * const fortify_func_name[] = { + EACH_FORTIFY_FUNC(MAKE_FORTIFY_FUNC_NAME) +}; + +void __fortify_report(const u8 reason) +{ + const u8 func = FORTIFY_REASON_FUNC(reason); + const bool write = FORTIFY_REASON_DIR(reason); + const char *name; + + name = fortify_func_name[min_t(u8, func, FORTIFY_FUNC_UNKNOWN)]; + WARN(1, "%s: detected buffer %s overflow\n", name, str_read_write(!write)); +} +EXPORT_SYMBOL(__fortify_report); + +void __fortify_panic(const u8 reason) { - pr_emerg("detected buffer overflow in %s\n", name); + __fortify_report(reason); BUG(); } -EXPORT_SYMBOL(fortify_panic); +EXPORT_SYMBOL(__fortify_panic); #endif /* CONFIG_FORTIFY_SOURCE */ diff --git a/tools/objtool/check.c b/tools/objtool/check.c index f937be1afe65..2d0a67ce1c51 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -197,6 +197,7 @@ static bool __dead_end_function(struct objtool_file *file, struct symbol *func, * attribute isn't provided in ELF data. Keep 'em sorted. */ static const char * const global_noreturns[] = { + "__fortify_panic", "__invalid_creds", "__module_put_and_kthread_exit", "__reiserfs_panic", @@ -208,7 +209,6 @@ static bool __dead_end_function(struct objtool_file *file, struct symbol *func, "do_group_exit", "do_task_dead", "ex_handler_msr_mce", - "fortify_panic", "kthread_complete_and_exit", "kthread_exit", "kunit_try_catch_throw", From patchwork Fri Apr 7 19:27:14 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 80997 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp489337vqo; Fri, 7 Apr 2023 12:31:53 -0700 (PDT) X-Google-Smtp-Source: AKy350YfKYBEISQAJ+pTHc5mR2SpBeAZPXkXZxa2tUXXAoJTWuGpCR11FRGDOvPOTNDqDEXPb9Q6 X-Received: by 2002:a17:907:1742:b0:878:52cd:9006 with SMTP id lf2-20020a170907174200b0087852cd9006mr506559ejc.69.1680895912876; Fri, 07 Apr 2023 12:31:52 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680895912; cv=none; d=google.com; s=arc-20160816; b=iqFgBcwDofkSjObKnImodmLQyEX4kcP2Rgi19cknbLi2eXTF087/sX21iw5q3U6BFU IZn/1tU/Fkqy9wAzZazvxRejuN9SlV/F4U7xUH4C8hs32Pa9tR6FSJwZRnrAyh4dMUr1 4bEA2+2UKu+ReMey1H5VAUTcsV07/zsmdPc/N1Vrnry595cjKewP9JuIZTd1DYU8WOxz rqPLIovEiw9AjeQvJwSrUis4ZodYRfklP7CzdpY+jDDTRSvhTJq36HRiDl+qs4K31rTd xMQfv1nhAqZXSQgzp6FB4sTIxON5Ge35qAGgjX5p7lHPTUBIojTNsC7J9WIkBShbwyNh s27A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=QtXr5RoVmaQryzufWycfOD9IzG3R0AifqNWgNZdzp4U=; b=LimKZ5MNPD3putMpYvkuDjVOyGDOlq7TaNZ+0iOIT+THW1TiW+WhTzOA31L639XfBq 4anyY2u6yTxbpt5hKk5MRky8hikzpRlBZwq1oU/FfI9tw8x0RwvtZ5SF1+jhMDCpOHds gtK8ytlbFEplvnyI8uroN3Gv5DPoCWA2kU2+xIdxl5PZ9S5zK8k23InEdnr9TBehdWRj mzmr1Zq/lNehADsYnPxy2kpOnRtc5pZAmQY0IJSzzuEPWZs3lZRoYctsKnQZcpEsrQOT CDj6tQArEWPOhP7h47CZRphz7q4B3Q3znbEDABhhWxJ0H81XfzgNLU4O8SOWqIugGTa7 2vVA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=XVmu2Rcn; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id o24-20020a1709064f9800b0094974b981d3si3730642eju.915.2023.04.07.12.31.28; Fri, 07 Apr 2023 12:31:52 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=XVmu2Rcn; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231343AbjDGT1o (ORCPT + 99 others); Fri, 7 Apr 2023 15:27:44 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53528 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229889AbjDGT1Z (ORCPT ); Fri, 7 Apr 2023 15:27:25 -0400 Received: from mail-pj1-x102b.google.com (mail-pj1-x102b.google.com [IPv6:2607:f8b0:4864:20::102b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 93A72AD02 for ; Fri, 7 Apr 2023 12:27:23 -0700 (PDT) Received: by mail-pj1-x102b.google.com with SMTP id r21-20020a17090aa09500b0024663a79050so1200792pjp.4 for ; Fri, 07 Apr 2023 12:27:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1680895643; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=QtXr5RoVmaQryzufWycfOD9IzG3R0AifqNWgNZdzp4U=; b=XVmu2Rcn3iTKoVxTQJIsHMhe8djtMAh8NZJjDrpP8Vb1i0P8WAILZIaTBH8DqTGo9o hcEltXOA2HGqONgkX+3oP4XYCMAi3SPD/C25tkpTbF2N2D0XF4Gay/TFB3L+gDq4zwKF 8rMD6UcbsMlk0maeGlA0TztvOjGTyUk91a90I= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680895643; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=QtXr5RoVmaQryzufWycfOD9IzG3R0AifqNWgNZdzp4U=; b=QIJySfaDcKn/OiHcYPWSWZb3faY8j97mzZXafZ25dBbyUat2+xIHFzYFhpzqVpmLp2 nCCyWegdLljqs1w0AYp7c+4/SqTY0pZo6hMD32i1QGtZPO4DelW/Lmb0B9M5aNSoTkPO WanNbL4YNM/2c558GSKXVctfSX6T1fzXnFdsawtF+nano7hKveIsub9tVusRJzFRtUPq 2ha9fydtj60/3kXrzmcB3xcrQnw1D6oxCUJ9qbuR1T0i9etH5RmtQ3D1Yj1eUKTjdA5L CYMR3I1MlBQHlDrDapLrcS+u2t8LAeXldAU9/xAiJ0VqseQ5JhrSlrkU/xRo4dryAJ0C MSng== X-Gm-Message-State: AAQBX9dcF+k3kP/v4JxvxnzYytCtyYiUAap7hPlKho6USq4me1qqURkx 1vOealZwh3rW8bDk8LfLb+oTcg== X-Received: by 2002:a17:90b:1e02:b0:23f:680e:78be with SMTP id pg2-20020a17090b1e0200b0023f680e78bemr3184365pjb.48.1680895642717; Fri, 07 Apr 2023 12:27:22 -0700 (PDT) Received: from www.outflux.net (198-0-35-241-static.hfc.comcastbusiness.net. [198.0.35.241]) by smtp.gmail.com with ESMTPSA id g5-20020a17090adac500b0023af8a3cf6esm5079479pjx.48.2023.04.07.12.27.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Apr 2023 12:27:21 -0700 (PDT) From: Kees Cook To: linux-hardening@vger.kernel.org Cc: Kees Cook , "Andy Shevchenko" , "Cezary Rojewski" , "Puyou Lu" , "Mark Brown" , "Josh Poimboeuf" , "Peter Zijlstra" , "Brendan Higgins" , "David Gow" , Andrew Morton , "Nathan Chancellor" , "Alexander Potapenko" , "Zhaoyang Huang" , "Randy Dunlap" , "Geert Uytterhoeven" , "Miguel Ojeda" , Alexander Lobakin , "Nick Desaulniers" , "Liam Howlett" , "Vlastimil Babka" , "Dan Williams" , "Rasmus Villemoes" , "Yury Norov" , "Jason A. Donenfeld" , "Sander Vanheule" , "Eric Biggers" , "Masami Hiramatsu (Google)" , "Andrey Konovalov" , "Linus Walleij" , "Daniel Latypov" , =?utf-8?b?Sm9zw6kgRXhww7NzaXRv?= , linux-kernel@vger.kernel.org, kunit-dev@googlegroups.com Subject: [PATCH v2 08/10] fortify: Provide KUnit counters for failure testing Date: Fri, 7 Apr 2023 12:27:14 -0700 Message-Id: <20230407192717.636137-8-keescook@chromium.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230407191904.gonna.522-kees@kernel.org> References: <20230407191904.gonna.522-kees@kernel.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=10499; h=from:subject; bh=HDkfKLZGYb4y6Gt1HP3WKO7W1wPBmVIa6+/k24ttCH0=; b=owEBbQKS/ZANAwAKAYly9N/cbcAmAcsmYgBkMG6TNfYywyhtqW2LcR0LneffaDquIBeTlMjpGadx 0zM/q7+JAjMEAAEKAB0WIQSlw/aPIp3WD3I+bhOJcvTf3G3AJgUCZDBukwAKCRCJcvTf3G3AJoNrEA CKgpbKDLWyn5CI6HVQrDnugMonKDm9XQ5Svz+EUgPoVEYM17r55MxTn6/cywJC6cfMnL7K5426HXZL 5BDwCtsHctmhrduJP7qtn5nu7yw5NAzmofy7FRI5SgPPSRDu7s227g6fr2qgpExDHzKIyXt5ajVGcJ 3H0xbFLZlLSscvH+R785t6M7lqFr8LjYdMTgevbxL7G8lvgHke/j4erxcXCb5JmPx2S0adgyGXifxf UzbIHBCIjcWVE9otKu0SLoWKfcYk5SjlLfcwY/9V0w9BYXXR+2Dqgz6ZfdGs7B/srBiplHp+1VtOa2 3Bct3EcFo+PR8AbUg+QCDzebXdOXL8YRFu8oYnScpgzmSTqoKbY1Iw6bqD4ZKKMaiwo39fKx1Htt7Y uolRIQjB7TueQW4OU+nHY7GdASfnZBN11NBWu5uZvY+rZyx0P+1F38k2vSOJ29CSMXyDI4EllysGAz SO98kotSp9mHoT72/5DR4d2JAXJniCfmpwvXTK2sk9BIfM08G/Fz1w/zwUMsHWZy3cEyxnlB6K1Ec5 UyYBozChKdBvQB3B53G2RTqGqjX6P5bj5c9q+NdHRtYQkycU3oMJieFyD//lUmRYWjZiSPNh/Cp/Yu zgTLlbtYjACaK77LHiZf65feNiJThh99mQ8ynMedhliw6dxfUjt5CC8XrD/g== X-Developer-Key: i=keescook@chromium.org; a=openpgp; fpr=A5C3F68F229DD60F723E6E138972F4DFDC6DC026 X-Spam-Status: No, score=-0.2 required=5.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1762547112315097063?= X-GMAIL-MSGID: =?utf-8?q?1762547112315097063?= The standard C string APIs were not designed to have a failure mode; they were expected to always succeed without memory safety issues. Normally, CONFIG_FORTIFY_SOURCE will use fortify_panic() to stop processing, as truncating a read or write may provide an even worse system state. However, this creates a problem for testing under things like KUnit, which needs a way to survive failures. When building with CONFIG_KUNIT, provide a failure path for all users for fortify_panic, and track whether the failure was a read overflow or a write overflow, for KUnit tests to examine. Inspired by similar logic in the slab tests. Signed-off-by: Kees Cook --- include/linux/fortify-string.h | 45 +++++++++++++++++++--------------- lib/fortify_kunit.c | 44 +++++++++++++++++++++++++++++++++ lib/string_helpers.c | 2 ++ 3 files changed, 71 insertions(+), 20 deletions(-) diff --git a/include/linux/fortify-string.h b/include/linux/fortify-string.h index 19906b45fb98..5d04c0e95854 100644 --- a/include/linux/fortify-string.h +++ b/include/linux/fortify-string.h @@ -15,8 +15,12 @@ #define FORTIFY_REASON(func, write) (FIELD_PREP(BIT(0), write) | \ FIELD_PREP(GENMASK(7, 1), func)) -#define fortify_panic(func, write) \ +#ifdef FORTIFY_KUNIT_OVERRIDE +# define fortify_panic kunit_fortify_panic +#else +# define fortify_panic(func, write, retfail) \ __fortify_panic(FORTIFY_REASON(func, write)) +#endif #define FORTIFY_READ 0 #define FORTIFY_WRITE 1 @@ -186,7 +190,7 @@ char *strncpy(char * const POS p, const char *q, __kernel_size_t size) if (__compiletime_lessthan(p_size, size)) __write_overflow(); if (p_size < size) - fortify_panic(FORTIFY_FUNC_strncpy, FORTIFY_WRITE); + fortify_panic(FORTIFY_FUNC_strncpy, FORTIFY_WRITE, p); return __underlying_strncpy(p, q, size); } @@ -217,7 +221,7 @@ __FORTIFY_INLINE __kernel_size_t strnlen(const char * const POS p, __kernel_size /* Do not check characters beyond the end of p. */ ret = __real_strnlen(p, maxlen < p_size ? maxlen : p_size); if (p_size <= ret && maxlen != ret) - fortify_panic(FORTIFY_FUNC_strnlen, FORTIFY_READ); + fortify_panic(FORTIFY_FUNC_strnlen, FORTIFY_READ, ret); return ret; } @@ -253,7 +257,7 @@ __kernel_size_t __fortify_strlen(const char * const POS p) return __underlying_strlen(p); ret = strnlen(p, p_size); if (p_size <= ret) - fortify_panic(FORTIFY_FUNC_strlen, FORTIFY_READ); + fortify_panic(FORTIFY_FUNC_strlen, FORTIFY_READ, ret); return ret; } @@ -295,7 +299,7 @@ __FORTIFY_INLINE size_t strlcpy(char * const POS p, const char * const POS q, si } if (size) { if (len >= p_size) - fortify_panic(FORTIFY_FUNC_strlcpy, FORTIFY_WRITE); + fortify_panic(FORTIFY_FUNC_strlcpy, FORTIFY_WRITE, q_len); __underlying_memcpy(p, q, len); p[len] = '\0'; } @@ -373,7 +377,7 @@ __FORTIFY_INLINE ssize_t strscpy(char * const POS p, const char * const POS q, s * p_size. */ if (len > p_size) - fortify_panic(FORTIFY_FUNC_strscpy, FORTIFY_WRITE); + fortify_panic(FORTIFY_FUNC_strscpy, FORTIFY_WRITE, -E2BIG); /* * We can now safely call vanilla strscpy because we are protected from: @@ -431,7 +435,7 @@ size_t strlcat(char * const POS p, const char * const POS q, size_t avail) /* Give up if string is already overflowed. */ if (p_size <= p_len) - fortify_panic(FORTIFY_FUNC_strlcat, FORTIFY_READ); + fortify_panic(FORTIFY_FUNC_strlcat, FORTIFY_READ, wanted); if (actual >= avail) { copy_len = avail - p_len - 1; @@ -440,7 +444,7 @@ size_t strlcat(char * const POS p, const char * const POS q, size_t avail) /* Give up if copy will overflow. */ if (p_size <= actual) - fortify_panic(FORTIFY_FUNC_strlcat, FORTIFY_WRITE); + fortify_panic(FORTIFY_FUNC_strlcat, FORTIFY_WRITE, wanted); __underlying_memcpy(p + p_len, q, copy_len); p[actual] = '\0'; @@ -469,7 +473,7 @@ char *strcat(char * const POS p, const char *q) const size_t p_size = __member_size(p); if (strlcat(p, q, p_size) >= p_size) - fortify_panic(FORTIFY_FUNC_strcat, FORTIFY_WRITE); + fortify_panic(FORTIFY_FUNC_strcat, FORTIFY_WRITE, p); return p; } @@ -505,13 +509,13 @@ char *strncat(char * const POS p, const char * const POS q, __kernel_size_t coun p_len = strlen(p); copy_len = strnlen(q, count); if (p_size < p_len + copy_len + 1) - fortify_panic(FORTIFY_FUNC_strncat, FORTIFY_WRITE); + fortify_panic(FORTIFY_FUNC_strncat, FORTIFY_WRITE, p); __underlying_memcpy(p + p_len, q, copy_len); p[p_len + copy_len] = '\0'; return p; } -__FORTIFY_INLINE void fortify_memset_chk(__kernel_size_t size, +__FORTIFY_INLINE bool fortify_memset_chk(__kernel_size_t size, const size_t p_size, const size_t p_size_field) { @@ -546,7 +550,8 @@ __FORTIFY_INLINE void fortify_memset_chk(__kernel_size_t size, * lengths are unknown.) */ if (p_size != SIZE_MAX && p_size < size) - fortify_panic(FORTIFY_FUNC_memset, FORTIFY_WRITE); + fortify_panic(FORTIFY_FUNC_memset, FORTIFY_WRITE, true); + return false; } #define __fortify_memset_chk(p, c, size, p_size, p_size_field) ({ \ @@ -645,9 +650,9 @@ __FORTIFY_INLINE bool fortify_memcpy_chk(__kernel_size_t size, * lengths are unknown.) */ if (p_size != SIZE_MAX && p_size < size) - fortify_panic(func, FORTIFY_WRITE); + fortify_panic(func, FORTIFY_WRITE, true); else if (q_size != SIZE_MAX && q_size < size) - fortify_panic(func, FORTIFY_READ); + fortify_panic(func, FORTIFY_READ, true); /* * Warn when writing beyond destination field size. @@ -747,7 +752,7 @@ __FORTIFY_INLINE void *memscan(void * const POS0 p, int c, __kernel_size_t size) if (__compiletime_lessthan(p_size, size)) __read_overflow(); if (p_size < size) - fortify_panic(FORTIFY_FUNC_memscan, FORTIFY_READ); + fortify_panic(FORTIFY_FUNC_memscan, FORTIFY_READ, NULL); return __real_memscan(p, c, size); } @@ -764,7 +769,7 @@ int memcmp(const void * const POS0 p, const void * const POS0 q, __kernel_size_t __read_overflow2(); } if (p_size < size || q_size < size) - fortify_panic(FORTIFY_FUNC_memcmp, FORTIFY_READ); + fortify_panic(FORTIFY_FUNC_memcmp, FORTIFY_READ, INT_MIN); return __underlying_memcmp(p, q, size); } @@ -776,7 +781,7 @@ void *memchr(const void * const POS0 p, int c, __kernel_size_t size) if (__compiletime_lessthan(p_size, size)) __read_overflow(); if (p_size < size) - fortify_panic(FORTIFY_FUNC_memchr, FORTIFY_READ); + fortify_panic(FORTIFY_FUNC_memchr, FORTIFY_READ, NULL); return __underlying_memchr(p, c, size); } @@ -788,7 +793,7 @@ __FORTIFY_INLINE void *memchr_inv(const void * const POS0 p, int c, size_t size) if (__compiletime_lessthan(p_size, size)) __read_overflow(); if (p_size < size) - fortify_panic(FORTIFY_FUNC_memchr_inv, FORTIFY_READ); + fortify_panic(FORTIFY_FUNC_memchr_inv, FORTIFY_READ, NULL); return __real_memchr_inv(p, c, size); } @@ -801,7 +806,7 @@ __FORTIFY_INLINE void *kmemdup(const void * const POS0 p, size_t size, gfp_t gfp if (__compiletime_lessthan(p_size, size)) __read_overflow(); if (p_size < size) - fortify_panic(FORTIFY_FUNC_kmemdup, FORTIFY_READ); + fortify_panic(FORTIFY_FUNC_kmemdup, FORTIFY_READ, NULL); return __real_kmemdup(p, size, gfp); } @@ -838,7 +843,7 @@ char *strcpy(char * const POS p, const char * const POS q) __write_overflow(); /* Run-time check for dynamic size overflow. */ if (p_size < size) - fortify_panic(FORTIFY_FUNC_strcpy, FORTIFY_WRITE); + fortify_panic(FORTIFY_FUNC_strcpy, FORTIFY_WRITE, p); __underlying_memcpy(p, q, size); return p; } diff --git a/lib/fortify_kunit.c b/lib/fortify_kunit.c index 524132f33cf0..ea2b39f279c2 100644 --- a/lib/fortify_kunit.c +++ b/lib/fortify_kunit.c @@ -15,12 +15,28 @@ */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +/* Call kunit_fortify_panic() instead of fortify_panic() */ +#define FORTIFY_KUNIT_OVERRIDE +void fortify_add_kunit_error(int write); +#define kunit_fortify_panic(func, write, retfail) \ + do { \ + __fortify_report(FORTIFY_REASON(func, write)); \ + fortify_add_kunit_error(write); \ + return (retfail); \ + } while (0) + #include +#include #include #include #include #include +static struct kunit_resource read_resource; +static struct kunit_resource write_resource; +static int fortify_read_overflows; +static int fortify_write_overflows; + static const char array_of_10[] = "this is 10"; static const char *ptr_of_11 = "this is 11!"; static char array_unknown[] = "compiler thinks I might change"; @@ -30,6 +46,25 @@ static char array_unknown[] = "compiler thinks I might change"; # define __compiletime_strlen __builtin_strlen #endif +void fortify_add_kunit_error(int write) +{ + struct kunit_resource *resource; + struct kunit *current_test; + + current_test = kunit_get_current_test(); + if (!current_test) + return; + + resource = kunit_find_named_resource(current_test, + write ? "fortify_write_overflows" + : "fortify_read_overflows"); + if (!resource) + return; + + (*(int *)resource->data)++; + kunit_put_resource(resource); +} + static void known_sizes_test(struct kunit *test) { KUNIT_EXPECT_EQ(test, __compiletime_strlen("88888888"), 8); @@ -317,6 +352,15 @@ static int fortify_test_init(struct kunit *test) if (!IS_ENABLED(CONFIG_FORTIFY_SOURCE)) kunit_skip(test, "Not built with CONFIG_FORTIFY_SOURCE=y"); + fortify_read_overflows = 0; + kunit_add_named_resource(test, NULL, NULL, &read_resource, + "fortify_read_overflows", + &fortify_read_overflows); + fortify_write_overflows = 0; + kunit_add_named_resource(test, NULL, NULL, &write_resource, + "fortify_write_overflows", + &fortify_write_overflows); + return 0; } diff --git a/lib/string_helpers.c b/lib/string_helpers.c index 96d502e1e578..38edde20e61b 100644 --- a/lib/string_helpers.c +++ b/lib/string_helpers.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include /** * string_get_size - get the size in the specified units From patchwork Fri Apr 7 19:27:15 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 81002 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp496342vqo; Fri, 7 Apr 2023 12:49:56 -0700 (PDT) X-Google-Smtp-Source: AKy350ZsPhH6Flnnb08M6t36QQzm1m6thzxm1gWKCUfi5nhYeeuolzMuLxIsoJKWzFLDQBefut2T X-Received: by 2002:a17:906:3455:b0:932:5f7d:db33 with SMTP id d21-20020a170906345500b009325f7ddb33mr552766ejb.34.1680896996521; Fri, 07 Apr 2023 12:49:56 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680896996; cv=none; d=google.com; s=arc-20160816; b=DbTgqiE74K+ybbG3PCChoIoiahpx94EHUAFD1bigA7fi/E+vjqtAHpTQ2uAd5B336s TRlj5WXqceBOG+IHf1W75feF+1rDfDWc48JKma8XQfLHQhwoC4Jt2vwnlwXT7ti9o4Q4 8tRsxETGqVN1JY4dYjzABA9Egd5BtPfDsguJmgSZq8Qr7qxc52BQeZDLgCy6G98qFgkU qY7z7r2zDIIosF0klr2SPqIKYxzrEt7wdy5RRE00MFhqqQhAz+uHZ81F6DFdwe2ax+gc xGiDOCU+XmIB4+GaYNNauEw+p9w1JRqyzl0LuXfq87HFgVIHTEDxZeynavObb2a9qi52 kcew== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=IKXPyf9/jVgEky/woKrd/ToiUHGkbctLniTEZtkVQes=; b=PJAVCUaBXIwnnZphPV7qf/6Kt8TQRz6E1udv8kDtWDBCULkD7K3ofnWhycI3mhw8sj lZ0rfRATRYFugac4Q+ivkvoK3YaMW4iEB1QLEhaq5e47fdjEtx6aXlOpLXQWPOvBn1Uv 6RrYoBf7BCIb378k3c6BV0oUVZ98kcQcSny6eCI7w8SEB8OQIU13ucw8T/NCqS6h6irP nWGTyAg/jOa9aJk6R+afC2UIIW4/JHnzt1sV9Udcf8u53B0CopRkg2dIlXeGpxWIGFMf nHd9Z4wftH4u3D9Jn9R9lEa/+bzsVYRlr760LRaZBEaCCWaazbz1RMsTn38/Q6b0Lerd v8xA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=I+kfyOmr; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id ss10-20020a170907c00a00b008b2712f79e8si161994ejc.940.2023.04.07.12.49.30; Fri, 07 Apr 2023 12:49:56 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=I+kfyOmr; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231315AbjDGT17 (ORCPT + 99 others); Fri, 7 Apr 2023 15:27:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54538 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229940AbjDGT1m (ORCPT ); Fri, 7 Apr 2023 15:27:42 -0400 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 7A508BBA1 for ; Fri, 7 Apr 2023 12:27:26 -0700 (PDT) Received: by mail-pj1-x102d.google.com with SMTP id q15-20020a17090a2dcf00b0023efab0e3bfso2166661pjm.3 for ; Fri, 07 Apr 2023 12:27:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1680895646; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=IKXPyf9/jVgEky/woKrd/ToiUHGkbctLniTEZtkVQes=; b=I+kfyOmr6Qoo6b3/ZrybUklENlej9HUCZeiHZWTfUK8hgYP2sFFTMsxQt8zVnLvW/K wYBqqv+1jfCkBmYfQalUiZEGod0FkWEtpF7XKo7EHsDPqB2ov5uQLVdJLwa8uTAZr5VX E503I7yHGHqXZ/Jf6c8jmieB91j0J0xp++8tw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680895646; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=IKXPyf9/jVgEky/woKrd/ToiUHGkbctLniTEZtkVQes=; b=3pkOv5gSPDVbnJ0gWX1TghEYphS1h766VNMFKt2ujVgH0aBp11q3So72fQge6o8+X1 H+AaXZjeCEg6kZ8Li8YyiYd0LHXaazspesr3theY5p6JS8u0254AcFukXgFj59QQk+l+ xcorMhYtpvbJBUtUWlyXmeLg6ME0kYhruC+mPR0qVFbCOUEA7OCKtnHhAOhtSlyKPAfj Adxrag4KbFzwQI93djofL6ibMbIhNnLZ0n5yiKrXV6xeDoLpqXgSdelmNyiToEZRechI TCFz5sH8RNPm5oFN6BrwNhRSnTiXF3Qj3V1Jjcx6klV+gxmEI31MtOIsyX4dMoVDdXdW 9pMQ== X-Gm-Message-State: AAQBX9e0yQ3VoC/GwnDwOS3cl7a+R65iIazhkdEBuo3a3IG3gJQEqOKZ XwC9HqjtpQYje+xNgH18XSFiMA== X-Received: by 2002:a05:6a20:7010:b0:cc:606a:4330 with SMTP id h16-20020a056a20701000b000cc606a4330mr3067846pza.55.1680895645530; Fri, 07 Apr 2023 12:27:25 -0700 (PDT) Received: from www.outflux.net (198-0-35-241-static.hfc.comcastbusiness.net. [198.0.35.241]) by smtp.gmail.com with ESMTPSA id y15-20020aa7804f000000b00590ede84b1csm3502406pfm.147.2023.04.07.12.27.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Apr 2023 12:27:21 -0700 (PDT) From: Kees Cook To: linux-hardening@vger.kernel.org Cc: Kees Cook , "Andy Shevchenko" , "Cezary Rojewski" , "Puyou Lu" , "Mark Brown" , "Josh Poimboeuf" , "Peter Zijlstra" , "Brendan Higgins" , "David Gow" , Andrew Morton , "Nathan Chancellor" , "Alexander Potapenko" , "Zhaoyang Huang" , "Randy Dunlap" , "Geert Uytterhoeven" , "Miguel Ojeda" , Alexander Lobakin , "Nick Desaulniers" , "Liam Howlett" , "Vlastimil Babka" , "Dan Williams" , "Rasmus Villemoes" , "Yury Norov" , "Jason A. Donenfeld" , "Sander Vanheule" , "Eric Biggers" , "Masami Hiramatsu (Google)" , "Andrey Konovalov" , "Linus Walleij" , "Daniel Latypov" , =?utf-8?b?Sm9zw6kgRXhww7NzaXRv?= , linux-kernel@vger.kernel.org, kunit-dev@googlegroups.com Subject: [PATCH v2 09/10] fortify: Add KUnit tests for runtime overflows Date: Fri, 7 Apr 2023 12:27:15 -0700 Message-Id: <20230407192717.636137-9-keescook@chromium.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230407191904.gonna.522-kees@kernel.org> References: <20230407191904.gonna.522-kees@kernel.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=28211; h=from:subject; bh=9234LPqVGxZ+vQONlRmA/WilFWlwyeVTGRc6LK6b9W4=; b=owEBbQKS/ZANAwAKAYly9N/cbcAmAcsmYgBkMG6TnXtnMdDU49QvmJyRXJ8CSL/Hg1N9YJdbQMRS /0eSRcuJAjMEAAEKAB0WIQSlw/aPIp3WD3I+bhOJcvTf3G3AJgUCZDBukwAKCRCJcvTf3G3AJjmPD/ 9xPFuTnIXCYrM0wPvMUs/6KEc5xlYocj5GeDJGbcW2VWChCjsDoP7kEyCGA2RM1/IEKzV7/klLFTRd YYaCD4P1DfN5YBbHpSOhtywUvCooQ95kg5yO6fdYSZ7WVhlPHLk7v6kgthy75zWZf0KqsSI3gX0wqU dYHmjBbjfdUQvTEPmKzNZefPtvPy5aPN0kbY6lLOj32OYVEbkvE/EAyrQNtRIXTy1M4jG5yHApaDnn MuoCqG++6q7XzrpS/KhfGkWvozecaGiWqyVZPpIDYgfGGcEXvfnISl47J/FrmaIWFTdC7kHgzkR+C9 NMxkHRQwhtGWRqY/YM+P33Vhv6kBWLPfW8KTWvQls+lW4XR1AicqWQ5EaxXZui5Z3vaRiu9V/13zHo AJKUx8nMk+0iL2gKdz9Ek1rPPKwJGJNooWqVGoldFq5kMTpqu7iLJneDi9x7q5LynjbXIf4LAy+YdW I7XnWtijlG/WebWYqwNQWbjh2iLF7aJUc1RGcmOjVUhtjx/4xKxpwKOYCe2DAfIJ+uOtv9isKM/XFX 0cy8N6OtA5u5Vm0DbS96mbeCNJlMtAAhIU5ZQWVvzfkvjC9Be4998aBXR0cGIIklbzArH1rY5N668T GinmVYfNDK+axxi1DNG2Tw5jWQvLvIV9onUmFI0Xdjebm9sak9xcQZ/f3qRA== X-Developer-Key: i=keescook@chromium.org; a=openpgp; fpr=A5C3F68F229DD60F723E6E138972F4DFDC6DC026 X-Spam-Status: No, score=-0.2 required=5.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1762548248911975880?= X-GMAIL-MSGID: =?utf-8?q?1762548248911975880?= With fortify overflows able to be redirected, we can use KUnit to exercise the overflow conditions. Add tests for every API covered by CONFIG_FORTIFY_SOURCE. Signed-off-by: Kees Cook --- lib/fortify_kunit.c | 673 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 673 insertions(+) diff --git a/lib/fortify_kunit.c b/lib/fortify_kunit.c index ea2b39f279c2..3206fe723110 100644 --- a/lib/fortify_kunit.c +++ b/lib/fortify_kunit.c @@ -347,6 +347,663 @@ DEFINE_ALLOC_SIZE_TEST_PAIR(kvmalloc) } while (0) DEFINE_ALLOC_SIZE_TEST_PAIR(devm_kmalloc) +/* + * We can't have an array at the end of a structure or else + * builds without -fstrict-flex-arrays=3 will report them as + * being an unknown length. Additionally, add bytes before + * and after the string to catch over/underflows if tests + * fail. + */ +struct fortify_padding { + unsigned long bytes_before; + char buf[32]; + unsigned long bytes_after; +}; +/* Force compiler into not being able to resolve size at compile-time. */ +static volatile int unconst; + +static void strlen_test(struct kunit *test) +{ + struct fortify_padding pad = { }; + int i, end = sizeof(pad.buf) - 1; + + /* Fill 31 bytes with valid characters. */ + for (i = 0; i < sizeof(pad.buf) - 1; i++) + pad.buf[i] = i + '0'; + /* Trailing bytes are still %NUL. */ + KUNIT_EXPECT_EQ(test, pad.buf[end], '\0'); + KUNIT_EXPECT_EQ(test, pad.bytes_after, 0); + + /* String is terminated, so strlen() is valid. */ + KUNIT_EXPECT_EQ(test, strlen(pad.buf), end); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); + + /* Make string unterminated, and recount. */ + pad.buf[end] = 'A'; + end = sizeof(pad.buf); + KUNIT_EXPECT_EQ(test, strlen(pad.buf), end); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 1); +} + +static void strnlen_test(struct kunit *test) +{ + struct fortify_padding pad = { }; + int i, end = sizeof(pad.buf) - 1; + + /* Fill 31 bytes with valid characters. */ + for (i = 0; i < sizeof(pad.buf) - 1; i++) + pad.buf[i] = i + '0'; + /* Trailing bytes are still %NUL. */ + KUNIT_EXPECT_EQ(test, pad.buf[end], '\0'); + KUNIT_EXPECT_EQ(test, pad.bytes_after, 0); + + /* String is terminated, so strnlen() is valid. */ + KUNIT_EXPECT_EQ(test, strnlen(pad.buf, sizeof(pad.buf)), end); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); + /* A truncated strnlen() will be safe, too. */ + KUNIT_EXPECT_EQ(test, strnlen(pad.buf, sizeof(pad.buf) / 2), + sizeof(pad.buf) / 2); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); + + /* Make string unterminated, and recount. */ + pad.buf[end] = 'A'; + end = sizeof(pad.buf); + /* Reading beyond with strncpy() will fail. */ + KUNIT_EXPECT_EQ(test, strnlen(pad.buf, end + 1), end); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 1); + KUNIT_EXPECT_EQ(test, strnlen(pad.buf, end + 2), end); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 2); + + /* Early-truncated is safe still, though. */ + KUNIT_EXPECT_EQ(test, strnlen(pad.buf, end), end); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 2); + + end = sizeof(pad.buf) / 2; + KUNIT_EXPECT_EQ(test, strnlen(pad.buf, end), end); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 2); +} + +static void strcpy_test(struct kunit *test) +{ + struct fortify_padding pad = { }; + char src[sizeof(pad.buf) + 1] = { }; + int i; + + /* Fill 31 bytes with valid characters. */ + for (i = 0; i < sizeof(src) - 2; i++) + src[i] = i + '0'; + + /* Destination is %NUL-filled to start with. */ + KUNIT_EXPECT_EQ(test, pad.bytes_before, 0); + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 3], '\0'); + KUNIT_EXPECT_EQ(test, pad.bytes_after, 0); + + /* Legitimate strcpy() 1 less than of max size. */ + KUNIT_ASSERT_TRUE(test, strcpy(pad.buf, src) + == pad.buf); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0); + /* Only last byte should be %NUL */ + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0'); + + src[sizeof(src) - 2] = 'A'; + /* But now we trip the overflow checking. */ + KUNIT_ASSERT_TRUE(test, strcpy(pad.buf, src) + == pad.buf); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 1); + /* Trailing %NUL -- thanks to FORTIFY. */ + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + /* And we will not have gone beyond. */ + KUNIT_EXPECT_EQ(test, pad.bytes_after, 0); + + src[sizeof(src) - 1] = 'A'; + /* And for sure now, two bytes past. */ + KUNIT_ASSERT_TRUE(test, strcpy(pad.buf, src) + == pad.buf); + /* + * Which trips both the strlen() on the unterminated src, + * and the resulting copy attempt. + */ + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 1); + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 2); + /* Trailing %NUL -- thanks to FORTIFY. */ + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + /* And we will not have gone beyond. */ + KUNIT_EXPECT_EQ(test, pad.bytes_after, 0); +} + +static void strncpy_test(struct kunit *test) +{ + struct fortify_padding pad = { }; + char src[] = "Copy me fully into a small buffer and I will overflow!"; + + /* Destination is %NUL-filled to start with. */ + KUNIT_EXPECT_EQ(test, pad.bytes_before, 0); + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 3], '\0'); + KUNIT_EXPECT_EQ(test, pad.bytes_after, 0); + + /* Legitimate strncpy() 1 less than of max size. */ + KUNIT_ASSERT_TRUE(test, strncpy(pad.buf, src, + sizeof(pad.buf) + unconst - 1) + == pad.buf); + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0); + /* Only last byte should be %NUL */ + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0'); + + /* Legitimate (though unterminated) max-size strncpy. */ + KUNIT_ASSERT_TRUE(test, strncpy(pad.buf, src, + sizeof(pad.buf) + unconst) + == pad.buf); + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0); + /* No trailing %NUL -- thanks strncpy API. */ + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + /* But we will not have gone beyond. */ + KUNIT_EXPECT_EQ(test, pad.bytes_after, 0); + + /* Now verify that FORTIFY is working... */ + KUNIT_ASSERT_TRUE(test, strncpy(pad.buf, src, + sizeof(pad.buf) + unconst + 1) + == pad.buf); + /* Should catch the overflow. */ + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 1); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + /* And we will not have gone beyond. */ + KUNIT_EXPECT_EQ(test, pad.bytes_after, 0); + + /* And further... */ + KUNIT_ASSERT_TRUE(test, strncpy(pad.buf, src, + sizeof(pad.buf) + unconst + 2) + == pad.buf); + /* Should catch the overflow. */ + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 2); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + /* And we will not have gone beyond. */ + KUNIT_EXPECT_EQ(test, pad.bytes_after, 0); +} + +static void strlcpy_test(struct kunit *test) +{ + struct fortify_padding pad = { }; + char src[] = "Copy me fully into a small buffer and I will overflow!"; + char tiny[4] = "abcd"; + + /* Destination is %NUL-filled to start with. */ + KUNIT_EXPECT_EQ(test, pad.bytes_before, 0); + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 3], '\0'); + KUNIT_EXPECT_EQ(test, pad.bytes_after, 0); + + /* Legitimate strlcpy() 1 less than of max size. */ + KUNIT_ASSERT_EQ(test, strlcpy(pad.buf, src, + sizeof(pad.buf) + unconst - 1), + sizeof(src) - 1); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0); + /* Keeping space for %NUL, last two bytes should be %NUL */ + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0'); + + /* Legitimate max-size strlcpy. */ + KUNIT_ASSERT_EQ(test, strlcpy(pad.buf, src, + sizeof(pad.buf) + unconst), + sizeof(src) - 1); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0); + /* A trailing %NUL will exist. */ + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + + /* Now verify that FORTIFY is working... */ + KUNIT_ASSERT_EQ(test, strlcpy(pad.buf, src, + sizeof(pad.buf) + unconst + 1), + sizeof(src) - 1); + /* Should catch the overflow. */ + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 1); + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + /* And we will not have gone beyond. */ + KUNIT_EXPECT_EQ(test, pad.bytes_after, 0); + + /* And much further... */ + KUNIT_ASSERT_EQ(test, strlcpy(pad.buf, src, + sizeof(src) * 2 + unconst), + sizeof(src) - 1); + /* Should catch the overflow. */ + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 2); + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + /* And we will not have gone beyond. */ + KUNIT_EXPECT_EQ(test, pad.bytes_after, 0); + + /* Catch over-read. */ + KUNIT_ASSERT_EQ(test, strlcpy(pad.buf, tiny, + sizeof(pad.buf) + unconst), + sizeof(tiny)); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 1); + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 2); +} + +static void strscpy_test(struct kunit *test) +{ + struct fortify_padding pad = { }; + char src[] = "Copy me fully into a small buffer and I will overflow!"; + + /* Destination is %NUL-filled to start with. */ + KUNIT_EXPECT_EQ(test, pad.bytes_before, 0); + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 3], '\0'); + KUNIT_EXPECT_EQ(test, pad.bytes_after, 0); + + /* Legitimate strscpy() 1 less than of max size. */ + KUNIT_ASSERT_EQ(test, strscpy(pad.buf, src, + sizeof(pad.buf) + unconst - 1), + -E2BIG); + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0); + /* Keeping space for %NUL, last two bytes should be %NUL */ + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0'); + + /* Legitimate max-size strscpy. */ + KUNIT_ASSERT_EQ(test, strscpy(pad.buf, src, + sizeof(pad.buf) + unconst), + -E2BIG); + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0); + /* A trailing %NUL will exist. */ + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + + /* Now verify that FORTIFY is working... */ + KUNIT_ASSERT_EQ(test, strscpy(pad.buf, src, + sizeof(pad.buf) + unconst + 1), + -E2BIG); + /* Should catch the overflow. */ + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 1); + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + /* And we will not have gone beyond. */ + KUNIT_EXPECT_EQ(test, pad.bytes_after, 0); + + /* And much further... */ + KUNIT_ASSERT_EQ(test, strscpy(pad.buf, src, + sizeof(src) * 2 + unconst), + -E2BIG); + /* Should catch the overflow. */ + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 2); + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + /* And we will not have gone beyond. */ + KUNIT_EXPECT_EQ(test, pad.bytes_after, 0); +} + +static void strcat_test(struct kunit *test) +{ + struct fortify_padding pad = { }; + char src[sizeof(pad.buf) / 2] = { }; + char one[] = "A"; + char two[] = "BC"; + int i; + + /* Fill 15 bytes with valid characters. */ + for (i = 0; i < sizeof(src) - 1; i++) + src[i] = i + 'A'; + + /* Destination is %NUL-filled to start with. */ + KUNIT_EXPECT_EQ(test, pad.bytes_before, 0); + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 3], '\0'); + KUNIT_EXPECT_EQ(test, pad.bytes_after, 0); + + /* Legitimate strcat() using less than half max size. */ + KUNIT_ASSERT_TRUE(test, strcat(pad.buf, src) == pad.buf); + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0); + /* Legitimate strcat() now 2 bytes shy of end. */ + KUNIT_ASSERT_TRUE(test, strcat(pad.buf, src) == pad.buf); + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0); + /* Last two bytes should be %NUL */ + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0'); + + /* Add one more character to the end. */ + KUNIT_ASSERT_TRUE(test, strcat(pad.buf, one) == pad.buf); + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0); + /* Last byte should be %NUL */ + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0'); + + /* And this one char will overflow. */ + KUNIT_ASSERT_TRUE(test, strcat(pad.buf, one) == pad.buf); + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 1); + /* Last byte should be %NUL thanks to FORTIFY. */ + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0'); + KUNIT_EXPECT_EQ(test, pad.bytes_after, 0); + + /* And adding two will overflow more. */ + KUNIT_ASSERT_TRUE(test, strcat(pad.buf, two) == pad.buf); + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 2); + /* Last byte should be %NUL thanks to FORTIFY. */ + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0'); + KUNIT_EXPECT_EQ(test, pad.bytes_after, 0); +} + +static void strncat_test(struct kunit *test) +{ + struct fortify_padding pad = { }; + char src[sizeof(pad.buf)] = { }; + int i, partial; + + /* Fill 31 bytes with valid characters. */ + partial = sizeof(src) / 2 - 1; + for (i = 0; i < partial; i++) + src[i] = i + 'A'; + + /* Destination is %NUL-filled to start with. */ + KUNIT_EXPECT_EQ(test, pad.bytes_before, 0); + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 3], '\0'); + KUNIT_EXPECT_EQ(test, pad.bytes_after, 0); + + /* Legitimate strncat() using less than half max size. */ + KUNIT_ASSERT_TRUE(test, strncat(pad.buf, src, partial) == pad.buf); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0); + /* Legitimate strncat() now 2 bytes shy of end. */ + KUNIT_ASSERT_TRUE(test, strncat(pad.buf, src, partial) == pad.buf); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0); + /* Last two bytes should be %NUL */ + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0'); + + /* Add one more character to the end. */ + KUNIT_ASSERT_TRUE(test, strncat(pad.buf, src, 1) == pad.buf); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0); + /* Last byte should be %NUL */ + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0'); + + /* And this one char will overflow. */ + KUNIT_ASSERT_TRUE(test, strncat(pad.buf, src, 1) == pad.buf); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 1); + /* Last byte should be %NUL thanks to FORTIFY. */ + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0'); + KUNIT_EXPECT_EQ(test, pad.bytes_after, 0); + + /* And adding two will overflow more. */ + KUNIT_ASSERT_TRUE(test, strncat(pad.buf, src, 2) == pad.buf); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 2); + /* Last byte should be %NUL thanks to FORTIFY. */ + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0'); + KUNIT_EXPECT_EQ(test, pad.bytes_after, 0); + + /* Force an unterminated destination, and overflow. */ + pad.buf[sizeof(pad.buf) - 1] = 'A'; + KUNIT_ASSERT_TRUE(test, strncat(pad.buf, src, 1) == pad.buf); + /* This will have tripped both strlen() and strcat(). */ + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 1); + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 3); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0'); + /* But we should not go beyond the end. */ + KUNIT_EXPECT_EQ(test, pad.bytes_after, 0); +} + +static void strlcat_test(struct kunit *test) +{ + struct fortify_padding pad = { }; + char src[sizeof(pad.buf)] = { }; + int i, partial; + int len = sizeof(pad.buf) + unconst; + + /* Fill 15 bytes with valid characters. */ + partial = sizeof(src) / 2 - 1; + for (i = 0; i < partial; i++) + src[i] = i + 'A'; + + /* Destination is %NUL-filled to start with. */ + KUNIT_EXPECT_EQ(test, pad.bytes_before, 0); + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 3], '\0'); + KUNIT_EXPECT_EQ(test, pad.bytes_after, 0); + + /* Legitimate strlcat() using less than half max size. */ + KUNIT_ASSERT_EQ(test, strlcat(pad.buf, src, len), partial); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0); + /* Legitimate strlcat() now 2 bytes shy of end. */ + KUNIT_ASSERT_EQ(test, strlcat(pad.buf, src, len), partial * 2); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0); + /* Last two bytes should be %NUL */ + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0'); + + /* Add one more character to the end. */ + KUNIT_ASSERT_EQ(test, strlcat(pad.buf, "Q", len), partial * 2 + 1); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0); + /* Last byte should be %NUL */ + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0'); + + /* And this one char will overflow. */ + KUNIT_ASSERT_EQ(test, strlcat(pad.buf, "V", len * 2), len); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 1); + /* Last byte should be %NUL thanks to FORTIFY. */ + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0'); + KUNIT_EXPECT_EQ(test, pad.bytes_after, 0); + + /* And adding two will overflow more. */ + KUNIT_ASSERT_EQ(test, strlcat(pad.buf, "QQ", len * 2), len + 1); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 2); + /* Last byte should be %NUL thanks to FORTIFY. */ + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0'); + KUNIT_EXPECT_EQ(test, pad.bytes_after, 0); + + /* Force an unterminated destination, and overflow. */ + pad.buf[sizeof(pad.buf) - 1] = 'A'; + KUNIT_ASSERT_EQ(test, strlcat(pad.buf, "TT", len * 2), len + 2); + /* This will have tripped both strlen() and strlcat(). */ + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 2); + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 2); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0'); + KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0'); + /* But we should not go beyond the end. */ + KUNIT_EXPECT_EQ(test, pad.bytes_after, 0); + + /* Force an unterminated source, and overflow. */ + memset(src, 'B', sizeof(src)); + pad.buf[sizeof(pad.buf) - 1] = '\0'; + KUNIT_ASSERT_EQ(test, strlcat(pad.buf, src, len * 3), len - 1 + sizeof(src)); + /* This will have tripped both strlen() and strlcat(). */ + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 3); + KUNIT_EXPECT_EQ(test, fortify_write_overflows, 3); + KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0'); + /* But we should not go beyond the end. */ + KUNIT_EXPECT_EQ(test, pad.bytes_after, 0); +} + +static void memscan_test(struct kunit *test) +{ + char haystack[] = "Where oh where is my memory range?"; + char *mem = haystack + strlen("Where oh where is "); + char needle = 'm'; + size_t len = sizeof(haystack) + unconst; + + KUNIT_ASSERT_PTR_EQ(test, memscan(haystack, needle, len), + mem); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); + /* Catch too-large range. */ + KUNIT_ASSERT_PTR_EQ(test, memscan(haystack, needle, len + 1), + NULL); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 1); + KUNIT_ASSERT_PTR_EQ(test, memscan(haystack, needle, len * 2), + NULL); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 2); +} + +static void memchr_test(struct kunit *test) +{ + char haystack[] = "Where oh where is my memory range?"; + char *mem = haystack + strlen("Where oh where is "); + char needle = 'm'; + size_t len = sizeof(haystack) + unconst; + + KUNIT_ASSERT_PTR_EQ(test, memchr(haystack, needle, len), + mem); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); + /* Catch too-large range. */ + KUNIT_ASSERT_PTR_EQ(test, memchr(haystack, needle, len + 1), + NULL); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 1); + KUNIT_ASSERT_PTR_EQ(test, memchr(haystack, needle, len * 2), + NULL); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 2); +} + +static void memchr_inv_test(struct kunit *test) +{ + char haystack[] = "Where oh where is my memory range?"; + char *mem = haystack + 1; + char needle = 'W'; + size_t len = sizeof(haystack) + unconst; + + /* Normal search is okay. */ + KUNIT_ASSERT_PTR_EQ(test, memchr_inv(haystack, needle, len), + mem); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); + /* Catch too-large range. */ + KUNIT_ASSERT_PTR_EQ(test, memchr_inv(haystack, needle, len + 1), + NULL); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 1); + KUNIT_ASSERT_PTR_EQ(test, memchr_inv(haystack, needle, len * 2), + NULL); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 2); +} + +static void memcmp_test(struct kunit *test) +{ + char one[] = "My mind is going ..."; + char two[] = "My mind is going ... I can feel it."; + size_t one_len = sizeof(one) + unconst - 1; + size_t two_len = sizeof(two) + unconst - 1; + + /* We match the first string (ignoring the %NUL). */ + KUNIT_ASSERT_EQ(test, memcmp(one, two, one_len), 0); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); + /* Still in bounds, but no longer matching. */ + KUNIT_ASSERT_EQ(test, memcmp(one, two, one_len + 1), -32); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); + + /* Catch too-large ranges. */ + KUNIT_ASSERT_EQ(test, memcmp(one, two, one_len + 2), INT_MIN); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 1); + + KUNIT_ASSERT_EQ(test, memcmp(two, one, two_len + 2), INT_MIN); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 2); +} + +static void kmemdup_test(struct kunit *test) +{ + char src[] = "I got Doom running on it!"; + char *copy; + size_t len = sizeof(src) + unconst; + + /* Copy is within bounds. */ + copy = kmemdup(src, len, GFP_KERNEL); + KUNIT_EXPECT_NOT_NULL(test, copy); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); + kfree(copy); + + /* Without %NUL. */ + copy = kmemdup(src, len - 1, GFP_KERNEL); + KUNIT_EXPECT_NOT_NULL(test, copy); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); + kfree(copy); + + /* Tiny bounds. */ + copy = kmemdup(src, 1, GFP_KERNEL); + KUNIT_EXPECT_NOT_NULL(test, copy); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0); + kfree(copy); + + /* Out of bounds by 1 byte. */ + copy = kmemdup(src, len + 1, GFP_KERNEL); + KUNIT_EXPECT_NULL(test, copy); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 1); + kfree(copy); + + /* Way out of bounds. */ + copy = kmemdup(src, len * 2, GFP_KERNEL); + KUNIT_EXPECT_NULL(test, copy); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 2); + kfree(copy); + + /* Starting offset causing out of bounds. */ + copy = kmemdup(src + 1, len, GFP_KERNEL); + KUNIT_EXPECT_NULL(test, copy); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 3); + kfree(copy); +} + static int fortify_test_init(struct kunit *test) { if (!IS_ENABLED(CONFIG_FORTIFY_SOURCE)) @@ -375,6 +1032,22 @@ static struct kunit_case fortify_test_cases[] = { KUNIT_CASE(alloc_size_kvmalloc_dynamic_test), KUNIT_CASE(alloc_size_devm_kmalloc_const_test), KUNIT_CASE(alloc_size_devm_kmalloc_dynamic_test), + KUNIT_CASE(strlen_test), + KUNIT_CASE(strnlen_test), + KUNIT_CASE(strcpy_test), + KUNIT_CASE(strncpy_test), + KUNIT_CASE(strlcpy_test), + KUNIT_CASE(strscpy_test), + KUNIT_CASE(strcat_test), + KUNIT_CASE(strncat_test), + KUNIT_CASE(strlcat_test), + /* skip memset: performs bounds checking on whole structs */ + /* skip memcpy: still using warn-and-clobber instead of hard-fail */ + KUNIT_CASE(memscan_test), + KUNIT_CASE(memchr_test), + KUNIT_CASE(memchr_inv_test), + KUNIT_CASE(memcmp_test), + KUNIT_CASE(kmemdup_test), {} }; From patchwork Fri Apr 7 19:27:16 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 80995 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp488309vqo; Fri, 7 Apr 2023 12:29:56 -0700 (PDT) X-Google-Smtp-Source: AKy350Zv0fvt4Bns58cZb3td4+5E/xzG//J18cudy5YF8qNzP1O94azvWRPm8opXHgmlzPcWOwKF X-Received: by 2002:a17:906:e098:b0:930:7ae6:9ebd with SMTP id gh24-20020a170906e09800b009307ae69ebdmr491046ejb.70.1680895796656; Fri, 07 Apr 2023 12:29:56 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680895796; cv=none; d=google.com; s=arc-20160816; b=IG+yxAV301soZ2gE6AZe7lwaM0NnneoaPJZYo46JDTdgaqlVzjaf1YsMOHoHv/MVqX EzUN4UEXX1kAs5ItotYN/FPD3fg81foM8EPzVoQJGSghCQrvbP3BGtcn8HNGjcA+090H BAh8JC5XQUo8F98blg/8rYAjpWwRHW9ga+PM84KrVaMOfgbxwykgN9oTpT8Vw2j127OL ikbTbSRo+ktI0SxhzW+XTzbpQWPXFuGxOFj5exdtIBMPEru0ZR3fsiK2RrCukV8rgxDL 1GhIqC/NZ2u/dBioY9fCWtN9VLiEcoEndXijJUs5bHyTdIp54Bt4OS881erYJfwT9cHp 3H2A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=TbRUNtQREL0DnI77lki5y+qi2N6+jLmYqH388JdhlwY=; b=VHG4WXCDcvo0ECRP6m7+4dxnhavzPr1QHZnsttlf4/hUYkWmWaZ/yCUt4AGkqlBTXy mx1Int/8j4kN0SfMCvvD0uf88YAGL2qvktBO+CY7Um/WgmrNam7xmPOXHgl0kS1gfaDX DACW2+ji4Jy54vgA4LqjU2EBq7zGdriYa6Ve1qpA4UEaDdvRubg16LWypAfGfnMEA/oF +FUJnKyvIY6mqqFEj/WmLf4dT5mpnTZ3Xf0Zr3n7Yky24f4KnVv1zdDbzqo5215cZIsW JzWmCXSFRi81C6dpoiieH8602//O8JBvNTw4ETizAG9XeAueNk/0V8vqXNWSKI1/X+46 TEhg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=FAoUtZ0I; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id bk10-20020a170906b0ca00b00940e715a40dsi2894269ejb.408.2023.04.07.12.29.32; Fri, 07 Apr 2023 12:29:56 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=FAoUtZ0I; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231326AbjDGT14 (ORCPT + 99 others); Fri, 7 Apr 2023 15:27:56 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54476 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229957AbjDGT1l (ORCPT ); Fri, 7 Apr 2023 15:27:41 -0400 Received: from mail-pj1-x1031.google.com (mail-pj1-x1031.google.com [IPv6:2607:f8b0:4864:20::1031]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 33606C165 for ; Fri, 7 Apr 2023 12:27:25 -0700 (PDT) Received: by mail-pj1-x1031.google.com with SMTP id 98e67ed59e1d1-24059dcdd90so140188a91.2 for ; Fri, 07 Apr 2023 12:27:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1680895644; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=TbRUNtQREL0DnI77lki5y+qi2N6+jLmYqH388JdhlwY=; b=FAoUtZ0IZEcsn04MhKwxFE63a6uQgiN8u8sEyytJFvZOkPTBTyAZapmS7BeOaptvI4 MSJ8t8Z4rx218WiQZnnghN1vBOuMYSy8orkJcuGTiqnbDgzi05q5GMxN0azPtCaPfTGG eGoC2vG4lKQLguk5JzWLG/h7g0gB/BBM4SmhU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680895644; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=TbRUNtQREL0DnI77lki5y+qi2N6+jLmYqH388JdhlwY=; b=qTNJN0zX7Xcp+q29TV2Xx4clfLCxwxSVxJGqPCeRp9IvyowxUGtdaxXIWO0udf/bcP afqtZhicXmeia9m99ltvnjBOrUq0iUTL1dNi02/npgELvrBY0J8DToStkOdASq62wvoV FYp9+3G2gXFGYhrsPKYIWmgIih2AU2W6QhHf57hYmRw4lM1o+Fbc/G475DpgbxiMvc6I zVG9qf4tBCgkAaXxCVMDEmejUfHohZdIYYpCtMGI0t7PZCBaCReDD05pUxBza+H2wtro Y7JWXMlwmWOGD8lSOgl6hlX/4OdC0DJNGwAuUdCBnpCh4AQsPBYB+o7W/xXJ4fHeBWpC I+yw== X-Gm-Message-State: AAQBX9fp2ilCYJsN8Iv9zbTzP8rUmrhTm/564zXawfGBse2/UzhJM7XH mBABwC6uGrLA8IK+TsEpXRqwcw== X-Received: by 2002:aa7:9489:0:b0:625:c048:2f81 with SMTP id z9-20020aa79489000000b00625c0482f81mr3829161pfk.32.1680895644532; Fri, 07 Apr 2023 12:27:24 -0700 (PDT) Received: from www.outflux.net (198-0-35-241-static.hfc.comcastbusiness.net. [198.0.35.241]) by smtp.gmail.com with ESMTPSA id v3-20020a654603000000b004fb3e5681cesm3021477pgq.20.2023.04.07.12.27.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Apr 2023 12:27:21 -0700 (PDT) From: Kees Cook To: linux-hardening@vger.kernel.org Cc: Kees Cook , "Andy Shevchenko" , "Cezary Rojewski" , "Puyou Lu" , "Mark Brown" , "Josh Poimboeuf" , "Peter Zijlstra" , "Brendan Higgins" , "David Gow" , Andrew Morton , "Nathan Chancellor" , "Alexander Potapenko" , "Zhaoyang Huang" , "Randy Dunlap" , "Geert Uytterhoeven" , "Miguel Ojeda" , Alexander Lobakin , "Nick Desaulniers" , "Liam Howlett" , "Vlastimil Babka" , "Dan Williams" , "Rasmus Villemoes" , "Yury Norov" , "Jason A. Donenfeld" , "Sander Vanheule" , "Eric Biggers" , "Masami Hiramatsu (Google)" , "Andrey Konovalov" , "Linus Walleij" , "Daniel Latypov" , =?utf-8?b?Sm9zw6kgRXhww7NzaXRv?= , linux-kernel@vger.kernel.org, kunit-dev@googlegroups.com Subject: [PATCH v2 10/10] fortify: Improve buffer overflow reporting Date: Fri, 7 Apr 2023 12:27:16 -0700 Message-Id: <20230407192717.636137-10-keescook@chromium.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230407191904.gonna.522-kees@kernel.org> References: <20230407191904.gonna.522-kees@kernel.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=11869; h=from:subject; bh=bpA1jsos8ihAGMBPbjj09ClSgIt8BDsSB6LmWIMM3eA=; b=owEBbQKS/ZANAwAKAYly9N/cbcAmAcsmYgBkMG6US5JDkRy/aBh8U7DiQHZBij17I90SlAMF25rf 8EgZM8yJAjMEAAEKAB0WIQSlw/aPIp3WD3I+bhOJcvTf3G3AJgUCZDBulAAKCRCJcvTf3G3AJuqlEA CgneoPbDTP3hoDMQ23AZmFarDboVoqlpZDMw7uGB9IzfSDNOQvJoiydTt7CA4FLc47zPXUQH5rTVZx 5Rz1Tb1jl0z9Hnkn8TzJr2hwSye+RgTnBsf0TWQdv2x9Fkc5K76aHENZRr7Jlo9aZrbGmIFoMUSgAN 1qJ8DJELMi3mwtohjEBq9utH8M1zemeXVn/NN03pDMZTWENrEeNgRgPvacbRosUz2tgjSZfH707Lw3 KllW0S3P3IEa/JcwofX69VG/bZK1rpmNx5zI2LWc9Qs8tgHnkZkBI4i2g4QDMArK8WGv0kC3bBTbiX 6EHiGE2nHiE6YsMIwvldLg+TiYReDQwqTQVoTZM9xO6li2I7xZa+4uEjmcPUbSB6RakJ1szLv1slZf 2Ahn0dhrnFl3jS6xDfOdjryZqMBgzxuV0BQiCgtBtvjlFcopV8nnnbtKkGBSFpWwLqim7WAz+bpf1Q hg9tRiXEfHulw9lxvi9HhKaUYGfy/LN9xx+gZJUIehuM1sTWY6bQTLfskIhG6e0LxGx83WLx5uaHAB PElOBRwzuTVNbSXvtIIOfCaGbkU9mM5dSvIEOz2GQn8E70fTwFeWuGBV8Q6x2Yu+zH02htgPCR82cs WOVAyWpkyqU19043PLPPcFNZjNY+MkV10D4gq8+O/dXUvZlvla5zIRf35t0g== X-Developer-Key: i=keescook@chromium.org; a=openpgp; fpr=A5C3F68F229DD60F723E6E138972F4DFDC6DC026 X-Spam-Status: No, score=-0.2 required=5.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1762546990943653301?= X-GMAIL-MSGID: =?utf-8?q?1762546990943653301?= Improve the reporting of buffer overflows under CONFIG_FORTIFY_SOURCE to help accelerate debugging efforts. The calculations are all just sitting in registers anyway, so pass them along to the function to be reported. For example, before: detected buffer overflow in memcpy and after: memcpy: detected buffer overflow: 4096 byte read from buffer of size 1 Signed-off-by: Kees Cook --- arch/arm/boot/compressed/misc.c | 2 +- arch/x86/boot/compressed/misc.c | 2 +- include/linux/fortify-string.h | 61 ++++++++++++++++++--------------- lib/fortify_kunit.c | 4 +-- lib/string_helpers.c | 9 ++--- 5 files changed, 42 insertions(+), 36 deletions(-) diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c index f31e2c949089..5487f64d8c3d 100644 --- a/arch/arm/boot/compressed/misc.c +++ b/arch/arm/boot/compressed/misc.c @@ -160,7 +160,7 @@ decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p, putstr(" done, booting the kernel.\n"); } -void __fortify_panic(const u8 reason) +void __fortify_panic(const u8 reason, size_t avail, size_t size) { error("detected buffer overflow"); } diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index aa45e7529a40..c1dc12abd6d9 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -470,7 +470,7 @@ asmlinkage __visible void *extract_kernel(void *rmode, memptr heap, return output + entry_offset; } -void __fortify_panic(const u8 reason) +void __fortify_panic(const u8 reason, size_t avail, size_t size) { error("detected buffer overflow"); } diff --git a/include/linux/fortify-string.h b/include/linux/fortify-string.h index 5d04c0e95854..a0002740d2a7 100644 --- a/include/linux/fortify-string.h +++ b/include/linux/fortify-string.h @@ -18,8 +18,8 @@ #ifdef FORTIFY_KUNIT_OVERRIDE # define fortify_panic kunit_fortify_panic #else -# define fortify_panic(func, write, retfail) \ - __fortify_panic(FORTIFY_REASON(func, write)) +# define fortify_panic(func, write, avail, size, retfail) \ + __fortify_panic(FORTIFY_REASON(func, write), avail, size) #endif #define FORTIFY_READ 0 @@ -51,8 +51,8 @@ enum fortify_func { EACH_FORTIFY_FUNC(MAKE_FORTIFY_FUNC) }; -void __fortify_report(const u8 reason); -void __fortify_panic(const u8 reason) __cold __noreturn; +void __fortify_report(const u8 reason, const size_t avail, const size_t size); +void __fortify_panic(const u8 reason, const size_t avail, const size_t size) __cold __noreturn; void __read_overflow(void) __compiletime_error("detected read beyond size of object (1st parameter)"); void __read_overflow2(void) __compiletime_error("detected read beyond size of object (2nd parameter)"); void __read_overflow2_field(size_t avail, size_t wanted) __compiletime_warning("detected read beyond size of field (2nd parameter); maybe use struct_group()?"); @@ -190,7 +190,7 @@ char *strncpy(char * const POS p, const char *q, __kernel_size_t size) if (__compiletime_lessthan(p_size, size)) __write_overflow(); if (p_size < size) - fortify_panic(FORTIFY_FUNC_strncpy, FORTIFY_WRITE, p); + fortify_panic(FORTIFY_FUNC_strncpy, FORTIFY_WRITE, p_size, size, p); return __underlying_strncpy(p, q, size); } @@ -221,7 +221,7 @@ __FORTIFY_INLINE __kernel_size_t strnlen(const char * const POS p, __kernel_size /* Do not check characters beyond the end of p. */ ret = __real_strnlen(p, maxlen < p_size ? maxlen : p_size); if (p_size <= ret && maxlen != ret) - fortify_panic(FORTIFY_FUNC_strnlen, FORTIFY_READ, ret); + fortify_panic(FORTIFY_FUNC_strnlen, FORTIFY_READ, p_size, ret + 1, ret); return ret; } @@ -257,7 +257,7 @@ __kernel_size_t __fortify_strlen(const char * const POS p) return __underlying_strlen(p); ret = strnlen(p, p_size); if (p_size <= ret) - fortify_panic(FORTIFY_FUNC_strlen, FORTIFY_READ, ret); + fortify_panic(FORTIFY_FUNC_strlen, FORTIFY_READ, p_size, ret + 1, ret); return ret; } @@ -298,8 +298,8 @@ __FORTIFY_INLINE size_t strlcpy(char * const POS p, const char * const POS q, si __write_overflow(); } if (size) { - if (len >= p_size) - fortify_panic(FORTIFY_FUNC_strlcpy, FORTIFY_WRITE, q_len); + if (p_size <= len) + fortify_panic(FORTIFY_FUNC_strlcpy, FORTIFY_WRITE, p_size, len + 1, q_len); __underlying_memcpy(p, q, len); p[len] = '\0'; } @@ -376,8 +376,8 @@ __FORTIFY_INLINE ssize_t strscpy(char * const POS p, const char * const POS q, s * Generate a runtime write overflow error if len is greater than * p_size. */ - if (len > p_size) - fortify_panic(FORTIFY_FUNC_strscpy, FORTIFY_WRITE, -E2BIG); + if (p_size < len) + fortify_panic(FORTIFY_FUNC_strscpy, FORTIFY_WRITE, p_size, len, -E2BIG); /* * We can now safely call vanilla strscpy because we are protected from: @@ -435,7 +435,7 @@ size_t strlcat(char * const POS p, const char * const POS q, size_t avail) /* Give up if string is already overflowed. */ if (p_size <= p_len) - fortify_panic(FORTIFY_FUNC_strlcat, FORTIFY_READ, wanted); + fortify_panic(FORTIFY_FUNC_strlcat, FORTIFY_READ, p_size, p_len + 1, wanted); if (actual >= avail) { copy_len = avail - p_len - 1; @@ -444,7 +444,7 @@ size_t strlcat(char * const POS p, const char * const POS q, size_t avail) /* Give up if copy will overflow. */ if (p_size <= actual) - fortify_panic(FORTIFY_FUNC_strlcat, FORTIFY_WRITE, wanted); + fortify_panic(FORTIFY_FUNC_strlcat, FORTIFY_WRITE, p_size, actual + 1, wanted); __underlying_memcpy(p + p_len, q, copy_len); p[actual] = '\0'; @@ -471,9 +471,11 @@ __FORTIFY_INLINE __diagnose_as(__builtin_strcat, 1, 2) char *strcat(char * const POS p, const char *q) { const size_t p_size = __member_size(p); + size_t wanted; - if (strlcat(p, q, p_size) >= p_size) - fortify_panic(FORTIFY_FUNC_strcat, FORTIFY_WRITE, p); + wanted = strlcat(p, q, p_size); + if (p_size <= wanted) + fortify_panic(FORTIFY_FUNC_strcat, FORTIFY_WRITE, p_size, wanted + 1, p); return p; } @@ -502,14 +504,15 @@ char *strncat(char * const POS p, const char * const POS q, __kernel_size_t coun { const size_t p_size = __member_size(p); const size_t q_size = __member_size(q); - size_t p_len, copy_len; + size_t p_len, copy_len, total; if (p_size == SIZE_MAX && q_size == SIZE_MAX) return __underlying_strncat(p, q, count); p_len = strlen(p); copy_len = strnlen(q, count); - if (p_size < p_len + copy_len + 1) - fortify_panic(FORTIFY_FUNC_strncat, FORTIFY_WRITE, p); + total = p_len + copy_len + 1; + if (p_size < total) + fortify_panic(FORTIFY_FUNC_strncat, FORTIFY_WRITE, p_size, total, p); __underlying_memcpy(p + p_len, q, copy_len); p[p_len + copy_len] = '\0'; return p; @@ -550,7 +553,7 @@ __FORTIFY_INLINE bool fortify_memset_chk(__kernel_size_t size, * lengths are unknown.) */ if (p_size != SIZE_MAX && p_size < size) - fortify_panic(FORTIFY_FUNC_memset, FORTIFY_WRITE, true); + fortify_panic(FORTIFY_FUNC_memset, FORTIFY_WRITE, p_size, size, true); return false; } @@ -650,9 +653,9 @@ __FORTIFY_INLINE bool fortify_memcpy_chk(__kernel_size_t size, * lengths are unknown.) */ if (p_size != SIZE_MAX && p_size < size) - fortify_panic(func, FORTIFY_WRITE, true); + fortify_panic(func, FORTIFY_WRITE, p_size, size, true); else if (q_size != SIZE_MAX && q_size < size) - fortify_panic(func, FORTIFY_READ, true); + fortify_panic(func, FORTIFY_READ, p_size, size, true); /* * Warn when writing beyond destination field size. @@ -752,7 +755,7 @@ __FORTIFY_INLINE void *memscan(void * const POS0 p, int c, __kernel_size_t size) if (__compiletime_lessthan(p_size, size)) __read_overflow(); if (p_size < size) - fortify_panic(FORTIFY_FUNC_memscan, FORTIFY_READ, NULL); + fortify_panic(FORTIFY_FUNC_memscan, FORTIFY_READ, p_size, size, NULL); return __real_memscan(p, c, size); } @@ -768,8 +771,10 @@ int memcmp(const void * const POS0 p, const void * const POS0 q, __kernel_size_t if (__compiletime_lessthan(q_size, size)) __read_overflow2(); } - if (p_size < size || q_size < size) - fortify_panic(FORTIFY_FUNC_memcmp, FORTIFY_READ, INT_MIN); + if (p_size < size) + fortify_panic(FORTIFY_FUNC_memcmp, FORTIFY_READ, p_size, size, INT_MIN); + else if (q_size < size) + fortify_panic(FORTIFY_FUNC_memcmp, FORTIFY_READ, q_size, size, INT_MIN); return __underlying_memcmp(p, q, size); } @@ -781,7 +786,7 @@ void *memchr(const void * const POS0 p, int c, __kernel_size_t size) if (__compiletime_lessthan(p_size, size)) __read_overflow(); if (p_size < size) - fortify_panic(FORTIFY_FUNC_memchr, FORTIFY_READ, NULL); + fortify_panic(FORTIFY_FUNC_memchr, FORTIFY_READ, p_size, size, NULL); return __underlying_memchr(p, c, size); } @@ -793,7 +798,7 @@ __FORTIFY_INLINE void *memchr_inv(const void * const POS0 p, int c, size_t size) if (__compiletime_lessthan(p_size, size)) __read_overflow(); if (p_size < size) - fortify_panic(FORTIFY_FUNC_memchr_inv, FORTIFY_READ, NULL); + fortify_panic(FORTIFY_FUNC_memchr_inv, FORTIFY_READ, p_size, size, NULL); return __real_memchr_inv(p, c, size); } @@ -806,7 +811,7 @@ __FORTIFY_INLINE void *kmemdup(const void * const POS0 p, size_t size, gfp_t gfp if (__compiletime_lessthan(p_size, size)) __read_overflow(); if (p_size < size) - fortify_panic(FORTIFY_FUNC_kmemdup, FORTIFY_READ, NULL); + fortify_panic(FORTIFY_FUNC_kmemdup, FORTIFY_READ, p_size, size, NULL); return __real_kmemdup(p, size, gfp); } @@ -843,7 +848,7 @@ char *strcpy(char * const POS p, const char * const POS q) __write_overflow(); /* Run-time check for dynamic size overflow. */ if (p_size < size) - fortify_panic(FORTIFY_FUNC_strcpy, FORTIFY_WRITE, p); + fortify_panic(FORTIFY_FUNC_strcpy, FORTIFY_WRITE, p_size, size, p); __underlying_memcpy(p, q, size); return p; } diff --git a/lib/fortify_kunit.c b/lib/fortify_kunit.c index 3206fe723110..6aac58eb6eb6 100644 --- a/lib/fortify_kunit.c +++ b/lib/fortify_kunit.c @@ -18,9 +18,9 @@ /* Call kunit_fortify_panic() instead of fortify_panic() */ #define FORTIFY_KUNIT_OVERRIDE void fortify_add_kunit_error(int write); -#define kunit_fortify_panic(func, write, retfail) \ +#define kunit_fortify_panic(func, write, avail, size, retfail) \ do { \ - __fortify_report(FORTIFY_REASON(func, write)); \ + __fortify_report(FORTIFY_REASON(func, write), avail, size); \ fortify_add_kunit_error(write); \ return (retfail); \ } while (0) diff --git a/lib/string_helpers.c b/lib/string_helpers.c index 38edde20e61b..9a8167535e1f 100644 --- a/lib/string_helpers.c +++ b/lib/string_helpers.c @@ -1029,20 +1029,21 @@ static const char * const fortify_func_name[] = { EACH_FORTIFY_FUNC(MAKE_FORTIFY_FUNC_NAME) }; -void __fortify_report(const u8 reason) +void __fortify_report(const u8 reason, const size_t avail, const size_t size) { const u8 func = FORTIFY_REASON_FUNC(reason); const bool write = FORTIFY_REASON_DIR(reason); const char *name; name = fortify_func_name[min_t(u8, func, FORTIFY_FUNC_UNKNOWN)]; - WARN(1, "%s: detected buffer %s overflow\n", name, str_read_write(!write)); + WARN(1, "%s: detected buffer overflow: %zu byte %s buffer of size %zu\n", + name, size, str_read_write(!write), avail); } EXPORT_SYMBOL(__fortify_report); -void __fortify_panic(const u8 reason) +void __fortify_panic(const u8 reason, const size_t avail, const size_t size) { - __fortify_report(reason); + __fortify_report(reason, avail, size); BUG(); } EXPORT_SYMBOL(__fortify_panic);