From: "Uladzislau Rezki (Sony)" urezki@gmail.com
[ Upstream commit 33b6a1f155d627f5bd80c7485c598ce45428f74f ]
Currently the call_rcu() API does not check whether a callback pointer is NULL. If NULL is passed, rcu_core() will try to invoke it, resulting in NULL pointer dereference and a kernel crash.
To prevent this and improve debuggability, this patch adds a check for NULL and emits a kernel stack trace to help identify a faulty caller.
Signed-off-by: Uladzislau Rezki (Sony) urezki@gmail.com Reviewed-by: Joel Fernandes joelagnelf@nvidia.com Signed-off-by: Joel Fernandes joelagnelf@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org ---
So I can see that in the current code, `debug_rcu_head_callback()` (called at line 2566 in rcu_do_batch) already checks for NULL func and dumps memory info, but it doesn't prevent the crash - it still proceeds to invoke the NULL function pointer at line 2568.
Now let me understand the commit more - it adds a check in `__call_rcu_common()` to catch NULL callbacks early and warn about them, preventing them from being queued at all.
## Analysis
**Answer: YES**
This commit should be backported to stable kernel trees for the following reasons:
1. **Fixes a Critical Bug**: The commit addresses a real kernel crash scenario where passing a NULL callback to `call_rcu()` results in a NULL pointer dereference when `rcu_do_batch()` tries to invoke the callback at line 2568 (`f(rhp)`). This is a serious bug that can crash the kernel.
2. **Small and Contained Fix**: The change is minimal - it adds just 4 lines of code: ```c /* Avoid NULL dereference if callback is NULL. */ if (WARN_ON_ONCE(!func)) return; ``` This is exactly the type of small, focused fix that stable trees prefer.
3. **Defensive Programming**: While the existing code already has `debug_rcu_head_callback()` that checks for NULL func and dumps memory info (as seen in similar commit #2), it doesn't prevent the crash. This commit adds a proper early return to prevent the NULL callback from being queued at all.
4. **No Side Effects**: The fix simply validates input parameters and returns early if invalid. It doesn't change any architecture, doesn't introduce new features, and has minimal risk of regression.
5. **Clear Bug Prevention**: The commit prevents a programming error (passing NULL callback) from escalating into a kernel crash. Even though passing NULL is a programmer error, the kernel should handle it gracefully rather than crashing.
6. **Similar to Stable-Worthy Commits**: Looking at the similar commits, commit #2 ("rcu: Dump memory object info if callback function is invalid") was marked as suitable for backporting (YES) and dealt with a similar issue of invalid callbacks. That commit added debugging for when callbacks become NULL after being queued, while this commit prevents NULL callbacks from being queued in the first place.
The fix follows the stable kernel rules perfectly: - It fixes a real bug (kernel crash) - It's small and obvious - It has been tested (as indicated by the review process) - It doesn't add features or change behavior for valid use cases - It improves kernel robustness without any downside
This is a textbook example of a commit that should be backported to stable trees to improve kernel reliability across all supported versions.
kernel/rcu/tree.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index cefa831c8cb32..552464dcffe27 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -3076,6 +3076,10 @@ __call_rcu_common(struct rcu_head *head, rcu_callback_t func, bool lazy_in) /* Misaligned rcu_head! */ WARN_ON_ONCE((unsigned long)head & (sizeof(void *) - 1));
+ /* Avoid NULL dereference if callback is NULL. */ + if (WARN_ON_ONCE(!func)) + return; + if (debug_rcu_head_queue(head)) { /* * Probable double call_rcu(), so leak the callback.