From patchwork Tue Jan 30 22:06:06 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 13538185 Received: from mail-pf1-f172.google.com (mail-pf1-f172.google.com [209.85.210.172]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E8D3278662 for ; Tue, 30 Jan 2024 22:06:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706652381; cv=none; b=umIYtXqPY8fKyU4hXMpD6zLDNe0XS39CUboOQRTHqGya5sRopRUtlBZDFmVrWOmNFW+BiK5yN89crgPh+QEZGVIhA1Q6d8l0a+3gJb1pBvryp5g21uOSBWZzbX9DsZuBAv2nkCaxd1jDa2FcvHAr5v1E8CZ+0UCraMihoSxT1I0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706652381; c=relaxed/simple; bh=mjbhQQsJHZNHQElAJyka1am+OsaRRifuj4xn9QRfLGM=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=CbTSkw4b1lx0XK+l6oNaLj4KUa9112KOC6emwy1+fi+38s1TbU2m9kxFeP7E3MU6pG0n8cxdu7ZBUAV7sGA0jaIXmscZxXSYDVA6a2k3+FcM/fG8YD8MQiArrJHtJMmPZqWwto1ECs3t3d9D0fY/rhazHQIeyaYX33BPcEPgD0Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=MhAo+yD3; arc=none smtp.client-ip=209.85.210.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="MhAo+yD3" Received: by mail-pf1-f172.google.com with SMTP id d2e1a72fcca58-6da202aa138so2726152b3a.2 for ; Tue, 30 Jan 2024 14:06:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1706652378; x=1707257178; darn=vger.kernel.org; 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=TXEWZ+ijn2Mktyo3GgFFo1opylml2uwjVnLpw+L5S/k=; b=MhAo+yD3yaTWH8UHw3ebbIh/luRgWzh6Pnhtrm+K8yG7sVe892qUaYABmE4jmoPlOd 5m02QtNfy57NU8uQEFV1sR8TTIC1NK66Z0jtp3DFcHk0JZF17PnnVS3mzE4x74Ll8b7A 4OrIp5OlKlVWa9UOSjcLknmAlb9tvlz48jvK4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706652378; x=1707257178; 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=TXEWZ+ijn2Mktyo3GgFFo1opylml2uwjVnLpw+L5S/k=; b=sLiqcd7NX3wwbxUwFO7Tk3AYJW/ov8NHikY8O7uy0gburAURgOCIdix90PyhiBcZ4j Y4V6NtajtgN+MXv6pQAsyOB+5WXbNhtATokDuvM39FjC6G10IJ47V/AIUj1fium7vok8 B2Yzp6C6hkHLiOhRuzLjT8ckkOg7pt6meNZ/gVVkkqLl1YIkh5RoPs/QHwhUsrUCPlu3 S55mmFQY7dz82NYqxSNkRCZihdC/Kt8gg1ur77iGgJ0jNzwaZiPGvJj+xLT3h+WzOtkn DPs2WE+udN9XzSWvd9QgnJJ/lwUbKdDaxSyfrIT3I8QoxzTrUO64oKWDCx5vX59vKx5r guyQ== X-Gm-Message-State: AOJu0YyBN3ja+lbHEIW/75EHeBm4mI7J9dh/aFhzGBBI8krUQFiinuqZ jcs/aLM4JEUQXq3zqoOGEUv41G+Ki0zkvIqegoqjcFBRgfGHMwSnF3JeAhqgiQ== X-Google-Smtp-Source: AGHT+IEd3zXlvSGgZ0mXCE1XjkvID5hcRbGGUrHAh6e87yThPodvIALQNu/8HwwxXls7VIkIq6gj+w== X-Received: by 2002:a05:6a20:c411:b0:19a:360c:75d8 with SMTP id en17-20020a056a20c41100b0019a360c75d8mr8249397pzb.14.1706652378406; Tue, 30 Jan 2024 14:06:18 -0800 (PST) Received: from www.outflux.net ([198.0.35.241]) by smtp.gmail.com with ESMTPSA id r11-20020a170903014b00b001d8dedeb0casm4331642plc.180.2024.01.30.14.06.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 30 Jan 2024 14:06:17 -0800 (PST) From: Kees Cook To: Rasmus Villemoes Cc: Kees Cook , "Gustavo A. R. Silva" , Justin Stitt , linux-hardening@vger.kernel.org, Andrew Morton , Nathan Chancellor , Nick Desaulniers , Bill Wendling , Mark Rutland , Miguel Ojeda , Marco Elver , Jakub Kicinski , Przemek Kitszel , Masahiro Yamada , linux-kernel@vger.kernel.org, llvm@lists.linux.dev Subject: [PATCH v2 1/5] overflow: Adjust check_*_overflow() kern-doc to reflect results Date: Tue, 30 Jan 2024 14:06:06 -0800 Message-Id: <20240130220614.1154497-1-keescook@chromium.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240130220218.it.154-kees@kernel.org> References: <20240130220218.it.154-kees@kernel.org> Precedence: bulk X-Mailing-List: linux-hardening@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=2716; i=keescook@chromium.org; h=from:subject; bh=mjbhQQsJHZNHQElAJyka1am+OsaRRifuj4xn9QRfLGM=; b=owEBbQKS/ZANAwAKAYly9N/cbcAmAcsmYgBluXLRXPWpxbxWBABUSnq7LV3ZR63LVVosG/CRP 5ZzpJGG3mKJAjMEAAEKAB0WIQSlw/aPIp3WD3I+bhOJcvTf3G3AJgUCZbly0QAKCRCJcvTf3G3A JsZ3D/47FGhmdQqxJrZ9wW+IfjOj5Z+/JJdT4A88xjMViD8m2y+sZ66ET8cpz0UxvZb8wc5ydbm kKGJkwmx2MxOImy/n06QpmWo+Jj6Hcb2x4MhjJrvG7QbIC8no338Da90doAljPBJQardE1fF7BX TAwaqrSw+31TcmCP/J6CJ3Zy1M7SMmYp0HdBNg7mIDikbW2FYa3oKBphdZXiLt38fjJJQf2jUFd CBKnBPtpk2Q42oSJwkvv0+WZj3zuvoFhIgRyLYf0i9QuXdQFK8IfVBZQi3UUcyJRTHJDYshhaTS yfLfrJ6F0nr8PdL9h2/IqewAUyNk+YiE0J1j+Ds70hYy9YypS/JaeNCvKq9n42FWNRatqLbtMEs HweyCRNsTPMccrf/ZSHVhW83m0QZP3tZ00lVm3rgNhL2Q/oa/pqerx8fp8YgQ/JgLeRgJt1eK2R ino8gJHkQp7HkP+owrvPQZBSFUjFFBc+7ZHhkOiOYDQ/1v7RZHuIH1CYRNyhzUdlSU+QrcgUX9F XfRFoAkuBd8qYpVccYsV+1/zKrZDgEW72okrPtTNzp1Rjo+eXk5QFw9bDTl/qo/CClNbY1F0PxT LKPYm7R9P1tk0jtAkCFen/ejWNEp8jvYos5ar8T5/53t/xYMN7kEw1Cj4gw2iJwJ5U7ELiklaKW B5/Vgg5InWPF4Aw== X-Developer-Key: i=keescook@chromium.org; a=openpgp; fpr=A5C3F68F229DD60F723E6E138972F4DFDC6DC026 The check_*_overflow() helpers will return results with potentially wrapped-around values. These values have always been checked by the selftests, so avoid the confusing language in the kern-doc. The idea of "safe for use" was relative to the expectation of whether or not the caller wants a wrapped value -- the calculation itself will always follow arithmetic wrapping rules. Cc: "Gustavo A. R. Silva" Cc: Justin Stitt Cc: linux-hardening@vger.kernel.org Signed-off-by: Kees Cook --- include/linux/overflow.h | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/include/linux/overflow.h b/include/linux/overflow.h index 7b5cf4a5cd19..4e741ebb8005 100644 --- a/include/linux/overflow.h +++ b/include/linux/overflow.h @@ -57,11 +57,9 @@ static inline bool __must_check __must_check_overflow(bool overflow) * @b: second addend * @d: pointer to store sum * - * Returns 0 on success. + * Returns 0 on success, 1 on wrap-around. * - * *@d holds the results of the attempted addition, but is not considered - * "safe for use" on a non-zero return value, which indicates that the - * sum has overflowed or been truncated. + * *@d holds the results of the attempted addition, which may wrap-around. */ #define check_add_overflow(a, b, d) \ __must_check_overflow(__builtin_add_overflow(a, b, d)) @@ -72,11 +70,9 @@ static inline bool __must_check __must_check_overflow(bool overflow) * @b: subtrahend; value to subtract from @a * @d: pointer to store difference * - * Returns 0 on success. + * Returns 0 on success, 1 on wrap-around. * - * *@d holds the results of the attempted subtraction, but is not considered - * "safe for use" on a non-zero return value, which indicates that the - * difference has underflowed or been truncated. + * *@d holds the results of the attempted subtraction, which may wrap-around. */ #define check_sub_overflow(a, b, d) \ __must_check_overflow(__builtin_sub_overflow(a, b, d)) @@ -87,11 +83,9 @@ static inline bool __must_check __must_check_overflow(bool overflow) * @b: second factor * @d: pointer to store product * - * Returns 0 on success. + * Returns 0 on success, 1 on wrap-around. * - * *@d holds the results of the attempted multiplication, but is not - * considered "safe for use" on a non-zero return value, which indicates - * that the product has overflowed or been truncated. + * *@d holds the results of the attempted multiplication, which may wrap-around. */ #define check_mul_overflow(a, b, d) \ __must_check_overflow(__builtin_mul_overflow(a, b, d)) From patchwork Tue Jan 30 22:06:07 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 13538181 Received: from mail-pg1-f180.google.com (mail-pg1-f180.google.com [209.85.215.180]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EB6767D3FD for ; Tue, 30 Jan 2024 22:06:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.180 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706652377; cv=none; b=hGSYM3gNeFE+5/Vjt4RZTIA8Z68OXuvt3Socux0UtLu+XtK2AogiLK7YTLzZP7Hub0YM5QMZEp4U9SoKLD1VJ6Nhu1HXffbL5GJZ9626+h0+dOV1LdzRDZ0PtXZNd90Msvtu92S/wG57otKE59ZNFU51p1iZDpEZ3yw0Ez9Ri4c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706652377; c=relaxed/simple; bh=wU5wiWooVyd2eqSdpoTBHd90qKwM9wZ/F9mLDiaQmqs=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=raE3R28UVkQHsQ6V0JIcgjWeWfRyeM7p0I7Wd0mj9bBHWpwDjNq/Qez+5BchrbvvVUD1oqyTL71wVTLDfDogIfRP5m24h+B/b7GDd92KQ731HRVq8F2ha6WpYf4AmBNfEfpCOzFMo5Pi8Ncs1FoFrxsv0DUoeWjGPNi2d/wOaKc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=kfOHYvuP; arc=none smtp.client-ip=209.85.215.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="kfOHYvuP" Received: by mail-pg1-f180.google.com with SMTP id 41be03b00d2f7-5d8b519e438so2282982a12.1 for ; Tue, 30 Jan 2024 14:06:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1706652375; x=1707257175; darn=vger.kernel.org; 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=kLoyWv8OtbHjtjHwspyJBOM+KJjmRvPEg1tZQlUAAzg=; b=kfOHYvuPK1IX9lQxpDuAMMkdrFbyN8cno0Ha9ci8dVkRYiASuC8nvrCc8rRKtx6IQQ jTPlb0LNX2b6M/6lKDIxvHsD4qWoJCdZv6SoM9gdN3vhLldAUmsNOKlmGMBdPcu3AIFU SVex/IriVcrHh7+OuSHKCikqRoynHK1d/Wr7M= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706652375; x=1707257175; 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=kLoyWv8OtbHjtjHwspyJBOM+KJjmRvPEg1tZQlUAAzg=; b=LchKRxf6VgmYdN+Ya3IpcVFVryuobbmrxHN2NFEO0Y7xKxrn+PzeTWVXms0JFSOn3k fL9PQ5HFmI71UdNZqivjpPQRAOnnm2vuQMj+rSK8AF7NuwtawZ4538k4cekPB24U/ZSz bTPLOMu0wKpYGOL/QRfg+XmvBh6eZ/DuUXGuGP+U0lse4t1ENSQCUp0YYBEEoA7B6kNi FNbIdeREocc7platPoFsFyDwkCis8+hpQkIUmqRwvN+zNd7nn5+QkFKcFMH6CX85v0zC uEC23UYgky+RmqJuPKeq/2+f7uyOPih8KIlWJYMBiM1/Hx2REZC5u2g8AIKzeJ4CUf6m t5yg== X-Gm-Message-State: AOJu0Yz7P7hc5XLwkSnkmKLBP0+WESW+6MvqYSJiqBEaw4Mhsk+/c9iD yviNIsuhbYPS2d46jRpU3mNsvm8LdGMJ4s76eXnOVgiMvyuPF6C2uh1L8qi+bw== X-Google-Smtp-Source: AGHT+IEhkW9fawB+RfxZA8/LTl4ybX0trJVe7R6hgeVDy2kpvJ5enfZuKr5R42usSZ3qcav99HXhKQ== X-Received: by 2002:a05:6a20:b9a7:b0:19c:7bc4:6b0 with SMTP id ff39-20020a056a20b9a700b0019c7bc406b0mr4716562pzb.42.1706652375177; Tue, 30 Jan 2024 14:06:15 -0800 (PST) Received: from www.outflux.net ([198.0.35.241]) by smtp.gmail.com with ESMTPSA id p12-20020a170902eacc00b001d72f6ba383sm3691421pld.224.2024.01.30.14.06.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 30 Jan 2024 14:06:14 -0800 (PST) From: Kees Cook To: Rasmus Villemoes Cc: Kees Cook , "Gustavo A. R. Silva" , Andrew Morton , Nathan Chancellor , Nick Desaulniers , Bill Wendling , Justin Stitt , llvm@lists.linux.dev, linux-hardening@vger.kernel.org, Mark Rutland , Miguel Ojeda , Marco Elver , Jakub Kicinski , Przemek Kitszel , Masahiro Yamada , linux-kernel@vger.kernel.org Subject: [PATCH v2 2/5] overflow: Expand check_add_overflow() for pointer addition Date: Tue, 30 Jan 2024 14:06:07 -0800 Message-Id: <20240130220614.1154497-2-keescook@chromium.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240130220218.it.154-kees@kernel.org> References: <20240130220218.it.154-kees@kernel.org> Precedence: bulk X-Mailing-List: linux-hardening@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=10664; i=keescook@chromium.org; h=from:subject; bh=wU5wiWooVyd2eqSdpoTBHd90qKwM9wZ/F9mLDiaQmqs=; b=owEBbQKS/ZANAwAKAYly9N/cbcAmAcsmYgBluXLROmJWNChP5gjc4TpxLGURO5jKzEEgWMbHO GpeBzggvUWJAjMEAAEKAB0WIQSlw/aPIp3WD3I+bhOJcvTf3G3AJgUCZbly0QAKCRCJcvTf3G3A JldrD/9TuUJyp3YsW0TEykPmrvgH9vU+VjqFQEapybkawwEcPT72Aav3rQMCiud+MIQNu6QDnza CziIeADD0D81cGp5ZDuEDQY/HMptU+dssftL2CzDrVhdYspifI9JTq7EzqvgPqZeSo4t9US+kdE VtNO3CQVdcCYyUkHY3/CaLNUTJXMbMIK8swjlCViq1GtWE6lINsWzXLvW73bdzXOIB87YTivK4h hUGpD80CMy+07kiguOKKqrZ1ZPg2Y3XRx4vKNyzho0Kg4J2FcPZ7Oz79L97PUwcvaFTavvGrxHd fiKI1LEhE6WcBZqugHyqNgTpWPGDxJzpNanmeVmDy9E0hoL4A1svI5VEmHAI+Ut4JVqCxfkM7iS sDmgJPatT0uJuTcqofzQ+awJUUlzRRUgE3GTHAcwKUJzC882pEk2y6JXA60mef01JINAyLuHV2f /dNrGRT5kg9DEak+3v3pvUdtF8p99GKUDb4fZDzhvPBPYfU0gWyNNpCYY3LruDTcwSzcFa/MeRH TwoZ3TqKgHYYg2sC1FrZNgYWC8oAtVXxLOXBHDPkmxvrwLggAs3Qu4Erms4l20o00Wbyk7G6MLO BqxhPRQG0RZHMXBZ2LriEnaX1mA6uS6p5PRqI6v/hLMX5bYBFzkkCBGwbO+VCZF/vAyQuQ4bnUT 3lM/omqZkKwDXgg== X-Developer-Key: i=keescook@chromium.org; a=openpgp; fpr=A5C3F68F229DD60F723E6E138972F4DFDC6DC026 The check_add_overflow() helper is mostly a wrapper around __builtin_add_overflow(), but GCC and Clang refuse to operate on pointer arguments that would normally be allowed if the addition were open-coded. For example, we have many places where pointer overflow is tested: struct foo *ptr; ... /* Check for overflow */ if (ptr + count < ptr) ... And in order to avoid running into the overflow sanitizers in the future, we need to rewrite these "intended" overflow checks: if (check_add_overflow(ptr, count, &result)) ... Frustratingly the argument type validation for __builtin_add_overflow() is done before evaluating __builtin_choose_expr(), so for arguments to be valid simultaneously for sizeof(*p) (when p may not be a pointer), and __builtin_add_overflow(a, ...) (when a may be a pointer), we must introduce wrappers that always produce a specific type (but they are only used in the places where the bogus arguments will be ignored). To test whether a variable is a pointer or not, introduce the __is_ptr() helper, which uses __builtin_classify_type() to find arrays and pointers (via the new __is_ptr_or_array() helper), and then decays arrays into pointers (via the new __decay() helper), to distinguish pointers from arrays. Additionally update the unit tests to cover pointer addition. Cc: Rasmus Villemoes Cc: "Gustavo A. R. Silva" Cc: Andrew Morton Cc: Nathan Chancellor Cc: Nick Desaulniers Cc: Bill Wendling Cc: Justin Stitt Cc: llvm@lists.linux.dev Cc: linux-hardening@vger.kernel.org Signed-off-by: Kees Cook --- include/linux/compiler_types.h | 10 +++++ include/linux/overflow.h | 44 ++++++++++++++++++- lib/overflow_kunit.c | 77 ++++++++++++++++++++++++++++++---- 3 files changed, 120 insertions(+), 11 deletions(-) diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h index 6f1ca49306d2..d27b58fddfaa 100644 --- a/include/linux/compiler_types.h +++ b/include/linux/compiler_types.h @@ -375,6 +375,16 @@ struct ftrace_likely_data { /* Are two types/vars the same type (ignoring qualifiers)? */ #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) +/* Is variable addressable? */ +#define __is_ptr_or_array(p) (__builtin_classify_type(p) == 5) + +/* Return an array decayed to a pointer. */ +#define __decay(p) \ + (&*__builtin_choose_expr(__is_ptr_or_array(p), p, NULL)) + +/* Report if variable is a pointer type. */ +#define __is_ptr(p) __same_type(p, __decay(p)) + /* * __unqual_scalar_typeof(x) - Declare an unqualified scalar type, leaving * non-scalar types unchanged. diff --git a/include/linux/overflow.h b/include/linux/overflow.h index 4e741ebb8005..210e5602e89b 100644 --- a/include/linux/overflow.h +++ b/include/linux/overflow.h @@ -51,6 +51,43 @@ static inline bool __must_check __must_check_overflow(bool overflow) return unlikely(overflow); } +/* Always produce an integral variable expression. */ +#define __filter_integral(x) \ + __builtin_choose_expr(!__is_ptr(x), (x), 0) + +/* Always produce a pointer value. */ +#define __filter_ptr(x) \ + __builtin_choose_expr(__is_ptr(x), (x), NULL) + +/* Always produce a pointer to an integral value. */ +#define __filter_ptrint(x) \ + __builtin_choose_expr(!__is_ptr(*(x)), x, &(int){ 0 }) + +/** + * __check_ptr_add_overflow() - Calculate pointer addition with overflow checking + * @a: pointer addend + * @b: numeric addend + * @d: pointer to store sum + * + * Returns 0 on success, 1 on wrap-around. + * + * Do not use this function directly, use check_add_overflow() instead. + * + * *@d holds the results of the attempted addition, which may wrap-around. + */ +#define __check_ptr_add_overflow(a, b, d) \ + ({ \ + typeof(a) __a = (a); \ + typeof(b) __b = (b); \ + size_t __bytes; \ + bool __overflow; \ + \ + /* we want to perform the wrap-around, but retain the result */ \ + __overflow = __builtin_mul_overflow(sizeof(*(__a)), __b, &__bytes); \ + __builtin_add_overflow((unsigned long)(__a), __bytes, (unsigned long *)(d)) || \ + __overflow; \ + }) + /** * check_add_overflow() - Calculate addition with overflow checking * @a: first addend @@ -61,8 +98,11 @@ static inline bool __must_check __must_check_overflow(bool overflow) * * *@d holds the results of the attempted addition, which may wrap-around. */ -#define check_add_overflow(a, b, d) \ - __must_check_overflow(__builtin_add_overflow(a, b, d)) +#define check_add_overflow(a, b, d) \ + __must_check_overflow(__builtin_choose_expr(__is_ptr(a), \ + __check_ptr_add_overflow(__filter_ptr(a), b, d), \ + __builtin_add_overflow(__filter_integral(a), b, \ + __filter_ptrint(d)))) /** * check_sub_overflow() - Calculate subtraction with overflow checking diff --git a/lib/overflow_kunit.c b/lib/overflow_kunit.c index c527f6b75789..2d106e880956 100644 --- a/lib/overflow_kunit.c +++ b/lib/overflow_kunit.c @@ -45,13 +45,18 @@ # define SKIP_64_ON_32(t) do { } while (0) #endif -#define DEFINE_TEST_ARRAY_TYPED(t1, t2, t) \ - static const struct test_ ## t1 ## _ ## t2 ## __ ## t { \ +#define DEFINE_TEST_ARRAY_NAMED_TYPED(n1, n2, n, t1, t2, t) \ + static const struct test_ ## n1 ## _ ## n2 ## __ ## n { \ t1 a; \ t2 b; \ - t sum, diff, prod; \ + t sum; \ + t diff; \ + t prod; \ bool s_of, d_of, p_of; \ - } t1 ## _ ## t2 ## __ ## t ## _tests[] + } n1 ## _ ## n2 ## __ ## n ## _tests[] + +#define DEFINE_TEST_ARRAY_TYPED(t1, t2, t) \ + DEFINE_TEST_ARRAY_NAMED_TYPED(t1, t2, t, t1, t2, t) #define DEFINE_TEST_ARRAY(t) DEFINE_TEST_ARRAY_TYPED(t, t, t) @@ -251,8 +256,10 @@ DEFINE_TEST_ARRAY(s64) = { }; #define check_one_op(t, fmt, op, sym, a, b, r, of) do { \ - int _a_orig = a, _a_bump = a + 1; \ - int _b_orig = b, _b_bump = b + 1; \ + typeof(a + 0) _a_orig = a; \ + typeof(a + 0) _a_bump = a + 1; \ + typeof(b + 0) _b_orig = b; \ + typeof(b + 0) _b_bump = b + 1; \ bool _of; \ t _r; \ \ @@ -260,13 +267,13 @@ DEFINE_TEST_ARRAY(s64) = { KUNIT_EXPECT_EQ_MSG(test, _of, of, \ "expected "fmt" "sym" "fmt" to%s overflow (type %s)\n", \ a, b, of ? "" : " not", #t); \ - KUNIT_EXPECT_EQ_MSG(test, _r, r, \ + KUNIT_EXPECT_TRUE_MSG(test, _r == r, \ "expected "fmt" "sym" "fmt" == "fmt", got "fmt" (type %s)\n", \ a, b, r, _r, #t); \ /* Check for internal macro side-effects. */ \ _of = check_ ## op ## _overflow(_a_orig++, _b_orig++, &_r); \ - KUNIT_EXPECT_EQ_MSG(test, _a_orig, _a_bump, "Unexpected " #op " macro side-effect!\n"); \ - KUNIT_EXPECT_EQ_MSG(test, _b_orig, _b_bump, "Unexpected " #op " macro side-effect!\n"); \ + KUNIT_EXPECT_TRUE_MSG(test, _a_orig == _a_bump, "Unexpected " #op " macro side-effect!\n"); \ + KUNIT_EXPECT_TRUE_MSG(test, _b_orig == _b_bump, "Unexpected " #op " macro side-effect!\n"); \ } while (0) #define DEFINE_TEST_FUNC_TYPED(n, t, fmt) \ @@ -333,6 +340,55 @@ DEFINE_TEST_ARRAY_TYPED(int, int, u8) = { }; DEFINE_TEST_FUNC_TYPED(int_int__u8, u8, "%d"); +#define DEFINE_TEST_PTR_FUNC_TYPED(n, t, fmt) \ +static void do_ptr_test_ ## n(struct kunit *test, const struct test_ ## n *p) \ +{ \ + /* we're only doing single-direction sums, no product or division */ \ + check_one_op(t, fmt, add, "+", p->a, p->b, p->sum, p->s_of);\ +} \ + \ +static void n ## _overflow_test(struct kunit *test) { \ + unsigned i; \ + \ + for (i = 0; i < ARRAY_SIZE(n ## _tests); ++i) \ + do_ptr_test_ ## n(test, &n ## _tests[i]); \ + kunit_info(test, "%zu %s arithmetic tests finished\n", \ + ARRAY_SIZE(n ## _tests), #n); \ +} + +DEFINE_TEST_ARRAY_NAMED_TYPED(void, int, void, void *, int, void *) = { + {NULL, 0, NULL, NULL, NULL, false, false, false}, + {(void *)0x30, 0x10, (void *)0x40, NULL, NULL, false, false, false}, + {(void *)ULONG_MAX, 0, (void *)ULONG_MAX, NULL, NULL, false, false, false}, + {(void *)ULONG_MAX, 1, NULL, NULL, NULL, true, false, false}, + {(void *)ULONG_MAX, INT_MAX, (void *)(INT_MAX - 1), NULL, NULL, true, false, false}, +}; +DEFINE_TEST_PTR_FUNC_TYPED(void_int__void, void *, "%lx"); + +struct _sized { + int a; + char b; +}; + +DEFINE_TEST_ARRAY_NAMED_TYPED(sized, int, sized, struct _sized *, int, struct _sized *) = { + {NULL, 0, NULL, NULL, NULL, false, false, false}, + {NULL, 1, (struct _sized *)(sizeof(struct _sized)), NULL, NULL, false, false, false}, + {NULL, 0x10, (struct _sized *)(sizeof(struct _sized) * 0x10), NULL, NULL, false, false, false}, + {(void *)(ULONG_MAX - sizeof(struct _sized)), 1, (struct _sized *)ULONG_MAX, NULL, NULL, false, false, false}, + {(void *)(ULONG_MAX - sizeof(struct _sized) + 1), 1, NULL, NULL, NULL, true, false, false}, + {(void *)(ULONG_MAX - sizeof(struct _sized) + 1), 2, (struct _sized *)(sizeof(struct _sized)), NULL, NULL, true, false, false}, + {(void *)(ULONG_MAX - sizeof(struct _sized) + 1), 3, (struct _sized *)(sizeof(struct _sized) * 2), NULL, NULL, true, false, false}, +}; +DEFINE_TEST_PTR_FUNC_TYPED(sized_int__sized, struct _sized *, "%lx"); + +DEFINE_TEST_ARRAY_NAMED_TYPED(sized, size_t, sized, struct _sized *, size_t, struct _sized *) = { + {NULL, 0, NULL, NULL, NULL, false, false, false}, + {NULL, 1, (struct _sized *)(sizeof(struct _sized)), NULL, NULL, false, false, false}, + {NULL, 0x10, (struct _sized *)(sizeof(struct _sized) * 0x10), NULL, NULL, false, false, false}, + {NULL, SIZE_MAX - 10, (struct _sized *)18446744073709551528UL, NULL, NULL, true, false, false}, +}; +DEFINE_TEST_PTR_FUNC_TYPED(sized_size_t__sized, struct _sized *, "%zu"); + /* Args are: value, shift, type, expected result, overflow expected */ #define TEST_ONE_SHIFT(a, s, t, expect, of) do { \ typeof(a) __a = (a); \ @@ -1122,6 +1178,9 @@ static struct kunit_case overflow_test_cases[] = { KUNIT_CASE(s32_s32__s32_overflow_test), KUNIT_CASE(u64_u64__u64_overflow_test), KUNIT_CASE(s64_s64__s64_overflow_test), + KUNIT_CASE(void_int__void_overflow_test), + KUNIT_CASE(sized_int__sized_overflow_test), + KUNIT_CASE(sized_size_t__sized_overflow_test), KUNIT_CASE(u32_u32__int_overflow_test), KUNIT_CASE(u32_u32__u8_overflow_test), KUNIT_CASE(u8_u8__int_overflow_test), From patchwork Tue Jan 30 22:06:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 13538183 Received: from mail-ot1-f41.google.com (mail-ot1-f41.google.com [209.85.210.41]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BEF967D411 for ; Tue, 30 Jan 2024 22:06:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706652379; cv=none; b=i7YSlyMVJ9YxIH/2U7lb0b01ZyCdWdTt2YtsC73lohSVcdBS1xu72kUevAOvJmdnYI6yW3wwDffe5qlZZBca+lglSp3C3bdphOSLkvDLCG/6+c9liwlyexBL1Wp8ay6Cs8bNcKA1cgJUtMOAfegafD9t+HT1JreAvIMZwaTXERI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706652379; c=relaxed/simple; bh=WUwqmJoFZQeyqmuC4k6x7kK2L9hMV5zmyghrfRiNqjc=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=j2WNKwMYoP/NnQSqvL+HZiH7ai+4jrwHY3yPKYFqnxNtaE+BlXDPhIj9aOWWbN3tI5jAEu/FDChXRWK5iAfuiYkMFG9OaeSEkU6eTw1MzAWRf5qVFKFHrZ8DGzbSVuEA6gokPVKyKxkyzspbUkkZoBsxWy8lXvSZSXBKhVRjuH0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=ZQonWnMl; arc=none smtp.client-ip=209.85.210.41 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="ZQonWnMl" Received: by mail-ot1-f41.google.com with SMTP id 46e09a7af769-6e117e0fee8so1904965a34.2 for ; Tue, 30 Jan 2024 14:06:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1706652377; x=1707257177; darn=vger.kernel.org; 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=0NouAp6ATROls5AjgSHn6FMH+dDN0Afdv78yAag0W0U=; b=ZQonWnMl0aC168QCaVQM8PAMVAq8b+Ruf4hbCJRwMHFvTR/UbyNpIr+wL8rBSxVrTs ucN+sdVB8sW5jhhUKshT9KwfwLydFuNAJ56NeU/hzATn30TKvKmKYJCFBf8k7lWHgQSh aPMh2Q2p9GBI0uYwHrxPdqB+KhTUo1veFen1Q= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706652377; x=1707257177; 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=0NouAp6ATROls5AjgSHn6FMH+dDN0Afdv78yAag0W0U=; b=Px4x5CT5jPc7BjeklYpE4cdAQ6GZietglBtzBBFbeJxkhVW1o/U1QFyh4VDcPQyr/V pKYV5jkWJLTW2Kn7pHfIxK4w51oDo8tfbh7zC4p7fy2EVascKZVD4+5iudA/uUjyDF/L 5EfHI8c1LfVBLwCpJdEd6OH/TtyeWAxcsxWxJQ8rpmxZTt6mNCtV0DDbmkswDjUHsogl N8enC1AgL44KfVpsJAfdb0+8+S9klBjV9euCh8S/7HVJ/0paRol2uaG0R3dO5m+XxmU9 F24ZZGKL+QTe2ipwDRucfq/jQgVeU4sgk1ceqRLXEAT2+ameAGYGJ8xlW2iBkaAd08LA yZIw== X-Gm-Message-State: AOJu0YwJCOZBITukpN2MbY9rcI8XaolP4JSxeSS2QBJuJUNpnh4xkCkI gt+U+5LVTjBCwZ65I28FWlCd1rGshgWEfXKS0gRhrz/CZyXKF8m1O9dxGkeVMA== X-Google-Smtp-Source: AGHT+IHM5CIjGnaWPVQJbefnPzKTqkXb953lJjgYmVucTvoMoZOsWJbs69yFvunQXf+9oTJH3ef9LQ== X-Received: by 2002:a05:6358:4318:b0:178:8ab7:e338 with SMTP id r24-20020a056358431800b001788ab7e338mr3080332rwc.22.1706652376816; Tue, 30 Jan 2024 14:06:16 -0800 (PST) Received: from www.outflux.net ([198.0.35.241]) by smtp.gmail.com with ESMTPSA id e20-20020a633714000000b005d8e280c879sm2373723pga.84.2024.01.30.14.06.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 30 Jan 2024 14:06:14 -0800 (PST) From: Kees Cook To: Rasmus Villemoes Cc: Kees Cook , "Gustavo A. R. Silva" , Justin Stitt , linux-hardening@vger.kernel.org, Andrew Morton , Nathan Chancellor , Nick Desaulniers , Bill Wendling , Mark Rutland , Miguel Ojeda , Marco Elver , Jakub Kicinski , Przemek Kitszel , Masahiro Yamada , linux-kernel@vger.kernel.org, llvm@lists.linux.dev Subject: [PATCH v2 3/5] overflow: Introduce add_would_overflow() Date: Tue, 30 Jan 2024 14:06:08 -0800 Message-Id: <20240130220614.1154497-3-keescook@chromium.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240130220218.it.154-kees@kernel.org> References: <20240130220218.it.154-kees@kernel.org> Precedence: bulk X-Mailing-List: linux-hardening@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=1484; i=keescook@chromium.org; h=from:subject; bh=WUwqmJoFZQeyqmuC4k6x7kK2L9hMV5zmyghrfRiNqjc=; b=owEBbQKS/ZANAwAKAYly9N/cbcAmAcsmYgBluXLSKrOGOdtE6GxGZsc08FzWIhOaMnOeNq/p8 lHKmLHU8x2JAjMEAAEKAB0WIQSlw/aPIp3WD3I+bhOJcvTf3G3AJgUCZbly0gAKCRCJcvTf3G3A JsybD/9hil900CeIkSDVu7dEhGUU7Eh3jgkpN4uvXxQKhpz1xxwIYnxerdxt4kUhSZ3PU7Wn+a8 y2tMl38HSeHfTMijx0VTRIz766tSzidw/km095DK7xlLqc1C7p0bOe1fXmjDJjZMo/h+B4iYAUP 786UqO4ZLOPpSWWjbEoirC1DSpvbcZbf9v7z1W8wRV1v25gyUBQOvYrUMm1YCOaMm0RQGLfuLPC 9VVUdvY4jETXBTpUlKQ7apR4LH+2R5ioDpI9ZaCEuIoZfny7BG9mJBkmXZuvWSrXUzwoqvhEQOi d/JwwmkQ97OSBCj3vYl/eYqvSADKpwdPKlHA1/LuyVDmqtbvEF5Zpvy/BxkFgcPvwProrebcWtj 4Kc0aWfaId1UDIVNhDIbt2cGolemw66t7obWCVe59lXAAxjT5g1SQpAbVmnvDU0Pq88Ty4chzEN a5B1zUIWzfXejwU/U02FFfpn6jzIxuavta2dAkaqF57YIfzdaiKfCqE6G78qg7/EIUwJ1qsKJlD NtnqoqDMkGYOdmKSvMerFSc6HJuJAPskCMyoatyDAXt3Lors/XN0qMiAFiPxyW1JE7Q/EvtUcer 2tuf3HJSurwaeE4R4tAEbTLHd0N57a495U5UbSpkLEwag6gPdKC/6sH5j119nzxFUVW0AxTv/+S YGphMUzZKOqjzuw== X-Developer-Key: i=keescook@chromium.org; a=openpgp; fpr=A5C3F68F229DD60F723E6E138972F4DFDC6DC026 For instances where only the overflow needs to be checked (and the sum isn't used), provide the new helper add_would_overflow(), which is a wrapper for check_add_overflow(). Cc: Rasmus Villemoes Cc: "Gustavo A. R. Silva" Cc: Justin Stitt Cc: linux-hardening@vger.kernel.org Signed-off-by: Kees Cook --- include/linux/overflow.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/linux/overflow.h b/include/linux/overflow.h index 210e5602e89b..3c46c648d2e8 100644 --- a/include/linux/overflow.h +++ b/include/linux/overflow.h @@ -104,6 +104,22 @@ static inline bool __must_check __must_check_overflow(bool overflow) __builtin_add_overflow(__filter_integral(a), b, \ __filter_ptrint(d)))) +/** + * add_would_overflow() - Check if an addition would overflow + * @var: variable to add to that is checked for overflow + * @offset: value to add + * + * Returns true if the sum would overflow. + * + * To keep a copy of the sum when the addition doesn't overflow, use + * check_add_overflow() instead. + */ +#define add_would_overflow(var, offset) \ + __must_check_overflow(({ \ + typeof(var) __result; \ + check_add_overflow(var, offset, &__result); \ + })) + /** * check_sub_overflow() - Calculate subtraction with overflow checking * @a: minuend; value to subtract from From patchwork Tue Jan 30 22:06:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 13538184 Received: from mail-pl1-f173.google.com (mail-pl1-f173.google.com [209.85.214.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E9EAC7D3F9 for ; Tue, 30 Jan 2024 22:06:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706652380; cv=none; b=YCZQ34w8LXf5h+fmXb98d9FwvIhTEkv2id4q5iVAtjYpqQ3pNkmgeL5NEZlElOUVi/rswnK2zNAuDEVAutX17tybOAJrr32eW1oiqXStdZxY68OPXT6LEC+9doil9e4LytAdiY8C7dwN2tPWjEvJlWEAHZauaH1yI5/9JvTZXXc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706652380; c=relaxed/simple; bh=Lsn3+N+1f8l6lRmtTSj3tYRTIPnbB1C3Ti+RJg8Mz0E=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=fXf0EgxDxBmTcXtt12t0eIiQbmK5ewJfHE4Dbj6d9w60IqNco9z3W+JGB0SAu+6mD73gQ0p0MwHssjpGLLRaF7ufLA9yWubeWrYUCxlbc5JHS/jlb19PD/b34hvCiENYcMe0vq4c/fevikjyyBNLTYDPdj1CzXcKuVmIZW6oHuA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=KqbwGoet; arc=none smtp.client-ip=209.85.214.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="KqbwGoet" Received: by mail-pl1-f173.google.com with SMTP id d9443c01a7336-1d731314e67so21611945ad.1 for ; Tue, 30 Jan 2024 14:06:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1706652377; x=1707257177; darn=vger.kernel.org; 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=WcwNGWRjXs5hTgiaUtk2cifYdvfoOCz6Y06w4rb2tvo=; b=KqbwGoet4mGX7QMurDGZxHWw1ezcxtwReh/5pmt0luh4xdsvA0Nt9VdaZsdwuJaK1h B9PuKq++5wz7aGlXCSsYO3reBhzLYNMQAU78r9BNLWSb6zWhAuGEmrCtc1gCBuxqyRTL OyL6R0CRcF6PlBR20Kvw22n5TL02vNRLE7c/8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706652377; x=1707257177; 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=WcwNGWRjXs5hTgiaUtk2cifYdvfoOCz6Y06w4rb2tvo=; b=VyF6KBF47+xO+TghLJEymiHnukTcI5XGA+DC5j4g/HL91hR2T4+NYhf6cvs+Ttif1p 8rjrSlGWlRCm1lQLTHe5YvnlNDQ1UP4XafHMnyep0MeZT7Vp46pQvkATOabUBnJo5FjM oubDil5FL2Yuw0zIgCuCwGqzbLPr6PODlS2kSrTcU1dyl62PPU4AJUmksSpdK1eQtO/b U746k5UdmLZHoCXImvOzpPbLIW407XDx0iipnEk/ZBMGbblXqag2Odss0MSPMwZHWgyP QUpoHFTWzJlVgJ2Eoh8AG/7b8YbMQV2cGiWJVWjrR1QS2KaTYrDRcZpmmLanYxpoul3m tkzQ== X-Gm-Message-State: AOJu0YwVaEr4UnwlmdzSZ2nG+og4gl6R6+pOoXOQxXq+JROphaS3wKMM AOlUiMxUUcV9uV8Qw2x6fNg6dqgUeWgIvd6Lh9PEQQU9VNg+X6qqTlfb8ICXfw== X-Google-Smtp-Source: AGHT+IFwGslklds9lr8c1QxuX+bIJ7/vmMB9zzJ44D/A0uB+OZi/8NBit+SgfyxTYtzD00MndD/IHg== X-Received: by 2002:a17:902:eb8a:b0:1d9:11dd:1443 with SMTP id q10-20020a170902eb8a00b001d911dd1443mr2343791plg.56.1706652377271; Tue, 30 Jan 2024 14:06:17 -0800 (PST) Received: from www.outflux.net ([198.0.35.241]) by smtp.gmail.com with ESMTPSA id q2-20020a17090311c200b001d919be90fdsm1021511plh.42.2024.01.30.14.06.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 30 Jan 2024 14:06:14 -0800 (PST) From: Kees Cook To: Rasmus Villemoes Cc: Kees Cook , Mark Rutland , Justin Stitt , linux-hardening@vger.kernel.org, "Gustavo A. R. Silva" , Andrew Morton , Nathan Chancellor , Nick Desaulniers , Bill Wendling , Miguel Ojeda , Marco Elver , Jakub Kicinski , Przemek Kitszel , Masahiro Yamada , linux-kernel@vger.kernel.org, llvm@lists.linux.dev Subject: [PATCH v2 4/5] overflow: Introduce add_wrap(), sub_wrap(), and mul_wrap() Date: Tue, 30 Jan 2024 14:06:09 -0800 Message-Id: <20240130220614.1154497-4-keescook@chromium.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240130220218.it.154-kees@kernel.org> References: <20240130220218.it.154-kees@kernel.org> Precedence: bulk X-Mailing-List: linux-hardening@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=4387; i=keescook@chromium.org; h=from:subject; bh=Lsn3+N+1f8l6lRmtTSj3tYRTIPnbB1C3Ti+RJg8Mz0E=; b=owEBbQKS/ZANAwAKAYly9N/cbcAmAcsmYgBluXLSe19O6Hvhh0igqhBhzvh/k2nMh67arN8UO ViDdP3DCpCJAjMEAAEKAB0WIQSlw/aPIp3WD3I+bhOJcvTf3G3AJgUCZbly0gAKCRCJcvTf3G3A Jl6SD/949IhkriFg68ZDIGgVjR+vt3zRnyJL3kmoeJ5EwTrfegqnwpEcSBAHuYt9EE5dphltzfG Xxju7AsQMKZy9Qi7who7pbzxSfOcx7AvjfSOpZrA2QUZfIvHtsKfkwel72z3/YEFmiVslEcd0LA h/w20GBNyE/QZD5xaEUGyY74qMuxV9rzeUFzaRQZtbEBuN578gGtjt+solHfAGj878JE5tjtfCa fYizb2R+/TIJ8c5txcNgiUThUvmlpYdpAZeugD3hdi3v/tCmIX+FZcDcYU/6bvj95r2WYS0MTh3 IHO63Tg8P7ySWnC6su/nGSuHYf2+6rHo/ZEit3wIkCNOXJ5NE/iAcM1UAAEfOtGyBELr9cIMHiW TSwh4cIN51YZTYFVwEpKwMxw0qi1pT7D70pgJRnDyA3VEwT09RzE5AyIfmJt0LSixzpdMyr2ro4 TuevDNqjiIZSSIe6jduIvJmt5AHiHl11YTXK92CQrWvCcGUXwEPVyCKiFxL1Sz8EjAmvEbQigE0 hIwsJEG09BwJNh6CaSQVMi+73ihg21dBrOyFNkNzrtlnWRf4UkoPTtg6yohpWwxhQTh2hhRRrFp KQ7zqDMuA13212l6WJ7ogVbceJxQ4taZI0ZiW2ogyZFE1oij+Dv94p0qVlwdVW8oVZQ1lxdl7wu Wnpi70NpXkvuPUQ== X-Developer-Key: i=keescook@chromium.org; a=openpgp; fpr=A5C3F68F229DD60F723E6E138972F4DFDC6DC026 Provide helpers that will perform wrapping addition, subtraction, or multiplication without tripping the arithmetic wrap-around sanitizers. The first argument is the type under which the wrap-around should happen with. In other words, these two calls will get very different results: mul_wrap(int, 50, 50) == 2500 mul_wrap(u8, 50, 50) == 196 Add to the selftests to validate behavior and lack of side-effects. Cc: Rasmus Villemoes Cc: Mark Rutland Cc: Justin Stitt Cc: linux-hardening@vger.kernel.org Signed-off-by: Kees Cook --- include/linux/overflow.h | 54 ++++++++++++++++++++++++++++++++++++++++ lib/overflow_kunit.c | 11 ++++++++ 2 files changed, 65 insertions(+) diff --git a/include/linux/overflow.h b/include/linux/overflow.h index 3c46c648d2e8..c9139f88578b 100644 --- a/include/linux/overflow.h +++ b/include/linux/overflow.h @@ -120,6 +120,24 @@ static inline bool __must_check __must_check_overflow(bool overflow) check_add_overflow(var, offset, &__result); \ })) +/** + * add_wrap() - Intentionally perform a wrapping addition + * @type: type for result of calculation + * @a: first addend + * @b: second addend + * + * Return the potentially wrapped-around addition without + * tripping any wrap-around sanitizers that may be enabled. + */ +#define add_wrap(type, a, b) \ + ({ \ + type __val; \ + if (check_add_overflow(a, b, &__val)) { \ + /* do nothing */ \ + } \ + __val; \ + }) + /** * check_sub_overflow() - Calculate subtraction with overflow checking * @a: minuend; value to subtract from @@ -133,6 +151,24 @@ static inline bool __must_check __must_check_overflow(bool overflow) #define check_sub_overflow(a, b, d) \ __must_check_overflow(__builtin_sub_overflow(a, b, d)) +/** + * sub_wrap() - Intentionally perform a wrapping subtraction + * @type: type for result of calculation + * @a: minuend; value to subtract from + * @b: subtrahend; value to subtract from @a + * + * Return the potentially wrapped-around subtraction without + * tripping any wrap-around sanitizers that may be enabled. + */ +#define sub_wrap(type, a, b) \ + ({ \ + type __val; \ + if (check_sub_overflow(a, b, &__val)) { \ + /* do nothing */ \ + } \ + __val; \ + }) + /** * check_mul_overflow() - Calculate multiplication with overflow checking * @a: first factor @@ -146,6 +182,24 @@ static inline bool __must_check __must_check_overflow(bool overflow) #define check_mul_overflow(a, b, d) \ __must_check_overflow(__builtin_mul_overflow(a, b, d)) +/** + * mul_wrap() - Intentionally perform a wrapping multiplication + * @type: type for result of calculation + * @a: first factor + * @b: second factor + * + * Return the potentially wrapped-around multiplication without + * tripping any wrap-around sanitizers that may be enabled. + */ +#define mul_wrap(type, a, b) \ + ({ \ + type __val; \ + if (check_mul_overflow(a, b, &__val)) { \ + /* do nothing */ \ + } \ + __val; \ + }) + /** * check_shl_overflow() - Calculate a left-shifted value and check overflow * @a: Value to be shifted diff --git a/lib/overflow_kunit.c b/lib/overflow_kunit.c index 2d106e880956..319f950872bd 100644 --- a/lib/overflow_kunit.c +++ b/lib/overflow_kunit.c @@ -273,6 +273,17 @@ DEFINE_TEST_ARRAY(s64) = { /* Check for internal macro side-effects. */ \ _of = check_ ## op ## _overflow(_a_orig++, _b_orig++, &_r); \ KUNIT_EXPECT_TRUE_MSG(test, _a_orig == _a_bump, "Unexpected " #op " macro side-effect!\n"); \ + KUNIT_EXPECT_TRUE_MSG(test, _b_orig == _b_bump, "Unexpected " #op " macro side-effect!\n"); \ + \ + _r = op ## _wrap(t, a, b); \ + KUNIT_EXPECT_TRUE_MSG(test, _r == r, \ + "expected "fmt" "sym" "fmt" == "fmt", got "fmt" (type %s)\n", \ + a, b, r, _r, #t); \ + /* Check for internal macro side-effects. */ \ + _a_orig = a; \ + _b_orig = b; \ + _r = op ## _wrap(t, _a_orig++, _b_orig++); \ + KUNIT_EXPECT_TRUE_MSG(test, _a_orig == _a_bump, "Unexpected " #op " macro side-effect!\n"); \ KUNIT_EXPECT_TRUE_MSG(test, _b_orig == _b_bump, "Unexpected " #op " macro side-effect!\n"); \ } while (0) From patchwork Tue Jan 30 22:06:10 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 13538186 Received: from mail-pl1-f177.google.com (mail-pl1-f177.google.com [209.85.214.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6AAE87866D for ; Tue, 30 Jan 2024 22:06:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.177 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706652381; cv=none; b=OdChUWA01MIFpS83iOisfyWbnHetV4C1S7EmnlnIVfg/fKi2oVv2FAD6tyu0Hfantwr/hLTsQeXS6hymIy4QbH2D5TDiQ+1n6+A5Egzb4M/9EKLz8W2JHRQvvJfwLTa29LbHBdH3gg3QFG8v8lYS9KLsfJ8DTBSKvzLXcxRZ+YM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706652381; c=relaxed/simple; bh=yC6D2Eizr2psrnwwA4qhvvtdQ0LcAEcPaifv0qco7Dk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=qA/59Db3DWJFE+q6r9WRZ/1fU0g6ZELrwBZV1vU03J7MfuSe7fjsuGNYOt40zuqhFIO0Ueh26N076OHhCOYAyGv1hJmCjWY28Kj/XvbGaN58dMIOOhyjzmeJLDItuH/nEExE0kIrF78UpVGPpd0ut86ar82r/1s0eGjVYservFw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=kKoYfoDG; arc=none smtp.client-ip=209.85.214.177 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="kKoYfoDG" Received: by mail-pl1-f177.google.com with SMTP id d9443c01a7336-1d8cea8bb3bso14860295ad.2 for ; Tue, 30 Jan 2024 14:06:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1706652378; x=1707257178; darn=vger.kernel.org; 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=lzQ7vFiYMTeVrAkzHMhY9QBXLQuQnHe/ph5NFW0GaXM=; b=kKoYfoDGuo1eyJQI8tlxF5tWUavzuAix9okxF0CE3AmOMgAT0GbU6k7PXMRDVL2RBj 0nnfeIfH6FgI8w6mpGioJEZDJ7e2uDkS/hXnvmoova2q1NqZ37JTWT3KYv9u7q/w1tds SuO/C2Anwepo5f248ibnFX5Dr/Wyi7ii8uUoQ= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706652378; x=1707257178; 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=lzQ7vFiYMTeVrAkzHMhY9QBXLQuQnHe/ph5NFW0GaXM=; b=rLsYbxLSneSiuQMDnXxEHBqBj1dgsbn0JzNTXsJUYtkVdTiTDrc6Id68s125DjLe9l 4EITfhqLY+45Yr3nWjH8++22HsLqXbnA0oSuelVPg16QDJzV9GUKYijbgieKv+luKme5 hM9QkQFuDfcbvpkUjmY1HYYWsq7aOBqDCKjwGjzqCXCsM5RpGa36dvwT2QKgC7/f5Mpo CJTkNOMpghpoM5Y6MYdnQAmx+lvcqQnS5P2AFnJxZDoIWIq5bjXADqCWbmoKcy7n6Tfl 1gmmZnYvj9g1eZlH7tlzYe3TISTaQRNRrj2vV/rf+8stEFBebzn5oXjW9YjH/YSNNRcY sKLA== X-Gm-Message-State: AOJu0YxqcYmgi4MvaAgHw6Qx0L3/s5txrRObJWufeTVi+NQFNGoe/X5P YCugXi7CBch/J5me7aCrqamLDp0deWA87UDax9D5GuewXAgcesBptCiOx8Wp7Q== X-Google-Smtp-Source: AGHT+IGzZlwU0MXV/5cSAxoNXH1SzaePvovUzfEFE1ulJPkFuOUHeABKKMVSmpksGBNhLRfKJuTKZw== X-Received: by 2002:a17:902:64c8:b0:1d7:75a0:3c86 with SMTP id y8-20020a17090264c800b001d775a03c86mr775656pli.66.1706652378708; Tue, 30 Jan 2024 14:06:18 -0800 (PST) Received: from www.outflux.net ([198.0.35.241]) by smtp.gmail.com with ESMTPSA id q6-20020a170902b10600b001d706912d1esm7690514plr.225.2024.01.30.14.06.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 30 Jan 2024 14:06:17 -0800 (PST) From: Kees Cook To: Rasmus Villemoes Cc: Kees Cook , Mark Rutland , "Gustavo A. R. Silva" , Justin Stitt , linux-hardening@vger.kernel.org, Andrew Morton , Nathan Chancellor , Nick Desaulniers , Bill Wendling , Miguel Ojeda , Marco Elver , Jakub Kicinski , Przemek Kitszel , Masahiro Yamada , linux-kernel@vger.kernel.org, llvm@lists.linux.dev Subject: [PATCH v2 5/5] overflow: Introduce inc_wrap() and dec_wrap() Date: Tue, 30 Jan 2024 14:06:10 -0800 Message-Id: <20240130220614.1154497-5-keescook@chromium.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240130220218.it.154-kees@kernel.org> References: <20240130220218.it.154-kees@kernel.org> Precedence: bulk X-Mailing-List: linux-hardening@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=6254; i=keescook@chromium.org; h=from:subject; bh=yC6D2Eizr2psrnwwA4qhvvtdQ0LcAEcPaifv0qco7Dk=; b=owEBbQKS/ZANAwAKAYly9N/cbcAmAcsmYgBluXLS0ATCJtp/qR8GBQF2YJ6xD8OeGPPuokIWa WIkyhk7RLiJAjMEAAEKAB0WIQSlw/aPIp3WD3I+bhOJcvTf3G3AJgUCZbly0gAKCRCJcvTf3G3A Ju4sD/wPbmqbSBI0CmdEMVroSWLFzHvcrcDEKt92REO7h0y2x+p8Ca4j2Q+roGDd5raGg96jqha uUUIej0AkmF/snly5wLNBli+Db3jFjRA67sUQ6Bmk/sIWkKhsuI7LOn2qeUgzQNM3C8bUI8mjUs zriVdFG4FNDe6j2zCPIRciZpUbEKXiKYYAcXb4o38CipVxVmx9v8QuKTEV1Ep4V+jaepOvqbASc vWXwsS9d5vqwMRqcAkwr1/71PtmuWO/NlR/Bmcyf16r1TCVqaZX6+zDQg1hgI7f9ay/8JfPBpdz YEYFRKHlDEuHhvLH4wM3SbW4iN3AA5puuVJlak08kvigQ4kSsbZyEXYa3j5W8ol+PbC//WM9jYj d+6LkAbhQQJUyDuNjbhhBrz/pmAyeUNzMJPQCauRBVmprN7o0utPp5qFmoUBARR75kUQ2arbLL6 KrxysxBajTAF5gaWUtUYh5VYo4Ol1kYosQituWY9U5BodZvdefIPURNMJ81Kh9a9NXocoGsz9JV V6gFF9OuqhwF82rRcxCel2l13GrNj3Gl87FMQRv8T33XXWEGcP/OTtkfrOeTH8yRhlxuKcIPBOi 9cCVQhUhqdjZvceD+FzJ8l9ctO9Ytv7SNTkscbfHleVQhI0i33YRSpN+Bnuxi464yuHHqFTkcNw e51m/Es65BQzHOw== X-Developer-Key: i=keescook@chromium.org; a=openpgp; fpr=A5C3F68F229DD60F723E6E138972F4DFDC6DC026 This allows replacements of the idioms "var += offset" and "var -= offset" with the inc_wrap() and dec_wrap() helpers respectively. They will avoid wrap-around sanitizer instrumentation. Add to the selftests to validate behavior and lack of side-effects. Cc: Rasmus Villemoes Cc: Mark Rutland Cc: "Gustavo A. R. Silva" Cc: Justin Stitt Cc: linux-hardening@vger.kernel.org Signed-off-by: Kees Cook --- include/linux/overflow.h | 28 +++++++++++++++++++++ lib/overflow_kunit.c | 54 ++++++++++++++++++++++++++++++++++------ 2 files changed, 75 insertions(+), 7 deletions(-) diff --git a/include/linux/overflow.h b/include/linux/overflow.h index c9139f88578b..075c30218145 100644 --- a/include/linux/overflow.h +++ b/include/linux/overflow.h @@ -138,6 +138,20 @@ static inline bool __must_check __must_check_overflow(bool overflow) __val; \ }) +/** + * inc_wrap() - Intentionally perform a wrapping increment + * @a: variable to be incremented + * @b: amount to add + * + * Increments @a by @b with wrap-around. Returns the resulting + * value of @a. Will not trip any wrap-around sanitizers. + */ +#define inc_wrap(var, offset) \ + ({ \ + typeof(var) *__ptr = &(var); \ + *__ptr = add_wrap(typeof(var), *__ptr, offset); \ + }) + /** * check_sub_overflow() - Calculate subtraction with overflow checking * @a: minuend; value to subtract from @@ -169,6 +183,20 @@ static inline bool __must_check __must_check_overflow(bool overflow) __val; \ }) +/** + * dec_wrap() - Intentionally perform a wrapping decrement + * @a: variable to be decremented + * @b: amount to subtract + * + * Decrements @a by @b with wrap-around. Returns the resulting + * value of @a. Will not trip any wrap-around sanitizers. + */ +#define dec_wrap(var, offset) \ + ({ \ + typeof(var) *__ptr = &(var); \ + *__ptr = sub_wrap(typeof(var), *__ptr, offset); \ + }) + /** * check_mul_overflow() - Calculate multiplication with overflow checking * @a: first factor diff --git a/lib/overflow_kunit.c b/lib/overflow_kunit.c index 319f950872bd..46af7ccde0c6 100644 --- a/lib/overflow_kunit.c +++ b/lib/overflow_kunit.c @@ -265,36 +265,76 @@ DEFINE_TEST_ARRAY(s64) = { \ _of = check_ ## op ## _overflow(a, b, &_r); \ KUNIT_EXPECT_EQ_MSG(test, _of, of, \ - "expected "fmt" "sym" "fmt" to%s overflow (type %s)\n", \ + "expected check "fmt" "sym" "fmt" to%s overflow (type %s)\n", \ a, b, of ? "" : " not", #t); \ KUNIT_EXPECT_TRUE_MSG(test, _r == r, \ - "expected "fmt" "sym" "fmt" == "fmt", got "fmt" (type %s)\n", \ + "expected check "fmt" "sym" "fmt" == "fmt", got "fmt" (type %s)\n", \ a, b, r, _r, #t); \ /* Check for internal macro side-effects. */ \ _of = check_ ## op ## _overflow(_a_orig++, _b_orig++, &_r); \ - KUNIT_EXPECT_TRUE_MSG(test, _a_orig == _a_bump, "Unexpected " #op " macro side-effect!\n"); \ - KUNIT_EXPECT_TRUE_MSG(test, _b_orig == _b_bump, "Unexpected " #op " macro side-effect!\n"); \ + KUNIT_EXPECT_TRUE_MSG(test, _a_orig == _a_bump, "Unexpected check " #op " macro side-effect!\n"); \ + KUNIT_EXPECT_TRUE_MSG(test, _b_orig == _b_bump, "Unexpected check " #op " macro side-effect!\n"); \ \ _r = op ## _wrap(t, a, b); \ KUNIT_EXPECT_TRUE_MSG(test, _r == r, \ - "expected "fmt" "sym" "fmt" == "fmt", got "fmt" (type %s)\n", \ + "expected wrap "fmt" "sym" "fmt" == "fmt", got "fmt" (type %s)\n", \ a, b, r, _r, #t); \ /* Check for internal macro side-effects. */ \ _a_orig = a; \ _b_orig = b; \ _r = op ## _wrap(t, _a_orig++, _b_orig++); \ - KUNIT_EXPECT_TRUE_MSG(test, _a_orig == _a_bump, "Unexpected " #op " macro side-effect!\n"); \ - KUNIT_EXPECT_TRUE_MSG(test, _b_orig == _b_bump, "Unexpected " #op " macro side-effect!\n"); \ + KUNIT_EXPECT_TRUE_MSG(test, _a_orig == _a_bump, "Unexpected wrap " #op " macro side-effect!\n"); \ + KUNIT_EXPECT_TRUE_MSG(test, _b_orig == _b_bump, "Unexpected wrap " #op " macro side-effect!\n"); \ +} while (0) + +static int global_counter; +static void bump_counter(void) { + global_counter ++; +} + +static int get_index(void) { + volatile int index = 0; + bump_counter(); + return index; +} + +#define check_self_op(fmt, op, sym, a, b) do { \ + typeof(a + 0) _a = a; \ + typeof(b + 0) _b = b; \ + typeof(a + 0) _a_sym = a; \ + typeof(a + 0) _a_orig[1] = { a }; \ + typeof(b + 0) _b_orig = b; \ + typeof(b + 0) _b_bump = b + 1; \ + typeof(a + 0) _r; \ + \ + _a_sym sym _b; \ + _r = op ## _wrap(_a, _b); \ + KUNIT_EXPECT_TRUE_MSG(test, _r == _a_sym, \ + "expected "fmt" "#op" "fmt" == "fmt", got "fmt"\n", \ + a, b, _a_sym, _r); \ + KUNIT_EXPECT_TRUE_MSG(test, _a == _a_sym, \ + "expected "fmt" "#op" "fmt" == "fmt", got "fmt"\n", \ + a, b, _a_sym, _a); \ + /* Check for internal macro side-effects. */ \ + global_counter = 0; \ + op ## _wrap(_a_orig[get_index()], _b_orig++); \ + KUNIT_EXPECT_EQ_MSG(test, global_counter, 1, "Unexpected " #op "_wrap() macro side-effect on arg1!\n"); \ + KUNIT_EXPECT_TRUE_MSG(test, _b_orig == _b_bump, "Unexpected " #op "_wrap() macro side-effect on arg2!\n"); \ } while (0) #define DEFINE_TEST_FUNC_TYPED(n, t, fmt) \ static void do_test_ ## n(struct kunit *test, const struct test_ ## n *p) \ { \ + /* check_{add,sub,mul}_overflow() and {add,sub,mul}_wrap() */ \ check_one_op(t, fmt, add, "+", p->a, p->b, p->sum, p->s_of); \ check_one_op(t, fmt, add, "+", p->b, p->a, p->sum, p->s_of); \ check_one_op(t, fmt, sub, "-", p->a, p->b, p->diff, p->d_of); \ check_one_op(t, fmt, mul, "*", p->a, p->b, p->prod, p->p_of); \ check_one_op(t, fmt, mul, "*", p->b, p->a, p->prod, p->p_of); \ + /* {inc,dec}_wrap() */ \ + check_self_op(fmt, inc, +=, p->a, p->b); \ + check_self_op(fmt, inc, +=, p->b, p->a); \ + check_self_op(fmt, dec, -=, p->a, p->b); \ } \ \ static void n ## _overflow_test(struct kunit *test) { \