-
Notifications
You must be signed in to change notification settings - Fork 723
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
link: wrap errors for Raw{At,De}tachProgram #320
Conversation
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.
I was about to open the same PR but my draft have the following changes 😛
diff --git a/internal/elf.go b/internal/elf.go
index 54a4313..88326bb 100644
--- a/internal/elf.go
+++ b/internal/elf.go
@@ -24,7 +24,7 @@ func NewSafeELFFile(r io.ReaderAt) (safe *SafeELFFile, err error) {
}
safe = nil
- err = fmt.Errorf("reading ELF file panicked: %s", r)
+ err = fmt.Errorf("reading ELF file panicked: %w", r)
}()
file, err := elf.NewFile(r)
@@ -44,7 +44,7 @@ func (se *SafeELFFile) Symbols() (syms []elf.Symbol, err error) {
}
syms = nil
- err = fmt.Errorf("reading ELF symbols panicked: %s", r)
+ err = fmt.Errorf("reading ELF symbols panicked: %w", r)
}()
syms, err = se.File.Symbols()
@@ -60,7 +60,7 @@ func (se *SafeELFFile) DynamicSymbols() (syms []elf.Symbol, err error) {
}
syms = nil
- err = fmt.Errorf("reading ELF dynamic symbols panicked: %s", r)
+ err = fmt.Errorf("reading ELF dynamic symbols panicked: %w", r)
}()
syms, err = se.File.DynamicSymbols()
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.
diff --git a/cmd/bpf2go/compile.go b/cmd/bpf2go/compile.go
index a7509e1..0f0b28f 100644
--- a/cmd/bpf2go/compile.go
+++ b/cmd/bpf2go/compile.go
@@ -91,7 +91,7 @@ func compile(args compileArgs) error {
}
if err := cmd.Start(); err != nil {
- return fmt.Errorf("can't execute %s: %s", args.cc, err)
+ return fmt.Errorf("can't execute %s: %w", args.cc, err)
}
if depRd != nil {
@@ -104,7 +104,7 @@ func compile(args compileArgs) error {
}
if err := cmd.Wait(); err != nil {
- return fmt.Errorf("%s: %s", args.cc, err)
+ return fmt.Errorf("%s: %w", args.cc, err)
}
return nil
Ah, I did a search-and-replace rather than checking for the cases where the format string was more complicated. I'll enable the |
Wait, @AkihiroSuda please stop sending reviews -- I'm fixing them all now. 😅 |
@cyphar Sure (FYI: my draft is at AkihiroSuda@650e297) |
@AkihiroSuda This now has fixes to pass all |
Thanks for the PR, error wrapping is a bit muddled at the moment. I'm conflicted about this change: we're not going to make all wrapped errors part of our API contract. That is, if your code relies on unwrapping an error that is not explicitly documented by a function we may well break it in the future. Are you OK with that? @ti-mo do you have opinions on error wrapping vs. no error wrapping? I also dug into the downstream issue you linked and I wonder whether you could use https://pkg.go.dev/github.com/cilium/ebpf/link#AttachCgroup instead? This should handle the cgroupv2 abstraction for you, including the bpf flags to use. |
We can't use that API for two reasons:
The first issue isn't that bad, but the second one kinda makes it untenable (I would've used that API if it weren't for the second issue). The only reason why we need to detect
The only thing we really care about is being able to get the underlying syscall error from |
Makes sense. What if we added an fd-only API? From your description it seems like something about BPF_F_REPLACE would still trip you up, but I'm missing context. How does your behaviour differ if F_REPLACE is not supported? Is the problem that the library forces BPF_F_REPLACE if F_ALLOW_MULTI is specified?
Yes please, it'll make it easier to review and get you unblocked. |
We have slightly strange fallback behaviour. If
Sure, I'll do that tomorrow. Thanks. |
This allows callers to detect the underlying syscall error, which is necessary for being able to implement safe fallbacks based on the error during program loading and unloading. runc in particular needs this to be able to implement BPF_F_REPLACE fallbacks correctly. Ref: opencontainers/runc#3008 Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
@florianl It would be nice if we could just directly use the feature probing that this library already does internally (and if we could do that, this PR wouldn't be necessary), but I expect that design discussions on such a feature will probably take some time -- we need some kind of workaround for this fairly quickly so we can do a runc release. But personally I think it's fairly reasonable to expect that the errors from a "raw program API" would allow you to get the underlying syscall error. I've updated this PR to only add wrapping to the |
A first proposal for feature probing is being worked on at the moment, but don't expect full coverage for all program and map types right out of the gate, that will take some time. Of course, if there is a strong use case for particular program types like I'm not sure where to go with this PR, though. On the surface, propagating errors all the way down to the user sounds reasonable. Do those errors then suddenly become part of the package API? Well, yes. We're not exporting sentinels, and we don't know which error(s) the kernel will give us. We could only document this like "returns error x when y" in godoc, but that doesn't make for a particularly strong API, as the kernel tends to change from under our feet. If we want to make that work long-term, adding tests for specific error returns would be a base requirement. @cyphar this includes your most recent changes (wrapping Would it be possible to just rely on 'there was an error' for now to kick off your fallback behaviour, or is it really important to know the cause? If you're willing to implement a workaround, you could string-match errors for now until a feature probe API is available. This prevents your particular pain from potentially knock-on effects to other users of the library. |
Good points @ti-mo.
Like I said, if it's not documented and tested it's not part of the API from my POV. @cyphar I merged the PR so that you are unblocked, but I'd suggest adding a test and documentation if you don't want this to regress. |
This allows callers to detect the underlying syscall error, which is
necessary for being able to implement safe fallbacks based on the error
during program loading and unloading. runc in particular needs this to
be able to implement BPF_F_REPLACE fallbacks correctly.
Ref: opencontainers/runc#3008
Signed-off-by: Aleksa Sarai cyphar@cyphar.com