On Sat, 20 Aug 2022 15:33:04 +0800 Muchun Song <muchun.song@xxxxxxxxx> wrote: > > > > + if (IS_ERR(t)) { > > /* failure at boot is fatal */ > > BUG_ON(system_state < SYSTEM_RUNNING); > > pr_err("Failed to start kswapd on node %d\n", nid); > > - pgdat->kswapd = NULL; > > + WRITE_ONCE(pgdat->kswapd, NULL); > > + } else { > > + WRITE_ONCE(pgdat->kswapd, t); > > } > > } > > IIUC, the race is like the followings: > > CPU 0: CPU 1: > > kswapd_run() > pgdat->kswapd = kthread_run() > if (IS_ERR(pgdat->kswapd)) > kswapd_is_running > // load pgdat->kswapd and it is NOT NULL. > pgdat->kswapd = NULL > task_is_running(pgdat->kswapd); // NULL pointer dereference > But don't we still have a bug? Sure, kswapd_is_running() will no longer deref a null pointer. But it now runs kswapd_is_running() against a task which has exited - a use-after-free?