Received: by 2002:a05:6358:11c7:b0:104:8066:f915 with SMTP id i7csp1402567rwl; Wed, 5 Apr 2023 17:03:46 -0700 (PDT) X-Google-Smtp-Source: AKy350Z2FutbcWzDMLMOrjH41Ao/S4WtR0aGf8g/U9BhqwxgZZzHRnu4eHDmTXBimMKUJo/qlGK/ X-Received: by 2002:a17:90a:5d:b0:23b:5155:30a9 with SMTP id 29-20020a17090a005d00b0023b515530a9mr8560358pjb.40.1680739426575; Wed, 05 Apr 2023 17:03:46 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680739426; cv=none; d=google.com; s=arc-20160816; b=QJDm/4idW7k2tph/bs5ZNf35KySuzxD2uJ4d4/ZydWaYCsqh4XBYNYxlIFXYY6cauk yj0zCsjPFPX3v3Pa4Nh2vj5BZoToM6ftAB6MwgwZ0xQ8KYAuws+AYJsGC/cO8Q95xi4B N5CYS3YefsnqH17+KL6EDwNkmr5DMrH8iadDVXFHR1SBrY64VjRq4WUiCJoIQUklCB79 XNtF7Av6zCN+6E/NPnc1E4uEVX8DuoA+JNL4PCo7kxLr2P2SQe9w18DeZJnxPrLHUXsH Oa7Dg2Kjpu4JpHR4O9KPSUkFqB3xPhbcSPT4QpjUDqy8fvXLDDZ4d1ihQUmMqvmcInqU fPhA== 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=ICBa1DtI6i1NF0+JonXqQyqUlpz7dmxfeFViA4mHGno=; b=AB7Xsg3mrOiS5xc/lK4JBdfb5luEf1Ni9pPqGu/zEue1HcQ+BGbMW+B4SpMrlQc2q4 wDUPtLMO9gle8Cy92ewRocrJ4Bi7Q/hUwov6KCwSjGeBMUjy8dV0s0XlbIKLiLh3h694 qNhX88rmWLek1WkhG0RnBuwWbgj8aLQfwUeCbFtrc7059a1VAG/I7zRMA5Te8DJeHgao bcaHkeTs6fZdf1N/NAWzsUNsAWBE/QvdAM1dC/tQ6msojHl7QwAo3rpHtugs66V6XwMP sNJ9awKbeH65m72s9fTphu/Pdh1KwmxbQyPVMhKjZlD+FHwuRIMqvto+ItW37156oaTP MXQQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=YwjTtcaH; 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 Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id j12-20020a170903024c00b001990a6daf9fsi195251plh.535.2023.04.05.17.03.34; Wed, 05 Apr 2023 17:03:46 -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=YwjTtcaH; 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 S231611AbjDFACU (ORCPT + 99 others); Wed, 5 Apr 2023 20:02:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47708 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229481AbjDFACR (ORCPT ); Wed, 5 Apr 2023 20:02:17 -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 90BB859E2 for ; Wed, 5 Apr 2023 17:02:16 -0700 (PDT) Received: by mail-pj1-x1033.google.com with SMTP id qe8-20020a17090b4f8800b0023f07253a2cso38923725pjb.3 for ; Wed, 05 Apr 2023 17:02:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1680739336; 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=ICBa1DtI6i1NF0+JonXqQyqUlpz7dmxfeFViA4mHGno=; b=YwjTtcaHeXgmNQCy+UZfNoSOdXZjRkV1nS2FVwslb/8WY3CT6punFfDFo1A6SEXcEN qgBvZR+YGmwakCTv/2s10NaRAHXxmobJgDox8sh2B8NnrDVlMF7kykKRvSfJHrnDfnaU CrwurUlZu5Q5vMrJKVxFEIoCEymN3rFYQ3lAE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680739336; 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=ICBa1DtI6i1NF0+JonXqQyqUlpz7dmxfeFViA4mHGno=; b=v4KygxbMR6Pznyh4hjTHwMEAimt/ulJGQc5/ePA3DhLttvT5lfboWu3nMoDvHqH5/z pBEm+JQXfKooeQJ/OQJJErD+i19oSmNY4D+/46OFyzD4mryUss0nvmdhWZQG44TD9mkj peaQcLbfkzszqDRFU/smtKAYbKE/kzGNSnJDpHSu4ONrmSog+wCgXl4903tlRjoUS8vY InhD4J15cwNDhdOAj8Plp4QjocZUE2pCZMWFGz7bq5esRU6TxV00H5FwF0LzlLzDh3PR AhdHl0thGisK/3ArecvsCKgxb5Et2nDjlYfPF5ci7MrwX694CggtNG6ZLveGnMeSZ2Hj iYfw== X-Gm-Message-State: AAQBX9fB5bsTKYaKFU1Gwf8C7PIFw6cQFKYhRGPRd+W/wT8IaXYYi2YL qItx0rZrV81ybnmtayUUvKvAfg== X-Received: by 2002:a05:6a20:835d:b0:d6:c9e2:1795 with SMTP id z29-20020a056a20835d00b000d6c9e21795mr788533pzc.27.1680739335996; Wed, 05 Apr 2023 17:02:15 -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 e5-20020a62ee05000000b005e099d7c30bsm11029461pfi.205.2023.04.05.17.02.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Apr 2023 17:02:13 -0700 (PDT) From: Kees Cook To: linux-hardening@vger.kernel.org Cc: Kees Cook , 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 , 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?q?Jos=C3=A9=20Exp=C3=B3sito?= , linux-kernel@vger.kernel.org, kunit-dev@googlegroups.com Subject: [PATCH 4/9] fortify: Add protection for strlcat() Date: Wed, 5 Apr 2023 17:02:03 -0700 Message-Id: <20230406000212.3442647-4-keescook@chromium.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230405235832.never.487-kees@kernel.org> References: <20230405235832.never.487-kees@kernel.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=3250; i=keescook@chromium.org; h=from:subject; bh=rj52x4JBej+qEjIHIHz74SGX8jVWOZs51u/oWt76v9o=; b=owEBbQKS/ZANAwAKAYly9N/cbcAmAcsmYgBkLgv//oEVXTENJ5N/QlhC1PcMOKe+fLOu/OWZjhUq cGEUJoqJAjMEAAEKAB0WIQSlw/aPIp3WD3I+bhOJcvTf3G3AJgUCZC4L/wAKCRCJcvTf3G3AJtbXD/ 0cKX83TNsTe99BigymaFdb/hrWnqygWzdMcLVPDMj6bXddgFVN05PUZvBqP0Jwk0Mq8PN+cVw1xnQK hhPe185jF6FVowhCd83A8Awzl37jFuXW3oIZnifmwtWfbrkV2NSpxlbyqqO1vdo0ZYVaCYCfiiyUql MMJn5QehjOT1vS6A+jJOPBaN9hyxiXjyUYtFvcwjbLXvSyU6plrXedx7Yw4T6Mc0rlBvcr19NfjVtx SBDX5WCJVrmYXhUQKAexomoOvuTHz7TW7gOBFNdtiVvHKOsM2QFnrcQ44xww1H1yZIeF21pWNK0Ure I2WsKEN9IDFqFN5sXbkRlKB5xgU3P3cO5wUw836+tvzaYwdYgrXCuMDD90mJ3kmNhj0NCdd8ugRoR9 xwidD22KGNV1BJA9dXt3yvPXn/p/zb5rgA2ltA+c+A2G17GmupmfOiRu+b/8PmYwyclrcAMVdMu7hr l5OyX3aP9Wy7l8plUlzY9SACEyxMyGShBhxL2VPBQRdQ3aOUdJ4Lx87cgMNGiP8UUNdUwd1PPuqGDF fVOmKgvKW7q4/GZZAwzD1UJJ9ByTmUdCbacrmlat93+NwU6D3/vpuhW5PYQVF6ZshQ7LFJvVU76sth fyZ5LHa4lq99coCOec13GLmFrtPJnP8d6IguezioiOVkUvn42/KNyEaccZiw== X-Developer-Key: i=keescook@chromium.org; a=openpgp; fpr=A5C3F68F229DD60F723E6E138972F4DFDC6DC026 Content-Transfer-Encoding: 8bit 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 From: Kees Cook The definition of strcat() was 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 c9de1f59ee80..875689aa83c3 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) +{ + size_t p_len, copy_len; + size_t p_size = __member_size(p); + size_t q_size = __member_size(q); + 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 * -- 2.34.1