From nobody Thu Oct 2 14:13:37 2025 Received: from mail-pf1-f201.google.com (mail-pf1-f201.google.com [209.85.210.201]) (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 56D99277C96 for ; Mon, 15 Sep 2025 19:19:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757963993; cv=none; b=noDaiSEPL8o8UEDjwGHSF0L2ZwRVPxaPIviGkrQtEJ3DZ4HSFN3kSNCHpt5PlyJ7nxgf1xk+PEGIW2KysdcRo6AjaRLyW8OzrVeQ7uOXVGZ9C47vlLXtYmnxpfWeeYfsD3VHZuaMpf0g59pLNul0bITvbUC6Oe1+qJ41bHpqscE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757963993; c=relaxed/simple; bh=go8QQIZyPGUp4PkxMDF6s9CZk99i9v2/qqZF6ke4mtg=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=GOsMXwbhHmRvKZw3uxAFpRzPgqBhlGS1WELnXKyigC5IeDRzsrQOHy6lVrJd/UEHD8sqk+C7kpnMf+Sgns2AVV1AXpwPN8NWaaOE10dBj8M57gcWzI9xpVwHt8/T0luoNc6dNwhoopA0loSz3CpjSI483P1OH/5XaZQblFJCYrI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--wakel.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=IlUgY25b; arc=none smtp.client-ip=209.85.210.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--wakel.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="IlUgY25b" Received: by mail-pf1-f201.google.com with SMTP id d2e1a72fcca58-76e2ea9366aso4334098b3a.2 for ; Mon, 15 Sep 2025 12:19:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1757963992; x=1758568792; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=lWO+pKXM4jrMlLY6TR5WyVhXPvUt8x12rN7+iA06M7s=; b=IlUgY25bSXYl0TmXg3EslR3D/UJirm/WceA/vm24nBsNDy3BZKeX8VZi//H7uhtoCn 220UeDlpPnofUHTx3gqQf3qZPKnM9MLlwl/+P9qUyJK4wivVT+AlnIjbJvXpsLqfU0Ce BqJ2Dk0sNUx7eVYCwg3VJd0EOrKQjtPDsMv6GvjPGud8pYxkiQ+4/B5r5e13C4wGzEb1 Ipdohf6+rmHAOu32eaYRpNvZJtXHQesrSrBBrgZsbj2x6aBWXhuE0lCxiZsKs0KLKnk/ pvurYLVtGfaRUHCdfhw95HW4SfPlysUi8uw1Iwdl1J9nA8KnXuwoUHv+QAq5rP9+0YpP F+Ow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1757963992; x=1758568792; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=lWO+pKXM4jrMlLY6TR5WyVhXPvUt8x12rN7+iA06M7s=; b=MyZnpn7P6mH6KN/svcZugwOsOvNLs63viychoQbv2podNGm7SlB56RIk65VWUqmh5/ KCXtjVT2tbrQNtIRYpx+Zx1aMw9bpRiLYmBBa35jw20yUumXPhqNzapMNL4JFnKZiy/g jn/n84GvONygJf0u+7ghEnChCebOin3JmMlc6AJV6bxb/90eac6aQr5YhxJPRQNsv2c7 Kvn2abU1JHqdV3pPtxNmVVvYPIiX8YMVNVLHgn63GrptJ/FOjxJ3U3NcqulS5VlAhNd6 t7Vo3QKjinQSFLZf0w59rCc+FEz4gdpA3SffIdnDnCm8ZOwdTxKR2Smkz3bEvl5Z2R2C IzIg== X-Forwarded-Encrypted: i=1; AJvYcCVR6pLPpl51jH93t14G+uUDLzPg7/ssMBMGt1shAkWRtjfhk9yBZHR/XiUL97srSJD7hNju4E1SKkuofaQ=@vger.kernel.org X-Gm-Message-State: AOJu0YyOmiqn1rE6fFSDWJ7drvRONG7foe3GJnGyofOC0x8KToIm6rmY Kv3JDXMMDi6RgdpPyZoi//ArDAC++Mg/9js4sk+0M2SeWtgXEGID30d33GjNYMG4iq51LmGuF5M +Ng== X-Google-Smtp-Source: AGHT+IHrAcKdifdBfvzg9iFv/i/1R3Icgb5FYVy4tL4b6A+2MkyfkLlRYL5Zu2ouqTtRPch9AwbMRhNFkQ== X-Received: from pffn25.prod.google.com ([2002:a62:e519:0:b0:772:5ec0:9124]) (user=wakel job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a00:2383:b0:772:4d52:ce5a with SMTP id d2e1a72fcca58-7761219409cmr15606700b3a.26.1757963991502; Mon, 15 Sep 2025 12:19:51 -0700 (PDT) Date: Tue, 16 Sep 2025 03:19:44 +0800 In-Reply-To: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: X-Mailer: git-send-email 2.51.0.384.g4c02a37b29-goog Message-ID: <20250915191944.9779-1-wakel@google.com> Subject: [PATCH v2] selftests/timers: Consolidate and fix 32-bit overflow in timespec_sub From: Wake Liu To: Anna-Maria Behnsen , Frederic Weisbecker , Thomas Gleixner , John Stultz , Shuah Khan , linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Cc: Stephen Boyd , wakel@google.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The timespec_sub function, as implemented in several timer selftests, is prone to integer overflow on 32-bit systems. The calculation `NSEC_PER_SEC * b.tv_sec` is performed using 32-bit arithmetic, and the result overflows before being stored in the 64-bit `ret` variable. This leads to incorrect time delta calculations and test failures. As suggested by tglx, this patch fixes the issue by: 1. Creating a new `static inline` helper function, `timespec_to_ns`, which safely converts a `timespec` to nanoseconds by casting `tv_sec` to `long long` before multiplying with `NSEC_PER_SEC`. 2. Placing the new helper and a rewritten `timespec_sub` into a common header: tools/testing/selftests/timers/helpers.h. 3. Removing the duplicated, buggy implementations from all timer selftests and replacing them with an #include of the new header. This consolidates the code and ensures the calculation is correctly performed using 64-bit arithmetic across all tests. Changes in v2: - Per tglx's feedback, instead of changing NSEC_PER_SEC globally, this version consolidates the buggy timespec_sub() implementations into a new 32-bit safe inline function in a shared header. - Amended the commit message to be more descriptive. --- .../selftests/timers/alarmtimer-suspend.c | 15 +++------ tools/testing/selftests/timers/helpers.h | 31 +++++++++++++++++++ tools/testing/selftests/timers/nanosleep.c | 2 +- tools/testing/selftests/timers/nsleep-lat.c | 12 ++----- .../testing/selftests/timers/valid-adjtimex.c | 8 ++--- 5 files changed, 43 insertions(+), 25 deletions(-) create mode 100644 tools/testing/selftests/timers/helpers.h diff --git a/tools/testing/selftests/timers/alarmtimer-suspend.c b/tools/te= sting/selftests/timers/alarmtimer-suspend.c index a9ef76ea6051..e85ab182abe5 100644 --- a/tools/testing/selftests/timers/alarmtimer-suspend.c +++ b/tools/testing/selftests/timers/alarmtimer-suspend.c @@ -31,8 +31,9 @@ #include #include #include "../kselftest.h" +#include "helpers.h" =20 -#define UNREASONABLE_LAT (NSEC_PER_SEC * 5) /* hopefully we resume in 5 se= cs */ +#define UNREASONABLE_LAT (NSEC_PER_SEC * 5LL) /* hopefully we resume in 5 = secs */ =20 #define SUSPEND_SECS 15 int alarmcount; @@ -70,14 +71,6 @@ char *clockstring(int clockid) } =20 =20 -long long timespec_sub(struct timespec a, struct timespec b) -{ - long long ret =3D NSEC_PER_SEC * b.tv_sec + b.tv_nsec; - - ret -=3D NSEC_PER_SEC * a.tv_sec + a.tv_nsec; - return ret; -} - int final_ret; =20 void sigalarm(int signo) @@ -88,8 +81,8 @@ void sigalarm(int signo) clock_gettime(alarm_clock_id, &ts); alarmcount++; =20 - delta_ns =3D timespec_sub(start_time, ts); - delta_ns -=3D NSEC_PER_SEC * SUSPEND_SECS * alarmcount; + delta_ns =3D timespec_sub(ts, start_time); + delta_ns -=3D (long long)NSEC_PER_SEC * SUSPEND_SECS * alarmcount; =20 printf("ALARM(%i): %ld:%ld latency: %lld ns ", alarmcount, ts.tv_sec, ts.tv_nsec, delta_ns); diff --git a/tools/testing/selftests/timers/helpers.h b/tools/testing/selft= ests/timers/helpers.h new file mode 100644 index 000000000000..652f20247091 --- /dev/null +++ b/tools/testing/selftests/timers/helpers.h @@ -0,0 +1,31 @@ +#ifndef SELFTESTS_TIMERS_HELPERS_H +#define SELFTESTS_TIMERS_HELPERS_H + +#include + +#ifndef NSEC_PER_SEC +#define NSEC_PER_SEC 1000000000L +#endif + +/* + * timespec_to_ns - Convert timespec to nanoseconds + */ +static inline long long timespec_to_ns(const struct timespec *ts) +{ + return ((long long) ts->tv_sec * NSEC_PER_SEC) + ts->tv_nsec; +} + +/* + * timespec_sub - Subtract two timespec values + * + * @a: first timespec + * @b: second timespec + * + * Returns a - b in nanoseconds. + */ +static inline long long timespec_sub(struct timespec a, struct timespec b) +{ + return timespec_to_ns(&a) - timespec_to_ns(&b); +} + +#endif /* SELFTESTS_TIMERS_HELPERS_H */ diff --git a/tools/testing/selftests/timers/nanosleep.c b/tools/testing/sel= ftests/timers/nanosleep.c index 252c6308c569..41c33629d5f0 100644 --- a/tools/testing/selftests/timers/nanosleep.c +++ b/tools/testing/selftests/timers/nanosleep.c @@ -138,7 +138,7 @@ int main(int argc, char **argv) fflush(stdout); =20 length =3D 10; - while (length <=3D (NSEC_PER_SEC * 10)) { + while (length <=3D (NSEC_PER_SEC * 10LL)) { ret =3D nanosleep_test(clockid, length); if (ret =3D=3D UNSUPPORTED) { ksft_test_result_skip("%-31s\n", clockstring(clockid)); diff --git a/tools/testing/selftests/timers/nsleep-lat.c b/tools/testing/se= lftests/timers/nsleep-lat.c index de23dc0c9f97..c888a77aab7a 100644 --- a/tools/testing/selftests/timers/nsleep-lat.c +++ b/tools/testing/selftests/timers/nsleep-lat.c @@ -26,6 +26,7 @@ #include #include #include "../kselftest.h" +#include "helpers.h" =20 #define UNRESONABLE_LATENCY 40000000 /* 40ms in nanosecs */ =20 @@ -74,14 +75,6 @@ struct timespec timespec_add(struct timespec ts, unsigne= d long long ns) } =20 =20 -long long timespec_sub(struct timespec a, struct timespec b) -{ - long long ret =3D NSEC_PER_SEC * b.tv_sec + b.tv_nsec; - - ret -=3D NSEC_PER_SEC * a.tv_sec + a.tv_nsec; - return ret; -} - int nanosleep_lat_test(int clockid, long long ns) { struct timespec start, end, target; @@ -146,7 +139,7 @@ int main(int argc, char **argv) continue; =20 length =3D 10; - while (length <=3D (NSEC_PER_SEC * 10)) { + while (length <=3D (NSEC_PER_SEC * 10LL)) { ret =3D nanosleep_lat_test(clockid, length); if (ret) break; @@ -164,3 +157,4 @@ int main(int argc, char **argv) =20 ksft_finished(); } + diff --git a/tools/testing/selftests/timers/valid-adjtimex.c b/tools/testin= g/selftests/timers/valid-adjtimex.c index 6b7801055ad1..a61d4b4739a2 100644 --- a/tools/testing/selftests/timers/valid-adjtimex.c +++ b/tools/testing/selftests/timers/valid-adjtimex.c @@ -260,16 +260,16 @@ int validate_set_offset(void) if (set_offset(-NSEC_PER_SEC - 1, 1)) return -1; =20 - if (set_offset(5 * NSEC_PER_SEC, 1)) + if (set_offset(5LL * NSEC_PER_SEC, 1)) return -1; =20 - if (set_offset(-5 * NSEC_PER_SEC, 1)) + if (set_offset(-5LL * NSEC_PER_SEC, 1)) return -1; =20 - if (set_offset(5 * NSEC_PER_SEC + NSEC_PER_SEC / 2, 1)) + if (set_offset(5LL * NSEC_PER_SEC + NSEC_PER_SEC / 2, 1)) return -1; =20 - if (set_offset(-5 * NSEC_PER_SEC - NSEC_PER_SEC / 2, 1)) + if (set_offset(-5LL * NSEC_PER_SEC - NSEC_PER_SEC / 2, 1)) return -1; =20 if (set_offset(USEC_PER_SEC - 1, 0)) --=20 2.51.0.384.g4c02a37b29-goog