*/
 static DEFINE_PER_CPU(long, kcsan_skip);
 
+/* For kcsan_prandom_u32_max(). */
+static DEFINE_PER_CPU(struct rnd_state, kcsan_rand_state);
+
 static __always_inline atomic_long_t *find_watchpoint(unsigned long addr,
                                                      size_t size,
                                                      bool expect_write,
        return true;
 }
 
+/*
+ * Returns a pseudo-random number in interval [0, ep_ro). See prandom_u32_max()
+ * for more details.
+ *
+ * The open-coded version here is using only safe primitives for all contexts
+ * where we can have KCSAN instrumentation. In particular, we cannot use
+ * prandom_u32() directly, as its tracepoint could cause recursion.
+ */
+static u32 kcsan_prandom_u32_max(u32 ep_ro)
+{
+       struct rnd_state *state = &get_cpu_var(kcsan_rand_state);
+       const u32 res = prandom_u32_state(state);
+
+       put_cpu_var(kcsan_rand_state);
+       return (u32)(((u64) res * ep_ro) >> 32);
+}
+
 static inline void reset_kcsan_skip(void)
 {
        long skip_count = kcsan_skip_watch -
                          (IS_ENABLED(CONFIG_KCSAN_SKIP_WATCH_RANDOMIZE) ?
-                                  prandom_u32_max(kcsan_skip_watch) :
+                                  kcsan_prandom_u32_max(kcsan_skip_watch) :
                                   0);
        this_cpu_write(kcsan_skip, skip_count);
 }
        return READ_ONCE(kcsan_enabled) && get_ctx()->disable_count == 0;
 }
 
-static inline unsigned int get_delay(int type)
+/* Introduce delay depending on context and configuration. */
+static void delay_access(int type)
 {
        unsigned int delay = in_task() ? kcsan_udelay_task : kcsan_udelay_interrupt;
        /* For certain access types, skew the random delay to be longer. */
        unsigned int skew_delay_order =
                (type & (KCSAN_ACCESS_COMPOUND | KCSAN_ACCESS_ASSERT)) ? 1 : 0;
 
-       return delay - (IS_ENABLED(CONFIG_KCSAN_DELAY_RANDOMIZE) ?
-                               prandom_u32_max(delay >> skew_delay_order) :
-                               0);
+       delay -= IS_ENABLED(CONFIG_KCSAN_DELAY_RANDOMIZE) ?
+                              kcsan_prandom_u32_max(delay >> skew_delay_order) :
+                              0;
+       udelay(delay);
 }
 
 void kcsan_save_irqtrace(struct task_struct *task)
         * Delay this thread, to increase probability of observing a racy
         * conflicting access.
         */
-       udelay(get_delay(type));
+       delay_access(type);
 
        /*
         * Re-read value, and check if it is as expected; if not, we infer a
        BUG_ON(!in_task());
 
        kcsan_debugfs_init();
+       prandom_seed_full_state(&kcsan_rand_state);
 
        /*
         * We are in the init task, and no other tasks should be running;