Skip to content

Commit

Permalink
linker: fix fd leak in fixupKfuncs
Browse files Browse the repository at this point in the history
The kfunc fixup code doesn't properly close the btf.Handle if the
compatibility check fails:

    leaked fd created at:
        github.com/cilium/ebpf/internal/sys.newFD+0x26
            /home/lorenz/dev/ebpf/internal/sys/fd.go:23
        github.com/cilium/ebpf/internal/sys.NewFD+0x24
            /home/lorenz/dev/ebpf/internal/sys/fd.go:63
        github.com/cilium/ebpf/internal/sys.BtfGetFdById+0x36
            /home/lorenz/dev/ebpf/internal/sys/types.go:583
        github.com/cilium/ebpf/btf.NewHandleFromID+0x2e
            /home/lorenz/dev/ebpf/btf/handle.go:83
        github.com/cilium/ebpf/btf.(*HandleIterator).Next+0xa4
            /home/lorenz/dev/ebpf/btf/handle.go:228
        github.com/cilium/ebpf.findTargetInModule+0xc9
            /home/lorenz/dev/ebpf/prog.go:965
        github.com/cilium/ebpf.findTargetInKernel+0xe4
            /home/lorenz/dev/ebpf/prog.go:943
        github.com/cilium/ebpf.fixupKfuncs+0x3ef
            /home/lorenz/dev/ebpf/linker.go:284
        github.com/cilium/ebpf.newProgramWithOptions+0x80d
            /home/lorenz/dev/ebpf/prog.go:277
        github.com/cilium/ebpf.(*collectionLoader).loadProgram+0x415
            /home/lorenz/dev/ebpf/collection.go:522
        github.com/cilium/ebpf.NewCollectionWithOptions+0x239
            /home/lorenz/dev/ebpf/collection.go:385
        github.com/cilium/ebpf.NewCollection+0x44
            /home/lorenz/dev/ebpf/collection.go:358
        github.com/cilium/ebpf.LoadCollection+0x45
            /home/lorenz/dev/ebpf/collection.go:680
        github.com/cilium/ebpf.TestInvalidKfunc+0xcb
            /home/lorenz/dev/ebpf/elf_reader_test.go:740
        testing.tRunner+0xfe
            /usr/local/go/src/testing/testing.go:1595
        runtime.goexit+0x0
            /usr/local/go/src/runtime/asm_amd64.s:1650

Signed-off-by: Lorenz Bauer <lmb@isovalent.com>
  • Loading branch information
lmb committed Oct 2, 2023
1 parent 7333aa6 commit 687471a
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 11 deletions.
28 changes: 19 additions & 9 deletions linker.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,12 @@ func (hs handles) fdArray() []int32 {
return fda
}

func (hs handles) close() {
for _, h := range hs {
h.Close()
func (hs *handles) Close() error {
var errs []error
for _, h := range *hs {
errs = append(errs, h.Close())
}
return errors.Join(errs...)
}

// splitSymbols splits insns into subsections delimited by Symbol Instructions.
Expand Down Expand Up @@ -231,7 +233,13 @@ func fixupAndValidate(insns asm.Instructions) error {
// fixupKfuncs loops over all instructions in search for kfunc calls.
// If at least one is found, the current kernels BTF and module BTFis are searched to set Instruction.Constant
// and Instruction.Offset to the correct values.
func fixupKfuncs(insns asm.Instructions) (handles, error) {
func fixupKfuncs(insns asm.Instructions) (_ handles, err error) {
closeOnError := func(c io.Closer) {
if err != nil {
c.Close()
}
}

iter := insns.Iterate()
for iter.Next() {
ins := iter.Ins
Expand All @@ -250,6 +258,8 @@ fixups:
}

fdArray := make(handles, 0)
defer closeOnError(&fdArray)

for {
ins := iter.Ins

Expand All @@ -276,6 +286,11 @@ fixups:
return nil, err
}

idx, err := fdArray.add(module)
if err != nil {
return nil, err
}

if err := btf.CheckTypeCompatibility(kfm.Type, target.(*btf.Func).Type); err != nil {
return nil, &incompatibleKfuncError{kfm.Name, err}
}
Expand All @@ -285,11 +300,6 @@ fixups:
return nil, err
}

idx, err := fdArray.add(module)
if err != nil {
return nil, err
}

ins.Constant = int64(id)
ins.Offset = int16(idx)

Expand Down
9 changes: 7 additions & 2 deletions prog.go
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions) (*Program, er
if err != nil {
return nil, fmt.Errorf("fixing up kfuncs: %w", err)
}
defer handles.close()
defer handles.Close()

if len(handles) > 0 {
fdArray := handles.fdArray()
Expand Down Expand Up @@ -922,7 +922,12 @@ func findProgramTargetInKernel(name string, progType ProgramType, attachType Att
}

id, err := spec.TypeID(target)
return module, id, err
if err != nil {
module.Close()
return nil, 0, err
}

return module, id, nil
}

// findTargetInKernel attempts to find a named type in the current kernel.
Expand Down

0 comments on commit 687471a

Please sign in to comment.