├── README.md ├── systemtap ├── sigterm-tracing.stp └── icmp-tracing.stp ├── LICENSE ├── ebpf ├── ext4-large-dir-tracing.py ├── linux-retransmit-tracing.py ├── forbidden-file-open.py ├── icmp-tracing.py ├── gunicorn-connection-in-use.py ├── go-https-tracing.py ├── tracing-sk-drop.py ├── analysis-read-file-time.py └── analysis-all-nfs-time.py └── .gitignore /README.md: -------------------------------------------------------------------------------- 1 | # linux-traceing-script -------------------------------------------------------------------------------- /systemtap/sigterm-tracing.stp: -------------------------------------------------------------------------------- 1 | %{ 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | %} 14 | 15 | function task_execname_by_pid:string (pid:long) %{ 16 | struct task_struct *task; 17 | 18 | task = pid_task(find_vpid(STAP_ARG_pid), PIDTYPE_PID); 19 | 20 | // proc_pid_cmdline(p, STAP_RETVALUE); 21 | snprintf(STAP_RETVALUE, MAXSTRINGLEN, "%s", task->comm); 22 | 23 | %} 24 | 25 | 26 | 27 | probe kernel.function("kill_something_info").call { 28 | if ($(sig) == 15) { 29 | pid_data = pid() 30 | /* IP */ 31 | 32 | printf("pid is:%d, command is: '%s', destination target is: %d\n",pid_data,task_execname_by_pid(pid_data), $pid) 33 | 34 | } else { 35 | next 36 | } 37 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Manjusaka 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /ebpf/ext4-large-dir-tracing.py: -------------------------------------------------------------------------------- 1 | from bcc import BPF 2 | 3 | bpf_text = """ 4 | #include 5 | BPF_RINGBUF_OUTPUT(events, 65536); 6 | 7 | struct event_data_t { 8 | u32 pid; 9 | }; 10 | 11 | int trace_ext4_dx_add_entry_return(struct pt_regs *ctx) { 12 | int ret = PT_REGS_RC(ctx); 13 | if (ret == 0) { 14 | return 0; 15 | } 16 | u32 pid=bpf_get_current_pid_tgid()>>32; 17 | struct event_data_t *event_data = events.ringbuf_reserve(sizeof(struct event_data_t)); 18 | if (!event_data) { 19 | return 0; 20 | } 21 | event_data->pid = pid; 22 | events.ringbuf_submit(event_data, sizeof(event_data)); 23 | return 0; 24 | } 25 | """ 26 | 27 | 28 | bpf = BPF(text=bpf_text) 29 | 30 | bpf.attach_kretprobe(event="ext4_dx_add_entry", fn_name="trace_ext4_dx_add_entry_return") 31 | 32 | def process_event_data(cpu, data, size): 33 | event = bpf["events"].event(data) 34 | print(f"Process {event.pid} ext4 failed") 35 | 36 | 37 | bpf["events"].open_ring_buffer(process_event_data) 38 | 39 | while True: 40 | try: 41 | bpf.ring_buffer_consume() 42 | except KeyboardInterrupt: 43 | exit() 44 | -------------------------------------------------------------------------------- /ebpf/linux-retransmit-tracing.py: -------------------------------------------------------------------------------- 1 | from bcc import BPF 2 | 3 | bpf_text = """ 4 | BPF_RINGBUF_OUTPUT(tcp_event, 65536); 5 | 6 | enum tcp_event_type { 7 | retrans_event, 8 | recv_rst_event, 9 | }; 10 | 11 | struct event_data_t { 12 | enum tcp_event_type type; 13 | u16 sport; 14 | u16 dport; 15 | u8 saddr[4]; 16 | u8 daddr[4]; 17 | u32 pid; 18 | }; 19 | 20 | TRACEPOINT_PROBE(tcp, tcp_retransmit_skb) 21 | { 22 | struct event_data_t event_data={}; 23 | event_data.type = retrans_event; 24 | event_data.sport = args->sport; 25 | event_data.dport = args->dport; 26 | event_data.pid=bpf_get_current_pid_tgid()>>32; 27 | bpf_probe_read_kernel(&event_data.saddr,sizeof(event_data.saddr), args->saddr); 28 | bpf_probe_read_kernel(&event_data.daddr,sizeof(event_data.daddr), args->daddr); 29 | tcp_event.ringbuf_output(&event_data, sizeof(struct event_data_t), 0); 30 | return 0; 31 | } 32 | 33 | TRACEPOINT_PROBE(tcp, tcp_receive_reset) 34 | { 35 | struct event_data_t event_data={}; 36 | event_data.type = recv_rst_event; 37 | event_data.sport = args->sport; 38 | event_data.dport = args->dport; 39 | event_data.pid=bpf_get_current_pid_tgid()>>32; 40 | bpf_probe_read_kernel(&event_data.saddr,sizeof(event_data.saddr), args->saddr); 41 | bpf_probe_read_kernel(&event_data.daddr,sizeof(event_data.daddr), args->daddr); 42 | tcp_event.ringbuf_output(&event_data, sizeof(struct event_data_t), 0); 43 | return 0; 44 | } 45 | 46 | """ 47 | 48 | bpf = BPF(text=bpf_text) 49 | 50 | 51 | def process_event_data(cpu, data, size): 52 | event = bpf["tcp_event"].event(data) 53 | event_type = "retransmit" if event.type == 0 else "recv_rst" 54 | print( 55 | "%s %d %d %s %s %d" 56 | % ( 57 | event_type, 58 | event.sport, 59 | event.dport, 60 | ".".join([str(i) for i in event.saddr]), 61 | ".".join([str(i) for i in event.daddr]), 62 | event.pid, 63 | ) 64 | ) 65 | 66 | 67 | bpf["tcp_event"].open_ring_buffer(process_event_data) 68 | 69 | 70 | while True: 71 | bpf.ring_buffer_consume() 72 | -------------------------------------------------------------------------------- /systemtap/icmp-tracing.stp: -------------------------------------------------------------------------------- 1 | %{ 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | %} 13 | 14 | function isicmp:long (data:long) 15 | %{ 16 | struct iphdr *ip; 17 | struct sk_buff *skb; 18 | int tmp = 0; 19 | 20 | skb = (struct sk_buff *) STAP_ARG_data; 21 | 22 | if (skb->protocol == htons(ETH_P_IP)){ 23 | ip = (struct iphdr *) skb->data; 24 | tmp = (ip->protocol == 1); 25 | } 26 | STAP_RETVALUE = tmp; 27 | %} 28 | 29 | function task_execname_by_pid:string (pid:long) %{ 30 | struct task_struct *task; 31 | 32 | task = pid_task(find_vpid(STAP_ARG_pid), PIDTYPE_PID); 33 | 34 | // proc_pid_cmdline(p, STAP_RETVALUE); 35 | snprintf(STAP_RETVALUE, MAXSTRINGLEN, "%s", task->comm); 36 | 37 | %} 38 | 39 | function ipsource:long (data:long) 40 | %{ 41 | struct sk_buff *skb; 42 | struct iphdr *ip; 43 | __be32 src; 44 | 45 | skb = (struct sk_buff *) STAP_ARG_data; 46 | 47 | ip = (struct iphdr *) skb->data; 48 | src = (__be32) ip->saddr; 49 | 50 | STAP_RETVALUE = src; 51 | %} 52 | 53 | /* Return ip destination address */ 54 | function ipdst:long (data:long) 55 | %{ 56 | struct sk_buff *skb; 57 | struct iphdr *ip; 58 | __be32 dst; 59 | 60 | skb = (struct sk_buff *) STAP_ARG_data; 61 | 62 | ip = (struct iphdr *) skb->data; 63 | dst = (__be32) ip->daddr; 64 | 65 | STAP_RETVALUE = dst; 66 | %} 67 | 68 | function parseIp:string (data:long) %{ 69 | sprintf(STAP_RETVALUE,"%d.%d,%d.%d",(int)STAP_ARG_data &0xFF,(int)(STAP_ARG_data>>8)&0xFF,(int)(STAP_ARG_data>>16)&0xFF,(int)(STAP_ARG_data>>24)&0xFF); 70 | %} 71 | 72 | 73 | probe kernel.function("ip_finish_output").call { 74 | if (isicmp($skb)) { 75 | pid_data = pid() 76 | /* IP */ 77 | ipdst = ipdst($skb) 78 | ipsrc = ipsource($skb) 79 | printf("pid is:%d,source address is:%s, destination address is %s, command is: '%s'\n",pid_data,parseIp(ipsrc),parseIp(ipdst),task_execname_by_pid(pid_data)) 80 | 81 | } else { 82 | next 83 | } 84 | } -------------------------------------------------------------------------------- /ebpf/forbidden-file-open.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | from bcc import BPF 3 | from numpy import byte 4 | 5 | bpf_text = """ 6 | #include 7 | #include 8 | 9 | 10 | struct event_data_t { 11 | u32 pid; 12 | int status; 13 | char data[{length}]; 14 | }; 15 | 16 | static inline bool equal_to_true(char *str) { 17 | char comparand[{length}]; 18 | bpf_probe_read_user(&comparand, sizeof(comparand), str); 19 | char compare[] = "{file_name}"; 20 | for (int i = 0; i < {length}; ++i) 21 | if (compare[i] != comparand[i]) 22 | return false; 23 | return true; 24 | } 25 | 26 | 27 | BPF_RINGBUF_OUTPUT(events, 65536); 28 | int trace_sys_openat(struct pt_regs *ctx) { 29 | 30 | u32 pid=bpf_get_current_pid_tgid()>>32; 31 | if (pid == {pid}){ 32 | return 0; 33 | } 34 | struct pt_regs *__ctx = (struct pt_regs *)PT_REGS_PARM1(ctx); 35 | char __user *filename ; 36 | bpf_probe_read_kernel(&filename, sizeof(filename), &(PT_REGS_PARM2(__ctx))); 37 | if (filename==NULL){ 38 | return 0; 39 | } 40 | if (equal_to_true(filename)){ 41 | struct event_data_t *event_data = events.ringbuf_reserve(sizeof(struct event_data_t)); 42 | if (!event_data) { 43 | return 0; 44 | } 45 | event_data->pid = pid; 46 | bpf_probe_read_user(&event_data->data, sizeof(event_data->data), filename); 47 | bpf_override_return(ctx, -EACCES); 48 | events.ringbuf_submit(event_data, sizeof(event_data)); 49 | } 50 | return 0; 51 | } 52 | """ 53 | args = argparse.ArgumentParser() 54 | args.add_argument("filename", nargs="?", default="") 55 | args.add_argument("pid", nargs="?", default="") 56 | 57 | filename=args.parse_args().filename 58 | pid=args.parse_args().pid 59 | 60 | bpf_text = bpf_text.replace("{file_name}", filename).replace("{length}", str(len(filename))).replace("{pid}", pid) 61 | 62 | bpf = BPF(text=bpf_text) 63 | 64 | bpf.attach_kprobe(event="__x64_sys_openat", fn_name="trace_sys_openat") 65 | 66 | # def process_event_data(cpu, data, size): 67 | # event = bpf["events"].event(data) 68 | # print(f"Process {event.pid} try to open {filename} but is forbidden,{event.status}, {event.data}") 69 | 70 | # bpf["events"].open_ring_buffer(process_event_data) 71 | while True: 72 | try: 73 | time.sleep(1) 74 | # bpf.ring_buffer_consume() 75 | except KeyboardInterrupt: 76 | exit() 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | -------------------------------------------------------------------------------- /ebpf/icmp-tracing.py: -------------------------------------------------------------------------------- 1 | from bcc import BPF 2 | import ctypes 3 | 4 | bpf_text = """ 5 | #include 6 | #include /* For TASK_COMM_LEN */ 7 | #include 8 | #include 9 | #include 10 | 11 | struct probe_icmp_sample { 12 | u32 pid; 13 | u32 daddress; 14 | u32 saddress; 15 | }; 16 | 17 | BPF_PERF_OUTPUT(probe_events); 18 | 19 | static inline unsigned char *custom_skb_network_header(const struct sk_buff *skb) 20 | { 21 | return skb->head + skb->network_header; 22 | } 23 | 24 | static inline struct iphdr *get_iphdr_in_icmp(const struct sk_buff *skb) 25 | { 26 | return (struct iphdr *)custom_skb_network_header(skb); 27 | } 28 | 29 | int probe_icmp(struct pt_regs *ctx, struct net *net, struct sock *sk, struct sk_buff *skb){ 30 | struct iphdr * ipdata=get_iphdr_in_icmp(skb); 31 | if (ipdata->protocol!=1){ 32 | return 1; 33 | } 34 | u64 __pid_tgid = bpf_get_current_pid_tgid(); 35 | u32 __pid = __pid_tgid; 36 | struct probe_icmp_sample __data = {0}; 37 | __data.pid = __pid; 38 | u32 daddress; 39 | u32 saddress; 40 | bpf_probe_read(&daddress, sizeof(ipdata->daddr), &ipdata->daddr); 41 | bpf_probe_read(&saddress, sizeof(ipdata->daddr), &ipdata->saddr); 42 | __data.daddress=daddress; 43 | __data.saddress=saddress; 44 | probe_events.perf_submit(ctx, &__data, sizeof(__data)); 45 | return 0; 46 | } 47 | 48 | """ 49 | 50 | 51 | class IcmpSamples(ctypes.Structure): 52 | _fields_ = [ 53 | ("pid", ctypes.c_uint32), 54 | ("daddress", ctypes.c_uint32), 55 | ("saddress", ctypes.c_uint32), 56 | ] 57 | 58 | 59 | bpf = BPF(text=bpf_text) 60 | 61 | filters = {} 62 | 63 | 64 | def parse_ip_address(data): 65 | results = [0, 0, 0, 0] 66 | results[3] = data & 0xFF 67 | results[2] = (data >> 8) & 0xFF 68 | results[1] = (data >> 16) & 0xFF 69 | results[0] = (data >> 24) & 0xFF 70 | return ".".join([str(i) for i in results[::-1]]) 71 | 72 | 73 | def print_icmp_event(cpu, data, size): 74 | # event = b["probe_icmp_events"].event(data) 75 | event = ctypes.cast(data, ctypes.POINTER(IcmpSamples)).contents 76 | daddress = parse_ip_address(event.daddress) 77 | print( 78 | f"pid:{event.pid}, daddress:{daddress}, saddress:{parse_ip_address(event.saddress)}" 79 | ) 80 | 81 | 82 | bpf.attach_kprobe(event="ip_finish_output", fn_name="probe_icmp") 83 | 84 | bpf["probe_events"].open_perf_buffer(print_icmp_event) 85 | while 1: 86 | try: 87 | bpf.kprobe_poll() 88 | except KeyboardInterrupt: 89 | exit() 90 | -------------------------------------------------------------------------------- /ebpf/gunicorn-connection-in-use.py: -------------------------------------------------------------------------------- 1 | from bcc import BPF 2 | import struct 3 | import socket 4 | 5 | bpf_text = """ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | BPF_RINGBUF_OUTPUT(events, 65536); 16 | 17 | 18 | struct event_data_t { 19 | u16 state; 20 | u32 saddr; 21 | u32 daddr; 22 | u16 lport; 23 | u16 dport; 24 | u16 type; 25 | }; 26 | 27 | static struct event_data_t * generate_event_data(struct sock *sk) { 28 | struct event_data_t *event_data=events.ringbuf_reserve(sizeof(struct event_data_t)); 29 | if (!event_data) { 30 | return NULL; 31 | } 32 | 33 | event_data->state = sk->__sk_common.skc_state; 34 | event_data->saddr = sk->__sk_common.skc_rcv_saddr; 35 | event_data->daddr = sk->__sk_common.skc_daddr; 36 | event_data->lport = sk->__sk_common.skc_num; 37 | event_data->dport = sk->__sk_common.skc_dport; 38 | return event_data; 39 | } 40 | 41 | int trace_tcp_fin(struct pt_regs *ctx, struct sock *sk) { 42 | u16 state = sk->__sk_common.skc_state; 43 | if (state != TCP_FIN_WAIT2) { 44 | return 0; 45 | } 46 | struct event_data_t *event_data=generate_event_data(sk); 47 | if (!event_data) { 48 | return 0; 49 | } 50 | event_data->type = 1; 51 | 52 | events.ringbuf_submit(event_data, sizeof(event_data)); 53 | return 0; 54 | } 55 | 56 | int trace_tcp_send_fin(struct pt_regs *ctx, struct sock *sk) { 57 | u16 state = sk->__sk_common.skc_state; 58 | if (state != TCP_FIN_WAIT1) { 59 | return 0; 60 | } 61 | struct event_data_t *event_data=generate_event_data(sk); 62 | if (!event_data) { 63 | return 0; 64 | } 65 | 66 | event_data->type = 2; 67 | 68 | events.ringbuf_submit(event_data, sizeof(event_data)); 69 | return 0; 70 | } 71 | 72 | 73 | 74 | 75 | """ 76 | 77 | bpf = BPF(text=bpf_text) 78 | 79 | bpf.attach_kprobe(event="tcp_fin", fn_name="trace_tcp_fin") 80 | bpf.attach_kprobe(event="tcp_send_fin", fn_name="trace_tcp_send_fin") 81 | 82 | 83 | def parse_ip_address(data): 84 | results = [0, 0, 0, 0] 85 | results[3] = data & 0xFF 86 | results[2] = (data >> 8) & 0xFF 87 | results[1] = (data >> 16) & 0xFF 88 | results[0] = (data >> 24) & 0xFF 89 | return ".".join([str(i) for i in results[::-1]]) 90 | 91 | 92 | def process_event_data(cpu, data, size): 93 | event = bpf["events"].event(data) 94 | print( 95 | f"Source Address:{parse_ip_address(event.saddr)}, Source Port: {event.lport}, Dest Address: {parse_ip_address(event.daddr)}, Dest Port: {socket.ntohs(event.dport)}, State: {event.state}, Action {'Send FIN' if event.type==2 else 'Receive FIN'}" 96 | ) 97 | 98 | 99 | bpf["events"].open_ring_buffer(process_event_data) 100 | while True: 101 | try: 102 | bpf.ring_buffer_consume() 103 | except KeyboardInterrupt: 104 | exit() 105 | -------------------------------------------------------------------------------- /ebpf/go-https-tracing.py: -------------------------------------------------------------------------------- 1 | from bcc import BPF 2 | import ctypes 3 | import binascii 4 | 5 | bpf_text = """ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | struct ipv4_data_t { 15 | u32 pid; 16 | u64 ip; 17 | u32 saddr; 18 | u32 daddr; 19 | u16 lport; 20 | u16 dport; 21 | u64 state; 22 | u64 type; 23 | u8 data[300]; 24 | u16 data_size; 25 | }; 26 | 27 | 28 | BPF_PERF_OUTPUT(ipv4_events); 29 | 30 | int trace_event(struct pt_regs *ctx,struct sock *sk, struct msghdr *msg, size_t size){ 31 | if (sk == NULL) 32 | return 0; 33 | u32 pid = bpf_get_current_pid_tgid() >> 32; 34 | 35 | 36 | // pull in details 37 | u16 family = sk->__sk_common.skc_family; 38 | u16 lport = sk->__sk_common.skc_num; 39 | u16 dport = sk->__sk_common.skc_dport; 40 | char state = sk->__sk_common.skc_state; 41 | 42 | if (family == AF_INET) { 43 | struct ipv4_data_t data4 = {}; 44 | data4.pid = pid; 45 | data4.ip = 4; 46 | //data4.type = type; 47 | data4.saddr = sk->__sk_common.skc_rcv_saddr; 48 | data4.daddr = sk->__sk_common.skc_daddr; 49 | // lport is host order 50 | data4.lport = lport; 51 | data4.dport = ntohs(dport); 52 | data4.state = state; 53 | struct iov_iter temp_iov_iter=msg->msg_iter; 54 | struct iovec *temp_iov=temp_iov_iter.iov; 55 | bpf_probe_read_kernel(&data4.data_size, 4, &temp_iov->iov_len); 56 | u8 * temp_ptr; 57 | bpf_probe_read_kernel(&temp_ptr, sizeof(temp_ptr), &temp_iov->iov_base); 58 | bpf_probe_read_kernel(&data4.data, sizeof(data4.data), temp_ptr); 59 | ipv4_events.perf_submit(ctx, &data4, sizeof(data4)); 60 | } 61 | return 0; 62 | } 63 | 64 | """ 65 | 66 | bpf = BPF(text=bpf_text) 67 | 68 | filters = {} 69 | 70 | 71 | def parse_ip_address(data): 72 | results = [0, 0, 0, 0] 73 | results[3] = data & 0xFF 74 | results[2] = (data >> 8) & 0xFF 75 | results[1] = (data >> 16) & 0xFF 76 | results[0] = (data >> 24) & 0xFF 77 | return ".".join([str(i) for i in results[::-1]]) 78 | 79 | 80 | def print_icmp_event(cpu, data, size): 81 | # event = b["probe_icmp_events"].event(data) 82 | # event = ctypes.cast(data, ctypes.POINTER(IcmpSamples)).contents 83 | event = bpf["ipv4_events"].event(data) 84 | daddress = parse_ip_address(event.daddr) 85 | # data=list(event.data) 86 | # temp=binascii.hexlify(data) 87 | body = bytearray(event.data).hex() 88 | if ( 89 | "c0 2f c0 30 c0 2b c0 2c cc a8 cc a9 c0 13 c0 09 c0 14 c0 0a 00 9c 00 9d 00 2f 00 35 c0 12 00 0a 13 01 13 03 13 02".replace( 90 | " ", "" 91 | ) 92 | in body 93 | ): 94 | # if "68747470" in temp.decode(): 95 | print( 96 | f"pid:{event.pid}, daddress:{daddress}, saddress:{parse_ip_address(event.saddr)}, {event.lport}, {event.dport}, {event.data_size}" 97 | ) 98 | 99 | 100 | bpf.attach_kprobe(event="tcp_sendmsg", fn_name="trace_event") 101 | 102 | bpf["ipv4_events"].open_perf_buffer(print_icmp_event) 103 | while 1: 104 | try: 105 | bpf.perf_buffer_poll() 106 | except KeyboardInterrupt: 107 | exit() 108 | -------------------------------------------------------------------------------- /ebpf/tracing-sk-drop.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | from bcc import BPF 3 | import ctypes 4 | 5 | bpf_text = """ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | struct event_data_t { 13 | u32 pid; 14 | u16 sport; 15 | u16 dport; 16 | u32 daddress; 17 | u32 saddress; 18 | }; 19 | 20 | BPF_RINGBUF_OUTPUT(events, 65536); 21 | BPF_HASH(action_info, pid_t, struct event_data_t); 22 | 23 | int trace_sk_drop_event_enter(struct pt_regs *ctx, const struct sock *sk, struct sk_buff *skb) { 24 | __u16 sport = 0, dport = 0; 25 | __be32 saddr = 0, daddr = 0; 26 | u32 pid = bpf_get_current_pid_tgid()>>32; 27 | u32 tid = bpf_get_current_pid_tgid(); 28 | if (pid!={PID}) { 29 | return 0; 30 | } 31 | if (sk->__sk_common.skc_family != AF_INET){ 32 | return 0; 33 | } 34 | struct inet_sock *inet_sk = (struct inet_sock *)sk; 35 | struct event_data_t event_data = {}; 36 | event_data.pid = pid; 37 | event_data.sport = inet_sk->inet_sport; 38 | event_data.dport = inet_sk->inet_dport; 39 | event_data.saddress=inet_sk->inet_saddr; 40 | event_data.daddress=inet_sk->inet_daddr; 41 | action_info.update(&tid, &event_data); 42 | return 0; 43 | } 44 | int trace_sk_drop_event_return(struct pt_regs *ctx) { 45 | u32 pid=bpf_get_current_pid_tgid()>>32; 46 | u32 tid=bpf_get_current_pid_tgid(); 47 | if (pid!={PID}) { 48 | return 0; 49 | } 50 | struct sock* ret = PT_REGS_RC(ctx); 51 | 52 | struct event_data_t *event_data=action_info.lookup(&tid); 53 | if (event_data==NULL){ 54 | return 0; 55 | } 56 | action_info.delete(&tid); 57 | if (!ret) { 58 | return 0; 59 | } 60 | struct event_data_t *new_event_data = events.ringbuf_reserve(sizeof(struct event_data_t)); 61 | if (!new_event_data){ 62 | return 0; 63 | } 64 | new_event_data->pid=event_data->pid; 65 | new_event_data->sport=event_data->sport; 66 | new_event_data->dport=event_data->dport; 67 | new_event_data->daddress=event_data->daddress; 68 | new_event_data->saddress=event_data->saddress; 69 | events.ringbuf_submit(new_event_data, sizeof(new_event_data)); 70 | } 71 | 72 | 73 | 74 | """ 75 | 76 | class EventSamples(ctypes.Structure): 77 | _fields_ = [ 78 | ("pid", ctypes.c_uint32), 79 | ("sport", ctypes.c_uint16), 80 | ("dport", ctypes.c_uint16), 81 | ("daddress", ctypes.c_uint32), 82 | ("saddress", ctypes.c_uint32), 83 | ] 84 | 85 | args = argparse.ArgumentParser() 86 | args.add_argument("pid", nargs="?", default="0") 87 | bpf_text = bpf_text.replace("{PID}", args.parse_args().pid) 88 | bpf = BPF(text=bpf_text) 89 | bpf.attach_kprobe(event="tcp_v4_syn_recv_sock", fn_name="trace_sk_drop_event_enter") 90 | bpf.attach_kretprobe(event="tcp_v4_syn_recv_sock", fn_name="trace_sk_drop_event_return") 91 | 92 | 93 | def parse_ip_address(data): 94 | results = [0, 0, 0, 0] 95 | results[3] = data & 0xFF 96 | results[2] = (data >> 8) & 0xFF 97 | results[1] = (data >> 16) & 0xFF 98 | results[0] = (data >> 24) & 0xFF 99 | return ".".join([str(i) for i in results[::-1]]) 100 | 101 | 102 | def process_event_data(cpu, data, size): 103 | # event = b["probe_icmp_events"].event(data) 104 | event = ctypes.cast(data, ctypes.POINTER(EventSamples)).contents 105 | daddress = parse_ip_address(event.daddress) 106 | print( 107 | f"pid:{event.pid}, daddress:{daddress}, saddress:{parse_ip_address(event.saddress)}, sport:{event.sport}, dport:{event.dport}" 108 | ) 109 | 110 | bpf["events"].open_ring_buffer(process_event_data) 111 | 112 | while True: 113 | try: 114 | bpf.ring_buffer_consume() 115 | except KeyboardInterrupt: 116 | exit() 117 | -------------------------------------------------------------------------------- /ebpf/analysis-read-file-time.py: -------------------------------------------------------------------------------- 1 | from bcc import BPF 2 | import time 3 | import argparse 4 | import pandas 5 | 6 | bpf_text = """ 7 | #include 8 | #include 9 | #include 10 | 11 | enum trace_mode { 12 | MODE_READ, 13 | MODE_WRITE, 14 | }; 15 | 16 | struct cache_data_t { 17 | u32 data_size; 18 | u64 ts; 19 | u32 name_len; 20 | char name[DNAME_INLINE_LEN]; 21 | }; 22 | 23 | struct event_data_t { 24 | enum trace_mode mode; 25 | u32 pid; 26 | u32 data_size; 27 | u64 delta_ts; 28 | u32 name_len; 29 | char name[DNAME_INLINE_LEN]; 30 | }; 31 | 32 | BPF_HASH(action_info, pid_t, struct cache_data_t); 33 | BPF_PERF_OUTPUT(events); 34 | 35 | 36 | static void trace_vfs_rw_action(struct pt_regs *ctx, struct file *file, char __user *buf, size_t count) { 37 | u32 pid=bpf_get_current_pid_tgid()>>32; 38 | u32 tid=bpf_get_current_pid_tgid(); 39 | if (pid!={PID}){ 40 | return; 41 | } 42 | struct dentry *dentry = file->f_path.dentry; 43 | int mode=file->f_inode->i_mode; 44 | if (dentry->d_name.len==0||!S_ISREG(mode)){ 45 | return; 46 | } 47 | struct cache_data_t cache_data={}; 48 | cache_data.data_size=count; 49 | cache_data.ts=bpf_ktime_get_ns(); 50 | bpf_probe_read_kernel(&cache_data.name, sizeof(cache_data.name), dentry->d_name.name); 51 | action_info.update(&tid, &cache_data); 52 | return; 53 | } 54 | 55 | static void trace_vfs_rw_action_return(struct pt_regs *ctx, int type) { 56 | u32 pid=bpf_get_current_pid_tgid()>>32; 57 | u32 tid=bpf_get_current_pid_tgid(); 58 | struct cache_data_t *cache_data=action_info.lookup(&tid); 59 | if (cache_data==NULL){ 60 | return; 61 | } 62 | action_info.delete(&tid); 63 | struct event_data_t event_data={}; 64 | event_data.mode=type; 65 | event_data.pid=pid; 66 | event_data.data_size=cache_data->data_size; 67 | event_data.delta_ts=bpf_ktime_get_ns()-cache_data->ts; 68 | bpf_probe_read_kernel(&event_data.name, sizeof(event_data.name), cache_data->name); 69 | events.perf_submit(ctx, &event_data, sizeof(event_data)); 70 | return; 71 | } 72 | 73 | int trace_vfs_rw_entry(struct pt_regs *ctx, struct file *file, char __user *buf, size_t count) { 74 | if (!(file->f_op->read_iter)&&!(file->f_op->write_iter)){ 75 | return 0; 76 | } 77 | trace_vfs_rw_action(ctx, file, buf, count); 78 | return 0; 79 | } 80 | 81 | int trace_vfs_read_exit(struct pt_regs *ctx){ 82 | trace_vfs_rw_action_return(ctx, MODE_READ); 83 | return 0; 84 | } 85 | 86 | int trace_vfs_write_exit(struct pt_regs *ctx){ 87 | trace_vfs_rw_action_return(ctx, MODE_WRITE); 88 | return 0; 89 | } 90 | 91 | """ 92 | 93 | args = argparse.ArgumentParser() 94 | args.add_argument("pid", nargs="?", default="0") 95 | 96 | bpf_text = bpf_text.replace("{PID}", args.parse_args().pid) 97 | 98 | bpf = BPF(text=bpf_text) 99 | 100 | bpf.attach_kprobe(event="vfs_read", fn_name="trace_vfs_rw_entry") 101 | bpf.attach_kprobe(event="vfs_write", fn_name="trace_vfs_rw_entry") 102 | bpf.attach_kretprobe(event="vfs_read", fn_name="trace_vfs_read_exit") 103 | bpf.attach_kretprobe(event="vfs_write", fn_name="trace_vfs_write_exit") 104 | 105 | read_data = [] 106 | write_data = [] 107 | 108 | 109 | def process_event_data(cpu, data, size): 110 | event = bpf["events"].event(data) 111 | result = {} 112 | result["pid"] = event.pid 113 | result["data_size"] = event.data_size 114 | result["delta_ts"] = event.delta_ts 115 | result["name"] = event.name.decode("utf-8", "replace") 116 | if event.mode == 0: 117 | read_data.append(result) 118 | else: 119 | write_data.append(result) 120 | 121 | 122 | bpf["events"].open_perf_buffer(process_event_data) 123 | while True: 124 | try: 125 | bpf.perf_buffer_poll() 126 | except KeyboardInterrupt: 127 | read_df = pandas.DataFrame(read_data) 128 | write_df = pandas.DataFrame(write_data) 129 | read_df.to_csv("read_file_time_with_nas.csv") 130 | write_df.to_csv("write_file_time_with_nas.csv") 131 | exit() 132 | -------------------------------------------------------------------------------- /ebpf/analysis-all-nfs-time.py: -------------------------------------------------------------------------------- 1 | from bcc import BPF 2 | import time 3 | import argparse 4 | import pandas 5 | 6 | bpf_text = """ 7 | #include 8 | #include 9 | #include 10 | 11 | enum trace_mode { 12 | NFS_OPEN, 13 | NFS_LOOKUP, 14 | NFS_GET_LINK, 15 | NFS_FILE_READ, 16 | NFS_READPAGE, 17 | NFS_PERMISSION, 18 | NFS_GETATTR, 19 | }; 20 | 21 | struct cache_data_t { 22 | u64 ts; 23 | }; 24 | 25 | struct event_data_t { 26 | enum trace_mode mode; 27 | u32 pid; 28 | u64 delta_ts; 29 | }; 30 | 31 | BPF_HASH(action_info, pid_t, struct cache_data_t); 32 | BPF_RINGBUF_OUTPUT(events, 65536); 33 | 34 | 35 | static void trace_action_enter() { 36 | u32 pid=bpf_get_current_pid_tgid()>>32; 37 | u32 tid=bpf_get_current_pid_tgid(); 38 | if (pid!={PID}){ 39 | return; 40 | } 41 | struct cache_data_t cache_data={}; 42 | cache_data.ts=bpf_ktime_get_ns(); 43 | action_info.update(&tid, &cache_data); 44 | return; 45 | } 46 | 47 | static void trace_action_return(struct pt_regs *ctx, int type) { 48 | u32 pid=bpf_get_current_pid_tgid()>>32; 49 | u32 tid=bpf_get_current_pid_tgid(); 50 | struct cache_data_t *cache_data=action_info.lookup(&tid); 51 | if (cache_data==NULL){ 52 | return; 53 | } 54 | action_info.delete(&tid); 55 | struct event_data_t *event_data=events.ringbuf_reserve(sizeof(struct event_data_t)); 56 | if (!event_data) { 57 | return ; 58 | } 59 | event_data->mode=type; 60 | event_data->pid=pid; 61 | event_data->delta_ts=bpf_ktime_get_ns()-cache_data->ts; 62 | events.ringbuf_submit(event_data, sizeof(event_data)); 63 | return; 64 | } 65 | 66 | int trace_nfs_open_enter(struct pt_regs *ctx, struct inode *inode, struct file *filp) { 67 | trace_action_enter(); 68 | return 0; 69 | } 70 | 71 | int trace_nfs_open_return(struct pt_regs *ctx) { 72 | trace_action_return(ctx, NFS_OPEN); 73 | return 0; 74 | } 75 | 76 | 77 | int trace_nfs_lookup_enter(struct pt_regs *ctx, struct inode *dir, struct dentry * dentry, unsigned int flags) { 78 | trace_action_enter(); 79 | return 0; 80 | } 81 | 82 | int trace_nfs_lookup_return(struct pt_regs *ctx) { 83 | trace_action_return(ctx, NFS_LOOKUP); 84 | return 0; 85 | } 86 | 87 | int trace_nfs_get_link_enter(struct pt_regs *ctx, struct dentry *dentry, struct inode *inode, struct delayed_call *done) { 88 | trace_action_enter(); 89 | return 0; 90 | } 91 | 92 | int trace_nfs_get_link_return(struct pt_regs *ctx) { 93 | trace_action_return(ctx, NFS_GET_LINK); 94 | return 0; 95 | } 96 | 97 | int trace_nfs_file_read_enter(struct pt_regs *ctx, struct kiocb *iocb, struct iov_iter *to) { 98 | trace_action_enter(); 99 | return 0; 100 | } 101 | 102 | int trace_nfs_file_read_return(struct pt_regs *ctx) { 103 | trace_action_return(ctx, NFS_FILE_READ); 104 | return 0; 105 | } 106 | 107 | int trace_nfs_readpage_enter(struct pt_regs *ctx, struct file *file, struct page *page) { 108 | trace_action_enter(); 109 | return 0; 110 | } 111 | 112 | int trace_nfs_readpage_return(struct pt_regs *ctx) { 113 | trace_action_return(ctx, NFS_READPAGE); 114 | return 0; 115 | } 116 | 117 | int trace_nfs_permission_enter(struct pt_regs *ctx, struct user_namespace *mnt_userns, struct inode *inode, int mask) { 118 | trace_action_enter(); 119 | return 0; 120 | } 121 | 122 | int trace_nfs_permission_return(struct pt_regs *ctx) { 123 | trace_action_return(ctx, NFS_PERMISSION); 124 | return 0; 125 | } 126 | 127 | int trace_nfs_getattr_enter(struct pt_regs *ctx, struct user_namespace *mnt_userns, const struct path *path, struct kstat *stat, u32 request_mask, unsigned int query_flags) { 128 | trace_action_enter(); 129 | return 0; 130 | } 131 | 132 | int trace_nfs_getattr_return(struct pt_regs *ctx) { 133 | trace_action_return(ctx, NFS_GETATTR); 134 | return 0; 135 | } 136 | 137 | """ 138 | 139 | args = argparse.ArgumentParser() 140 | args.add_argument("pid", nargs="?", default="0") 141 | 142 | bpf_text = bpf_text.replace("{PID}", args.parse_args().pid) 143 | 144 | bpf = BPF(text=bpf_text) 145 | 146 | bpf.attach_kprobe(event="nfs_open", fn_name="trace_nfs_open_enter") 147 | bpf.attach_kprobe(event="nfs_lookup", fn_name="trace_nfs_lookup_enter") 148 | bpf.attach_kprobe(event="nfs_get_link", fn_name="trace_nfs_get_link_enter") 149 | bpf.attach_kprobe(event="nfs_file_read", fn_name="trace_nfs_file_read_enter") 150 | bpf.attach_kprobe(event="nfs_readpage", fn_name="trace_nfs_readpage_enter") 151 | bpf.attach_kprobe(event="nfs_permission", fn_name="trace_nfs_permission_enter") 152 | bpf.attach_kprobe(event="nfs_getattr", fn_name="trace_nfs_getattr_enter") 153 | 154 | bpf.attach_kretprobe(event="nfs_open", fn_name="trace_nfs_open_return") 155 | bpf.attach_kretprobe(event="nfs_lookup", fn_name="trace_nfs_lookup_return") 156 | bpf.attach_kretprobe(event="nfs_get_link", fn_name="trace_nfs_get_link_return") 157 | bpf.attach_kretprobe(event="nfs_file_read", fn_name="trace_nfs_file_read_return") 158 | bpf.attach_kretprobe(event="nfs_readpage", fn_name="trace_nfs_readpage_return") 159 | bpf.attach_kretprobe(event="nfs_permission", fn_name="trace_nfs_permission_return") 160 | bpf.attach_kretprobe(event="nfs_getattr", fn_name="trace_nfs_getattr_return") 161 | 162 | 163 | read_data = [] 164 | 165 | 166 | def process_event_data(cpu, data, size): 167 | event = bpf["events"].event(data) 168 | result = {} 169 | result["pid"] = event.pid 170 | result["delta_ts"] = event.delta_ts 171 | result["mode"] = event.mode 172 | read_data.append(result) 173 | 174 | 175 | bpf["events"].open_ring_buffer(process_event_data) 176 | while True: 177 | try: 178 | bpf.ring_buffer_consume() 179 | except KeyboardInterrupt: 180 | read_df = pandas.DataFrame(read_data) 181 | read_df.to_csv("read_file_time_with_nas_detail.csv") 182 | exit() 183 | --------------------------------------------------------------------------------