diff --git a/src/Makefile b/src/Makefile index 8be6c3dc1933c971c9917393962629d1f5b42714..70f6e4b4dc53a5d34f6d0007cdb94254e45dc16c 100644 --- a/src/Makefile +++ b/src/Makefile @@ -9,7 +9,7 @@ INCLUDES := -I$(OUTPUT) -idirafter $(abspath ../libbpf/include) CFLAGS := -g -Wall ARCH := $(shell uname -m | sed 's/x86_64/x86/') -APPS = minimal bootstrap uprobe task task_bulk task_mmap task_sleep task_bulk_minimal task_ag task_find task_find_magic +APPS = minimal bootstrap uprobe task task_bulk task_mmap task_sleep task_bulk_minimal task_ag task_find task_filter_magic # Get Clang's default includes on this system. We'll explicitly add these dirs # to the includes list when compiling with `-target bpf` because otherwise some diff --git a/src/task-find-magic b/src/task-find-magic new file mode 100755 index 0000000000000000000000000000000000000000..a97489ec4c5adee70c69b99dae9b176972d42433 --- /dev/null +++ b/src/task-find-magic @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +set -euo pipefail + +path=$1 +args=${@:2} + +src_dir=$(dirname "$(command -v $0)") + +find "${path}" | env -C "$src_dir" ./task_filter_magic ${args} diff --git a/src/task_find_magic.bpf.c b/src/task_filter_magic.bpf.c similarity index 100% rename from src/task_find_magic.bpf.c rename to src/task_filter_magic.bpf.c diff --git a/src/task_find_magic.c b/src/task_filter_magic.c similarity index 57% rename from src/task_find_magic.c rename to src/task_filter_magic.c index ff69d61eda637d2e60eb48d02181761253eb57a4..45a0c7a1fe4af4777e55a691d58743baa79744f2 100644 --- a/src/task_find_magic.c +++ b/src/task_filter_magic.c @@ -19,11 +19,11 @@ #include <sys/resource.h> #include <bpf/libbpf.h> -#define NAME task_find_magic -#define NAME_BPF task_find_magic_bpf -#define BPF_OPEN task_find_magic_bpf__open -#define BPF_LOAD task_find_magic_bpf__load -#define BPF_DESTROY task_find_magic_bpf__destroy +#define NAME task_filter_magic +#define NAME_BPF task_filter_magic_bpf +#define BPF_OPEN task_filter_magic_bpf__open +#define BPF_LOAD task_filter_magic_bpf__load +#define BPF_DESTROY task_filter_magic_bpf__destroy /* https://stackoverflow.com/questions/5873722/c-macro-dynamic-include */ #define __header(x) #x @@ -144,18 +144,8 @@ static void plog(const unsigned int level, const char *fmt, ...) { va_end(args); } -static int search_buf_user(const char *buf, size_t f_len, const char *file_full_path, - const char *literal) { - size_t literal_len = strlen(literal); - for (int i = 0; i < f_len - literal_len + 1; i++) { - if (!memcmp(buf + i, literal, literal_len)) - printf("%d\n", i); - } - return EXIT_SUCCESS; -} - static int search_buf_bpf(const char *buf, size_t f_len, const char *file_full_path, - const char *literal) { + const char *magic) { struct NAME_BPF *skel; int err; @@ -191,118 +181,60 @@ destroy: return EXIT_SUCCESS; } -static int search_buf(const char *buf, size_t f_len, const char *file_full_path, - const char *literal, bool variant_bpf) { - if (variant_bpf) { - return search_buf_bpf(buf, f_len, file_full_path, literal); - } else { - return search_buf_user(buf, f_len, file_full_path, literal); - } +static char *safe_fgets(char *s, int size, FILE *stream) { + char *res = fgets(s, size, stream); + if (res == NULL && ferror(stream)) { + perror("fgets"); + exit(EXIT_FAILURE); + } + return res; } -static int search_file(const char *file_full_path, const char *literal, bool variant_bpf) { - int err = EXIT_SUCCESS; - int fd = -1; - off_t f_len = 0; - char *buf = NULL; - struct stat statbuf; - int rv = 0; - int matches_count = -1; - FILE *fp = NULL; - - rv = stat(file_full_path, &statbuf); - if (rv != 0) { - log_err("Skipping %s: Error fstat()ing file.", file_full_path); - err = EXIT_FAILURE; - goto cleanup; - } - - // handling only regular files and FIFOs - if (!S_ISREG(statbuf.st_mode) && !S_ISFIFO(statbuf.st_mode)) { - log_err("Skipping %s: Mode %u is not a file.", file_full_path, statbuf.st_mode); - err = EXIT_FAILURE; - goto cleanup; - } - - fd = open(file_full_path, O_RDONLY); - if (fd < 0) { - /* XXXX: strerror is not thread-safe */ - log_err("Skipping %s: Error opening file: %s", file_full_path, strerror(errno)); - err = EXIT_FAILURE; - goto cleanup; - } - - // repeating stat check with file handle to prevent TOCTOU issue - rv = fstat(fd, &statbuf); - if (rv != 0) { - log_err("Skipping %s: Error fstat()ing file.", file_full_path); - err = EXIT_FAILURE; - goto cleanup; - } - - // handling only regular files and FIFOs - if (!S_ISREG(statbuf.st_mode) && !S_ISFIFO(statbuf.st_mode)) { - log_err("Skipping %s: Mode %u is not a file.", file_full_path, statbuf.st_mode); - err = EXIT_FAILURE; - goto cleanup; - } - - if (statbuf.st_mode & S_IFIFO) { - log_debug("%s is a named pipe. stream searching", file_full_path); - err = EXIT_FAILURE; - goto cleanup; - } +#define MAX_PATHLEN 512 - f_len = statbuf.st_size; - - buf = mmap(0, f_len, PROT_READ, MAP_PRIVATE, fd, 0); - if (buf == MAP_FAILED) { - log_err("File %s failed to load: %s.", file_full_path, strerror(errno)); - err = EXIT_FAILURE; - goto cleanup; - } -#if HAVE_MADVISE - madvise(buf, f_len, MADV_SEQUENTIAL); -#elif HAVE_POSIX_FADVISE - posix_fadvise(fd, 0, f_len, POSIX_MADV_SEQUENTIAL); -#endif +static int filter_magic(size_t offset, const char *magic) { + while (true) { + char pathbuf[MAX_PATHLEN]; + char *ptr = fgets(pathbuf, MAX_PATHLEN, stdin); + if (ptr == NULL) { + if (ferror(stdin)) { + log_err("fgets(stdin) failed"); + return EXIT_FAILURE; + } else { + log_debug("EOF reached"); + return EXIT_SUCCESS; + } + } - search_buf(buf, f_len, file_full_path, literal, variant_bpf); + pathbuf[strlen(pathbuf)] = '\0'; -cleanup: - if (buf != NULL) { - if (buf != MAP_FAILED) { - munmap(buf, f_len); - } - } - if (fd != -1) { - close(fd); + log_debug("pathbuf = %s", pathbuf); } - - return err; } int main(int argc, char **argv) { - bool variant_bpf = true; - bool fixed_strings = false; /* literal */ bool debug = false; - char *literal; - char *path; + bool variant_bpf = true; + size_t offset = 0; + char *magic; int c; opterr = 0; - while ((c = getopt(argc, argv, "v:" "F" "D")) != -1) { + while ((c = getopt(argc, argv, "v:" "D" "o:" "m:")) != -1) { switch (c) { case 'v': variant_bpf = strcmp("bpf", optarg) == 0; break; - case 'F': - fixed_strings = true; - break; case 'D': debug = true; break; + case 'o': + offset = atoi(optarg); + break; + case 'm': + magic = optarg; + break; case '?': if (optopt == 'v') { fprintf(stderr, "Option -%c requires an argument.\n", optopt); @@ -317,19 +249,17 @@ int main(int argc, char **argv) return EXIT_FAILURE; } } - if (optind != argc - 2 || !fixed_strings) { + if (optind != argc) { print_usage(argv); return EXIT_FAILURE; - } else { - literal = argv[optind]; - path = argv[optind+1]; } if (debug) { set_log_level(LOG_LEVEL_DEBUG); - fprintf(stderr, "%s: variant_bpf=%d, fixed_strings=%d, debug=%d, literal='%s', path='%s'\n", - argv[0], variant_bpf, fixed_strings, debug, literal, path); + fprintf(stderr, "%s: variant_bpf=%d, debug=%d, magic='%s', offset='%llu'\n", + argv[0], variant_bpf, debug, magic, offset); } - return search_file(path, literal, variant_bpf); + + filter_magic(offset, magic); } diff --git a/src/task_find_magic.h b/src/task_filter_magic.h similarity index 100% rename from src/task_find_magic.h rename to src/task_filter_magic.h