-
Notifications
You must be signed in to change notification settings - Fork 286
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add the ability to detach an eBPF program #986
base: main
Are you sure you want to change the base?
Conversation
Our user-space software agent has, until now, relied on catching the `SIGINT` signal (i.e. Ctl+C) for the application to know when to exit. Exiting causes handles in Rust to go out of scope, which invokes `Drop` handlers and unloads eBPF programs and maps from the kernel. However, if any unhandled signal were to cause the application to exit un-gracefully, `Drop` handlers would not be invoked, and eBPF resources would remain loaded in the kernel. The number of loaded programs would build up over time as the application is restarted. Gracefully handling more types of signals is a good approach, but is best effort. If the drop logic were to fail, or an unhandle-able signal were received, resources would be left behind. A robust approach is to perform cleanup on application startup, where previously loaded eBPF programs are identified and unloaded from the kernel. To support that effort, this change adds the a public `detach_program()` function, which wraps the internal `bpf_prog_detach()`.
✅ Deploy Preview for aya-rs-docs ready!Built without sensitive environment variables
To edit notification comments on pull requests, go to your Netlify site configuration. |
That holds true only in very specific circumstances. Any BPF syscall that returns an FD has them set CLOEXEC, so FDs will get cleaned up when your process exits - gracefully or not. Specific cases that this doesn't work are thinks like TC (which uses netlink) etc... and my guess is that you're using one of theses types of program.
If you let me know what type of program you're having issue with I can point you in the right direction. EDIT: Based on your other open PR I'll assume it's SockOps. |
I think you're saying that once SockOps programs are updated to attach with |
Yep I'm 99% sure that's the case. |
I am seeing similar problem for TC program. I have attached the eBPF program on TC-Egress hook and sometimes they linger around. @dave-tucker can you share the references on how to cleanup existing TC eBPF program during startup? |
Correct, |
This feature is this still needed if you want to use Kernel <5.7, right? If the app crashes the program will not be deleted. https://github.com/aya-rs/aya/blob/main/aya/src/programs/sock_ops.rs pub fn attach<T: AsFd>(
&mut self,
cgroup: T,
mode: CgroupAttachMode,
) -> Result<SockOpsLinkId, ProgramError> {
/...
if KernelVersion::current().unwrap() >= KernelVersion::new(5, 7, 0) {
let link_fd = bpf_link_create(...)
//...
} else {
let link = ProgAttachLink::attach(prog_fd, cgroup_fd, attach_type, mode)?;
// ...
}
} |
Our user-space software agent has, until now, relied on catching the
SIGINT
signal (i.e. Ctl+C) for the application to know when to exit. Exiting causes handles in Rust to go out of scope, which invokesDrop
handlers and unloads eBPF programs and maps from the kernel. However, if any unhandled signal were to cause the application to exit un-gracefully,Drop
handlers would not be invoked, and eBPF resources would remain loaded in the kernel. The number of loaded programs would build up over time as the application is restarted.Gracefully handling more types of signals is a good approach, but is best effort. If the drop logic were to fail, or an unhandle-able signal were received, resources would be left behind. A robust approach is to perform cleanup on application startup, where previously loaded eBPF programs are identified and unloaded from the kernel.
To support that effort, this change adds the a public
detach_program()
function, which wraps the internalbpf_prog_detach()
.