LCOV - code coverage report
Current view: top level - kernel - tracepoint.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 22 208 10.6 %
Date: 2022-04-01 14:17:54 Functions: 4 22 18.2 %
Branches: 5 103 4.9 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-or-later
       2                 :            : /*
       3                 :            :  * Copyright (C) 2008-2014 Mathieu Desnoyers
       4                 :            :  */
       5                 :            : #include <linux/module.h>
       6                 :            : #include <linux/mutex.h>
       7                 :            : #include <linux/types.h>
       8                 :            : #include <linux/jhash.h>
       9                 :            : #include <linux/list.h>
      10                 :            : #include <linux/rcupdate.h>
      11                 :            : #include <linux/tracepoint.h>
      12                 :            : #include <linux/err.h>
      13                 :            : #include <linux/slab.h>
      14                 :            : #include <linux/sched/signal.h>
      15                 :            : #include <linux/sched/task.h>
      16                 :            : #include <linux/static_key.h>
      17                 :            : 
      18                 :            : extern tracepoint_ptr_t __start___tracepoints_ptrs[];
      19                 :            : extern tracepoint_ptr_t __stop___tracepoints_ptrs[];
      20                 :            : 
      21                 :            : DEFINE_SRCU(tracepoint_srcu);
      22                 :            : EXPORT_SYMBOL_GPL(tracepoint_srcu);
      23                 :            : 
      24                 :            : /* Set to 1 to enable tracepoint debug output */
      25                 :            : static const int tracepoint_debug;
      26                 :            : 
      27                 :            : #ifdef CONFIG_MODULES
      28                 :            : /*
      29                 :            :  * Tracepoint module list mutex protects the local module list.
      30                 :            :  */
      31                 :            : static DEFINE_MUTEX(tracepoint_module_list_mutex);
      32                 :            : 
      33                 :            : /* Local list of struct tp_module */
      34                 :            : static LIST_HEAD(tracepoint_module_list);
      35                 :            : #endif /* CONFIG_MODULES */
      36                 :            : 
      37                 :            : /*
      38                 :            :  * tracepoints_mutex protects the builtin and module tracepoints.
      39                 :            :  * tracepoints_mutex nests inside tracepoint_module_list_mutex.
      40                 :            :  */
      41                 :            : static DEFINE_MUTEX(tracepoints_mutex);
      42                 :            : 
      43                 :            : static struct rcu_head *early_probes;
      44                 :            : static bool ok_to_free_tracepoints;
      45                 :            : 
      46                 :            : /*
      47                 :            :  * Note about RCU :
      48                 :            :  * It is used to delay the free of multiple probes array until a quiescent
      49                 :            :  * state is reached.
      50                 :            :  */
      51                 :            : struct tp_probes {
      52                 :            :         struct rcu_head rcu;
      53                 :            :         struct tracepoint_func probes[0];
      54                 :            : };
      55                 :            : 
      56                 :          0 : static inline void *allocate_probes(int count)
      57                 :            : {
      58         [ #  # ]:          0 :         struct tp_probes *p  = kmalloc(struct_size(p, probes, count),
      59                 :            :                                        GFP_KERNEL);
      60         [ #  # ]:          0 :         return p == NULL ? NULL : p->probes;
      61                 :            : }
      62                 :            : 
      63                 :          0 : static void srcu_free_old_probes(struct rcu_head *head)
      64                 :            : {
      65                 :          0 :         kfree(container_of(head, struct tp_probes, rcu));
      66                 :          0 : }
      67                 :            : 
      68                 :          0 : static void rcu_free_old_probes(struct rcu_head *head)
      69                 :            : {
      70                 :          0 :         call_srcu(&tracepoint_srcu, head, srcu_free_old_probes);
      71                 :          0 : }
      72                 :            : 
      73                 :         11 : static __init int release_early_probes(void)
      74                 :            : {
      75                 :         11 :         struct rcu_head *tmp;
      76                 :            : 
      77                 :         11 :         ok_to_free_tracepoints = true;
      78                 :            : 
      79         [ -  + ]:         11 :         while (early_probes) {
      80                 :          0 :                 tmp = early_probes;
      81                 :          0 :                 early_probes = tmp->next;
      82                 :          0 :                 call_rcu(tmp, rcu_free_old_probes);
      83                 :            :         }
      84                 :            : 
      85                 :         11 :         return 0;
      86                 :            : }
      87                 :            : 
      88                 :            : /* SRCU is initialized at core_initcall */
      89                 :            : postcore_initcall(release_early_probes);
      90                 :            : 
      91                 :          0 : static inline void release_probes(struct tracepoint_func *old)
      92                 :            : {
      93         [ #  # ]:          0 :         if (old) {
      94                 :          0 :                 struct tp_probes *tp_probes = container_of(old,
      95                 :            :                         struct tp_probes, probes[0]);
      96                 :            : 
      97                 :            :                 /*
      98                 :            :                  * We can't free probes if SRCU is not initialized yet.
      99                 :            :                  * Postpone the freeing till after SRCU is initialized.
     100                 :            :                  */
     101         [ #  # ]:          0 :                 if (unlikely(!ok_to_free_tracepoints)) {
     102                 :          0 :                         tp_probes->rcu.next = early_probes;
     103                 :          0 :                         early_probes = &tp_probes->rcu;
     104                 :          0 :                         return;
     105                 :            :                 }
     106                 :            : 
     107                 :            :                 /*
     108                 :            :                  * Tracepoint probes are protected by both sched RCU and SRCU,
     109                 :            :                  * by calling the SRCU callback in the sched RCU callback we
     110                 :            :                  * cover both cases. So let us chain the SRCU and sched RCU
     111                 :            :                  * callbacks to wait for both grace periods.
     112                 :            :                  */
     113                 :          0 :                 call_rcu(&tp_probes->rcu, rcu_free_old_probes);
     114                 :            :         }
     115                 :            : }
     116                 :            : 
     117                 :          0 : static void debug_print_probes(struct tracepoint_func *funcs)
     118                 :            : {
     119                 :          0 :         int i;
     120                 :            : 
     121                 :          0 :         if (!tracepoint_debug || !funcs)
     122                 :          0 :                 return;
     123                 :            : 
     124                 :            :         for (i = 0; funcs[i].func; i++)
     125                 :            :                 printk(KERN_DEBUG "Probe %d : %p\n", i, funcs[i].func);
     126                 :            : }
     127                 :            : 
     128                 :            : static struct tracepoint_func *
     129                 :          0 : func_add(struct tracepoint_func **funcs, struct tracepoint_func *tp_func,
     130                 :            :          int prio)
     131                 :            : {
     132                 :          0 :         struct tracepoint_func *old, *new;
     133                 :          0 :         int nr_probes = 0;
     134                 :          0 :         int pos = -1;
     135                 :            : 
     136   [ #  #  #  # ]:          0 :         if (WARN_ON(!tp_func->func))
     137                 :            :                 return ERR_PTR(-EINVAL);
     138                 :            : 
     139                 :          0 :         debug_print_probes(*funcs);
     140                 :          0 :         old = *funcs;
     141         [ #  # ]:          0 :         if (old) {
     142                 :            :                 /* (N -> N+1), (N != 0, 1) probes */
     143         [ #  # ]:          0 :                 for (nr_probes = 0; old[nr_probes].func; nr_probes++) {
     144                 :            :                         /* Insert before probes of lower priority */
     145   [ #  #  #  # ]:          0 :                         if (pos < 0 && old[nr_probes].prio < prio)
     146                 :          0 :                                 pos = nr_probes;
     147         [ #  # ]:          0 :                         if (old[nr_probes].func == tp_func->func &&
     148         [ #  # ]:          0 :                             old[nr_probes].data == tp_func->data)
     149                 :            :                                 return ERR_PTR(-EEXIST);
     150                 :            :                 }
     151                 :            :         }
     152                 :            :         /* + 2 : one for new probe, one for NULL func */
     153                 :          0 :         new = allocate_probes(nr_probes + 2);
     154         [ #  # ]:          0 :         if (new == NULL)
     155                 :            :                 return ERR_PTR(-ENOMEM);
     156         [ #  # ]:          0 :         if (old) {
     157         [ #  # ]:          0 :                 if (pos < 0) {
     158                 :          0 :                         pos = nr_probes;
     159                 :          0 :                         memcpy(new, old, nr_probes * sizeof(struct tracepoint_func));
     160                 :            :                 } else {
     161                 :            :                         /* Copy higher priority probes ahead of the new probe */
     162                 :          0 :                         memcpy(new, old, pos * sizeof(struct tracepoint_func));
     163                 :            :                         /* Copy the rest after it. */
     164                 :          0 :                         memcpy(new + pos + 1, old + pos,
     165                 :          0 :                                (nr_probes - pos) * sizeof(struct tracepoint_func));
     166                 :            :                 }
     167                 :            :         } else
     168                 :            :                 pos = 0;
     169                 :          0 :         new[pos] = *tp_func;
     170                 :          0 :         new[nr_probes + 1].func = NULL;
     171                 :          0 :         *funcs = new;
     172                 :          0 :         debug_print_probes(*funcs);
     173                 :          0 :         return old;
     174                 :            : }
     175                 :            : 
     176                 :            : static void *func_remove(struct tracepoint_func **funcs,
     177                 :            :                 struct tracepoint_func *tp_func)
     178                 :            : {
     179                 :            :         int nr_probes = 0, nr_del = 0, i;
     180                 :            :         struct tracepoint_func *old, *new;
     181                 :            : 
     182                 :            :         old = *funcs;
     183                 :            : 
     184                 :            :         if (!old)
     185                 :            :                 return ERR_PTR(-ENOENT);
     186                 :            : 
     187                 :            :         debug_print_probes(*funcs);
     188                 :            :         /* (N -> M), (N > 1, M >= 0) probes */
     189                 :            :         if (tp_func->func) {
     190                 :            :                 for (nr_probes = 0; old[nr_probes].func; nr_probes++) {
     191                 :            :                         if (old[nr_probes].func == tp_func->func &&
     192                 :            :                              old[nr_probes].data == tp_func->data)
     193                 :            :                                 nr_del++;
     194                 :            :                 }
     195                 :            :         }
     196                 :            : 
     197                 :            :         /*
     198                 :            :          * If probe is NULL, then nr_probes = nr_del = 0, and then the
     199                 :            :          * entire entry will be removed.
     200                 :            :          */
     201                 :            :         if (nr_probes - nr_del == 0) {
     202                 :            :                 /* N -> 0, (N > 1) */
     203                 :            :                 *funcs = NULL;
     204                 :            :                 debug_print_probes(*funcs);
     205                 :            :                 return old;
     206                 :            :         } else {
     207                 :            :                 int j = 0;
     208                 :            :                 /* N -> M, (N > 1, M > 0) */
     209                 :            :                 /* + 1 for NULL */
     210                 :            :                 new = allocate_probes(nr_probes - nr_del + 1);
     211                 :            :                 if (new == NULL)
     212                 :            :                         return ERR_PTR(-ENOMEM);
     213                 :            :                 for (i = 0; old[i].func; i++)
     214                 :            :                         if (old[i].func != tp_func->func
     215                 :            :                                         || old[i].data != tp_func->data)
     216                 :            :                                 new[j++] = old[i];
     217                 :            :                 new[nr_probes - nr_del].func = NULL;
     218                 :            :                 *funcs = new;
     219                 :            :         }
     220                 :            :         debug_print_probes(*funcs);
     221                 :            :         return old;
     222                 :            : }
     223                 :            : 
     224                 :            : /*
     225                 :            :  * Add the probe function to a tracepoint.
     226                 :            :  */
     227                 :          0 : static int tracepoint_add_func(struct tracepoint *tp,
     228                 :            :                                struct tracepoint_func *func, int prio)
     229                 :            : {
     230                 :          0 :         struct tracepoint_func *old, *tp_funcs;
     231                 :          0 :         int ret;
     232                 :            : 
     233   [ #  #  #  # ]:          0 :         if (tp->regfunc && !static_key_enabled(&tp->key)) {
     234                 :          0 :                 ret = tp->regfunc();
     235         [ #  # ]:          0 :                 if (ret < 0)
     236                 :            :                         return ret;
     237                 :            :         }
     238                 :            : 
     239                 :          0 :         tp_funcs = rcu_dereference_protected(tp->funcs,
     240                 :            :                         lockdep_is_held(&tracepoints_mutex));
     241                 :          0 :         old = func_add(&tp_funcs, func, prio);
     242         [ #  # ]:          0 :         if (IS_ERR(old)) {
     243         [ #  # ]:          0 :                 WARN_ON_ONCE(PTR_ERR(old) != -ENOMEM);
     244                 :          0 :                 return PTR_ERR(old);
     245                 :            :         }
     246                 :            : 
     247                 :            :         /*
     248                 :            :          * rcu_assign_pointer has as smp_store_release() which makes sure
     249                 :            :          * that the new probe callbacks array is consistent before setting
     250                 :            :          * a pointer to it.  This array is referenced by __DO_TRACE from
     251                 :            :          * include/linux/tracepoint.h using rcu_dereference_sched().
     252                 :            :          */
     253                 :          0 :         rcu_assign_pointer(tp->funcs, tp_funcs);
     254         [ #  # ]:          0 :         if (!static_key_enabled(&tp->key))
     255                 :          0 :                 static_key_slow_inc(&tp->key);
     256                 :          0 :         release_probes(old);
     257                 :          0 :         return 0;
     258                 :            : }
     259                 :            : 
     260                 :            : /*
     261                 :            :  * Remove a probe function from a tracepoint.
     262                 :            :  * Note: only waiting an RCU period after setting elem->call to the empty
     263                 :            :  * function insures that the original callback is not used anymore. This insured
     264                 :            :  * by preempt_disable around the call site.
     265                 :            :  */
     266                 :          0 : static int tracepoint_remove_func(struct tracepoint *tp,
     267                 :            :                 struct tracepoint_func *func)
     268                 :            : {
     269                 :          0 :         struct tracepoint_func *old, *tp_funcs;
     270                 :            : 
     271                 :          0 :         tp_funcs = rcu_dereference_protected(tp->funcs,
     272                 :            :                         lockdep_is_held(&tracepoints_mutex));
     273                 :          0 :         old = func_remove(&tp_funcs, func);
     274         [ #  # ]:          0 :         if (IS_ERR(old)) {
     275         [ #  # ]:          0 :                 WARN_ON_ONCE(PTR_ERR(old) != -ENOMEM);
     276                 :          0 :                 return PTR_ERR(old);
     277                 :            :         }
     278                 :            : 
     279         [ #  # ]:          0 :         if (!tp_funcs) {
     280                 :            :                 /* Removed last function */
     281   [ #  #  #  # ]:          0 :                 if (tp->unregfunc && static_key_enabled(&tp->key))
     282                 :          0 :                         tp->unregfunc();
     283                 :            : 
     284         [ #  # ]:          0 :                 if (static_key_enabled(&tp->key))
     285                 :          0 :                         static_key_slow_dec(&tp->key);
     286                 :            :         }
     287                 :          0 :         rcu_assign_pointer(tp->funcs, tp_funcs);
     288                 :          0 :         release_probes(old);
     289                 :          0 :         return 0;
     290                 :            : }
     291                 :            : 
     292                 :            : /**
     293                 :            :  * tracepoint_probe_register_prio -  Connect a probe to a tracepoint with priority
     294                 :            :  * @tp: tracepoint
     295                 :            :  * @probe: probe handler
     296                 :            :  * @data: tracepoint data
     297                 :            :  * @prio: priority of this function over other registered functions
     298                 :            :  *
     299                 :            :  * Returns 0 if ok, error value on error.
     300                 :            :  * Note: if @tp is within a module, the caller is responsible for
     301                 :            :  * unregistering the probe before the module is gone. This can be
     302                 :            :  * performed either with a tracepoint module going notifier, or from
     303                 :            :  * within module exit functions.
     304                 :            :  */
     305                 :          0 : int tracepoint_probe_register_prio(struct tracepoint *tp, void *probe,
     306                 :            :                                    void *data, int prio)
     307                 :            : {
     308                 :          0 :         struct tracepoint_func tp_func;
     309                 :          0 :         int ret;
     310                 :            : 
     311                 :          0 :         mutex_lock(&tracepoints_mutex);
     312                 :          0 :         tp_func.func = probe;
     313                 :          0 :         tp_func.data = data;
     314                 :          0 :         tp_func.prio = prio;
     315                 :          0 :         ret = tracepoint_add_func(tp, &tp_func, prio);
     316                 :          0 :         mutex_unlock(&tracepoints_mutex);
     317                 :          0 :         return ret;
     318                 :            : }
     319                 :            : EXPORT_SYMBOL_GPL(tracepoint_probe_register_prio);
     320                 :            : 
     321                 :            : /**
     322                 :            :  * tracepoint_probe_register -  Connect a probe to a tracepoint
     323                 :            :  * @tp: tracepoint
     324                 :            :  * @probe: probe handler
     325                 :            :  * @data: tracepoint data
     326                 :            :  *
     327                 :            :  * Returns 0 if ok, error value on error.
     328                 :            :  * Note: if @tp is within a module, the caller is responsible for
     329                 :            :  * unregistering the probe before the module is gone. This can be
     330                 :            :  * performed either with a tracepoint module going notifier, or from
     331                 :            :  * within module exit functions.
     332                 :            :  */
     333                 :          0 : int tracepoint_probe_register(struct tracepoint *tp, void *probe, void *data)
     334                 :            : {
     335                 :          0 :         return tracepoint_probe_register_prio(tp, probe, data, TRACEPOINT_DEFAULT_PRIO);
     336                 :            : }
     337                 :            : EXPORT_SYMBOL_GPL(tracepoint_probe_register);
     338                 :            : 
     339                 :            : /**
     340                 :            :  * tracepoint_probe_unregister -  Disconnect a probe from a tracepoint
     341                 :            :  * @tp: tracepoint
     342                 :            :  * @probe: probe function pointer
     343                 :            :  * @data: tracepoint data
     344                 :            :  *
     345                 :            :  * Returns 0 if ok, error value on error.
     346                 :            :  */
     347                 :          0 : int tracepoint_probe_unregister(struct tracepoint *tp, void *probe, void *data)
     348                 :            : {
     349                 :          0 :         struct tracepoint_func tp_func;
     350                 :          0 :         int ret;
     351                 :            : 
     352                 :          0 :         mutex_lock(&tracepoints_mutex);
     353                 :          0 :         tp_func.func = probe;
     354                 :          0 :         tp_func.data = data;
     355                 :          0 :         ret = tracepoint_remove_func(tp, &tp_func);
     356                 :          0 :         mutex_unlock(&tracepoints_mutex);
     357                 :          0 :         return ret;
     358                 :            : }
     359                 :            : EXPORT_SYMBOL_GPL(tracepoint_probe_unregister);
     360                 :            : 
     361                 :          0 : static void for_each_tracepoint_range(
     362                 :            :                 tracepoint_ptr_t *begin, tracepoint_ptr_t *end,
     363                 :            :                 void (*fct)(struct tracepoint *tp, void *priv),
     364                 :            :                 void *priv)
     365                 :            : {
     366                 :          0 :         tracepoint_ptr_t *iter;
     367                 :            : 
     368                 :          0 :         if (!begin)
     369                 :            :                 return;
     370   [ #  #  #  # ]:          0 :         for (iter = begin; iter < end; iter++)
     371                 :          0 :                 fct(tracepoint_ptr_deref(iter), priv);
     372                 :            : }
     373                 :            : 
     374                 :            : #ifdef CONFIG_MODULES
     375                 :          0 : bool trace_module_has_bad_taint(struct module *mod)
     376                 :            : {
     377                 :          0 :         return mod->taints & ~((1 << TAINT_OOT_MODULE) | (1 << TAINT_CRAP) |
     378                 :            :                                (1 << TAINT_UNSIGNED_MODULE));
     379                 :            : }
     380                 :            : 
     381                 :            : static BLOCKING_NOTIFIER_HEAD(tracepoint_notify_list);
     382                 :            : 
     383                 :            : /**
     384                 :            :  * register_tracepoint_notifier - register tracepoint coming/going notifier
     385                 :            :  * @nb: notifier block
     386                 :            :  *
     387                 :            :  * Notifiers registered with this function are called on module
     388                 :            :  * coming/going with the tracepoint_module_list_mutex held.
     389                 :            :  * The notifier block callback should expect a "struct tp_module" data
     390                 :            :  * pointer.
     391                 :            :  */
     392                 :          0 : int register_tracepoint_module_notifier(struct notifier_block *nb)
     393                 :            : {
     394                 :          0 :         struct tp_module *tp_mod;
     395                 :          0 :         int ret;
     396                 :            : 
     397                 :          0 :         mutex_lock(&tracepoint_module_list_mutex);
     398                 :          0 :         ret = blocking_notifier_chain_register(&tracepoint_notify_list, nb);
     399         [ #  # ]:          0 :         if (ret)
     400                 :          0 :                 goto end;
     401         [ #  # ]:          0 :         list_for_each_entry(tp_mod, &tracepoint_module_list, list)
     402                 :          0 :                 (void) nb->notifier_call(nb, MODULE_STATE_COMING, tp_mod);
     403                 :          0 : end:
     404                 :          0 :         mutex_unlock(&tracepoint_module_list_mutex);
     405                 :          0 :         return ret;
     406                 :            : }
     407                 :            : EXPORT_SYMBOL_GPL(register_tracepoint_module_notifier);
     408                 :            : 
     409                 :            : /**
     410                 :            :  * unregister_tracepoint_notifier - unregister tracepoint coming/going notifier
     411                 :            :  * @nb: notifier block
     412                 :            :  *
     413                 :            :  * The notifier block callback should expect a "struct tp_module" data
     414                 :            :  * pointer.
     415                 :            :  */
     416                 :          0 : int unregister_tracepoint_module_notifier(struct notifier_block *nb)
     417                 :            : {
     418                 :          0 :         struct tp_module *tp_mod;
     419                 :          0 :         int ret;
     420                 :            : 
     421                 :          0 :         mutex_lock(&tracepoint_module_list_mutex);
     422                 :          0 :         ret = blocking_notifier_chain_unregister(&tracepoint_notify_list, nb);
     423         [ #  # ]:          0 :         if (ret)
     424                 :          0 :                 goto end;
     425         [ #  # ]:          0 :         list_for_each_entry(tp_mod, &tracepoint_module_list, list)
     426                 :          0 :                 (void) nb->notifier_call(nb, MODULE_STATE_GOING, tp_mod);
     427                 :          0 : end:
     428                 :          0 :         mutex_unlock(&tracepoint_module_list_mutex);
     429                 :          0 :         return ret;
     430                 :            : 
     431                 :            : }
     432                 :            : EXPORT_SYMBOL_GPL(unregister_tracepoint_module_notifier);
     433                 :            : 
     434                 :            : /*
     435                 :            :  * Ensure the tracer unregistered the module's probes before the module
     436                 :            :  * teardown is performed. Prevents leaks of probe and data pointers.
     437                 :            :  */
     438                 :          0 : static void tp_module_going_check_quiescent(struct tracepoint *tp, void *priv)
     439                 :            : {
     440         [ #  # ]:          0 :         WARN_ON_ONCE(tp->funcs);
     441                 :          0 : }
     442                 :            : 
     443                 :         11 : static int tracepoint_module_coming(struct module *mod)
     444                 :            : {
     445                 :         11 :         struct tp_module *tp_mod;
     446                 :         11 :         int ret = 0;
     447                 :            : 
     448         [ -  + ]:         11 :         if (!mod->num_tracepoints)
     449                 :            :                 return 0;
     450                 :            : 
     451                 :            :         /*
     452                 :            :          * We skip modules that taint the kernel, especially those with different
     453                 :            :          * module headers (for forced load), to make sure we don't cause a crash.
     454                 :            :          * Staging, out-of-tree, and unsigned GPL modules are fine.
     455                 :            :          */
     456         [ #  # ]:          0 :         if (trace_module_has_bad_taint(mod))
     457                 :            :                 return 0;
     458                 :          0 :         mutex_lock(&tracepoint_module_list_mutex);
     459                 :          0 :         tp_mod = kmalloc(sizeof(struct tp_module), GFP_KERNEL);
     460         [ #  # ]:          0 :         if (!tp_mod) {
     461                 :          0 :                 ret = -ENOMEM;
     462                 :          0 :                 goto end;
     463                 :            :         }
     464                 :          0 :         tp_mod->mod = mod;
     465                 :          0 :         list_add_tail(&tp_mod->list, &tracepoint_module_list);
     466                 :          0 :         blocking_notifier_call_chain(&tracepoint_notify_list,
     467                 :            :                         MODULE_STATE_COMING, tp_mod);
     468                 :          0 : end:
     469                 :          0 :         mutex_unlock(&tracepoint_module_list_mutex);
     470                 :          0 :         return ret;
     471                 :            : }
     472                 :            : 
     473                 :          0 : static void tracepoint_module_going(struct module *mod)
     474                 :            : {
     475                 :          0 :         struct tp_module *tp_mod;
     476                 :            : 
     477         [ #  # ]:          0 :         if (!mod->num_tracepoints)
     478                 :            :                 return;
     479                 :            : 
     480                 :          0 :         mutex_lock(&tracepoint_module_list_mutex);
     481         [ #  # ]:          0 :         list_for_each_entry(tp_mod, &tracepoint_module_list, list) {
     482         [ #  # ]:          0 :                 if (tp_mod->mod == mod) {
     483                 :          0 :                         blocking_notifier_call_chain(&tracepoint_notify_list,
     484                 :            :                                         MODULE_STATE_GOING, tp_mod);
     485                 :          0 :                         list_del(&tp_mod->list);
     486                 :          0 :                         kfree(tp_mod);
     487                 :            :                         /*
     488                 :            :                          * Called the going notifier before checking for
     489                 :            :                          * quiescence.
     490                 :            :                          */
     491                 :          0 :                         for_each_tracepoint_range(mod->tracepoints_ptrs,
     492         [ #  # ]:          0 :                                 mod->tracepoints_ptrs + mod->num_tracepoints,
     493                 :            :                                 tp_module_going_check_quiescent, NULL);
     494                 :            :                         break;
     495                 :            :                 }
     496                 :            :         }
     497                 :            :         /*
     498                 :            :          * In the case of modules that were tainted at "coming", we'll simply
     499                 :            :          * walk through the list without finding it. We cannot use the "tainted"
     500                 :            :          * flag on "going", in case a module taints the kernel only after being
     501                 :            :          * loaded.
     502                 :            :          */
     503                 :          0 :         mutex_unlock(&tracepoint_module_list_mutex);
     504                 :            : }
     505                 :            : 
     506                 :         22 : static int tracepoint_module_notify(struct notifier_block *self,
     507                 :            :                 unsigned long val, void *data)
     508                 :            : {
     509                 :         22 :         struct module *mod = data;
     510                 :         22 :         int ret = 0;
     511                 :            : 
     512      [ +  -  + ]:         22 :         switch (val) {
     513                 :         11 :         case MODULE_STATE_COMING:
     514                 :         11 :                 ret = tracepoint_module_coming(mod);
     515                 :         11 :                 break;
     516                 :            :         case MODULE_STATE_LIVE:
     517                 :            :                 break;
     518                 :          0 :         case MODULE_STATE_GOING:
     519                 :          0 :                 tracepoint_module_going(mod);
     520                 :          0 :                 break;
     521                 :            :         case MODULE_STATE_UNFORMED:
     522                 :            :                 break;
     523                 :            :         }
     524                 :         22 :         return ret;
     525                 :            : }
     526                 :            : 
     527                 :            : static struct notifier_block tracepoint_module_nb = {
     528                 :            :         .notifier_call = tracepoint_module_notify,
     529                 :            :         .priority = 0,
     530                 :            : };
     531                 :            : 
     532                 :         11 : static __init int init_tracepoints(void)
     533                 :            : {
     534                 :         11 :         int ret;
     535                 :            : 
     536                 :         11 :         ret = register_module_notifier(&tracepoint_module_nb);
     537         [ -  + ]:         11 :         if (ret)
     538                 :          0 :                 pr_warn("Failed to register tracepoint module enter notifier\n");
     539                 :            : 
     540                 :         11 :         return ret;
     541                 :            : }
     542                 :            : __initcall(init_tracepoints);
     543                 :            : #endif /* CONFIG_MODULES */
     544                 :            : 
     545                 :            : /**
     546                 :            :  * for_each_kernel_tracepoint - iteration on all kernel tracepoints
     547                 :            :  * @fct: callback
     548                 :            :  * @priv: private data
     549                 :            :  */
     550                 :          0 : void for_each_kernel_tracepoint(void (*fct)(struct tracepoint *tp, void *priv),
     551                 :            :                 void *priv)
     552                 :            : {
     553         [ #  # ]:          0 :         for_each_tracepoint_range(__start___tracepoints_ptrs,
     554                 :            :                 __stop___tracepoints_ptrs, fct, priv);
     555                 :          0 : }
     556                 :            : EXPORT_SYMBOL_GPL(for_each_kernel_tracepoint);
     557                 :            : 
     558                 :            : #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
     559                 :            : 
     560                 :            : /* NB: reg/unreg are called while guarded with the tracepoints_mutex */
     561                 :            : static int sys_tracepoint_refcount;
     562                 :            : 
     563                 :          0 : int syscall_regfunc(void)
     564                 :            : {
     565                 :          0 :         struct task_struct *p, *t;
     566                 :            : 
     567         [ #  # ]:          0 :         if (!sys_tracepoint_refcount) {
     568                 :          0 :                 read_lock(&tasklist_lock);
     569   [ #  #  #  # ]:          0 :                 for_each_process_thread(p, t) {
     570                 :          0 :                         set_tsk_thread_flag(t, TIF_SYSCALL_TRACEPOINT);
     571                 :            :                 }
     572                 :          0 :                 read_unlock(&tasklist_lock);
     573                 :            :         }
     574                 :          0 :         sys_tracepoint_refcount++;
     575                 :            : 
     576                 :          0 :         return 0;
     577                 :            : }
     578                 :            : 
     579                 :          0 : void syscall_unregfunc(void)
     580                 :            : {
     581                 :          0 :         struct task_struct *p, *t;
     582                 :            : 
     583                 :          0 :         sys_tracepoint_refcount--;
     584         [ #  # ]:          0 :         if (!sys_tracepoint_refcount) {
     585                 :          0 :                 read_lock(&tasklist_lock);
     586   [ #  #  #  # ]:          0 :                 for_each_process_thread(p, t) {
     587                 :          0 :                         clear_tsk_thread_flag(t, TIF_SYSCALL_TRACEPOINT);
     588                 :            :                 }
     589                 :          0 :                 read_unlock(&tasklist_lock);
     590                 :            :         }
     591                 :          0 : }
     592                 :            : #endif

Generated by: LCOV version 1.14