Skip to content
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

Infinite loops when iterating over BPF tables #198

Open
Deputation opened this issue Oct 6, 2023 · 2 comments
Open

Infinite loops when iterating over BPF tables #198

Deputation opened this issue Oct 6, 2023 · 2 comments
Labels
bug Something isn't working help wanted Extra attention is needed

Comments

@Deputation
Copy link

I encountered an issue related to the iteration of BPF table entries, which resulted in an infinite loop. The loop continually processes the table going over it and restarting from the start without ever really stopping.

The issue arises during the iteration of BPF entries in a table using table.iter(). In the loop, the same entries seem to be processed repeatedly, leading to an infinite loop and prohibiting the iteration from reaching its expected end.

Faulty code snippet:

let mut bpf_entries: Vec<FilterRules> = Vec::new();

eprintln!("Starting to iterate BPF entries");
for entry in table.iter() {
    eprintln!("Processing a BPF entry");
    unsafe {
        let rule: FilterRules = ptr::read_unaligned(entry.key.as_ptr() as *const _);
        bpf_entries.push(rule);
    }
}
eprintln!("Finished processing BPF entries");

I anticipated that the iterator would process each entry in the BPF table exactly once, eventually reaching the end of the table and exiting the loop. If this is not the expected behavior (as the examples of the library would imply) this issue can simply be closed.

Workaround:

let mut bpf_entries: Vec<FilterRules> = Vec::new();
let mut seen_entries: std::collections::HashSet<Vec<u8>> = std::collections::HashSet::new();

eprintln!("Starting to iterate BPF entries");
for entry in table.iter() {
    eprintln!("Processing a BPF entry");
    unsafe {
        if seen_entries.contains(&entry.key) {
            eprintln!("Duplicate BPF entry found. Exiting loop.");
            break;
        }

        seen_entries.insert(entry.key.clone());
        let rule: FilterRules = ptr::read_unaligned(entry.key.as_ptr() as *const _);
        bpf_entries.push(rule);
    }
}
eprintln!("Finished processing BPF entries");

I would greatly appreciate clarification on whether the described behavior is expected or if it might be a potential bug. Specifically, is the iterator designed to restart from the beginning of the entries after each loop, or should it progress through each entry once and subsequently exit the loop?

@brayniac
Copy link
Collaborator

@Deputation - I believe the correct behavior would be to iterate through the table entries once and return None.

I'd suggest taking a look at libbpf-rs instead of this crate though.

@brayniac
Copy link
Collaborator

I'd happily accept a PR that fixes this and publish a new version of the crate. But I've migrated to libbpf-rs so there's not much active focus on these crates right now.

@brayniac brayniac added bug Something isn't working help wanted Extra attention is needed labels Oct 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants