From aaaff5b3a2580ef4c4f9a7ceb6669cbe1d378de8 Mon Sep 17 00:00:00 2001 From: Timo Beckers Date: Fri, 13 Jan 2023 10:56:03 +0100 Subject: [PATCH] prog,btf: explicitly refuse ambiguous AttachTo targets See cilium/ebpf#894 for more context. Explicitly refuse loading programs with multiple AttachTo candidates. BTF needs to carry more information to allow disambiguating between them. The kernel API likely needs to be extended to allow specifying which candidate to pick. Signed-off-by: Timo Beckers --- btf/btf.go | 18 +++++++++--------- prog.go | 6 ++++++ 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/btf/btf.go b/btf/btf.go index 89e644f5c..7327c8010 100644 --- a/btf/btf.go +++ b/btf/btf.go @@ -25,6 +25,7 @@ var ( ErrNotSupported = internal.ErrNotSupported ErrNotFound = errors.New("not found") ErrNoExtendedInfo = errors.New("no extended info") + ErrMultipleTypes = errors.New("multiple type candidates") ) // ID represents the unique ID of a BTF object. @@ -564,16 +565,15 @@ func (s *Spec) AnyTypeByName(name string) (Type, error) { return types[0], nil } -// TypeByName searches for a Type with a specific name. Since multiple -// Types with the same name can exist, the parameter typ is taken to -// narrow down the search in case of a clash. +// TypeByName searches for a Type with a specific name. Since multiple Types +// with the same name can exist, the parameter typ is taken to narrow down the +// search in case of a clash. // -// typ must be a non-nil pointer to an implementation of a Type. -// On success, the address of the found Type will be copied to typ. +// typ must be a non-nil pointer to an implementation of a Type. On success, the +// address of the found Type will be copied to typ. // -// Returns an error wrapping ErrNotFound if no matching -// Type exists in the Spec. If multiple candidates are found, -// an error is returned. +// Returns an error wrapping ErrNotFound if no matching Type exists in the Spec. +// Returns an error wrapping ErrMultipleTypes if multiple candidates are found. func (s *Spec) TypeByName(name string, typ interface{}) error { typeInterface := reflect.TypeOf((*Type)(nil)).Elem() @@ -610,7 +610,7 @@ func (s *Spec) TypeByName(name string, typ interface{}) error { } if candidate != nil { - return fmt.Errorf("type %s: multiple candidates for %T", name, typ) + return fmt.Errorf("type %s(%T): %w", name, typ, ErrMultipleTypes) } candidate = typ diff --git a/prog.go b/prog.go index a113a5ff2..2f7333d28 100644 --- a/prog.go +++ b/prog.go @@ -891,6 +891,12 @@ func findTargetInKernel(name string, progType ProgramType, attachType AttachType } return module, id, nil } + // See cilium/ebpf#894. Until we can disambiguate between equally-named kernel + // symbols, we should explicitly refuse program loads. They will not reliably + // do what the caller intended. + if errors.Is(err, btf.ErrMultipleTypes) { + return nil, 0, fmt.Errorf("attaching to ambiguous kernel symbol is not supported: %w", err) + } if err != nil { return nil, 0, fmt.Errorf("find target for %s in vmlinux: %w", featureName, err) }