0001
0002 #include <linux/kdebug.h>
0003 #include <linux/kprobes.h>
0004 #include <linux/export.h>
0005 #include <linux/notifier.h>
0006 #include <linux/rcupdate.h>
0007 #include <linux/vmalloc.h>
0008 #include <linux/reboot.h>
0009
0010
0011
0012
0013
0014
0015 BLOCKING_NOTIFIER_HEAD(reboot_notifier_list);
0016
0017
0018
0019
0020
0021
0022 static int notifier_chain_register(struct notifier_block **nl,
0023 struct notifier_block *n,
0024 bool unique_priority)
0025 {
0026 while ((*nl) != NULL) {
0027 if (unlikely((*nl) == n)) {
0028 WARN(1, "notifier callback %ps already registered",
0029 n->notifier_call);
0030 return -EEXIST;
0031 }
0032 if (n->priority > (*nl)->priority)
0033 break;
0034 if (n->priority == (*nl)->priority && unique_priority)
0035 return -EBUSY;
0036 nl = &((*nl)->next);
0037 }
0038 n->next = *nl;
0039 rcu_assign_pointer(*nl, n);
0040 return 0;
0041 }
0042
0043 static int notifier_chain_unregister(struct notifier_block **nl,
0044 struct notifier_block *n)
0045 {
0046 while ((*nl) != NULL) {
0047 if ((*nl) == n) {
0048 rcu_assign_pointer(*nl, n->next);
0049 return 0;
0050 }
0051 nl = &((*nl)->next);
0052 }
0053 return -ENOENT;
0054 }
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068 static int notifier_call_chain(struct notifier_block **nl,
0069 unsigned long val, void *v,
0070 int nr_to_call, int *nr_calls)
0071 {
0072 int ret = NOTIFY_DONE;
0073 struct notifier_block *nb, *next_nb;
0074
0075 nb = rcu_dereference_raw(*nl);
0076
0077 while (nb && nr_to_call) {
0078 next_nb = rcu_dereference_raw(nb->next);
0079
0080 #ifdef CONFIG_DEBUG_NOTIFIERS
0081 if (unlikely(!func_ptr_is_kernel_text(nb->notifier_call))) {
0082 WARN(1, "Invalid notifier called!");
0083 nb = next_nb;
0084 continue;
0085 }
0086 #endif
0087 ret = nb->notifier_call(nb, val, v);
0088
0089 if (nr_calls)
0090 (*nr_calls)++;
0091
0092 if (ret & NOTIFY_STOP_MASK)
0093 break;
0094 nb = next_nb;
0095 nr_to_call--;
0096 }
0097 return ret;
0098 }
0099 NOKPROBE_SYMBOL(notifier_call_chain);
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116 static int notifier_call_chain_robust(struct notifier_block **nl,
0117 unsigned long val_up, unsigned long val_down,
0118 void *v)
0119 {
0120 int ret, nr = 0;
0121
0122 ret = notifier_call_chain(nl, val_up, v, -1, &nr);
0123 if (ret & NOTIFY_STOP_MASK)
0124 notifier_call_chain(nl, val_down, v, nr-1, NULL);
0125
0126 return ret;
0127 }
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143 int atomic_notifier_chain_register(struct atomic_notifier_head *nh,
0144 struct notifier_block *n)
0145 {
0146 unsigned long flags;
0147 int ret;
0148
0149 spin_lock_irqsave(&nh->lock, flags);
0150 ret = notifier_chain_register(&nh->head, n, false);
0151 spin_unlock_irqrestore(&nh->lock, flags);
0152 return ret;
0153 }
0154 EXPORT_SYMBOL_GPL(atomic_notifier_chain_register);
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166 int atomic_notifier_chain_register_unique_prio(struct atomic_notifier_head *nh,
0167 struct notifier_block *n)
0168 {
0169 unsigned long flags;
0170 int ret;
0171
0172 spin_lock_irqsave(&nh->lock, flags);
0173 ret = notifier_chain_register(&nh->head, n, true);
0174 spin_unlock_irqrestore(&nh->lock, flags);
0175 return ret;
0176 }
0177 EXPORT_SYMBOL_GPL(atomic_notifier_chain_register_unique_prio);
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188 int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
0189 struct notifier_block *n)
0190 {
0191 unsigned long flags;
0192 int ret;
0193
0194 spin_lock_irqsave(&nh->lock, flags);
0195 ret = notifier_chain_unregister(&nh->head, n);
0196 spin_unlock_irqrestore(&nh->lock, flags);
0197 synchronize_rcu();
0198 return ret;
0199 }
0200 EXPORT_SYMBOL_GPL(atomic_notifier_chain_unregister);
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219 int atomic_notifier_call_chain(struct atomic_notifier_head *nh,
0220 unsigned long val, void *v)
0221 {
0222 int ret;
0223
0224 rcu_read_lock();
0225 ret = notifier_call_chain(&nh->head, val, v, -1, NULL);
0226 rcu_read_unlock();
0227
0228 return ret;
0229 }
0230 EXPORT_SYMBOL_GPL(atomic_notifier_call_chain);
0231 NOKPROBE_SYMBOL(atomic_notifier_call_chain);
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241 bool atomic_notifier_call_chain_is_empty(struct atomic_notifier_head *nh)
0242 {
0243 return !rcu_access_pointer(nh->head);
0244 }
0245
0246
0247
0248
0249
0250
0251 static int __blocking_notifier_chain_register(struct blocking_notifier_head *nh,
0252 struct notifier_block *n,
0253 bool unique_priority)
0254 {
0255 int ret;
0256
0257
0258
0259
0260
0261
0262 if (unlikely(system_state == SYSTEM_BOOTING))
0263 return notifier_chain_register(&nh->head, n, unique_priority);
0264
0265 down_write(&nh->rwsem);
0266 ret = notifier_chain_register(&nh->head, n, unique_priority);
0267 up_write(&nh->rwsem);
0268 return ret;
0269 }
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281 int blocking_notifier_chain_register(struct blocking_notifier_head *nh,
0282 struct notifier_block *n)
0283 {
0284 return __blocking_notifier_chain_register(nh, n, false);
0285 }
0286 EXPORT_SYMBOL_GPL(blocking_notifier_chain_register);
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298 int blocking_notifier_chain_register_unique_prio(struct blocking_notifier_head *nh,
0299 struct notifier_block *n)
0300 {
0301 return __blocking_notifier_chain_register(nh, n, true);
0302 }
0303 EXPORT_SYMBOL_GPL(blocking_notifier_chain_register_unique_prio);
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315 int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,
0316 struct notifier_block *n)
0317 {
0318 int ret;
0319
0320
0321
0322
0323
0324
0325 if (unlikely(system_state == SYSTEM_BOOTING))
0326 return notifier_chain_unregister(&nh->head, n);
0327
0328 down_write(&nh->rwsem);
0329 ret = notifier_chain_unregister(&nh->head, n);
0330 up_write(&nh->rwsem);
0331 return ret;
0332 }
0333 EXPORT_SYMBOL_GPL(blocking_notifier_chain_unregister);
0334
0335 int blocking_notifier_call_chain_robust(struct blocking_notifier_head *nh,
0336 unsigned long val_up, unsigned long val_down, void *v)
0337 {
0338 int ret = NOTIFY_DONE;
0339
0340
0341
0342
0343
0344
0345 if (rcu_access_pointer(nh->head)) {
0346 down_read(&nh->rwsem);
0347 ret = notifier_call_chain_robust(&nh->head, val_up, val_down, v);
0348 up_read(&nh->rwsem);
0349 }
0350 return ret;
0351 }
0352 EXPORT_SYMBOL_GPL(blocking_notifier_call_chain_robust);
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367
0368
0369
0370 int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
0371 unsigned long val, void *v)
0372 {
0373 int ret = NOTIFY_DONE;
0374
0375
0376
0377
0378
0379
0380 if (rcu_access_pointer(nh->head)) {
0381 down_read(&nh->rwsem);
0382 ret = notifier_call_chain(&nh->head, val, v, -1, NULL);
0383 up_read(&nh->rwsem);
0384 }
0385 return ret;
0386 }
0387 EXPORT_SYMBOL_GPL(blocking_notifier_call_chain);
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404 int raw_notifier_chain_register(struct raw_notifier_head *nh,
0405 struct notifier_block *n)
0406 {
0407 return notifier_chain_register(&nh->head, n, false);
0408 }
0409 EXPORT_SYMBOL_GPL(raw_notifier_chain_register);
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421 int raw_notifier_chain_unregister(struct raw_notifier_head *nh,
0422 struct notifier_block *n)
0423 {
0424 return notifier_chain_unregister(&nh->head, n);
0425 }
0426 EXPORT_SYMBOL_GPL(raw_notifier_chain_unregister);
0427
0428 int raw_notifier_call_chain_robust(struct raw_notifier_head *nh,
0429 unsigned long val_up, unsigned long val_down, void *v)
0430 {
0431 return notifier_call_chain_robust(&nh->head, val_up, val_down, v);
0432 }
0433 EXPORT_SYMBOL_GPL(raw_notifier_call_chain_robust);
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452 int raw_notifier_call_chain(struct raw_notifier_head *nh,
0453 unsigned long val, void *v)
0454 {
0455 return notifier_call_chain(&nh->head, val, v, -1, NULL);
0456 }
0457 EXPORT_SYMBOL_GPL(raw_notifier_call_chain);
0458
0459 #ifdef CONFIG_SRCU
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470
0471
0472
0473
0474
0475 int srcu_notifier_chain_register(struct srcu_notifier_head *nh,
0476 struct notifier_block *n)
0477 {
0478 int ret;
0479
0480
0481
0482
0483
0484
0485 if (unlikely(system_state == SYSTEM_BOOTING))
0486 return notifier_chain_register(&nh->head, n, false);
0487
0488 mutex_lock(&nh->mutex);
0489 ret = notifier_chain_register(&nh->head, n, false);
0490 mutex_unlock(&nh->mutex);
0491 return ret;
0492 }
0493 EXPORT_SYMBOL_GPL(srcu_notifier_chain_register);
0494
0495
0496
0497
0498
0499
0500
0501
0502
0503
0504
0505 int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh,
0506 struct notifier_block *n)
0507 {
0508 int ret;
0509
0510
0511
0512
0513
0514
0515 if (unlikely(system_state == SYSTEM_BOOTING))
0516 return notifier_chain_unregister(&nh->head, n);
0517
0518 mutex_lock(&nh->mutex);
0519 ret = notifier_chain_unregister(&nh->head, n);
0520 mutex_unlock(&nh->mutex);
0521 synchronize_srcu(&nh->srcu);
0522 return ret;
0523 }
0524 EXPORT_SYMBOL_GPL(srcu_notifier_chain_unregister);
0525
0526
0527
0528
0529
0530
0531
0532
0533
0534
0535
0536
0537
0538
0539
0540
0541
0542 int srcu_notifier_call_chain(struct srcu_notifier_head *nh,
0543 unsigned long val, void *v)
0544 {
0545 int ret;
0546 int idx;
0547
0548 idx = srcu_read_lock(&nh->srcu);
0549 ret = notifier_call_chain(&nh->head, val, v, -1, NULL);
0550 srcu_read_unlock(&nh->srcu, idx);
0551 return ret;
0552 }
0553 EXPORT_SYMBOL_GPL(srcu_notifier_call_chain);
0554
0555
0556
0557
0558
0559
0560
0561
0562
0563
0564
0565
0566
0567 void srcu_init_notifier_head(struct srcu_notifier_head *nh)
0568 {
0569 mutex_init(&nh->mutex);
0570 if (init_srcu_struct(&nh->srcu) < 0)
0571 BUG();
0572 nh->head = NULL;
0573 }
0574 EXPORT_SYMBOL_GPL(srcu_init_notifier_head);
0575
0576 #endif
0577
0578 static ATOMIC_NOTIFIER_HEAD(die_chain);
0579
0580 int notrace notify_die(enum die_val val, const char *str,
0581 struct pt_regs *regs, long err, int trap, int sig)
0582 {
0583 struct die_args args = {
0584 .regs = regs,
0585 .str = str,
0586 .err = err,
0587 .trapnr = trap,
0588 .signr = sig,
0589
0590 };
0591 RCU_LOCKDEP_WARN(!rcu_is_watching(),
0592 "notify_die called but RCU thinks we're quiescent");
0593 return atomic_notifier_call_chain(&die_chain, val, &args);
0594 }
0595 NOKPROBE_SYMBOL(notify_die);
0596
0597 int register_die_notifier(struct notifier_block *nb)
0598 {
0599 return atomic_notifier_chain_register(&die_chain, nb);
0600 }
0601 EXPORT_SYMBOL_GPL(register_die_notifier);
0602
0603 int unregister_die_notifier(struct notifier_block *nb)
0604 {
0605 return atomic_notifier_chain_unregister(&die_chain, nb);
0606 }
0607 EXPORT_SYMBOL_GPL(unregister_die_notifier);