суббота, 28 августа 2021 г.

linux kernel tracing

It`s hard to believe but linux kernel has almost exact copy of windows ETW - event tracing. It is just as difficult to make it work, it is poorly documented, very complex and fragile. And yes, as you can guess - it also can`t show who and which parts of it in use. So I wrote some code to dump registered funcs in tracepoints and to check file ops for files in /sys/kernel/tracing/events

Lets start with tracepoints. As you see this structure has strange looked list of functions in field funcs, and calling happens in functions like event_triggers_call. How we can find this tracepoints? Well,  they stored in trace_event_call->tp and array of pointers to trace_event_call located between symbols __start_ftrace_events__stop_ftrace_events. Unfortunately all this treasures located in discardable section .init.data. But because they were all declared in the same manner we can find them by name - all symbols with prefix __tracepoint_ is what we need. So some examples (you can run lkmem -c -t vmlinux system.map to get this):

 __tracepoint_sys_enter at 0xffffffff8b82e340: enabled 0 cnt 0
  regfunc 0xffffffff8a192330 - kernel!syscall_regfunc
  unregfunc 0xffffffff8a1923f0 - kernel!syscall_unregfunc


Well, no clients right now - cnt 0

Next about /sys/kernel/tracing/events files (this is perverted inhuman interface to manage trace events). I just dumping file->f_path.dentry->d_inode->i_fop for each such file. Sample of output (you can achieve this with lkmem -s vmlinux system.map path_to_some_sys_kernel_tracing_file):


res /sys/kernel/tracing/events/alarmtimer/alarmtimer_cancel/enable: (nil)
 inode: 0xffffa07f9ae86be0
 s_op: 0xffffffff8b0a3000 - kernel!tracefs_super_operations
 inode->i_fop: 0xffffffff8b06b4c0 - kernel!ftrace_enable_fops
res /sys/kernel/tracing/events/alarmtimer/alarmtimer_cancel/filter: (nil)
 inode: 0xffffa07f9ae877c0
 s_op: 0xffffffff8b0a3000 - kernel!tracefs_super_operations
 inode->i_fop: 0xffffffff8b06b160 - kernel!ftrace_event_filter_fops
res /sys/kernel/tracing/events/alarmtimer/alarmtimer_cancel/format: (nil)
 inode: 0xffffa07f9ae86980
 s_op: 0xffffffff8b0a3000 - kernel!tracefs_super_operations
 inode->i_fop: 0xffffffff8b06b3a0 - kernel!ftrace_event_format_fops

Why it`s very important to check this table? Lets assume that some bad guy want to hide something from you. One way this can be done is replace pointer to file_operations to your own, now if somebody want enable trace event with
 echo 1 > /sys/kernel/debug/tracing/events/sched/sched_wakeup/enable
your version of event_enable_write will be called. And in the opposite direction when somebody wants to check is tracing enabled - calling your version of event_enable_read. For obvious reasons, I will not provide code examples for such patches

Комментариев нет:

Отправить комментарий