diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-10-23 09:27:26 -1000 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-10-23 09:27:26 -1000 |
| commit | 88442d9f0d6084cb986cd9d635efc7744199e3fe (patch) | |
| tree | 27b8f1f0f73674fc96dcc2edf87f1dc82d41cdf2 /kernel | |
| parent | 2ee2475e15b4ff8fda89a9edcb77dfd871de1386 (diff) | |
| parent | bd3cc16d1d7d584911f856adc458f242b1c7e85f (diff) | |
Merge tag 'kcsan-20261020-v7.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/melver/linux
Pull KCSAN updates from Marco Elver:
- Avoid division by zero in kcsan_prandom_u32_max()
- test: Do not count report printing time against test duration
* tag 'kcsan-20261020-v7.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/melver/linux:
kcsan: test: Do not count report printing time against test duration
kcsan: Avoid division by zero in kcsan_prandom_u32_max()
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/kcsan/core.c | 7 | ||||
| -rw-r--r-- | kernel/kcsan/kcsan_test.c | 34 |
2 files changed, 37 insertions, 4 deletions
diff --git a/kernel/kcsan/core.c b/kernel/kcsan/core.c index 2db82661cd60..a3aa5e5b039d 100644 --- a/kernel/kcsan/core.c +++ b/kernel/kcsan/core.c @@ -290,8 +290,9 @@ should_watch(struct kcsan_ctx *ctx, const volatile void *ptr, size_t size, int t } /* - * Returns a pseudo-random number in interval [0, ep_ro). Simple linear - * congruential generator, using constants from "Numerical Recipes". + * Returns a pseudo-random number in interval [0, ep_ro), or 0 if ep_ro is 0, + * which the runtime-tunable callers may pass. Simple linear congruential + * generator, using constants from "Numerical Recipes". */ static u32 kcsan_prandom_u32_max(u32 ep_ro) { @@ -300,7 +301,7 @@ static u32 kcsan_prandom_u32_max(u32 ep_ro) state = 1664525 * state + 1013904223; this_cpu_write(kcsan_rand_state, state); - return state % ep_ro; + return reciprocal_scale(state, ep_ro); } static inline void reset_kcsan_skip(void) diff --git a/kernel/kcsan/kcsan_test.c b/kernel/kcsan/kcsan_test.c index ae758150ccb9..760686e130ad 100644 --- a/kernel/kcsan/kcsan_test.c +++ b/kernel/kcsan/kcsan_test.c @@ -48,6 +48,9 @@ static void (*access_kernels[2])(void); static struct task_struct **threads; /* Lists of threads. */ static unsigned long end_time; /* End time of test. */ +static unsigned long end_time_max; /* Upper bound for end time of test. */ +static unsigned long report_budget; /* Time left when report printing began. */ +static bool report_paused; /* Paused while a report is printing. */ /* Report as observed from console. */ static struct { @@ -69,17 +72,46 @@ begin_test_checks(void (*func1)(void), void (*func2)(void)) * least one race is reported. */ end_time = jiffies + msecs_to_jiffies(CONFIG_KCSAN_REPORT_ONCE_IN_MS + 500); + end_time_max = end_time + msecs_to_jiffies(10000); + report_paused = false; /* Signal start; release potential initialization of shared data. */ smp_store_release(&access_kernels[0], func1); smp_store_release(&access_kernels[1], func2); } +/* + * Printing a report may take a while, e.g. if a printk emergency section (such + * as with CONFIG_KCSAN_VERBOSE) flushes a console backlog synchronously. Do not + * count the time a test-related report is being printed against the test's + * time budget, so that a slow report is neither missed, nor prevents observing + * other reports. Returns true if checking must continue. + */ +static __no_kcsan bool pause_for_report(void) +{ + const int nlines = READ_ONCE(observed.nlines); + const bool in_progress = nlines == 1 || nlines == 2; + + if (in_progress && !report_paused) { + report_paused = true; + report_budget = time_before(jiffies, end_time) ? end_time - jiffies : 0; + } else if (!in_progress && report_paused) { + report_paused = false; + end_time = jiffies + report_budget; + if (time_after(end_time, end_time_max)) + end_time = end_time_max; + /* Check the now complete report at least once. */ + return true; + } + + return report_paused && time_before(jiffies, end_time_max); +} + /* End test checking loop. */ static __no_kcsan inline bool end_test_checks(bool stop) { - if (!stop && time_before(jiffies, end_time)) { + if (!stop && (pause_for_report() || time_before(jiffies, end_time))) { /* Continue checking */ might_sleep(); return false; |
