diff --git a/source/sysak.c b/source/sysak.c index e0f6234ce9901d0d319cc7b1cdbeaefb9119de10..84f069a6c93beb9d669ff7838e6a41aab3cebc5c 100644 --- a/source/sysak.c +++ b/source/sysak.c @@ -307,10 +307,8 @@ static int down_install(const char *component_name) sprintf(ko_path, "%s/%s", module_path, kern_version); sprintf(ko_file, "%s/%s/%s", module_path, kern_version, "sysak.ko"); - sprintf(btf_file, "%s/%s/vmlinux-%s", tools_path, kern_version, kern_version); if (access(ko_path,0) != 0) mkdir(ko_path, 0755 ); - //sprintf(download_cmd, "wget %s/sysak/sysak_modules/%s/%s/sysak.ko -P %s/%s 1&>/dev/null", // sysak_components_server, machine, module_tag, module_path, kern_version); sprintf(download_cmd, "wget %s/sysak/modules/%s/sysak-%s.ko -O %s/%s/sysak.ko 1&>/dev/null", @@ -321,6 +319,7 @@ static int down_install(const char *component_name) ret = 0; return ret; } else if (strcmp(component_name, "btf") == 0) { + sprintf(btf_file, "%s/vmlinux-%s", tools_path, kern_version); //sprintf(download_cmd, "wget %s/coolbpf/btf/%s/vmlinux-%s -P %s/%s 1&>/dev/null", // sysak_components_server, machine, kern_version, tools_path, kern_version); sprintf(download_cmd, "wget %s/coolbpf/btf/%s/vmlinux-%s -P %s 1&>/dev/null", @@ -335,50 +334,95 @@ static int down_install(const char *component_name) } } -static int check_or_install_components(const char *name) +static int pre_down_install(const char *module, const char *btf, const char *compents) { - char compents_path[MAX_WORK_PATH_LEN]; - const char *promt = "has not been installed, do you want to auto download and install ? Enter Y/N:"; - char user_input = ' '; int ret = 0; bool download = false; + char user_input = ' '; + char *btf_name = "btf"; + char *module_name = "sysak_modules"; + const char *promt = "has not been installed, do you want to auto download and install ? Enter Y/N:"; - if (strcmp(name, "sysak_modules") == 0) - sprintf(compents_path, "%s%s%s", module_path, kern_version, module); - else if (strcmp(name, "btf") == 0) - sprintf(compents_path, "%s/vmlinux-%s", tools_path, kern_version); - else - sprintf(compents_path, "%s%s", tools_path, name); + if (auto_get_components){ + download = true; + }else{ + if (module && btf) + printf("%s and %s %s", module_name, btf_name, promt); + else if (module) + printf("%s %s", module_name, promt); + else if (btf) + printf("%s %s", btf_name, promt); + else + printf("%s %s", compents, promt); + scanf("%c", &user_input); - if (access(compents_path, 0) != 0) { - if (auto_get_components) { - //printf("auto_get_components is %d", auto_get_components); + if (user_input == 'y' || user_input == 'Y') download = true; - } else { - printf("%s %s", name, promt); - scanf("%c", &user_input); - - if (user_input == 'y' || user_input == 'Y') - download = true; - } + } - if (download) { - ret = down_install(name); - if (ret < 0 || access(compents_path, 0) != 0) - ret = -EEXIST; - } else { + if (download) { + if (module) + ret = down_install(module_name); + if (btf) + ret = down_install(btf_name); + if (compents) + ret = down_install(compents); + if (ret < 0) + ret = -EEXIST; + } else { ret = -EEXIST; - } } + return ret; +} + +static int check_or_install_components(const char *name) +{ + char compents_path[MAX_WORK_PATH_LEN]; + char ko_path[MAX_WORK_PATH_LEN]; + char btf_path[MAX_WORK_PATH_LEN]; + char *need_module = NULL, *need_btf = NULL; + bool need_compents = false; + bool download = false; + int ret = 0; + need_module = strstr(name, "sysak_modules"); + need_btf = strstr(name, "btf"); + + if (need_module || need_btf) { + if (need_module) + sprintf(ko_path, "%s%s%s", module_path, kern_version, module); + if (need_btf) + sprintf(btf_path, "%s/vmlinux-%s", tools_path, kern_version); + } else { + sprintf(compents_path, "%s%s", tools_path, name); + need_compents = true; + } + + if (access(ko_path, 0) == 0) + need_module = NULL; + if (access(btf_path, 0) == 0) + need_btf = NULL; + + if (need_module && need_btf){ + ret = pre_down_install(need_module, need_btf, NULL); + } else if (need_module) { + ret = pre_down_install(need_module, NULL, NULL); + } else if (need_btf){ + ret = pre_down_install(NULL, need_btf, NULL); + } else if (need_compents){ + ret = pre_down_install(NULL, NULL, name); + } return ret; } static int do_prev_depend(void) { + if (pre_module && btf_depend) + return check_or_install_components("sysak_modules and btf"); + if (pre_module) { if (!check_or_install_components("sysak_modules")) - return mod_ctrl(true); + return mod_ctrl(true);; printf("sysak_modules not installed, exit ...\n"); return -1; } @@ -582,19 +626,30 @@ static bool tool_rule_parse(char *path, char *tool) while(fgets(buf, sizeof(buf), fp)) { char tools_name[MAX_NAME_LEN]; + char class_name[MAX_NAME_LEN]; pstr = buf; - sscanf(buf,"%*[^:]:%[^:]",tools_name); + sscanf(buf,"%[^:]:%[^:]", class_name, tools_name); + if (strstr(class_name,"combine")) + if (strstr(class_name,"/")) + continue; + if (strcmp(tools_name, tool)) { continue; } pstr = strstr(buf, ":prev{"); - if (pstr) + if (pstr){ sscanf(pstr, ":prev{%[^}]};post{%[^}]}", prev_dep, post_dep, run_depend); + } pstr = strstr(buf, ":python-dep{"); if (pstr) sscanf(pstr, ":python-dep{%[^}]}", run_depend); + pstr = strstr(buf, "bpf"); + if (pstr){ + btf_depend = true; + } + fclose(fp); return true; } diff --git a/source/tools/combine/Makefile b/source/tools/combine/Makefile index 6a58b3a5ece546dfb4ae837da8a53425d6927491..d1f4ce62411d4608866cab6f5ea47f713b8112e2 100644 --- a/source/tools/combine/Makefile +++ b/source/tools/combine/Makefile @@ -1 +1,2 @@ + include $(SRC)/mk/sub.mk diff --git a/source/tools/combine/iosdiag/Makefile b/source/tools/combine/iosdiag/Makefile index 4d1f7df8b9d50cbfdd7921989e6d6c77fc293faa..3dcb46b17aa979506d8b44b41fa1572cb269de47 100644 --- a/source/tools/combine/iosdiag/Makefile +++ b/source/tools/combine/iosdiag/Makefile @@ -1,3 +1,4 @@ target := iosdiag +DEPEND := "prev{default modin};post{default modun};{bpf}" include $(SRC)/mk/sub.mk diff --git a/source/tools/detect/fs/fanotifytrace/Makefile b/source/tools/detect/fs/fanotifytrace/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..08454581385ea648987ef72225c0f554c7e79d44 --- /dev/null +++ b/source/tools/detect/fs/fanotifytrace/Makefile @@ -0,0 +1,8 @@ + +newdirs := $(shell find ./ -type d) + +bpfsrcs := $(wildcard bpf/*.bpf.c) +csrcs := $(wildcard *.c) +target := fanotifytrace + +include $(SRC)/mk/bpf.mk diff --git a/source/tools/detect/fs/fanotifytrace/README.md b/source/tools/detect/fs/fanotifytrace/README.md new file mode 100644 index 0000000000000000000000000000000000000000..f903a27c9167396ce282c23d5ea0c9ac57c1f6b7 --- /dev/null +++ b/source/tools/detect/fs/fanotifytrace/README.md @@ -0,0 +1,11 @@ +# 功能说明 +fanotify跟踪工具 + +使用说明: +Usage: sysak fanotifytrace [options] +Options: + --syscallid/-i sspecify the syscallid,default is fanotify_init id(300) + --help/-h help info +example: sysak fanotifytrace #trace fanotify_init + +# 效果演示 \ No newline at end of file diff --git a/source/tools/detect/fs/fanotifytrace/bpf/fanotifytrace.bpf.c b/source/tools/detect/fs/fanotifytrace/bpf/fanotifytrace.bpf.c new file mode 100644 index 0000000000000000000000000000000000000000..3389e752a9158f94bb7aa58fb868ef9a961834df --- /dev/null +++ b/source/tools/detect/fs/fanotifytrace/bpf/fanotifytrace.bpf.c @@ -0,0 +1,64 @@ +#include +#include +#include +#include "../fanotifytrace.h" + +#define _(P) ({ \ + typeof(P) val; \ + __builtin_memset(&val, 0, sizeof(val)); \ + bpf_probe_read(&val, sizeof(val), &P); \ + val; \ +}) + +struct bpf_map_def SEC("maps") args_map = { + .type = BPF_MAP_TYPE_HASH, + .key_size = sizeof(int), + .value_size = sizeof(struct args), + .max_entries = 1, +}; + +struct syscalls_enter_fanotifyinit_args { + unsigned long long unused; + int syscall_nr; + long flags; + long event_f_flags; +}; + +struct raw_sys_enter_arg { + struct trace_entry ent; + long int id; + long unsigned int args[6]; + char __data[0]; +}; + +struct { + __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); + __uint(key_size, sizeof(u32)); + __uint(value_size, sizeof(u32)); +} fanotify_events SEC(".maps"); + +SEC("tp/raw_syscalls/sys_enter") +int handle_raw_sys_enter(struct raw_sys_enter_arg *ctx) +{ + u64 now; + int pid, i = 0; + bool match; + char comm[TASK_COMM_LEN] = {0}; + struct task_struct *task; + struct args *argp; + struct task_info new1; + + argp = bpf_map_lookup_elem(&args_map, &i); + if (ctx->id == _(argp->syscallid)){ + __builtin_memset(&new1, 0, sizeof(struct task_info)); + bpf_get_current_comm(new1.comm,TASK_COMM_LEN); + new1.pid = bpf_get_current_pid_tgid(); + new1.time = bpf_ktime_get_ns(); + new1.syscallid = ctx->id; + bpf_perf_event_output(ctx, &fanotify_events, BPF_F_CURRENT_CPU, + &new1, sizeof(new1)); + } + return 0; +} + +char LICENSE[] SEC("license") = "GPL"; diff --git a/source/tools/detect/fs/fanotifytrace/fanotifytrace.c b/source/tools/detect/fs/fanotifytrace/fanotifytrace.c new file mode 100644 index 0000000000000000000000000000000000000000..cfa19b76d327d22e8cc0267bae54e2714a954616 --- /dev/null +++ b/source/tools/detect/fs/fanotifytrace/fanotifytrace.c @@ -0,0 +1,221 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "bpf/fanotifytrace.skel.h" +#include "fanotifytrace.h" + +long int syscallid = FANOTIFY_INIT_ID; +bool verbose = false; +FILE *fanotifyinit_fd = NULL; +static volatile sig_atomic_t exiting; + + +char *log_dir = "/var/log/sysak/fanotifytrace"; +char *fanotifyinit_data = "/var/log/sysak/fanotifytrace/fanotify_init.log"; + +struct option longopts[] = { + //{ "time", no_argument, NULL, 't' }, + { "syscallid", no_argument, NULL, 'i' }, + { "help", no_argument, NULL, 'h' }, + { 0, 0, 0, 0}, +}; + +static void usage(void) +{ + fprintf(stdout, + "Usage: sysak fanotifytrace [options] [args]\n" + "Options:\n" + " --syscallid/-i specify the syscallid,default is fanotify_init id\n" + " --help/-h help info\n" + "example: sysak fanotifytrace #trace fanotify_init\n"); + exit(EXIT_FAILURE); +} + +static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args) +{ + if (verbose) + return vfprintf(stderr, format, args); + else + return 0; +} + +static void sig_int(int signo) +{ + exiting = 1; +} + +static void sig_alarm(int signo) +{ + exiting = 1; +} + +static void bump_memlock_rlimit(void) +{ + struct rlimit rlim_new = { + .rlim_cur = RLIM_INFINITY, + .rlim_max = RLIM_INFINITY, + }; + + if (setrlimit(RLIMIT_MEMLOCK, &rlim_new)) { + fprintf(stderr, "Failed to increase RLIMIT_MEMLOCK limit!\n"); + exit(1); + } +} + +void stamp_to_date(__u64 stamp, char dt[], int len) +{ + time_t t, diff, last; + struct tm *tm; + struct timespec ts; + + clock_gettime(CLOCK_MONOTONIC, &ts); + last = time(&t); + if (stamp) { + diff = ts.tv_sec * SEC_TO_NS + ts.tv_nsec - stamp; + diff = diff / SEC_TO_NS; + last = t - diff; + } + tm = localtime(&last); + strftime(dt, len, "%F %H:%M:%S", tm); +} + +static int prepare_dictory(char *path) +{ + int ret = 0; + + if (access(path,0) != 0) + ret = mkdir(path, 0777); + + return ret; +} + +void handle_event(void *ctx, int cpu, void *data, __u32 data_sz) +{ + const struct task_info *dp = data; + char date[MAX_DATE]; + + stamp_to_date(dp->time, date, MAX_DATE); + fprintf(fanotifyinit_fd, "%-48s\t%-10u\t%-16s\t%-12s\t%-10lu\n", dp->comm, dp->pid, date, "fanotify_init", dp->syscallid); +} + +void handle_lost_events(void *ctx, int cpu, __u64 lost_cnt) +{ + printf("Lost %llu events on CPU #%d!\n", lost_cnt, cpu); +} + +int fanotify_handler(int poll_fd, struct fanotifytrace_bpf *skel) +{ + int err = 0; + struct perf_buffer *pb = NULL; + struct perf_buffer_opts pb_opts = {}; + + if (access(fanotifyinit_data,0) != 0){ + fanotifyinit_fd = fopen(fanotifyinit_data, "a+"); + fprintf(fanotifyinit_fd, "%-48s\t%-10s\t%-16s\t%-12s\t%-10s\n", "Name", "Pid","Time", "event", "Syscall Number"); + } else { + fanotifyinit_fd = fopen(fanotifyinit_data, "a+"); + } + + pb_opts.sample_cb = handle_event; + pb_opts.lost_cb = handle_lost_events; + pb = perf_buffer__new(poll_fd, 64, &pb_opts); + if (!pb) { + err = -errno; + fprintf(stderr, "failed to open perf buffer: %d\n", err); + goto clean_nosched; + } + + err = fanotifytrace_bpf__attach(skel); + if (err) { + fprintf(stderr, "Failed to attach BPF skeleton\n"); + return err; + } + while (!exiting) { + err = perf_buffer__poll(pb, 100); + if (err < 0 && err != -EINTR) { + fprintf(stderr, "error polling perf buffer: %s\n", strerror(-err)); + goto clean_nosched; + } + /* reset err to return 0 if exiting */ + err = 0; + } +clean_nosched: + fclose(fanotifyinit_fd); + perf_buffer__free(pb); + return err; +} + +int main(int argc, char *argv[]) +{ + int opt; + int err = 0, map_fd1, map_fd2, args_key = 0; + struct fanotifytrace_bpf *skel; + struct args args; + + while ((opt = getopt_long(argc, argv, "i:hv", longopts, NULL)) != -1) { + switch (opt) { + case 'i': + if (optarg) + syscallid = (long int)strtoul(optarg, NULL, 10); + break; + case 'h': + usage(); + break; + case 'v': + verbose = true; + break; + default: + break; + } + } + + libbpf_set_print(libbpf_print_fn); + bump_memlock_rlimit(); + + prepare_dictory(log_dir); + + skel = fanotifytrace_bpf__open(); + if (!skel) { + fprintf(stderr, "Failed to open BPF skeleton\n"); + return 1; + } + + err = fanotifytrace_bpf__load(skel); + if (err) { + fprintf(stderr, "Failed to load BPF skeleton, errno:%d\n",err); + return 1; + } + if (signal(SIGINT, sig_int) == SIG_ERR || + signal(SIGALRM, sig_alarm) == SIG_ERR) { + fprintf(stderr, "can't set signal handler: %s\n", strerror(errno)); + goto cleanup; + } + + map_fd1 = bpf_map__fd(skel->maps.args_map); + args.syscallid = syscallid; + err = bpf_map_update_elem(map_fd1, &args_key, &args, 0); + if (err) { + fprintf(stderr, "Failed to update flag map\n"); + goto cleanup; + } + map_fd2 = bpf_map__fd(skel->maps.fanotify_events); + + printf("Starting trace, Can hit to abort and report\n"); + err = fanotify_handler(map_fd2, skel); + +cleanup: + fanotifytrace_bpf__destroy(skel); + return err; +} diff --git a/source/tools/detect/fs/fanotifytrace/fanotifytrace.h b/source/tools/detect/fs/fanotifytrace/fanotifytrace.h new file mode 100644 index 0000000000000000000000000000000000000000..237183607535b14074b4e912c5ea5afeed84fb8c --- /dev/null +++ b/source/tools/detect/fs/fanotifytrace/fanotifytrace.h @@ -0,0 +1,28 @@ +#ifndef __FANOTIFYTRACE_H +#define __FANOTIFYTRACE_H + +#define TASK_COMM_LEN 16 +#define MAX_DATE 128 +#define FANOTIFY_INIT_ID 300 +#define FANOTIFY_MARK_ID 301 +#define SEC_TO_NS (1000*1000*1000) +#define SEC_TO_MS (1000*1000) + +struct args { + long int syscallid; +}; + +struct task_info { + __u32 pid; + char comm[16]; + __u64 time; + long int syscallid; + long int syscallid_args; +}; + +struct ksym { + long addr; + char *name; +}; +#endif + diff --git a/source/tools/detect/fs/fanotifytrace/sample/fanotify_sample.c b/source/tools/detect/fs/fanotifytrace/sample/fanotify_sample.c new file mode 100644 index 0000000000000000000000000000000000000000..0504d2d1d68922d541e85344af81ff5365753efa --- /dev/null +++ b/source/tools/detect/fs/fanotifytrace/sample/fanotify_sample.c @@ -0,0 +1,113 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char** argv) +{ + int fan; + int mount_fd, event_fd; + char buf[4096]; + char fdpath[32]; + char path[PATH_MAX + 1]; + struct file_handle *file_handle; + struct fanotify_response response; + + ssize_t buflen, linklen; + struct fanotify_event_metadata *metadata; + struct fanotify_event_info_fid *fid; + + if (argc != 2) { + fprintf(stderr, "Usage: %s /dir\n", argv[0]); + exit(EXIT_FAILURE); + } + + mount_fd = open(argv[1], O_DIRECTORY | O_RDONLY); + if (mount_fd == -1) { + perror(argv[1]); + exit(EXIT_FAILURE); + } + + fan = fanotify_init(FAN_CLASS_NOTIF | FAN_CLASS_CONTENT | FAN_NONBLOCK, O_RDWR); + if(fan == -1) { + perror("fanotify_init"); + exit(EXIT_FAILURE); + } + + int ret = fanotify_mark(fan, + FAN_MARK_ADD, + FAN_OPEN_PERM | FAN_MODIFY | FAN_EVENT_ON_CHILD, + AT_FDCWD, + argv[1] + ); + if(ret == -1) { + perror("fanotify_mark"); + exit(EXIT_FAILURE); + } + + while(1) { + //buflen = read(fan, buf, sizeof(buf)); + metadata = (struct fanotify_event_metadata*)&buf; + + for (; FAN_EVENT_OK(metadata, buflen); metadata = FAN_EVENT_NEXT(metadata, buflen)) { + //fid = (struct fanotify_event_info_fid *) (metadata + 1); + //file_handle = (struct file_handle *) fid->handle; + + /* Ensure that the event info is of the correct type */ + + /*if (fid->hdr.info_type != FAN_EVENT_ON_CHILD) { + + fprintf(stderr, "Received unexpected event info type.\n"); + exit(EXIT_FAILURE); + }*/ + + if (metadata->mask == FAN_OPEN_PERM) + printf("FAN_OPEN"); + + //if (metadata->mask == FAN_DELETE) + // printf("FAN_DELETE"); + + if (metadata->mask == FAN_MODIFY) + printf("FAN_MODIFY"); + + /* event_fd = open_by_handle_at(mount_fd, file_handle, O_RDONLY); + if (event_fd == -1) { + if (errno == ESTALE) { + printf("File handle is no longer valid. " + "File has been deleted\n"); + continue; + } else { + perror("open_by_handle_at"); + exit(EXIT_FAILURE); + } + }*/ + if (metadata->mask & FAN_OPEN_PERM) { + printf("FAN_OPEN_PERM: "); + + /* Allow file to be opened */ + + response.fd = metadata->fd; + response.response = FAN_ALLOW; + write(fan, &response, + sizeof(struct fanotify_response)); + } + + + sprintf(fdpath, "/proc/self/fd/%d", metadata->fd); + linklen = readlink(fdpath, path, sizeof(path) - 1); + if (linklen == -1) { + perror("readlink"); + } + path[linklen] = '\0'; + printf("%s\n", path); + + close(metadata->fd); + metadata = FAN_EVENT_NEXT(metadata, buflen); + } + } +}