aya-rs / aya

Aya is an eBPF library for the Rust programming language, built with a focus on developer experience and operability.
https://aya-rs.dev/book/
Apache License 2.0
3.1k stars 272 forks source link

Best practice for keeping probes attached (prevent detaching) #739

Open benlcb opened 1 year ago

benlcb commented 1 year ago

What is the current best practice for keeping probes attached? The function introduced in https://github.com/aya-rs/aya/issues/51 no longer seems to exist.

My expectation would be that simply forgetting the aya::Bpf object would be enough:

let bpf  = Bpf::load(include_bytes_aligned!(
     "../../build/private/cargo-target/bpfel-unknown-none/debug/salty-bpf-elf"
))?;
 for (pname, pref) in bpf.programs_mut() {
            match pname {
                "myprobe" => myprobe = Some(pref.try_into()?),
...
myprobe.load()?;
myprobe.pin(format!("{}{}", PATH_TO_BPF_FS, stringify!(myprobe)))?;
let link = myprobe
            .attach(std::os::fd::AsRawFd::as_raw_fd(
                mycgroup.as_ref().unwrap(),
            ))?;

mem::forget(bpf);

This didn't work. I also tried to first take the link:

let link = myprobe.take_link(link);
mem::forget(link);
mem::forget(bpf);

For both these combinations I don't see any attached probes after quitting the program: Before:

dev-dsk-bbarzen-1a-b0339ef3 % sudo bpftool cgroup tree                                    
CgroupPath
ID       AttachType      AttachFlags     Name           
/mnt/cgroup2
608      ingress         multi           myprobe

After:

~: sudo bpftool cgroup tree
CgroupPath
ID       AttachType      AttachFlags     Name 
astoycos commented 1 year ago

I would think the best practice here would be to pin the link before forgetting it... something like what we do here https://github.com/aya-rs/aya/blob/main/test/integration-test/src/tests/load.rs#L437

benlcb commented 1 year ago

Thank you for your fast answer! Given that these tests are only implemented for Xdp, Uprobe, Kprobe and Tracepoint, do I assume correctly that it is not yet implemented for any other probe type?

E.g. FdLink: From<amzn_aya::programs::CgroupSockLink> is not implemented.

Or is there another mechanism for these other probes?

benlcb commented 1 year ago

Spent some more time looking into this, I think the functionality around pinning is not fully implemented for all program types. I wrote this little patch an it works, though it is not ready for a PR.

fdlink_conversion.patch

@astoycos I am willing to work on a clean implementation for this. Since you worked on the implementation of some probe types, did you already have a plan in mind how this is supposed to work for the remaining ones? Should I just implement a suggestion, or should I connect with you or someone else first? There is also a SOCK_OPS type specific detaching problem I would like to discuss.

astoycos commented 1 year ago

Hiya @benlcb 👋 Sorry I missed your original response.. It's funny in our documentation for FDLink we tell users that

/// Fd links are returned directly when attaching some program types (for
/// instance [`crate::programs::cgroup_skb::CgroupSkb`]),

But that doesn't seem to be true 🙉 or maybe it was before https://lore.kernel.org/bpf/CAEf4Bzbt_aVR5HyW_MuYvxT1fMBKD3xZOw3rEuHtj1i_T8NO_g@mail.gmail.com/T/ merged... anyways it looks like we need to implement try_from and try-into for all the Cgroup link types.

did you already have a plan in mind how this is supposed to work for the remaining ones? Should I just implement a suggestion, or should I connect with you or someone else first?

If you want feel free to open a PR, I'm happy to review! If not I can do it as well. Lets just make sure to add integration tests for the new programs 👍

There is also a SOCK_OPS type specific detaching problem I would like to discuss.

Sure what's the issue?

benlcb commented 1 year ago

But that doesn't seem to be true 🙉 Haha yes I saw that too. I'll get a PR ready over the weekend.

Sure what's the issue? SOCK_OPS does not appear to be detached by simply deleting the FD from the BPF file system. So it keeps running, and I think we need to explicitly detach it using the information in the ProgAttachLink. For example, if a user tries to detach it using PinnedLink, that won't work. (I'll get a failing test for that ready as well).

My use case looks like that: I'm running a program which attaches probes and then quits. Later on, the same program is run again to detach the probes.

I would like to figure out what additions are needed to enable this kind of workflow.

Maybe we can create a public ::new function for ProgAttachLink, so users can populate those themselves. But this doesn't sound easy to use, since the user would need to know what FDs to put where.

Another thought might be to derive Serialize, Deserialize for ProgAttachLink (or their wrappers) so users can save them to disk, and reload them for detaching.

Maybe you have a better idea?