History

notifier: Return an error when a callback has already been registered

Return -EEXIST when a notifier callback has already been registered on a notifier chain. This should avoid any homegrown registration tracking at the callsite like https://lore.kernel.org/amd-gfx/20210512013058.6827-1-mukul.joshi@amd.com for example. This version is an alternative of https://lore.kernel.org/r/20211108101157.15189-1-bp@alien8.de which needed to touch every caller not checking the registration routine's return value.

Borislav Petkov committed 4 years ago

Commit 5abb0651 parent fc74e0a1 file · +8 −7Browse files

Unified · Split

kernel/notifier.c+8−7
@@ -20,12 +20,13 @@ BLOCKING_NOTIFIER_HEAD(reboot_notifier_list); · 19 unmodified lines
20 */20 */
21 21
22static int notifier_chain_register(struct notifier_block **nl,22static int notifier_chain_register(struct notifier_block **nl,
23 struct notifier_block *n)23 struct notifier_block *n)
24{24{
25 while ((*nl) != NULL) {25 while ((*nl) != NULL) {
26 if (unlikely((*nl) == n)) {26 if (unlikely((*nl) == n)) {
27 WARN(1, "double register detected");27 WARN(1, "notifier callback %ps already registered",
28 return 0;28 n->notifier_call);
29 return -EEXIST;
29 }30 }
30 if (n->priority > (*nl)->priority)31 if (n->priority > (*nl)->priority)
31 break;32 break;
@@ -134,7 +135,7 @@ static int notifier_call_chain_robust(struct notifier_block **nl, · 102 unmodified lines
134 *135 *
135 * Adds a notifier to an atomic notifier chain.136 * Adds a notifier to an atomic notifier chain.
136 *137 *
137 * Currently always returns zero.138 * Returns 0 on success, %-EEXIST on error.
138 */139 */
139int atomic_notifier_chain_register(struct atomic_notifier_head *nh,140int atomic_notifier_chain_register(struct atomic_notifier_head *nh,
140 struct notifier_block *n)141 struct notifier_block *n)
@@ -216,7 +217,7 @@ NOKPROBE_SYMBOL(atomic_notifier_call_chain); · 75 unmodified lines
216 * Adds a notifier to a blocking notifier chain.217 * Adds a notifier to a blocking notifier chain.
217 * Must be called in process context.218 * Must be called in process context.
218 *219 *
219 * Currently always returns zero.220 * Returns 0 on success, %-EEXIST on error.
220 */221 */
221int blocking_notifier_chain_register(struct blocking_notifier_head *nh,222int blocking_notifier_chain_register(struct blocking_notifier_head *nh,
222 struct notifier_block *n)223 struct notifier_block *n)
@@ -335,7 +336,7 @@ EXPORT_SYMBOL_GPL(blocking_notifier_call_chain); · 112 unmodified lines
335 * Adds a notifier to a raw notifier chain.336 * Adds a notifier to a raw notifier chain.
336 * All locking must be provided by the caller.337 * All locking must be provided by the caller.
337 *338 *
338 * Currently always returns zero.339 * Returns 0 on success, %-EEXIST on error.
339 */340 */
340int raw_notifier_chain_register(struct raw_notifier_head *nh,341int raw_notifier_chain_register(struct raw_notifier_head *nh,
341 struct notifier_block *n)342 struct notifier_block *n)
@@ -406,7 +407,7 @@ EXPORT_SYMBOL_GPL(raw_notifier_call_chain); · 64 unmodified lines
406 * Adds a notifier to an SRCU notifier chain.407 * Adds a notifier to an SRCU notifier chain.
407 * Must be called in process context.408 * Must be called in process context.
408 *409 *
409 * Currently always returns zero.410 * Returns 0 on success, %-EEXIST on error.
410 */411 */
411int srcu_notifier_chain_register(struct srcu_notifier_head *nh,412int srcu_notifier_chain_register(struct srcu_notifier_head *nh,
412 struct notifier_block *n)413 struct notifier_block *n)