Passing a complex lockdep condition to __list_check_rcu results in false positive lockdep splat due to incorrect expression evaluation. For example, a lockdep check condition `cond1 || cond2` is evaluated as `!cond1 || cond2 && !rcu_read_lock_any_held()` which, according to operator precedence, evaluates to `!cond1 || (cond2 && !rcu_read_lock_any_held())`. This would result in a lockdep splat when cond1 is false and cond2 is true which is logically incorrect.
Showing the changes to include/linux (1 of 1 file). Show all
Unified · Split
| @@ -60,9 +60,9 @@ static inline void INIT_LIST_HEAD_RCU(struct list_head *list) · 59 unmodified lines | ||
| 60 | 60 | #define __list_check_rcu(dummy, cond, extra...) \ |
| 61 | 61 | ({ \ |
| 62 | 62 | check_arg_count_one(extra); \ |
| 63 | − RCU_LOCKDEP_WARN(!cond && !rcu_read_lock_any_held(), \ | |
| 63 | + RCU_LOCKDEP_WARN(!(cond) && !rcu_read_lock_any_held(), \ | |
| 64 | 64 | "RCU-list traversed in non-reader section!"); \ |
| 65 | − }) | |
| 65 | + }) | |
| 66 | 66 | #else |
| 67 | 67 | #define __list_check_rcu(dummy, cond, extra...) \ |
| 68 | 68 | ({ check_arg_count_one(extra); }) |