}
EXPORT_SYMBOL_GPL(tracepoint_probe_unregister);
- static LIST_HEAD(old_probes);
- static int need_update;
-
- static void tracepoint_add_old_probes(void *old)
- {
- need_update = 1;
- if (old) {
- struct tp_probes *tp_probes = container_of(old,
- struct tp_probes, probes[0]);
- list_add(&tp_probes->u.list, &old_probes);
- }
- }
-
- /**
- * tracepoint_probe_register_noupdate - register a probe but not connect
- * @name: tracepoint name
- * @probe: probe handler
- *
- * caller must call tracepoint_probe_update_all()
- */
- int tracepoint_probe_register_noupdate(const char *name, void *probe,
- void *data)
- {
- struct tracepoint_func *old;
-
- mutex_lock(&tracepoints_mutex);
- old = tracepoint_add_probe(name, probe, data);
- if (IS_ERR(old)) {
- mutex_unlock(&tracepoints_mutex);
- return PTR_ERR(old);
- }
- tracepoint_add_old_probes(old);
- mutex_unlock(&tracepoints_mutex);
- return 0;
- }
- EXPORT_SYMBOL_GPL(tracepoint_probe_register_noupdate);
-
- /**
- * tracepoint_probe_unregister_noupdate - remove a probe but not disconnect
- * @name: tracepoint name
- * @probe: probe function pointer
- *
- * caller must call tracepoint_probe_update_all()
- */
- int tracepoint_probe_unregister_noupdate(const char *name, void *probe,
- void *data)
- {
- struct tracepoint_func *old;
-
- mutex_lock(&tracepoints_mutex);
- old = tracepoint_remove_probe(name, probe, data);
- if (IS_ERR(old)) {
- mutex_unlock(&tracepoints_mutex);
- return PTR_ERR(old);
- }
- tracepoint_add_old_probes(old);
- mutex_unlock(&tracepoints_mutex);
- return 0;
- }
- EXPORT_SYMBOL_GPL(tracepoint_probe_unregister_noupdate);
-
- /**
- * tracepoint_probe_update_all - update tracepoints
- */
- void tracepoint_probe_update_all(void)
- {
- LIST_HEAD(release_probes);
- struct tp_probes *pos, *next;
-
- mutex_lock(&tracepoints_mutex);
- if (!need_update) {
- mutex_unlock(&tracepoints_mutex);
- return;
- }
- if (!list_empty(&old_probes))
- list_replace_init(&old_probes, &release_probes);
- need_update = 0;
- tracepoint_update_probes();
- mutex_unlock(&tracepoints_mutex);
- list_for_each_entry_safe(pos, next, &release_probes, u.list) {
- list_del(&pos->u.list);
- call_rcu_sched(&pos->u.rcu, rcu_free_old_probes);
- }
- }
- EXPORT_SYMBOL_GPL(tracepoint_probe_update_all);
-
- /**
- * tracepoint_get_iter_range - Get a next tracepoint iterator given a range.
- * @tracepoint: current tracepoints (in), next tracepoint (out)
- * @begin: beginning of the range
- * @end: end of the range
- *
- * Returns whether a next tracepoint has been found (1) or not (0).
- * Will return the first tracepoint in the range if the input tracepoint is
- * NULL.
- */
- static int tracepoint_get_iter_range(struct tracepoint * const **tracepoint,
- struct tracepoint * const *begin, struct tracepoint * const *end)
- {
- if (!*tracepoint && begin != end) {
- *tracepoint = begin;
- return 1;
- }
- if (*tracepoint >= begin && *tracepoint < end)
- return 1;
- return 0;
- }
-
- #ifdef CONFIG_MODULES
- static void tracepoint_get_iter(struct tracepoint_iter *iter)
- {
- int found = 0;
- struct tp_module *iter_mod;
-
- /* Core kernel tracepoints */
- if (!iter->module) {
- found = tracepoint_get_iter_range(&iter->tracepoint,
- __start___tracepoints_ptrs,
- __stop___tracepoints_ptrs);
- if (found)
- goto end;
- }
- /* Tracepoints in modules */
- mutex_lock(&tracepoints_mutex);
- list_for_each_entry(iter_mod, &tracepoint_module_list, list) {
- /*
- * Sorted module list
- */
- if (iter_mod < iter->module)
- continue;
- else if (iter_mod > iter->module)
- iter->tracepoint = NULL;
- found = tracepoint_get_iter_range(&iter->tracepoint,
- iter_mod->tracepoints_ptrs,
- iter_mod->tracepoints_ptrs
- + iter_mod->num_tracepoints);
- if (found) {
- iter->module = iter_mod;
- break;
- }
- }
- mutex_unlock(&tracepoints_mutex);
- end:
- if (!found)
- tracepoint_iter_reset(iter);
- }
- #else /* CONFIG_MODULES */
- static void tracepoint_get_iter(struct tracepoint_iter *iter)
- {
- int found = 0;
-
- /* Core kernel tracepoints */
- found = tracepoint_get_iter_range(&iter->tracepoint,
- __start___tracepoints_ptrs,
- __stop___tracepoints_ptrs);
- if (!found)
- tracepoint_iter_reset(iter);
- }
- #endif /* CONFIG_MODULES */
-
- void tracepoint_iter_start(struct tracepoint_iter *iter)
- {
- tracepoint_get_iter(iter);
- }
- EXPORT_SYMBOL_GPL(tracepoint_iter_start);
-
- void tracepoint_iter_next(struct tracepoint_iter *iter)
- {
- iter->tracepoint++;
- /*
- * iter->tracepoint may be invalid because we blindly incremented it.
- * Make sure it is valid by marshalling on the tracepoints, getting the
- * tracepoints from following modules if necessary.
- */
- tracepoint_get_iter(iter);
- }
- EXPORT_SYMBOL_GPL(tracepoint_iter_next);
-
- void tracepoint_iter_stop(struct tracepoint_iter *iter)
- {
- }
- EXPORT_SYMBOL_GPL(tracepoint_iter_stop);
-
- void tracepoint_iter_reset(struct tracepoint_iter *iter)
- {
- #ifdef CONFIG_MODULES
- iter->module = NULL;
- #endif /* CONFIG_MODULES */
- iter->tracepoint = NULL;
- }
- EXPORT_SYMBOL_GPL(tracepoint_iter_reset);
#ifdef CONFIG_MODULES
+bool trace_module_has_bad_taint(struct module *mod)
+{
+ return mod->taints & ~((1 << TAINT_OOT_MODULE) | (1 << TAINT_CRAP));
+}
+
static int tracepoint_module_coming(struct module *mod)
{
- struct tp_module *tp_mod, *iter;
+ struct tp_module *tp_mod;
int ret = 0;
+ if (!mod->num_tracepoints)
+ return 0;
+
/*
* We skip modules that taint the kernel, especially those with different
* module headers (for forced load), to make sure we don't cause a crash.