android_kernel_msm-6.1_noth.../kernel
Linus Torvalds 2c4b1ec683 Fix tracepoint race between static_call and callback data
As callbacks to a tracepoint are paired with the data that is passed in when
 the callback is registered to the tracepoint, it must have that data passed
 to the callback when the tracepoint is triggered, else bad things will
 happen. To keep the two together, they are both assigned to a tracepoint
 structure and added to an array. The tracepoint call site will dereference
 the structure (via RCU) and call the callback in that structure along with
 the data in that structure. This keeps the callback and data tightly
 coupled.
 
 Because of the overhead that retpolines have on tracepoint callbacks, if
 there's only one callback attached to a tracepoint (a common case), then it
 is called via a static call (code modified to do a direct call instead of an
 indirect call). But to implement this, the data had to be decoupled from the
 callback, as now the callback is implemented via a direct call from the
 static call and not an indirect call from the dereferenced structure.
 
 Note, the static call only calls a callback used when there's a single
 callback attached to the tracepoint. If more than one callback is attached
 to the same tracepoint, then the static call will call an iterator
 function that goes back to dereferencing the structure keeping the callback
 and its data tightly coupled again.
 
 Issues can arise when going from 0 callbacks to one, as the static call is
 assigned to the callback, and it must take care that the data passed to it
 is loaded before the static call calls the callback. Going from 1 to 2
 callbacks is not an issue, as long as the static call is updated to the
 iterator before the tracepoint structure array is updated via RCU. Going
 from 2 to more or back down to 2 is not an issue as the iterator can handle
 all theses cases. But going from 2 to 1, care must be taken as the static
 call is now calling a callback and the data that is loaded must be the data
 for that callback.
 
 Care was taken to ensure the callback and data would be in-sync, but after
 a bug was reported, it became clear that not enough was done to make sure
 that was the case. These changes address this.
 
 The first change is to compare the old and new data instead of the old and
 new callback, as it's the data that can corrupt the callback, even if the
 callback is the same (something getting freed).
 
 The next change is to convert these transitions into states, to make it
 easier to know when a synchronization is needed, and to perform those
 synchronizations. The problem with this patch is that it slows down
 disabling all events from under a second, to making it take over 10 seconds
 to do the same work. But that is addressed in the final patch.
 
 The final patch uses the RCU state functions to keep track of the RCU state
 between the transitions, and only needs to perform the synchronization if an
 RCU synchronization hasn't been done already. This brings the performance of
 disabling all events back to its original value. That's because no
 synchronization is required between disabling tracepoints but is required
 when enabling a tracepoint after its been disabled. If an RCU
 synchronization happens after the tracepoint is disabled, and before it is
 re-enabled, there's no need to do the synchronization again.
 
 Both the second and third patch have subtle complexities that they are
 separated into two patches. But because the second patch causes such a
 regression in performance, the third patch adds a "Fixes" tag to the second
 patch, such that the two must be backported together and not just the second
 patch.
 -----BEGIN PGP SIGNATURE-----
 
 iIoEABYIADIWIQRRSw7ePDh/lE+zeZMp5XQQmuv6qgUCYQ15TBQccm9zdGVkdEBn
 b29kbWlzLm9yZwAKCRAp5XQQmuv6qnmmAP4hoA34CDr5hrd8mYLeKptW63f5Nd1w
 fVZjprfa1wJhZAEAq39OeRCT4Fb2hIeZNBNUnLU90f+J6NH5QFDEhW+CkAI=
 =JcZS
 -----END PGP SIGNATURE-----

Merge tag 'trace-v5.14-rc4-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace

