Linux跟踪技术官方文档
https://docs.kernel.org/trace/index.html
TRACES
Ftrace手动Uprobe Hook
Ftrace手动Kprobe Hook
Ftrace内核Hook技术
#查看debugfs
mount |grep debugfs
debugfs on /sys/kernel/debug type debugfs (rw,nosuid,nodev,noexec,relatime)
#查看tracefs,低版本内核挂载在/sys/kernel/debug/tracing下面
mount |grep tracefs
tracefs on /sys/kernel/tracing type tracefs (rw,nosuid,nodev,noexec,relatime)
tracefs on /sys/kernel/debug/tracing type tracefs (rw,nosuid,nodev,noexec,relatime)
sudo ls /sys/kernel/debug/tracing
#available_filter_functions:linux 内核开启了kprobe,记录了内核中所有可以被探测的列表。
available_events options stack_trace
available_filter_functions osnoise stack_trace_filter
available_tracers per_cpu synthetic_events
buffer_percent printk_formats timestamp_mode
buffer_size_kb README trace
buffer_total_size_kb saved_cmdlines trace_clock
current_tracer saved_cmdlines_size trace_marker
dynamic_events saved_tgids trace_marker_raw
dyn_ftrace_total_info set_event trace_options
enabled_functions set_event_notrace_pid trace_pipe
error_log set_event_pid trace_stat
events set_ftrace_filter tracing_cpumask
free_buffer set_ftrace_notrace tracing_max_latency
function_profile_enabled set_ftrace_notrace_pid tracing_on
hwlat_detector set_ftrace_pid tracing_thresh
instances set_graph_function uprobe_events
kprobe_events set_graph_notrace uprobe_profile
kprobe_profile snapshot
max_graph_depth stack_max_size
#查看kprobe函数个数
#linux 内核中所有可以被kprobe探测的函数列表。
sudo cat /sys/kernel/debug/tracing/available_filter_functions |wc -l
53763
sudo bpftrace -l "kprobe:*" |wc -l
53763
#稳定的函数接口 kproc
sudo cat /sys/kernel/tracing/available_events|wc -l
sudo bpftrace -l "tracepoint:*" |wc -l
#以events结尾的表示tracefs当前正在hook的函数列表
#这个是总的,包括kprobe uprobe 等事件
/sys/kernel/debug/tracing/dynamic_events
1500
1518
#event目录 存放可以监控的hook 点,通过目录去分类
sudo ls /sys/kernel/tracing/events
echo '--------------------'
#系统调用相关的, enter,exit 进入、退出的点
sudo ls /sys/kernel/tracing/events/syscalls
alarmtimer gpio mptcp scsi
amd_cpu header_event msr signal
avc header_page napi skb
block huge_memory neigh smbus
bpf_test_run hwmon net sock
bpf_trace hyperv netlink spi
bridge i2c nmi swiotlb
cgroup initcall oom sync_trace
clk intel_iommu osnoise syscalls
compaction interconnect page_isolation task
cpuhp iocost pagemap tcp
cros_ec iomap page_pool thermal
dev iommu percpu thermal_power_allocator
devfreq io_uring power timer
devlink irq printk tlb
dma_fence irq_matrix pwm udp
drm irq_vectors qdisc vmscan
enable jbd2 ras vsock
error_report kmem raw_syscalls vsyscall
exceptions libata rcu wbt
ext4 mce regmap workqueue
fib mdio regulator writeback
fib6 migrate resctrl x86_fpu
filelock mmap rpm xdp
filemap mmap_lock rseq xen
fs_dax mmc rtc xhci-hcd
ftrace module sched
--------------------\n\r
enable sys_enter_writev
filter sys_exit_accept
sys_enter_accept sys_exit_accept4
sys_enter_accept4 sys_exit_access
sys_enter_access sys_exit_acct
sys_enter_acct sys_exit_add_key
sys_enter_add_key sys_exit_adjtimex
sys_enter_adjtimex sys_exit_alarm
sys_enter_alarm sys_exit_arch_prctl
sys_enter_arch_prctl sys_exit_bind
sys_enter_bind sys_exit_bpf
sys_enter_bpf sys_exit_brk
sys_enter_brk sys_exit_capget
sys_enter_capget sys_exit_capset
sys_enter_capset sys_exit_chdir
sys_enter_chdir sys_exit_chmod
sys_enter_chmod sys_exit_chown
sys_enter_chown sys_exit_chroot
sys_enter_chroot sys_exit_clock_adjtime
sys_enter_clock_adjtime sys_exit_clock_getres
sys_enter_clock_getres sys_exit_clock_gettime
sys_enter_clock_gettime sys_exit_clock_nanosleep
sys_enter_clock_nanosleep sys_exit_clock_settime
sys_enter_clock_settime sys_exit_clone
sys_enter_clone sys_exit_clone3
sys_enter_clone3 sys_exit_close
sys_enter_close sys_exit_close_range
sys_enter_close_range sys_exit_connect
sys_enter_connect sys_exit_copy_file_range
sys_enter_copy_file_range sys_exit_creat
sys_enter_creat sys_exit_delete_module
sys_enter_delete_module sys_exit_dup
sys_enter_dup sys_exit_dup2
sys_enter_dup2 sys_exit_dup3
sys_enter_dup3 sys_exit_epoll_create
sys_enter_epoll_create sys_exit_epoll_create1
sys_enter_epoll_create1 sys_exit_epoll_ctl
sys_enter_epoll_ctl sys_exit_epoll_pwait
sys_enter_epoll_pwait sys_exit_epoll_pwait2
sys_enter_epoll_pwait2 sys_exit_epoll_wait
sys_enter_epoll_wait sys_exit_eventfd
sys_enter_eventfd sys_exit_eventfd2
sys_enter_eventfd2 sys_exit_execve
sys_enter_execve sys_exit_execveat
sys_enter_execveat sys_exit_exit
sys_enter_exit sys_exit_exit_group
sys_enter_exit_group sys_exit_faccessat
sys_enter_faccessat sys_exit_faccessat2
sys_enter_faccessat2 sys_exit_fadvise64
sys_enter_fadvise64 sys_exit_fallocate
sys_enter_fallocate sys_exit_fanotify_init
sys_enter_fanotify_init sys_exit_fanotify_mark
sys_enter_fanotify_mark sys_exit_fchdir
sys_enter_fchdir sys_exit_fchmod
sys_enter_fchmod sys_exit_fchmodat
sys_enter_fchmodat sys_exit_fchown
sys_enter_fchown sys_exit_fchownat
sys_enter_fchownat sys_exit_fcntl
sys_enter_fcntl sys_exit_fdatasync
sys_enter_fdatasync sys_exit_fgetxattr
sys_enter_fgetxattr sys_exit_finit_module
sys_enter_finit_module sys_exit_flistxattr
sys_enter_flistxattr sys_exit_flock
sys_enter_flock sys_exit_fork
sys_enter_fork sys_exit_fremovexattr
sys_enter_fremovexattr sys_exit_fsconfig
sys_enter_fsconfig sys_exit_fsetxattr
sys_enter_fsetxattr sys_exit_fsmount
sys_enter_fsmount sys_exit_fsopen
sys_enter_fsopen sys_exit_fspick
sys_enter_fspick sys_exit_fstatfs
sys_enter_fstatfs sys_exit_fsync
sys_enter_fsync sys_exit_ftruncate
sys_enter_ftruncate sys_exit_futex
sys_enter_futex sys_exit_futimesat
sys_enter_futimesat sys_exit_getcpu
sys_enter_getcpu sys_exit_getcwd
sys_enter_getcwd sys_exit_getdents
sys_enter_getdents sys_exit_getdents64
sys_enter_getdents64 sys_exit_getegid
sys_enter_getegid sys_exit_geteuid
sys_enter_geteuid sys_exit_getgid
sys_enter_getgid sys_exit_getgroups
sys_enter_getgroups sys_exit_getitimer
sys_enter_getitimer sys_exit_get_mempolicy
sys_enter_get_mempolicy sys_exit_getpeername
sys_enter_getpeername sys_exit_getpgid
sys_enter_getpgid sys_exit_getpgrp
sys_enter_getpgrp sys_exit_getpid
sys_enter_getpid sys_exit_getppid
sys_enter_getppid sys_exit_getpriority
sys_enter_getpriority sys_exit_getrandom
sys_enter_getrandom sys_exit_getresgid
sys_enter_getresgid sys_exit_getresuid
sys_enter_getresuid sys_exit_getrlimit
sys_enter_getrlimit sys_exit_get_robust_list
sys_enter_get_robust_list sys_exit_getrusage
sys_enter_getrusage sys_exit_getsid
sys_enter_getsid sys_exit_getsockname
sys_enter_getsockname sys_exit_getsockopt
sys_enter_getsockopt sys_exit_gettid
sys_enter_gettid sys_exit_gettimeofday
sys_enter_gettimeofday sys_exit_getuid
sys_enter_getuid sys_exit_getxattr
sys_enter_getxattr sys_exit_init_module
sys_enter_init_module sys_exit_inotify_add_watch
sys_enter_inotify_add_watch sys_exit_inotify_init
sys_enter_inotify_init sys_exit_inotify_init1
sys_enter_inotify_init1 sys_exit_inotify_rm_watch
sys_enter_inotify_rm_watch sys_exit_io_cancel
sys_enter_io_cancel sys_exit_ioctl
sys_enter_ioctl sys_exit_io_destroy
sys_enter_io_destroy sys_exit_io_getevents
sys_enter_io_getevents sys_exit_ioperm
sys_enter_ioperm sys_exit_io_pgetevents
sys_enter_io_pgetevents sys_exit_iopl
sys_enter_iopl sys_exit_ioprio_get
sys_enter_ioprio_get sys_exit_ioprio_set
sys_enter_ioprio_set sys_exit_io_setup
sys_enter_io_setup sys_exit_io_submit
sys_enter_io_submit sys_exit_io_uring_enter
sys_enter_io_uring_enter sys_exit_io_uring_register
sys_enter_io_uring_register sys_exit_io_uring_setup
sys_enter_io_uring_setup sys_exit_kcmp
sys_enter_kcmp sys_exit_kexec_file_load
sys_enter_kexec_file_load sys_exit_kexec_load
sys_enter_kexec_load sys_exit_keyctl
sys_enter_keyctl sys_exit_kill
sys_enter_kill sys_exit_landlock_add_rule
sys_enter_landlock_add_rule sys_exit_landlock_create_ruleset
sys_enter_landlock_create_ruleset sys_exit_landlock_restrict_self
sys_enter_landlock_restrict_self sys_exit_lchown
sys_enter_lchown sys_exit_lgetxattr
sys_enter_lgetxattr sys_exit_link
sys_enter_link sys_exit_linkat
sys_enter_linkat sys_exit_listen
sys_enter_listen sys_exit_listxattr
sys_enter_listxattr sys_exit_llistxattr
sys_enter_llistxattr sys_exit_lremovexattr
sys_enter_lremovexattr sys_exit_lseek
sys_enter_lseek sys_exit_lsetxattr
sys_enter_lsetxattr sys_exit_madvise
sys_enter_madvise sys_exit_mbind
sys_enter_mbind sys_exit_membarrier
sys_enter_membarrier sys_exit_memfd_create
sys_enter_memfd_create sys_exit_memfd_secret
sys_enter_memfd_secret sys_exit_migrate_pages
sys_enter_migrate_pages sys_exit_mincore
sys_enter_mincore sys_exit_mkdir
sys_enter_mkdir sys_exit_mkdirat
sys_enter_mkdirat sys_exit_mknod
sys_enter_mknod sys_exit_mknodat
sys_enter_mknodat sys_exit_mlock
sys_enter_mlock sys_exit_mlock2
sys_enter_mlock2 sys_exit_mlockall
sys_enter_mlockall sys_exit_mmap
sys_enter_mmap sys_exit_modify_ldt
sys_enter_modify_ldt sys_exit_mount
sys_enter_mount sys_exit_mount_setattr
sys_enter_mount_setattr sys_exit_move_mount
sys_enter_move_mount sys_exit_move_pages
sys_enter_move_pages sys_exit_mprotect
sys_enter_mprotect sys_exit_mq_getsetattr
sys_enter_mq_getsetattr sys_exit_mq_notify
sys_enter_mq_notify sys_exit_mq_open
sys_enter_mq_open sys_exit_mq_timedreceive
sys_enter_mq_timedreceive sys_exit_mq_timedsend
sys_enter_mq_timedsend sys_exit_mq_unlink
sys_enter_mq_unlink sys_exit_mremap
sys_enter_mremap sys_exit_msgctl
sys_enter_msgctl sys_exit_msgget
sys_enter_msgget sys_exit_msgrcv
sys_enter_msgrcv sys_exit_msgsnd
sys_enter_msgsnd sys_exit_msync
sys_enter_msync sys_exit_munlock
sys_enter_munlock sys_exit_munlockall
sys_enter_munlockall sys_exit_munmap
sys_enter_munmap sys_exit_name_to_handle_at
sys_enter_name_to_handle_at sys_exit_nanosleep
sys_enter_nanosleep sys_exit_newfstat
sys_enter_newfstat sys_exit_newfstatat
sys_enter_newfstatat sys_exit_newlstat
sys_enter_newlstat sys_exit_newstat
sys_enter_newstat sys_exit_newuname
sys_enter_newuname sys_exit_open
sys_enter_open sys_exit_openat
sys_enter_openat sys_exit_openat2
sys_enter_openat2 sys_exit_open_by_handle_at
sys_enter_open_by_handle_at sys_exit_open_tree
sys_enter_open_tree sys_exit_pause
sys_enter_pause sys_exit_perf_event_open
sys_enter_perf_event_open sys_exit_personality
sys_enter_personality sys_exit_pidfd_getfd
sys_enter_pidfd_getfd sys_exit_pidfd_open
sys_enter_pidfd_open sys_exit_pidfd_send_signal
sys_enter_pidfd_send_signal sys_exit_pipe
sys_enter_pipe sys_exit_pipe2
sys_enter_pipe2 sys_exit_pivot_root
sys_enter_pivot_root sys_exit_pkey_alloc
sys_enter_pkey_alloc sys_exit_pkey_free
sys_enter_pkey_free sys_exit_pkey_mprotect
sys_enter_pkey_mprotect sys_exit_poll
sys_enter_poll sys_exit_ppoll
sys_enter_ppoll sys_exit_prctl
sys_enter_prctl sys_exit_pread64
sys_enter_pread64 sys_exit_preadv
sys_enter_preadv sys_exit_preadv2
sys_enter_preadv2 sys_exit_prlimit64
sys_enter_prlimit64 sys_exit_process_madvise
sys_enter_process_madvise sys_exit_process_mrelease
sys_enter_process_mrelease sys_exit_process_vm_readv
sys_enter_process_vm_readv sys_exit_process_vm_writev
sys_enter_process_vm_writev sys_exit_pselect6
sys_enter_pselect6 sys_exit_ptrace
sys_enter_ptrace sys_exit_pwrite64
sys_enter_pwrite64 sys_exit_pwritev
sys_enter_pwritev sys_exit_pwritev2
sys_enter_pwritev2 sys_exit_quotactl
sys_enter_quotactl sys_exit_quotactl_fd
sys_enter_quotactl_fd sys_exit_read
sys_enter_read sys_exit_readahead
sys_enter_readahead sys_exit_readlink
sys_enter_readlink sys_exit_readlinkat
sys_enter_readlinkat sys_exit_readv
sys_enter_readv sys_exit_reboot
sys_enter_reboot sys_exit_recvfrom
sys_enter_recvfrom sys_exit_recvmmsg
sys_enter_recvmmsg sys_exit_recvmsg
sys_enter_recvmsg sys_exit_remap_file_pages
sys_enter_remap_file_pages sys_exit_removexattr
sys_enter_removexattr sys_exit_rename
sys_enter_rename sys_exit_renameat
sys_enter_renameat sys_exit_renameat2
sys_enter_renameat2 sys_exit_request_key
sys_enter_request_key sys_exit_restart_syscall
sys_enter_restart_syscall sys_exit_rmdir
sys_enter_rmdir sys_exit_rseq
sys_enter_rseq sys_exit_rt_sigaction
sys_enter_rt_sigaction sys_exit_rt_sigpending
sys_enter_rt_sigpending sys_exit_rt_sigprocmask
sys_enter_rt_sigprocmask sys_exit_rt_sigqueueinfo
sys_enter_rt_sigqueueinfo sys_exit_rt_sigreturn
sys_enter_rt_sigreturn sys_exit_rt_sigsuspend
sys_enter_rt_sigsuspend sys_exit_rt_sigtimedwait
sys_enter_rt_sigtimedwait sys_exit_rt_tgsigqueueinfo
sys_enter_rt_tgsigqueueinfo sys_exit_sched_getaffinity
sys_enter_sched_getaffinity sys_exit_sched_getattr
sys_enter_sched_getattr sys_exit_sched_getparam
sys_enter_sched_getparam sys_exit_sched_get_priority_max
sys_enter_sched_get_priority_max sys_exit_sched_get_priority_min
sys_enter_sched_get_priority_min sys_exit_sched_getscheduler
sys_enter_sched_getscheduler sys_exit_sched_rr_get_interval
sys_enter_sched_rr_get_interval sys_exit_sched_setaffinity
sys_enter_sched_setaffinity sys_exit_sched_setattr
sys_enter_sched_setattr sys_exit_sched_setparam
sys_enter_sched_setparam sys_exit_sched_setscheduler
sys_enter_sched_setscheduler sys_exit_sched_yield
sys_enter_sched_yield sys_exit_seccomp
sys_enter_seccomp sys_exit_select
sys_enter_select sys_exit_semctl
sys_enter_semctl sys_exit_semget
sys_enter_semget sys_exit_semop
sys_enter_semop sys_exit_semtimedop
sys_enter_semtimedop sys_exit_sendfile64
sys_enter_sendfile64 sys_exit_sendmmsg
sys_enter_sendmmsg sys_exit_sendmsg
sys_enter_sendmsg sys_exit_sendto
sys_enter_sendto sys_exit_setdomainname
sys_enter_setdomainname sys_exit_setfsgid
sys_enter_setfsgid sys_exit_setfsuid
sys_enter_setfsuid sys_exit_setgid
sys_enter_setgid sys_exit_setgroups
sys_enter_setgroups sys_exit_sethostname
sys_enter_sethostname sys_exit_setitimer
sys_enter_setitimer sys_exit_set_mempolicy
sys_enter_set_mempolicy sys_exit_setns
sys_enter_setns sys_exit_setpgid
sys_enter_setpgid sys_exit_setpriority
sys_enter_setpriority sys_exit_setregid
sys_enter_setregid sys_exit_setresgid
sys_enter_setresgid sys_exit_setresuid
sys_enter_setresuid sys_exit_setreuid
sys_enter_setreuid sys_exit_setrlimit
sys_enter_setrlimit sys_exit_set_robust_list
sys_enter_set_robust_list sys_exit_setsid
sys_enter_setsid sys_exit_setsockopt
sys_enter_setsockopt sys_exit_set_tid_address
sys_enter_set_tid_address sys_exit_settimeofday
sys_enter_settimeofday sys_exit_setuid
sys_enter_setuid sys_exit_setxattr
sys_enter_setxattr sys_exit_shmat
sys_enter_shmat sys_exit_shmctl
sys_enter_shmctl sys_exit_shmdt
sys_enter_shmdt sys_exit_shmget
sys_enter_shmget sys_exit_shutdown
sys_enter_shutdown sys_exit_sigaltstack
sys_enter_sigaltstack sys_exit_signalfd
sys_enter_signalfd sys_exit_signalfd4
sys_enter_signalfd4 sys_exit_socket
sys_enter_socket sys_exit_socketpair
sys_enter_socketpair sys_exit_splice
sys_enter_splice sys_exit_statfs
sys_enter_statfs sys_exit_statx
sys_enter_statx sys_exit_swapoff
sys_enter_swapoff sys_exit_swapon
sys_enter_swapon sys_exit_symlink
sys_enter_symlink sys_exit_symlinkat
sys_enter_symlinkat sys_exit_sync
sys_enter_sync sys_exit_sync_file_range
sys_enter_sync_file_range sys_exit_syncfs
sys_enter_syncfs sys_exit_sysfs
sys_enter_sysfs sys_exit_sysinfo
sys_enter_sysinfo sys_exit_syslog
sys_enter_syslog sys_exit_tee
sys_enter_tee sys_exit_tgkill
sys_enter_tgkill sys_exit_time
sys_enter_time sys_exit_timer_create
sys_enter_timer_create sys_exit_timer_delete
sys_enter_timer_delete sys_exit_timerfd_create
sys_enter_timerfd_create sys_exit_timerfd_gettime
sys_enter_timerfd_gettime sys_exit_timerfd_settime
sys_enter_timerfd_settime sys_exit_timer_getoverrun
sys_enter_timer_getoverrun sys_exit_timer_gettime
sys_enter_timer_gettime sys_exit_timer_settime
sys_enter_timer_settime sys_exit_times
sys_enter_times sys_exit_tkill
sys_enter_tkill sys_exit_truncate
sys_enter_truncate sys_exit_umask
sys_enter_umask sys_exit_umount
sys_enter_umount sys_exit_unlink
sys_enter_unlink sys_exit_unlinkat
sys_enter_unlinkat sys_exit_unshare
sys_enter_unshare sys_exit_userfaultfd
sys_enter_userfaultfd sys_exit_ustat
sys_enter_ustat sys_exit_utime
sys_enter_utime sys_exit_utimensat
sys_enter_utimensat sys_exit_utimes
sys_enter_utimes sys_exit_vfork
sys_enter_vfork sys_exit_vhangup
sys_enter_vhangup sys_exit_vmsplice
sys_enter_vmsplice sys_exit_wait4
sys_enter_wait4 sys_exit_waitid
sys_enter_waitid sys_exit_write
sys_enter_write sys_exit_writev
#所有的event 监测点的总开关,启用,如果在子目录下只对子目录起作用。
echo 1> /sys/kernel/tracing/events/enable
#只监控 sys_enter sys_exit
echo 1> /sys/kernel/debug/tracing/events/raw_syscalls/enable
#只监控 sys_enter
echo 1> /sys/kernel/debug/tracing/events/raw_syscalls/sys_enter/enable
echo "#filter 是过滤器,过滤进程id"
sudo ls /sys/kernel/debug/tracing/events/raw_syscalls/sys_enter
bash: echo: write error: Invalid argument
bash: echo: write error: Invalid argument
bash: echo: write error: Invalid argument
#filter 是过滤器,过来进程id
enable filter format hist id inject trigger
echo format 描述了接口的字段信息
sudo cat /sys/kernel/debug/tracing/events/raw_syscalls/sys_enter/format
format 描述了接口的字段信息n
name: sys_enter
ID: 348
format:
field:unsigned short common_type; offset:0; size:2; signed:0;
field:unsigned char common_flags; offset:2; size:1; signed:0;
field:unsigned char common_preempt_count; offset:3; size:1; signed:0;
field:int common_pid; offset:4; size:4; signed:1;
field:long id; offset:8; size:8; signed:1;
field:unsigned long args[6]; offset:16; size:48; signed:0;
print fmt: "NR %ld (%lx, %lx, %lx, %lx, %lx, %lx)", REC->id, REC->args[0], REC->args[1], REC->args[2], REC->args[3], REC->args[4], REC->args[5]
#开启uprobes,手动激活添加时才存在
sudo ls /sys/kernel/debug/tracing/events/uprobes
# 查看程序的位置。
readelf -s /bin/bash | grep readline | grep FUNC
cat: /sys/kernel/debug/tracing/events/uprobes: No such file or directory
328: 00000000000b7c90 594 FUNC GLOBAL DEFAULT 16 readline_internal_char
813: 00000000000b7160 351 FUNC GLOBAL DEFAULT 16 readline_internal_setup
863: 00000000000870e0 76 FUNC GLOBAL DEFAULT 16 posix_readline_initialize
882: 00000000000b84f0 154 FUNC GLOBAL DEFAULT 16 readline
1239: 0000000000087370 1963 FUNC GLOBAL DEFAULT 16 initialize_readline
1824: 000000000008faa0 69 FUNC GLOBAL DEFAULT 16 pcomp_set_readline_variab
2041: 00000000000b72c0 288 FUNC GLOBAL DEFAULT 16 readline_internal_teardow
#设置跟踪点
sudo bash -c 'echo p:readline /bin/bash:0x00000000000b7c90 %ip %ax > /sys/kernel/debug/tracing/uprobe_events'
echo @#查看跟踪点或者调试点的信息
sudo cat /sys/kernel/debug/tracing/uprobe_events
#开启uprobes 成功后, uprobes目录创建成功,readline创建成果
ls /sys/kernel/debug/tracing/events/uprobes/readline
@#查看跟踪点或者调试点的信息
p:uprobes/readline /bin/bash:0x00000000000b7c90 arg1=%ip arg2=%ax
enable filter format hist id inject trigger
echo @#开启追踪
sudo bash -c 'echo 1 > /sys/kernel/debug/tracing/events/uprobes/readline/enable'
sudo bash -c 'echo 1 >/sys/kernel/debug/tracing/tracing_on'
@#开启追踪
# 查看日志信息,trace_pipe是基于trace的管道,读取完就会消失
#sudo cat /sys/kernel/debug/tracing/trace_pipe
sudo cat /sys/kernel/debug/tracing/trace
# tracer: nop
#
# entries-in-buffer/entries-written: 8/8 #P:4
#
# _-----=> irqs-off
# / _----=> need-resched
# | / _---=> hardirq/softirq
# || / _--=> preempt-depth
# ||| / _-=> migrate-disable
# |||| / delay
# TASK-PID CPU# ||||| TIMESTAMP FUNCTION
# | | | ||||| | |
bash-809624 [003] ..... 272913.606499: readline: (0x556e620d6c90) arg1=0x556e620d6c90 arg2=0x0
bash-809624 [003] ..... 272913.657051: readline: (0x556e620d6c90) arg1=0x556e620d6c90 arg2=0x0
bash-809624 [003] ..... 272913.657239: readline: (0x556e620d6c90) arg1=0x556e620d6c90 arg2=0x0
bash-809624 [003] ..... 272918.054206: readline: (0x556e620d6c90) arg1=0x556e620d6c90 arg2=0x0
bash-809624 [003] ..... 272918.054315: readline: (0x556e620d6c90) arg1=0x556e620d6c90 arg2=0x0
bash-809624 [003] ..... 272918.104849: readline: (0x556e620d6c90) arg1=0x556e620d6c90 arg2=0x0
bash-809624 [003] ..... 272918.104963: readline: (0x556e620d6c90) arg1=0x556e620d6c90 arg2=0x0
bash-809624 [003] ..... 272918.155528: readline: (0x556e620d6c90) arg1=0x556e620d6c90 arg2=0x0
#关闭readline
sudo bash -c 'echo 0 > /sys/kernel/debug/tracing/events/uprobes/readline/enable'
#关闭 all
sudo bash -c 'echo 0 > /sys/kernel/debug/tracing/events/enable'
# 关闭单个的events
sudo bash -c 'echo >/sys/kernel/debug/tracing/kprobe_events'
sudo bash -c 'echo >/sys/kernel/debug/tracing/uprobe_events'
sudo bash -c 'echo 0 >/proc/sys/kernel/ftrace_enabled'
sudo bash -c 'echo 0 >/sys/kernel/debug/tracing/tracing_on'
# ftrace缺点,正在跟踪激活的情况,是没有办法添加其他的激活的。
#设置跟踪点
sudo bash -c 'echo p:readline /bin/bash:0x00000000000b7c90 %ip %ax > /sys/kernel/debug/tracing/uprobe_events'
bash: /sys/kernel/debug/tracing/uprobe_events: Device or resource busy
perf-tools工具,老的方案
https://github.com/brendangregg/perf-tools/blob/master/opensnoop
https://elixir.bootlin.com/linux/v5.15.52/source/samples/ftrace/ftrace-direct.c
#cp /lib/modules/5.15.0-92-generic/build/vmlinux .
cd /home/abc/src/kernel/linux
make M=samples/ftrace clean
make M=samples/ftrace
#BTF [M] samples/ftrace/ftrace-direct-modify.ko
#BTF 已经加入
CLEAN samples/ftrace/Module.symvers
CC [M] samples/ftrace/ftrace-direct.o
CC [M] samples/ftrace/ftrace-direct-too.o
CC [M] samples/ftrace/ftrace-direct-modify.o
CC [M] samples/ftrace/sample-trace-array.o
MODPOST samples/ftrace/Module.symvers
CC [M] samples/ftrace/ftrace-direct-modify.mod.o
LD [M] samples/ftrace/ftrace-direct-modify.ko
BTF [M] samples/ftrace/ftrace-direct-modify.ko
CC [M] samples/ftrace/ftrace-direct-too.mod.o
LD [M] samples/ftrace/ftrace-direct-too.ko
BTF [M] samples/ftrace/ftrace-direct-too.ko
CC [M] samples/ftrace/ftrace-direct.mod.o
LD [M] samples/ftrace/ftrace-direct.ko
BTF [M] samples/ftrace/ftrace-direct.ko
CC [M] samples/ftrace/sample-trace-array.mod.o
LD [M] samples/ftrace/sample-trace-array.ko
BTF [M] samples/ftrace/sample-trace-array.ko
sudo insmod samples/ftrace/ftrace-direct.ko
insmod: ERROR: could not insert module samples/ftrace/ftrace-direct.ko: Operation not permitted
#sudo bash -c 'echo 0 >/proc/sys/kernel/ftrace_enabled'
sudo bash -c 'echo 1 >/sys/kernel/debug/tracing/tracing_on'
#sudo cat /sys/kernel/debug/tracing/trace_pipe
https://github.com/ilammy/ftrace-hook/blob/master/ftrace_hook.c
/*
* Hooking kernel functions using ftrace framework
*
* Copyright (c) 2018 ilammy
*/
#define pr_fmt(fmt) "ftrace_hook: " fmt
#include <linux/ftrace.h>
#include <linux/kallsyms.h>
#include <linux/kernel.h>
#include <linux/linkage.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/version.h>
#include <linux/kprobes.h>
MODULE_DESCRIPTION("Example module hooking clone() and execve() via ftrace");
MODULE_AUTHOR("ilammy <[email protected]>");
MODULE_LICENSE("GPL");
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,7,0)
static unsigned long lookup_name(const char *name)
{
struct kprobe kp = {
.symbol_name = name
};
unsigned long retval;
if (register_kprobe(&kp) < 0) return 0;
retval = (unsigned long) kp.addr;
unregister_kprobe(&kp);
return retval;
}
#else
static unsigned long lookup_name(const char *name)
{
return kallsyms_lookup_name(name);
}
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,11,0)
#define FTRACE_OPS_FL_RECURSION FTRACE_OPS_FL_RECURSION_SAFE
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,11,0)
#define ftrace_regs pt_regs
static __always_inline struct pt_regs *ftrace_get_regs(struct ftrace_regs *fregs)
{
return fregs;
}
#endif
/*
* There are two ways of preventing vicious recursive loops when hooking:
* - detect recusion using function return address (USE_FENTRY_OFFSET = 0)
* - avoid recusion by jumping over the ftrace call (USE_FENTRY_OFFSET = 1)
*/
#define USE_FENTRY_OFFSET 0
/**
* struct ftrace_hook - describes a single hook to install
*
* @name: name of the function to hook
*
* @function: pointer to the function to execute instead
*
* @original: pointer to the location where to save a pointer
* to the original function
*
* @address: kernel address of the function entry
*
* @ops: ftrace_ops state for this function hook
*
* The user should fill in only &name, &hook, &orig fields.
* Other fields are considered implementation details.
*/
struct ftrace_hook {
const char *name;
void *function;
void *original;
unsigned long address;
struct ftrace_ops ops;
};
static int fh_resolve_hook_address(struct ftrace_hook *hook)
{
hook->address = lookup_name(hook->name);
if (!hook->address) {
pr_debug("unresolved symbol: %s\n", hook->name);
return -ENOENT;
}
#if USE_FENTRY_OFFSET
*((unsigned long*) hook->original) = hook->address + MCOUNT_INSN_SIZE;
#else
*((unsigned long*) hook->original) = hook->address;
#endif
return 0;
}
static void notrace fh_ftrace_thunk(unsigned long ip, unsigned long parent_ip,
struct ftrace_ops *ops, struct ftrace_regs *fregs)
{
struct pt_regs *regs = ftrace_get_regs(fregs);
struct ftrace_hook *hook = container_of(ops, struct ftrace_hook, ops);
#if USE_FENTRY_OFFSET
regs->ip = (unsigned long)hook->function;
#else
if (!within_module(parent_ip, THIS_MODULE))
regs->ip = (unsigned long)hook->function;
#endif
}
/**
* fh_install_hooks() - register and enable a single hook
* @hook: a hook to install
*
* Returns: zero on success, negative error code otherwise.
*/
int fh_install_hook(struct ftrace_hook *hook)
{
int err;
err = fh_resolve_hook_address(hook);
if (err)
return err;
/*
* We're going to modify %rip register so we'll need IPMODIFY flag
* and SAVE_REGS as its prerequisite. ftrace's anti-recursion guard
* is useless if we change %rip so disable it with RECURSION.
* We'll perform our own checks for trace function reentry.
*/
hook->ops.func = fh_ftrace_thunk;
hook->ops.flags = FTRACE_OPS_FL_SAVE_REGS
| FTRACE_OPS_FL_RECURSION
| FTRACE_OPS_FL_IPMODIFY;
err = ftrace_set_filter_ip(&hook->ops, hook->address, 0, 0);
if (err) {
pr_debug("ftrace_set_filter_ip() failed: %d\n", err);
return err;
}
err = register_ftrace_function(&hook->ops);
if (err) {
pr_debug("register_ftrace_function() failed: %d\n", err);
ftrace_set_filter_ip(&hook->ops, hook->address, 1, 0);
return err;
}
return 0;
}
/**
* fh_remove_hooks() - disable and unregister a single hook
* @hook: a hook to remove
*/
void fh_remove_hook(struct ftrace_hook *hook)
{
int err;
err = unregister_ftrace_function(&hook->ops);
if (err) {
pr_debug("unregister_ftrace_function() failed: %d\n", err);
}
err = ftrace_set_filter_ip(&hook->ops, hook->address, 1, 0);
if (err) {
pr_debug("ftrace_set_filter_ip() failed: %d\n", err);
}
}
/**
* fh_install_hooks() - register and enable multiple hooks
* @hooks: array of hooks to install
* @count: number of hooks to install
*
* If some hooks fail to install then all hooks will be removed.
*
* Returns: zero on success, negative error code otherwise.
*/
int fh_install_hooks(struct ftrace_hook *hooks, size_t count)
{
int err;
size_t i;
for (i = 0; i < count; i++) {
err = fh_install_hook(&hooks[i]);
if (err)
goto error;
}
return 0;
error:
while (i != 0) {
fh_remove_hook(&hooks[--i]);
}
return err;
}
/**
* fh_remove_hooks() - disable and unregister multiple hooks
* @hooks: array of hooks to remove
* @count: number of hooks to remove
*/
void fh_remove_hooks(struct ftrace_hook *hooks, size_t count)
{
size_t i;
for (i = 0; i < count; i++)
fh_remove_hook(&hooks[i]);
}
#ifndef CONFIG_X86_64
#error Currently only x86_64 architecture is supported
#endif
#if defined(CONFIG_X86_64) && (LINUX_VERSION_CODE >= KERNEL_VERSION(4,17,0))
#define PTREGS_SYSCALL_STUBS 1
#endif
/*
* Tail call optimization can interfere with recursion detection based on
* return address on the stack. Disable it to avoid machine hangups.
*/
#if !USE_FENTRY_OFFSET
#pragma GCC optimize("-fno-optimize-sibling-calls")
#endif
#ifdef PTREGS_SYSCALL_STUBS
static asmlinkage long (*real_sys_clone)(struct pt_regs *regs);
static asmlinkage long fh_sys_clone(struct pt_regs *regs)
{
long ret;
pr_info("clone() before\n");
ret = real_sys_clone(regs);
pr_info("clone() after: %ld\n", ret);
return ret;
}
#else
static asmlinkage long (*real_sys_clone)(unsigned long clone_flags,
unsigned long newsp, int __user *parent_tidptr,
int __user *child_tidptr, unsigned long tls);
static asmlinkage long fh_sys_clone(unsigned long clone_flags,
unsigned long newsp, int __user *parent_tidptr,
int __user *child_tidptr, unsigned long tls)
{
long ret;
pr_info("clone() before\n");
ret = real_sys_clone(clone_flags, newsp, parent_tidptr,
child_tidptr, tls);
pr_info("clone() after: %ld\n", ret);
return ret;
}
#endif
static char *duplicate_filename(const char __user *filename)
{
char *kernel_filename;
kernel_filename = kmalloc(4096, GFP_KERNEL);
if (!kernel_filename)
return NULL;
if (strncpy_from_user(kernel_filename, filename, 4096) < 0) {
kfree(kernel_filename);
return NULL;
}
return kernel_filename;
}
#ifdef PTREGS_SYSCALL_STUBS
static asmlinkage long (*real_sys_execve)(struct pt_regs *regs);
static asmlinkage long fh_sys_execve(struct pt_regs *regs)
{
long ret;
char *kernel_filename;
kernel_filename = duplicate_filename((void*) regs->di);
pr_info("execve() before: %s\n", kernel_filename);
kfree(kernel_filename);
ret = real_sys_execve(regs);
pr_info("execve() after: %ld\n", ret);
return ret;
}
#else
static asmlinkage long (*real_sys_execve)(const char __user *filename,
const char __user *const __user *argv,
const char __user *const __user *envp);
static asmlinkage long fh_sys_execve(const char __user *filename,
const char __user *const __user *argv,
const char __user *const __user *envp)
{
long ret;
char *kernel_filename;
kernel_filename = duplicate_filename(filename);
pr_info("execve() before: %s\n", kernel_filename);
kfree(kernel_filename);
ret = real_sys_execve(filename, argv, envp);
pr_info("execve() after: %ld\n", ret);
return ret;
}
#endif
/*
* x86_64 kernels have a special naming convention for syscall entry points in newer kernels.
* That's what you end up with if an architecture has 3 (three) ABIs for system calls.
*/
#ifdef PTREGS_SYSCALL_STUBS
#define SYSCALL_NAME(name) ("__x64_" name)
#else
#define SYSCALL_NAME(name) (name)
#endif
#define HOOK(_name, _function, _original) \
{ \
.name = SYSCALL_NAME(_name), \
.function = (_function), \
.original = (_original), \
}
static struct ftrace_hook demo_hooks[] = {
HOOK("sys_clone", fh_sys_clone, &real_sys_clone),
HOOK("sys_execve", fh_sys_execve, &real_sys_execve),
};
static int fh_init(void)
{
int err;
err = fh_install_hooks(demo_hooks, ARRAY_SIZE(demo_hooks));
if (err)
return err;
pr_info("module loaded\n");
return 0;
}
module_init(fh_init);
static void fh_exit(void)
{
fh_remove_hooks(demo_hooks, ARRAY_SIZE(demo_hooks));
pr_info("module unloaded\n");
}
module_exit(fh_exit);