-
Notifications
You must be signed in to change notification settings - Fork 3.8k
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 new targeted error injection tool #1633
Conversation
bpf_override_return is a very powerful mechanism for error injection, with the caveat that it requires whitelisting of the functions to be overriden. inject.py will take a call chain and optional set of predicates as input, and inject the appropriate error when both the call chain and all predicates are satisfied. Signed-off-by: Howard McLauchlan <[email protected]>
[buildbot, ok to test] |
G'Day, Thanks, should be a useful tool, and great to see a tool for this 4.16 feature already! Some suggestions:
Instead of:
(note that I adjusted whitespace because it was hard to read on one line!) Imagine this instead:
Or (if the "->" symbol was really necessary for parsing):
Or even this:
At least that looks like something I've seen before -- an ftrace stack trace! :)
To fail at 0.1%. This could be added later on as an extra feature. Or maybe it can already be done with a predicate?
|
Thanks for the quick feedback, I just want to talk through some of these points before I push an update:
The rest I will fix and push soon. Cheers, |
The failure percentages can be added later, using the bpf random function. Kernel support was added so that tracing programs can use it, but I don't think we have an example tool yet. For a 0-99 random number, I think it works like this: bpf_get_prandom_u32() % 100 The first example is looking much better:
But I'm still wondering why we need to -I anything, and what of linux/fs.h is used there? Here's a guess: if we forced a #include of linux/mm.h by default (for the kmalloc failure mode), would that mean we need a lot fewer -I's? Eg: def _generate_program(self):
# leave out auto includes for now
self.program += '#include <linux/mm.h>\n'
for include in (self.args.include or []):
self.program += "#include <%s>\n" % include
[...] Would this then work as the hello world example?
|
Looks good. Does this work? (multiline)
|
Yep, works fine. |
thanks! |
After writing a bunch of BPF scripts to error inject specific call paths with
bpf_override_return()
, I thought it'd be nice if a lot of the boilerplate could be reused and consolidated. Here's a BPF tool that should handle a fairly wide range of use cases for error injection withbpf_override_return()
.inject.py constructs and runs a BPF program which takes a call chain and optional predicates as input, as well as a specified error mode. While the script is executing, if the call chain + predicates are met, the appropriate error will be injected into the chosen error mode.
A major caveat is that due to the nature of this tool, it's really easy to accidentally brick whatever you're running it on. So it's fairly imperative to make sure your input is correct or suddenly you find every kmalloc() on your system failing (I did this a lot).
I've also made an attempt to ensure correctness even in recursive situations. I didn't find any actual kernel examples, but made a contrived module for testing purposes to convince myself it was functional. I could probably get that organized in a presentable format if necessary, but neglected to include it here.
I had to work around some verifier/rewriter issues; this resulted in some slightly unconventional code:
*(x->y)
. To get around this, I introduced aSTRCMP
macro to do some minor rewriting of my own. This macro bypasses both of those issues when using strings in predicates, but is not very robust.For use cases and examples, see inject_example.txt
For details related to implementation, refer to the big comment block in inject.py.
Please let me know what you'd like changed.
Cheers,