Pull tracing fixes from Steven Rostedt:
 "Fix tracepoint race between static_call and callback data

  As callbacks to a tracepoint are paired with the data that is passed
  in when the callback is registered to the tracepoint, it must have
  that data passed to the callback when the tracepoint is triggered,
  else bad things will happen. To keep the two together, they are both
  assigned to a tracepoint structure and added to an array. The
  tracepoint call site will dereference the structure (via RCU) and call
  the callback in that structure along with the data in that structure.
  This keeps the callback and data tightly coupled.

  Because of the overhead that retpolines have on tracepoint callbacks,
  if there's only one callback attached to a tracepoint (a common case),
  then it is called via a static call (code modified to do a direct call
  instead of an indirect call). But to implement this, the data had to
  be decoupled from the callback, as now the callback is implemented via
  a direct call from the static call and not an indirect call from the
  dereferenced structure.

  Note, the static call only calls a callback used when there's a single
  callback attached to the tracepoint. If more than one callback is
  attached to the same tracepoint, then the static call will call an
  iterator function that goes back to dereferencing the structure
  keeping the callback and its data tightly coupled again.

  Issues can arise when going from 0 callbacks to one, as the static
  call is assigned to the callback, and it must take care that the data
  passed to it is loaded before the static call calls the callback.
  Going from 1 to 2 callbacks is not an issue, as long as the static
  call is updated to the iterator before the tracepoint structure array
  is updated via RCU. Going from 2 to more or back down to 2 is not an
  issue as the iterator can handle all theses cases. But going from 2 to
  1, care must be taken as the static call is now calling a callback and
  the data that is loaded must be the data for that callback.

  Care was taken to ensure the callback and data would be in-sync, but
  after a bug was reported, it became clear that not enough was done to
  make sure that was the case. These changes address this.

  The first change is to compare the old and new data instead of the old
  and new callback, as it's the data that can corrupt the callback, even
  if the callback is the same (something getting freed).

  The next change is to convert these transitions into states, to make
  it easier to know when a synchronization is needed, and to perform
  those synchronizations. The problem with this patch is that it slows
  down disabling all events from under a second, to making it take over
  10 seconds to do the same work. But that is addressed in the final
  patch.

  The final patch uses the RCU state functions to keep track of the RCU
  state between the transitions, and only needs to perform the
  synchronization if an RCU synchronization hasn't been done already.
  This brings the performance of disabling all events back to its
  original value. That's because no synchronization is required between
  disabling tracepoints but is required when enabling a tracepoint after
  its been disabled. If an RCU synchronization happens after the
  tracepoint is disabled, and before it is re-enabled, there's no need
  to do the synchronization again.

  Both the second and third patch have subtle complexities that they are
  separated into two patches. But because the second patch causes such a
  regression in performance, the third patch adds a "Fixes" tag to the
  second patch, such that the two must be backported together and not
  just the second patch"

* tag 'trace-v5.14-rc4-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace:
  tracepoint: Use rcu get state and cond sync for static call updates
  tracepoint: Fix static call function vs data state mismatch
  tracepoint: static call: Compare data on transition from 2->1 callees
