From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.5 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id CF6EDC4320A for ; Sun, 22 Aug 2021 07:57:12 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 8072E61051 for ; Sun, 22 Aug 2021 07:57:12 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 8072E61051 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=kvack.org Received: by kanga.kvack.org (Postfix) id A75128D0007; Sun, 22 Aug 2021 03:57:00 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 97FEE8D000B; Sun, 22 Aug 2021 03:57:00 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 66E318D0009; Sun, 22 Aug 2021 03:57:00 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0208.hostedemail.com [216.40.44.208]) by kanga.kvack.org (Postfix) with ESMTP id 36DC98D0007 for ; Sun, 22 Aug 2021 03:57:00 -0400 (EDT) Received: from smtpin31.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay03.hostedemail.com (Postfix) with ESMTP id DC1B082499A8 for ; Sun, 22 Aug 2021 07:56:59 +0000 (UTC) X-FDA: 78501960558.31.2F5531A Received: from mail-pg1-f179.google.com (mail-pg1-f179.google.com [209.85.215.179]) by imf10.hostedemail.com (Postfix) with ESMTP id 987DB600198A for ; Sun, 22 Aug 2021 07:56:59 +0000 (UTC) Received: by mail-pg1-f179.google.com with SMTP id q2so13636223pgt.6 for ; Sun, 22 Aug 2021 00:56:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=/IK2hUcT/4MYA89svC69IqQzJMxj9iX8eWhKLXV32Iw=; b=QCLdF+eD0anvEeWmalPSIHQDeFFhVXfkPNxoAL80wy2cfcL6ACoqSdB9gkksbW4ara cUfJu5UBfqt9XyNRqvYrrwTAQ1GEBtmaHDiKfHYgEdDdFVCzLFgdXRmHOzKPfysJQzjS z/xEGc3jiiIXY7kxxXwT+9TFBnlrpvOxikJ2E= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=/IK2hUcT/4MYA89svC69IqQzJMxj9iX8eWhKLXV32Iw=; b=F1T+os57k4+O3tUmc5yc7whzj3/IHcVAtRr8cys8nJr7DRw9gE2wOqG2hArnLxAMtC OEieogFp/BvVsQDIO5b89LKN3VrTmNiU251OdpKRsn/prEuQabVYWB4TBvwJEqe1xZPa xtIb3N2zJul2KDEXM8LYSEKoNvqF4wNrcRA16K8p0WbH0F7zWmnOv0iHhvVPk9Y/f8wq 9yqdfFxlJW5ozWT13srhNEsTGtXP/RYG+paIbQOFxJrWTABJ5/BCNRivVFKu4lzZZHnu ECT34mutUZ2NT3Gpti2o7AUbs+KpRszY8iriIpzCHx9lEBN75SChMvAfmDoMivB4ukaU dTvQ== X-Gm-Message-State: AOAM533f+ztp9e456B31qCcnbNFzmNBgxhvT6XlZ0ZuXTkPtxfU95IQS gLBnkonpdAi665B2+ZHrRHBk1AxEspa+qw== X-Google-Smtp-Source: ABdhPJzq+TtZMZSw8dHF+lSpjwFHFLC/dgieYhWajSzCVBQ6JialEzTQyJ9NmX8gtFmU5viJM2uayw== X-Received: by 2002:a63:5604:: with SMTP id k4mr26801500pgb.363.1629619018842; Sun, 22 Aug 2021 00:56:58 -0700 (PDT) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id m28sm14880372pgl.9.2021.08.22.00.56.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 22 Aug 2021 00:56:57 -0700 (PDT) From: Kees Cook To: linux-kernel@vger.kernel.org Cc: Kees Cook , Rasmus Villemoes , Daniel Micay , Francis Laniel , Bart Van Assche , David Gow , linux-mm@kvack.org, clang-built-linux@googlegroups.com, linux-hardening@vger.kernel.org Subject: [PATCH for-next 19/25] fortify: Allow strlen() and strnlen() to pass compile-time known lengths Date: Sun, 22 Aug 2021 00:51:16 -0700 Message-Id: <20210822075122.864511-20-keescook@chromium.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210822075122.864511-1-keescook@chromium.org> References: <20210822075122.864511-1-keescook@chromium.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=4037; h=from:subject; bh=A8Geo8n4i5qwpvkI4vHxNJg+9VAd1dz9Zyf2I1wPWkI=; b=owEBbQKS/ZANAwAKAYly9N/cbcAmAcsmYgBhIgH41/syAnC8eDuJXMCDQbQtT/FS9k5h9kcLncy9 eJedf0qJAjMEAAEKAB0WIQSlw/aPIp3WD3I+bhOJcvTf3G3AJgUCYSIB+AAKCRCJcvTf3G3AJrn9D/ 9w5dThNsyCdRB28y4gKpDDLcvUjRa1Q7oKkwUtwYdV4cfAf+oyY6FWe+T3MEuQEGGcOExyAmym8iuM YdmWCH662e/XOVtgNQqcXFcLIOs0PWUTdV1Ps7VotgZMQFC2oVwakzruXHCfkyrKUEtcR5z0CILGRn t8zpD6TGNmD40Ks+KA3xAF4dpBjzIzL5Z/Sbix2dA6CwwEOedcVhEoOZkwefsdAqsCRIDrsxe46uhR yTqT1Py3Ztyo4HBf5/fq0ZvpqMNknPbP2I9+yxFrBfP2wJDCZcS7MR2x7q/USsg4Jm4oUzdL4M869d XaY4fTLBn0Skhh1lYpQRY7tw0HAru9lWcfYHIwQpzINLpSk4Gtcnik3fND1lF7OcQSnu/HmTyRBWes Pw83R50BMTQ8a/vjGbbbKml6GSvKB+UsGwvFTPgRD6xN71rN8D8YCvPxS+12ubmM+cTDFHZ/BX0QuD lMXeN2s9Zzs584Jq/4VOo/4f6vtSgmd2BOwzfyyDo+eYNHIPxS4YFZGaxGjcxgp9Tqz6cnc+5iHa1s 9lIm/i+0pU3Q0IcYwzFXrhkrNCarXCgQ8jI+7+dMIxsDfQQBkh+kv4HVXAM7bqjhArAiqt5J+w+QSP jotniJxsBv+glaPCKkmwkAM/MdceVn/RgSpZqz9gbeHZz+aD8fXSw7K9N+FQ== X-Developer-Key: i=keescook@chromium.org; a=openpgp; fpr=A5C3F68F229DD60F723E6E138972F4DFDC6DC026 X-Rspamd-Queue-Id: 987DB600198A Authentication-Results: imf10.hostedemail.com; dkim=pass header.d=chromium.org header.s=google header.b=QCLdF+eD; dmarc=pass (policy=none) header.from=chromium.org; spf=pass (imf10.hostedemail.com: domain of keescook@chromium.org designates 209.85.215.179 as permitted sender) smtp.mailfrom=keescook@chromium.org X-Rspamd-Server: rspam01 X-Stat-Signature: o19xx3czfikuo535mkaimxmmn3gmjjs3 X-HE-Tag: 1629619019-604890 Content-Transfer-Encoding: quoted-printable X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: Under CONFIG_FORTIFY_SOURCE, it is possible for the compiler to perform strlen() and strnlen() at compile-time when the string size is known. This is required to support compile-time overflow checking in strlcpy(). Signed-off-by: Kees Cook --- include/linux/fortify-string.h | 47 ++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/include/linux/fortify-string.h b/include/linux/fortify-strin= g.h index a3cb1d9aacce..e232a63fd826 100644 --- a/include/linux/fortify-string.h +++ b/include/linux/fortify-string.h @@ -10,6 +10,18 @@ void __read_overflow(void) __compiletime_error("detect= ed read beyond size of obj void __read_overflow2(void) __compiletime_error("detected read beyond si= ze of object (2nd parameter)"); void __write_overflow(void) __compiletime_error("detected write beyond s= ize of object (1st parameter)"); =20 +#define __compiletime_strlen(p) ({ \ + size_t ret =3D (size_t)-1; \ + size_t p_size =3D __builtin_object_size(p, 1); \ + if (p_size !=3D (size_t)-1) { \ + size_t p_len =3D p_size - 1; \ + if (__builtin_constant_p(p[p_len]) && \ + p[p_len] =3D=3D '\0') \ + ret =3D __builtin_strlen(p); \ + } \ + ret; \ +}) + #if defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS) extern void *__underlying_memchr(const void *p, int c, __kernel_size_t s= ize) __RENAME(memchr); extern int __underlying_memcmp(const void *p, const void *q, __kernel_si= ze_t size) __RENAME(memcmp); @@ -60,21 +72,31 @@ extern __kernel_size_t __real_strnlen(const char *, _= _kernel_size_t) __RENAME(st __FORTIFY_INLINE __kernel_size_t strnlen(const char *p, __kernel_size_t = maxlen) { size_t p_size =3D __builtin_object_size(p, 1); - __kernel_size_t ret =3D __real_strnlen(p, maxlen < p_size ? maxlen : p_= size); + size_t p_len =3D __compiletime_strlen(p); + size_t ret; + + /* We can take compile-time actions when maxlen is const. */ + if (__builtin_constant_p(maxlen) && p_len !=3D (size_t)-1) { + /* If p is const, we can use its compile-time-known len. */ + if (maxlen >=3D p_size) + return p_len; + } =20 + /* Do no check characters beyond the end of p. */ + ret =3D __real_strnlen(p, maxlen < p_size ? maxlen : p_size); if (p_size <=3D ret && maxlen !=3D ret) fortify_panic(__func__); return ret; } =20 +/* defined after fortified strnlen to reuse it. */ __FORTIFY_INLINE __kernel_size_t strlen(const char *p) { __kernel_size_t ret; size_t p_size =3D __builtin_object_size(p, 1); =20 - /* Work around gcc excess stack consumption issue */ - if (p_size =3D=3D (size_t)-1 || - (__builtin_constant_p(p[p_size - 1]) && p[p_size - 1] =3D=3D '\0')) + /* Give up if we don't know how large p is. */ + if (p_size =3D=3D (size_t)-1) return __underlying_strlen(p); ret =3D strnlen(p, p_size); if (p_size <=3D ret) @@ -86,24 +108,27 @@ __FORTIFY_INLINE __kernel_size_t strlen(const char *= p) extern size_t __real_strlcpy(char *, const char *, size_t) __RENAME(strl= cpy); __FORTIFY_INLINE size_t strlcpy(char *p, const char *q, size_t size) { - size_t ret; size_t p_size =3D __builtin_object_size(p, 1); size_t q_size =3D __builtin_object_size(q, 1); + size_t q_len; /* Full count of source string length. */ + size_t len; /* Count of characters going into destination. */ =20 if (p_size =3D=3D (size_t)-1 && q_size =3D=3D (size_t)-1) return __real_strlcpy(p, q, size); - ret =3D strlen(q); - if (size) { - size_t len =3D (ret >=3D size) ? size - 1 : ret; - - if (__builtin_constant_p(len) && len >=3D p_size) + q_len =3D strlen(q); + len =3D (q_len >=3D size) ? size - 1 : q_len; + if (__builtin_constant_p(size) && __builtin_constant_p(q_len) && size) = { + /* Write size is always larger than destintation. */ + if (len >=3D p_size) __write_overflow(); + } + if (size) { if (len >=3D p_size) fortify_panic(__func__); __underlying_memcpy(p, q, len); p[len] =3D '\0'; } - return ret; + return q_len; } =20 /* defined after fortified strnlen to reuse it */ --=20 2.30.2