{"id":18417520,"url":"https://github.com/redcanaryco/redcanary-ebpf-sensor","last_synced_at":"2025-04-13T11:52:16.812Z","repository":{"id":37103504,"uuid":"332041938","full_name":"redcanaryco/redcanary-ebpf-sensor","owner":"redcanaryco","description":"Red Canary's eBPF Sensor","archived":false,"fork":false,"pushed_at":"2024-07-05T21:37:29.000Z","size":1565,"stargazers_count":102,"open_issues_count":0,"forks_count":14,"subscribers_count":23,"default_branch":"main","last_synced_at":"2025-03-27T03:03:32.853Z","etag":null,"topics":["ebpf","edr-solutions","sensor"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/redcanaryco.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-01-22T19:23:43.000Z","updated_at":"2025-03-21T14:51:51.000Z","dependencies_parsed_at":"2023-11-30T03:23:58.848Z","dependency_job_id":"5a24ed7c-7f79-4b39-9e07-47c13d895944","html_url":"https://github.com/redcanaryco/redcanary-ebpf-sensor","commit_stats":{"total_commits":106,"total_committers":11,"mean_commits":9.636363636363637,"dds":"0.42452830188679247","last_synced_commit":"c4c5850440fc3a2ceae901d18b03c75a8ddae8a2"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redcanaryco%2Fredcanary-ebpf-sensor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redcanaryco%2Fredcanary-ebpf-sensor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redcanaryco%2Fredcanary-ebpf-sensor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redcanaryco%2Fredcanary-ebpf-sensor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/redcanaryco","download_url":"https://codeload.github.com/redcanaryco/redcanary-ebpf-sensor/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248710438,"owners_count":21149188,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ebpf","edr-solutions","sensor"],"created_at":"2024-11-06T04:09:48.913Z","updated_at":"2025-04-13T11:52:16.793Z","avatar_url":"https://github.com/redcanaryco.png","language":"C","funding_links":[],"categories":["Projects Related to eBPF","eBPF 相关项目"],"sub_categories":["Security","安全"],"readme":"# redcanary-ebpf-sensor\n\nThis project consists of a variety of eBPF applications aimed at gathering events\nof interest for [Red Canary's Linux EDR](https://redcanary.com/products/linux-edr/)\nproduct.\n\nThese applications do not use [BCC](https://github.com/iovisor/bcc) to build. The\nmain objective of this design is to have a compile once, run everywhere application.\n\n## Build\n\nTo build this project run:\n\nFor building both x86_64 and aarch64 architectures\n`docker compose up`\n\nTo build either x86_64 or aarch64 architectures\n`docker compose run --rm ebpf-amd make all`\nor\n`docker compose run --rm ebpf-arm make all`\n\n---\n\nA vscode cpp properties files has been included. Make sure to update the include path with the path\non your local system where the kernel header files are located\n\nFor convenience-sake, when running in a system with apt (e.g., Ubuntu)\nyou can run `sudo make dev` to build all of the eBPF programs into the\nlocal `build/` directory. This command uses the kernel version of the\ncurrently running system.\n\n## Gotchas and Patterns\n\n### Dummy Telemetry Event\n\nAt the beginning of the programs we often have code that looks like:\n\n```c\nprocess_message_t pm = {0};\n```\n\nWe then proceed to send `\u0026pm` to our functions and set the proper values there. This is done for two reasons:\n\n1. We want to save stack space, so by creating a single dummy event at\n   the top we can remind ourselves that this is the only event we ever\n   want to have at a time and it is meant to be reused.\n\n2. The eBPF verifier does not like uninitialized padding. When\n   initializing a padded struct in C, not all of the space occupied by\n   the struct necessarily gets initialized as padding may exist\n   between fields, or empty space unused by some union members. The\n   eBPF verifier does not like this so to guarantee nothing is\n   unitialized we need to zero out all of the space for the event\n   struct. For more information see [this\n   issue](https://github.com/iovisor/bcc/issues/2623).\n\n### Per CPU structures\n\nBe careful when using PERCPU structures (such as\n`BPF_MAP_TYPE_PERFCPU_ARRAY`). While an eBPF program is not\npreemptable, syscalls are. This means that a kprobe for a syscall may\nhappen in one CPU but its kretprobe will happen in a different\nCPU. This means that passing data using per cpu structures accross\nprograms will not always work in multicore systems. Note, however,\nthat tail calling is *NOT* preemptable, so it is okay to pass\ninformation using per cpu structures through tail calls.\n\n### Multi-message events\n\nWhenever possible a single event (i.e., syscall) should emit only a\nsingle message during its `kretprobe`. You cannot have synchronizaiton\nissues if there is only one message. When this is not possible we need\nto be careful because syscalls may start and finish in different CPUs\n(they are preemptable). All messages in the same program will be in\nthe same per-CPU buffer but messages for the same syscall but in\ndifferent non-tailcalled programs (e.g., `kprobe` vs `kretprobe`) will\nnot necessarily be put in the same per-CPU buffer which means\nuser-space may read them at different times. To avoid synchronization\nissues all messages for a single event (i.e., syscall) should be sent\nin the same `kretprobe` or tail calls from it and should share a\n(unique enough) event id. Because they are all from the same probe we\ncan guarantee the order and thus not having to re-order events in\nuser-space. The event id is used as the identifier for user space to\nknow what messages to combine into the same event.\n\n### Kretprobe not firing\n\nKretprobes are not guaranteed to fire so we cannot rely on it as a\ncleanup strategy. Because of this our maps that send messages from\n`kprobe` to `kretprobe`s are LRU maps such that any message that we\ndidn't clean up in a `kretprobe` will eventually be evicted.\n\n## Validate Instruction Count\n\nDue to older kernel limitations (\u003c 5.2) the instruction limit for our\nebpf programs is 4096. This was changed in Kernel 5.2+ to be 1 million\nbut we cannot rely on that at this time. To verify that we aren't\ngoing over the limit, after modifying an ebpf program run it through\n`llvm-objdump` and check its instruction count:\n\n```bash\nllvm-objdump -d \u003cPATH_TO_COMPILED_FILE\u003e -j \u003cSPECIFIC_SECTION_TO_ANALYZE\u003e | less\n```\n\nYou may ommit the `-j \u003cSPECIFIC_SECTION_TO_ANALYZE\u003e` if you want to\ncheck all the sections at the same time.\n\neBPF programs can branch (but not jump back!) so make sure to check\nthat none of the branches go over the 4096 instructions limit.\n\n# Development with clangd\n\nIf clangd is used as the LSP, compile commands can be easily generated with:\n\n```bash\nbear -- make dev\n```\n\nAfter that `clangd` should be able to pickup the created\n`compile_commands.json`. A config exists in `.clangd` to further tweak\nin case the compile commands are not enough for clangd to have a\nsuccessful build.\n\n# Licensing\n\nPlease note, these programs are mostly licensed under GPL, which is\nrequired to leverage BPF features critical for gathering security\ntelemetry.\n\n```c\nchar _license[] SEC(\"license\") = \"GPL\";\n```\n\nIf you bundle these programs with your own code (for example, by using\n`include_bytes!()` in Rust), that extends GPL to your code base.  If\nyou wish to use your own code with its own license alongside these\nprograms, you'll need to build, manage, and distribute them\nseparately.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fredcanaryco%2Fredcanary-ebpf-sensor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fredcanaryco%2Fredcanary-ebpf-sensor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fredcanaryco%2Fredcanary-ebpf-sensor/lists"}