-
Notifications
You must be signed in to change notification settings - Fork 246
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
feat: Add an option to register allowed ranges of memory #110
Conversation
55bbcd1
to
1e691ee
Compare
Thanks a lot!
Yes please, that would really help for the review |
1e691ee
to
20cdbe1
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot for this work!
I'm not sure how much I want to extend the API to add verifier-specific features, as long as the project doesn't have a robust verifier. But allowing some memory address ranges seems like a fairly basic requirement to add some helpers, so let's go for it. Your API changes, and the PR overall, look good.
I have three comments, however:
- Could you please update the README to mention the new function (probably below
register_helper()
)? - I'd like to have a test (under
tests
, or maybe even an end-to-end test underexamples
) with a simple helper that uses a range of allowed memory, to avoid any kind of regression on that feature, before I merge. - And then one nit, could you please rename the attribute into something more descriptive than
allowed
? For example,allowed_memory
, more verbose but easier to understand. I'd typically expect a boolean flag rather than an address map for something calledallowed
.
If I may ask, what's the use case behind the PR? Do you have your own implementation of maps? May I also ask what you're doing with rbpf, if you're free to tell?
20cdbe1
to
6ba9627
Compare
I will add an end-to-end test in examples. Asserting that we can add My usecase is to have an easy to use way to test ebpf programs. We are building a variety of network programs, which enforce some policy and need to do a bit of packet parsing. |
Thanks for the details, that's an interesting use case.
No doubt about that. I'd like to have maps in rbpf, but I don't have the time to really work on the project and I don't expect to come up with an implementation myself in the foreseeable future (I understand you're not asking - I'm just clarifying). If anyone can and wants to contribute a PR for that they're welcome, obviously. |
6ba9627
to
216d80c
Compare
I've added an end to end example I know what it is to be short on time. |
216d80c
to
5d65c9d
Compare
<Rebased with the hope that the Appveyor workflow will pass> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks nice, thanks!
Besides some more nits on allowed_memory
and the case on eBPF, Linux, Rust, my main concern is the license for your example. I'd like to avoid GPL if we can, and I'd like SPDX headers for the new files, please.
5d65c9d
to
a4e2916
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks all good, thank you!
I'd just like to find a moment to run the examples myself before merging, I'll try to do it tonight.
OK so I tried to compile the program myself, but I got mixed results. File structureOne thing that I observe is that after your changes, we get a new warning when building the crate: $ cargo test
warning: An explicit [[example]] section is specified in Cargo.toml which currently
disables Cargo from automatically inferring other example targets.
This inference behavior will change in the Rust 2018 edition and the following
files will be included as a example target:
* examples/ebpf-allowed-memory.rs
This is likely to break cargo build or cargo test as these files may not be
ready to be compiled as a example target today. You can future-proof yourself
and disable this warning by adding `autoexamples = false` to your [package]
section. You may also move the files to a location where Cargo would not
automatically infer them to be a target, such as in subfolders.
For more information on this warning you can consult
https://github.com/rust-lang/cargo/issues/5330 I understand this is because we don't set an edition in the Cargo.toml. I don't think editions were a thing when I created the Cargo.toml. We may want to address that in the future, but for now, it would be nice to avoid that warning. Looking at the files you added: $ git show --pretty="" --name-only --stat -- examples/
examples/allowed-memory.o
examples/allowed_memory.rs
examples/ebpf-allowed-memory.rs We could maybe pick up the suggestion from the warning and move the auxiliary files into a subdir? It would make it clear that the files are related to the Compiling - Part 1So I tried to compile the eBPF program by installing the [package]
name = "ebpf-allowed-memory"
version = "0.1.0"
edition = "2021"
[dependencies]
aya-ebpf = "0.1.0" Coming back to my first item on the file structure, moving the example auxiliary files under their own subdirectory would allow us to add this Cargo.toml to Compiling - Part 2So once I had my Cargo.toml I tried the command again and hit aya-rs/bpf-linker#220, not sure if you hit that one, too. Anyway, I managed to compile by adding the In the end, I produced an object file that contains more eBPF functions that yours, for some reason. I have But the good thing is that SummarySo my suggestion would be to make it easier to recompile the eBPF program, by making sure we can just run the compile command (even better, shrink it to And, nice work! |
I'm sorry for the compilation troubles. I didn't get the warning when running locally, or I would have taken care of it. You are correct that in order to compile the ebpf program you need to create a small cargo project. It can't be compiled as is. I included the source "for reference" more than anything else. I think your suggestion is good. It makes it easier to recreate the binary. I didn't bump into the bpf-linker bug, the program was compiled with |
Certain kernel helpers return pointers to kernel managed memory, which the ebpf program is allowed to load and read. In order to implement stubs for these using rbpf, we need a way to mark these ranges of memory as safe for the check_mem function. The API specifically deals with adresses, because helpers need to be function types and not closures. This means the pointers to objects returned from them need to be static, and dealing with references to static objects gets clunky. So I have chosen to push the obtaining of the addresses into calling code. Signed-off-by: Wouter Dullaert <[email protected]>
a4e2916
to
1eac352
Compare
I agree we should commit it, I did keep it in my commit but moved it: I'm also fine with your approach of copying it to a more visible path. I didn't know of Earthly before. Is it intended to commit that file, with the pointer to the Exoscale Docker registry (containing Can you please sign-off the second commit? |
Sorry, I did not intend to commit that. |
Moving the source code for the ebpf program into a subfolder will prevent it from accidentally being run as an example. We are still committing the resulting object file, to prevent creating a hard dependency on the aya build toolchain to run the example tests in this repository. Signed-off-by: Wouter Dullaert <[email protected]>
1eac352
to
b13ff15
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All good this time, thanks a lot!
Certain kernel helpers return pointers to kernel managed memory, which the ebpf program is allowed to load and read.
In order to implement stubs for these using rbpf, we need a way to mark these ranges of memory as safe for the check_mem function.
The API specifically deals with adresses, because helpers need to be function types and not closures. This means the pointers to objects returned from them need to be static, and dealing with references to static objects gets clunky. So I have chosen to push the obtaining of the addresses into calling code.
I did do other experiments, such as trying to allow closures, but I couldn't figure out how to implement that in the jit. (I'm sure it's doable, but exhausted my yak shaving time budget for this). It also didn't end up getting rid of the 'static' requirement on references returned from helper stubs, due to the Box you have to put the closures in to store them in a hashmap.
The only real way to make this easier is to have actual maps built-in to the VM, so we can transfer the ownership of the objects to the VM. How you make that generic with regards to the map definitions in the ebpf programs is still an open question for me though.
At least with this PR I can run/test my programs and I don't have to disable the memory checks.
My apologies for the format changes: rust-analyzers autoformat seems to have different opinions than the style here.
I can try to minimize the diff if that is important to you.