2021-08-06 12:36:46 -07:00
..
bpf bpf: Fix leakage due to insufficient speculative store bypass mitigation 2021-07-29 00:27:52 +02:00
cgroup cgroup1: fix leaked context root causing sporadic NULL deref in LTP 2021-07-21 06:39:20 -10:00
configs drivers/char: remove /dev/kmem for good 2021-05-07 00:26:34 -07:00
debug kernel: debug: Fix unreachable code in gdb_serial_stub() 2021-07-12 11:03:35 -05:00
dma dma-mapping: handle vmalloc addresses in dma_common_{mmap,get_sgtable} 2021-07-16 11:30:26 +02:00
entry tick/nohz: Only check for RCU deferred wakeup on user/guest entry when needed 2021-05-31 10:14:49 +02:00
events Merge branch 'akpm' (patches from Andrew) 2021-06-29 17:29:11 -07:00
gcov Kconfig: Introduce ARCH_WANTS_NO_INSTR and CC_HAS_NO_PROFILE_FN_ATTR 2021-06-22 11:07:18 -07:00
irq irqchip fixes for 5.14, take #1 2021-07-09 15:35:13 +02:00
kcsan Merge branch 'kcsan.2021.05.18a' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu 2021-07-04 12:29:16 -07:00
livepatch Livepatching changes for 5.13 2021-04-27 18:14:38 -07:00
locking Locking fixes: 2021-07-11 11:06:09 -07:00
power PM: hibernate: disable when there are active secretmem users 2021-07-08 11:48:21 -07:00
printk printk changes for 5.14 2021-06-29 12:07:18 -07:00
rcu rcu: Fix pr_info() formats and values in show_rcu_gp_kthreads() 2021-07-06 15:53:12 -07:00
sched Three fixes: 2021-07-11 11:13:57 -07:00
time timers: Fix get_next_timer_interrupt() with no timers pending 2021-07-15 01:23:54 +02:00
trace tracing: Quiet smp_processor_id() use in preemptable warning in hwlat 2021-08-05 09:27:31 -04:00
.gitignore .gitignore: prefix local generated files with a slash 2021-05-02 00:43:35 +09:00
acct.c kernel/acct.c: use #elif instead of #end and #elif 2020-12-15 22:46:15 -08:00
async.c kernel/async.c: remove async_unregister_domain() 2021-05-07 00:26:33 -07:00
audit.c lsm: separate security_task_getsecid() into subjective and objective variants 2021-03-22 15:23:32 -04:00
audit.h audit: remove trailing spaces and tabs 2021-06-10 20:59:05 -04:00
audit_fsnotify.c audit_alloc_mark(): don't open-code ERR_CAST() 2021-02-23 10:25:27 -05:00
audit_tree.c audit: Use list_move instead of list_del/list_add 2021-06-08 22:18:35 -04:00
audit_watch.c fsnotify: generalize handle_inode_event() 2020-12-03 14:58:35 +01:00
auditfilter.c lsm: separate security_task_getsecid() into subjective and objective variants 2021-03-22 15:23:32 -04:00
auditsc.c audit: remove trailing spaces and tabs 2021-06-10 20:59:05 -04:00
backtracetest.c
bounds.c
capability.c capability: handle idmapped mounts 2021-01-24 14:27:16 +01:00
cfi.c add support for Clang CFI 2021-04-08 16:04:20 -07:00
compat.c
configs.c
context_tracking.c
cpu.c A fix for the CPU hotplug and cpusets interaction: 2021-06-29 12:23:02 -07:00
cpu_pm.c
crash_core.c kdump: use vmlinux_build_id to simplify 2021-07-08 11:48:22 -07:00
crash_dump.c
cred.c Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace 2021-06-28 20:39:26 -07:00
delayacct.c delayacct: Add sysctl to enable at runtime 2021-05-12 11:43:25 +02:00
dma.c
exec_domain.c
exit.c Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace 2021-06-28 20:39:26 -07:00
extable.c
fail_function.c fault-injection: handle EI_ETYPE_TRUE 2020-12-15 22:46:19 -08:00
fork.c Merge branch 'akpm' (patches from Andrew) 2021-06-29 17:29:11 -07:00
freezer.c sched: Add get_current_state() 2021-06-18 11:43:08 +02:00
futex.c Locking changes for this cycle: 2021-06-28 11:45:29 -07:00
gen_kheaders.sh kbuild: clean up ${quiet} checks in shell scripts 2021-05-27 04:01:50 +09:00
groups.c groups: simplify struct group_info allocation 2021-02-26 09:41:03 -08:00
hung_task.c Merge branch 'akpm' (patches from Andrew) 2021-07-02 12:08:10 -07:00
iomem.c
irq_work.c irq_work: Make irq_work_queue() NMI-safe again 2021-06-10 10:00:08 +02:00
jump_label.c jump_label: Fix jump_label_text_reserved() vs __init 2021-07-05 10:46:20 +02:00
kallsyms.c module: add printk formats to add module build ID to stacktraces 2021-07-08 11:48:22 -07:00
kcmp.c Merge branch 'exec-update-lock-for-v5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace 2020-12-15 19:36:48 -08:00
Kconfig.freezer
Kconfig.hz
Kconfig.locks
Kconfig.preempt sched/core: Disable CONFIG_SCHED_CORE by default 2021-06-28 22:43:05 +02:00
kcov.c kernel: make kcov_common_handle consider the current context 2020-11-02 18:00:20 -08:00
kexec.c
kexec_core.c kernel.h: split out panic and oops helpers 2021-07-01 11:06:04 -07:00
kexec_elf.c
kexec_file.c kernel: kexec_file: fix error return code of kexec_calculate_store_digests() 2021-05-07 00:26:32 -07:00
kexec_internal.h kexec: move machine_kexec_post_load() to public interface 2021-02-22 12:33:26 +00:00
kheaders.c
kmod.c modules: add CONFIG_MODPROBE_PATH 2021-05-07 00:26:33 -07:00
kprobes.c Locking fixes: 2021-07-11 11:06:09 -07:00
ksysfs.c
kthread.c Merge branch 'akpm' (patches from Andrew) 2021-06-29 17:29:11 -07:00
latencytop.c
Makefile kbuild: update config_data.gz only when the content of .config is changed 2021-05-02 00:43:35 +09:00
module-internal.h
module.c module: add printk formats to add module build ID to stacktraces 2021-07-08 11:48:22 -07:00
module_signature.c module: harden ELF info handling 2021-01-19 10:24:45 +01:00
module_signing.c module: harden ELF info handling 2021-01-19 10:24:45 +01:00
notifier.c
nsproxy.c fixes-v5.11 2020-12-14 16:40:27 -08:00
padata.c
panic.c kernel.h: split out panic and oops helpers 2021-07-01 11:06:04 -07:00
params.c Modules updates for v5.11 2020-12-17 13:01:31 -08:00
pid.c Merge branch 'exec-update-lock-for-v5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace 2020-12-15 19:36:48 -08:00
pid_namespace.c fixes-v5.11 2020-12-14 16:40:27 -08:00
profile.c kernel: Initialize cpumask before parsing 2021-04-10 13:35:54 +02:00
ptrace.c sched: Change task_struct::state 2021-06-18 11:43:09 +02:00
range.c
reboot.c reboot: Add hardware protection power-off 2021-06-21 13:08:36 +01:00
regset.c
relay.c relay: allow the use of const callback structs 2020-12-15 22:46:18 -08:00
resource.c kernel/resource: fix return code check in __request_free_mem_region 2021-05-14 19:41:32 -07:00
resource_kunit.c resource: provide meaningful MODULE_LICENSE() in test suite 2020-11-25 18:52:35 +01:00
rseq.c rseq: Optimise rseq_get_rseq_cs() and clear_rseq_cs() 2021-04-14 18:04:09 +02:00
scftorture.c scftorture: Avoid false-positive warnings in scftorture_invoker() 2021-07-06 12:37:55 -07:00
scs.c scs: switch to vmapped shadow stacks 2020-12-01 10:30:28 +00:00
seccomp.c seccomp: Support atomic "addfd + send reply" 2021-06-28 12:49:52 -07:00
signal.c Fix UCOUNT_RLIMIT_SIGPENDING counter leak 2021-07-08 11:43:24 -07:00
smp.c smp: Fix smp_call_function_single_async prototype 2021-05-06 15:33:49 +02:00
smpboot.c smpboot: fix duplicate and misplaced inlining directive 2021-07-25 11:06:37 -07:00
smpboot.h
softirq.c sched: Introduce task_is_running() 2021-06-18 11:43:07 +02:00
stackleak.c
stacktrace.c
static_call.c static_call: Fix static_call_text_reserved() vs __init 2021-07-05 10:46:33 +02:00
stop_machine.c stop_machine: Add caller debug info to queue_stop_cpus_work 2021-03-23 16:01:58 +01:00
sys.c Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace 2021-06-28 20:39:26 -07:00
sys_ni.c mm: introduce memfd_secret system call to create "secret" memory areas 2021-07-08 11:48:21 -07:00
sysctl-test.c kernel/sysctl-test: Remove some casts which are no-longer required 2021-06-23 16:41:24 -06:00
sysctl.c Merge branch 'akpm' (patches from Andrew) 2021-07-02 12:08:10 -07:00
task_work.c kasan: record task_work_add() call stack 2021-04-30 11:20:42 -07:00
taskstats.c treewide: rename nla_strlcpy to nla_strscpy. 2020-11-16 08:08:54 -08:00
test_kprobes.c
torture.c torture: Replace torture_init_begin string with %s 2021-03-08 14:22:28 -08:00
tracepoint.c tracepoint: Use rcu get state and cond sync for static call updates 2021-08-06 10:54:41 -04:00
tsacct.c
ucount.c ucounts: Fix race condition between alloc_ucounts and put_ucounts 2021-07-28 12:31:51 -05:00
uid16.c
uid16.h
umh.c kernel/umh.c: fix some spelling mistakes 2021-05-07 00:26:34 -07:00
up.c A set of locking related fixes and updates: 2021-05-09 13:07:03 -07:00
user-return-notifier.c
user.c Reimplement RLIMIT_MEMLOCK on top of ucounts 2021-04-30 14:14:02 -05:00
user_namespace.c Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace 2021-06-28 20:39:26 -07:00
usermode_driver.c Merge branch 'work.namei' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2021-07-03 11:41:14 -07:00
utsname.c
utsname_sysctl.c
watch_queue.c watch_queue: rectify kernel-doc for init_watch() 2021-01-26 11:16:34 +00:00
watchdog.c kernel: watchdog: modify the explanation related to watchdog thread 2021-06-29 10:53:46 -07:00
watchdog_hld.c
workqueue.c workqueue: fix UAF in pwq_unbound_release_workfn() 2021-07-21 06:42:31 -10:00
workqueue_internal.h