srcu: Tighten cleanup_srcu_struct() GP checks
authorPaul E. McKenney <paulmck@kernel.org>
Wed, 12 Jan 2022 17:52:44 +0000 (09:52 -0800)
committerPaul E. McKenney <paulmck@kernel.org>
Mon, 11 Apr 2022 22:31:01 +0000 (15:31 -0700)
Currently, cleanup_srcu_struct() checks for a grace period in progress,
but it does not check for a grace period that has not yet started but
which might start at any time.  Such a situation could result in a
use-after-free bug, so this commit adds a check for a grace period that
is needed but not yet started to cleanup_srcu_struct().

Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
kernel/rcu/srcutree.c

index 6833d88..d30e4db 100644 (file)
@@ -382,9 +382,11 @@ void cleanup_srcu_struct(struct srcu_struct *ssp)
                        return; /* Forgot srcu_barrier(), so just leak it! */
        }
        if (WARN_ON(rcu_seq_state(READ_ONCE(ssp->srcu_gp_seq)) != SRCU_STATE_IDLE) ||
+           WARN_ON(rcu_seq_current(&ssp->srcu_gp_seq) != ssp->srcu_gp_seq_needed) ||
            WARN_ON(srcu_readers_active(ssp))) {
-               pr_info("%s: Active srcu_struct %p state: %d\n",
-                       __func__, ssp, rcu_seq_state(READ_ONCE(ssp->srcu_gp_seq)));
+               pr_info("%s: Active srcu_struct %p read state: %d gp state: %lu/%lu\n",
+                       __func__, ssp, rcu_seq_state(READ_ONCE(ssp->srcu_gp_seq)),
+                       rcu_seq_current(&ssp->srcu_gp_seq), ssp->srcu_gp_seq_needed);
                return; /* Caller forgot to stop doing call_srcu()? */
        }
        free_percpu(ssp->sda);