diff --git a/docs/perl_env.md b/docs/perl_env.md index 5165e83..e2a6f7e 100644 --- a/docs/perl_env.md +++ b/docs/perl_env.md @@ -27,4 +27,9 @@ pre-commit run -a ## package update ```shell sudo PERL5LIB=$PERL5LIB $(which minil) test +``` + +## bpf printk +```shell +sudo cat /sys/kernel/debug/tracing/trace_pipe ``` \ No newline at end of file diff --git a/sample/kprobe_file_open_tracker/build.sh b/sample/kprobe_file_open_tracker/build.sh new file mode 100755 index 0000000..c402373 --- /dev/null +++ b/sample/kprobe_file_open_tracker/build.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +clang -O3 -emit-llvm -c kprobe_file_open_tracker.c -o - | llc -march=bpf -filetype=obj -o kprobe_file_open_tracker.o diff --git a/sample/kprobe_file_open_tracker/kprobe_file_open_tracker.c b/sample/kprobe_file_open_tracker/kprobe_file_open_tracker.c new file mode 100644 index 0000000..d22cc4a --- /dev/null +++ b/sample/kprobe_file_open_tracker/kprobe_file_open_tracker.c @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include +#include +#include + +char __license[] SEC("license") = "Dual MIT/GPL"; + +#define MAX_FILENAME_LEN 128 +#define MAX_ENTRIES 1024 + +struct file_open_info +{ + __u32 count; + char filename[MAX_FILENAME_LEN]; +}; + +struct bpf_map_def SEC("maps") file_open_map = { + .type = BPF_MAP_TYPE_HASH, + .key_size = sizeof(__u32), + .value_size = sizeof(struct file_open_info), + .max_entries = MAX_ENTRIES, +}; + +SEC("kprobe/sys_open") +int kprobe_sys_open(struct pt_regs *ctx) +{ + __u32 pid = bpf_get_current_pid_tgid() >> 32; + + // __userを削除 + const char *filename_ptr = (const char *)PT_REGS_PARM1(ctx); + char filename[MAX_FILENAME_LEN]; + int ret = bpf_probe_read_kernel_str(filename, sizeof(filename), filename_ptr); + if (ret < 0) + { + bpf_printk("bpf_probe_read_user_str failed: %d\n", ret); + return 0; + } + bpf_printk("filename: %s\n", filename); + struct file_open_info info = {}; + struct file_open_info *pinfo; + + pinfo = bpf_map_lookup_elem(&file_open_map, &pid); + if (pinfo) + { + // 既存のエントリがある場合はカウントを増加 + info.count = pinfo->count + 1; + } + else + { + // 新しいエントリの場合はカウントを1に設定 + info.count = 1; + } + + // ファイル名をコピー + __builtin_memcpy(&info.filename, filename, sizeof(info.filename)); + bpf_printk("pid: %d\n", pid); + // bpf_printk("filename: %s\n", info.filename); + // マップを更新 + bpf_map_update_elem(&file_open_map, &pid, &info, BPF_ANY); + + return 0; +} diff --git a/sample/kprobe_file_open_tracker/kprobe_file_open_tracker.pl b/sample/kprobe_file_open_tracker/kprobe_file_open_tracker.pl new file mode 100644 index 0000000..fe4c7b1 --- /dev/null +++ b/sample/kprobe_file_open_tracker/kprobe_file_open_tracker.pl @@ -0,0 +1,54 @@ +#!/usr/bin/env perl + +use strict; +use warnings; +use utf8; +use lib '../../lib'; +use Sys::Ebpf::Loader; +use Sys::Ebpf::Link::Perf::Kprobe; + +my $file = "kprobe_file_open_tracker.o"; +my $loader = Sys::Ebpf::Loader->new($file); +my $data = $loader->load_elf(); + +my $kprobe_fn = "kprobe/sys_open"; + +my ( $map_data, $prog_fd ) = $loader->load_bpf($kprobe_fn); +my $map_file_open = $map_data->{file_open_map}; +$map_file_open->{key_schema} = [ [ 'pid', 'uint32' ] ]; +$map_file_open->{value_schema} + = [ [ 'count', 'uint32' ], [ 'filename', 'string[128]' ] ]; + +my $kprobe_info + = Sys::Ebpf::Link::Perf::Kprobe::attach_kprobe( $prog_fd, $kprobe_fn ); + +print "Program FD: $prog_fd\n"; +print "ファイルオープンの追跡を開始します。Ctrl+Cで停止します。\n"; + +$map_file_open->update( { pid => $$ }, { count => 0, filename => "sample" } ); + +while (1) { + my $prev_key = undef; + my $has_entries = 0; + while ( defined( my $key = $map_file_open->get_next_key($prev_key) ) ) { + $has_entries = 1; + my $value = $map_file_open->lookup($key); + if ( defined $value ) { + printf "PID: %d, ファイル名: %s, オープン回数: %d\n", + $key->{pid}, $value->{filename}, $value->{count}; + } + $prev_key = $key; + sleep(1); + } + if ( !$has_entries ) { + print "マップにエントリがありません。\n"; + } + print "---\n"; + sleep(1); +} + +END { + if ($kprobe_info) { + Sys::Ebpf::Link::Perf::Kprobe::detach_kprobe($kprobe_info); + } +} diff --git a/sample/xdp_count_8080_port/build.sh b/sample/xdp_count_8080_port/build.sh new file mode 100755 index 0000000..17f75d4 --- /dev/null +++ b/sample/xdp_count_8080_port/build.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +clang -O3 -emit-llvm -c xdp_count_8080_port.c -o - | llc -march=bpf -filetype=obj -o xdp_count_8080_port.o diff --git a/sample/xdp_count_8080_port/xdp_count_8080_port.c b/sample/xdp_count_8080_port/xdp_count_8080_port.c new file mode 100644 index 0000000..41aae62 --- /dev/null +++ b/sample/xdp_count_8080_port/xdp_count_8080_port.c @@ -0,0 +1,56 @@ +#include +#include +#include +#include +#include +#include +#include + +struct bpf_map_def SEC("maps") xdp_map = { + .type = BPF_MAP_TYPE_ARRAY, + .key_size = sizeof(__u32), + .value_size = sizeof(__u64), + .max_entries = 1, +}; + +SEC("xdp/xdp_count_8080_port") +int xdp_count_8080_port(struct xdp_md *ctx) +{ + void *data = (void *)(long)ctx->data; + void *data_end = (void *)(long)ctx->data_end; + struct ethhdr *eth = data; + __u32 key = 0; + __u64 *value; + + // Ethernetヘッダのサイズ確認 + if (data + sizeof(*eth) > data_end) + return XDP_PASS; + + // IPヘッダの確認 + struct iphdr *ip = data + sizeof(*eth); + if ((void *)ip + sizeof(*ip) > data_end) + return XDP_PASS; + + // TCPパケットかどうかを確認 + if (ip->protocol != IPPROTO_TCP) + return XDP_PASS; + + // TCPヘッダの確認 + struct tcphdr *tcp = (void *)ip + sizeof(*ip); + if ((void *)tcp + sizeof(*tcp) > data_end) + return XDP_PASS; + + // 目的ポートが8080かどうか確認 + if (tcp->dest == bpf_htons(8080)) + { + value = bpf_map_lookup_elem(&xdp_map, &key); + if (value) + { + __sync_fetch_and_add(value, 1); + } + } + + return XDP_PASS; +} + +char _license[] SEC("license") = "GPL"; diff --git a/sample/xdp_dport_counter/xdp_dport_counter.pl b/sample/xdp_count_8080_port/xdp_count_8080_port.pl similarity index 94% rename from sample/xdp_dport_counter/xdp_dport_counter.pl rename to sample/xdp_count_8080_port/xdp_count_8080_port.pl index e2a0a94..9141ebe 100644 --- a/sample/xdp_dport_counter/xdp_dport_counter.pl +++ b/sample/xdp_count_8080_port/xdp_count_8080_port.pl @@ -8,11 +8,11 @@ use Sys::Ebpf::Loader; use Sys::Ebpf::Link::Netlink::Xdp; -my $file = "xdp_dport_counter.o"; +my $file = "xdp_count_8080_port.o"; my $loader = Sys::Ebpf::Loader->new($file); my $data = $loader->load_elf(); -my $xdp_fn = "xdp/xdp_pass"; +my $xdp_fn = "xdp/xdp_count_8080_port"; my ( $map_data, $prog_fd ) = $loader->load_bpf($xdp_fn); my $map_xdp_map = $map_data->{xdp_map}; diff --git a/sample/xdp_dport_counter/build.sh b/sample/xdp_dport_counter/build.sh deleted file mode 100755 index 809afb3..0000000 --- a/sample/xdp_dport_counter/build.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -clang -O3 -emit-llvm -c xdp_dport_counter.c -o - | llc -march=bpf -filetype=obj -o xdp_dport_counter.o diff --git a/sample/xdp_dport_counter/xdp_dport_counter.c b/sample/xdp_dport_counter/xdp_dport_counter.c deleted file mode 100644 index 3a64db2..0000000 --- a/sample/xdp_dport_counter/xdp_dport_counter.c +++ /dev/null @@ -1,26 +0,0 @@ -#include -#include - -struct bpf_map_def SEC("maps") xdp_map = { - .type = BPF_MAP_TYPE_ARRAY, - .key_size = sizeof(__u32), - .value_size = sizeof(__u64), - .max_entries = 1, -}; - -SEC("xdp/xdp_pass") -int xdp_pass_func(struct xdp_md *ctx) -{ - __u32 key = 0; - __u64 *value; - - value = bpf_map_lookup_elem(&xdp_map, &key); - if (value) - { - __sync_fetch_and_add(value, 1); - } - - return XDP_PASS; -} - -char _license[] SEC("license") = "GPL"; diff --git a/script/remove_bak.sh b/script/remove_bak.sh old mode 100644 new mode 100755