As discussed here:

  https://lore.kernel.org/all/20221106212427.739928660@goodmis.org/

Add a "shutdown" state for timers. This is performed by the new
timer_shutdown_sync() and timer_shutdown() function calls. When this is
called on a timer, it will no longer be able to be re-armed. This should
be called before a timer is freed to prevent it from being re-armed after
being removed from the timer queue and then causing a crash in the timer
code when the timer triggers.

This required renaming some functions that were using the name
timer_shutdown() statically to something more appropriate.

Then a coccinelle script was executed on the entire kernel tree to find
the trivial locations that remove the timer and then frees the object that
the timer exists on.

These changes are not enough to solve all the locations where timers may
be of an issue. But by adding the shutdown infrastructure and the obvious
cases, the more complex cases can be added after they have been reviewed
more closely.
treewide: Convert del_timer*() to timer_shutdown*()

Due to several bugs caused by timers being re-armed after they are
shutdown and just before they are freed, a new state of timers was added
called "shutdown". After a timer is set to this state, then it can no
longer be re-armed, and will trigger a warning if it is.

The following script was run to find all the trivial locations where
del_timer() or del_timer_sync() is called in the same function that the
object holding the timer is freed. It also ignores any locations where the
timer->function is modified between the del_timer*() and the free(), as
that is not considered a "trivial" case.

This was created by using a coccinelle script and the following commands:

 $ cat timer.cocci
@@
expression ptr, slab;
identifier timer, rfield;
@@
(
-       del_timer(&ptr->timer);
+       timer_shutdown(&ptr->timer);
|
-       del_timer_sync(&ptr->timer);
+       timer_shutdown_sync(&ptr->timer);
)
  ... when strict
      when != ptr->timer
(
        kfree_rcu(ptr, rfield);
|
        kmem_cache_free(slab, ptr);
|
        kfree(ptr);
)

 $ spatch --dir timer.cocci . > /tmp/t.patch
 $ patch -p1 < /tmp/t.patch

Link: https://lkml.kernel.org/r/20221106212702.547242324@goodmis.org

Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: Anna-Maria Gleixner <anna-maria@linutronix.de>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Julia Lawall <Julia.Lawall@inria.fr>
Tested-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
70 files changed