Skip to content

Commit 27470e0

Browse files
info: Return dedicated error when program info is restricted
On systems where the `kernel.kptr_restrict` and `net.core.bpf_jit_harden` sysctls are enabled, certain fields in the program info may be restricted. When this is the case xlated and jitted instruction, line info, and function info are unavailable. When such fields are unavailable, we do get ..len fields set to non-zero values, but the kernel will have not written any data to the pointers provided. At present when this happens we don't recognize this and attempt to parse the empty buffers resulting in a `parse func info: offset 0: type ID 0 is a *btf.Void, but expected a Func` error. The only clue we have that this is happening is that the kernel will zero out the insns pointer. This commit adds logic to detect when this happens and then returns a dedicated `ErrInfoRestricted` error so this case can be handled gracefully. Signed-off-by: Dylan Reimerink <[email protected]>
1 parent ae22611 commit 27470e0

File tree

3 files changed

+42
-0
lines changed

3 files changed

+42
-0
lines changed

info.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,8 @@ type ProgramInfo struct {
301301
btf btf.ID
302302
loadTime time.Duration
303303

304+
restricted bool
305+
304306
maps []MapID
305307
insns []byte
306308
jitedSize uint32
@@ -477,6 +479,14 @@ func newProgramInfoFromFd(fd *sys.FD) (*ProgramInfo, error) {
477479
}
478480
}
479481

482+
if info.XlatedProgLen > 0 && info2.XlatedProgInsns.IsNil() {
483+
pi.restricted = true
484+
pi.insns = nil
485+
pi.lineInfos = nil
486+
pi.funcInfos = nil
487+
pi.jitedInfo = programJitedInfo{}
488+
}
489+
480490
return &pi, nil
481491
}
482492

@@ -556,6 +566,10 @@ func (pi *ProgramInfo) btfSpec() (*btf.Spec, error) {
556566
return spec, nil
557567
}
558568

569+
// ErrInfoRestricted when kernel.kptr_restrict and net.core.bpf_jit_harden are set, the kernel may restrict access
570+
// to certain bits of the program info.
571+
var ErrInfoRestricted = errors.New("program info restricted by combination of kernel.kptr_restrict and net.core.bpf_jit_harden")
572+
559573
// LineInfos returns the BTF line information of the program.
560574
//
561575
// Available from 5.0.
@@ -564,6 +578,10 @@ func (pi *ProgramInfo) btfSpec() (*btf.Spec, error) {
564578
// ErrNotSupported if the program was created without BTF or if the kernel
565579
// doesn't support the field.
566580
func (pi *ProgramInfo) LineInfos() (btf.LineOffsets, error) {
581+
if pi.restricted {
582+
return nil, ErrInfoRestricted
583+
}
584+
567585
if len(pi.lineInfos) == 0 {
568586
return nil, fmt.Errorf("insufficient permissions or unsupported kernel: %w", ErrNotSupported)
569587
}
@@ -606,6 +624,10 @@ func (pi *ProgramInfo) Instructions() (asm.Instructions, error) {
606624
return nil, fmt.Errorf("read instructions: %w", internal.ErrNotSupportedOnOS)
607625
}
608626

627+
if pi.restricted {
628+
return nil, ErrInfoRestricted
629+
}
630+
609631
// If the calling process is not BPF-capable or if the kernel doesn't
610632
// support getting xlated instructions, the field will be zero.
611633
if len(pi.insns) == 0 {
@@ -676,6 +698,10 @@ func (pi *ProgramInfo) Instructions() (asm.Instructions, error) {
676698
//
677699
// Available from 4.13. Reading this metadata requires CAP_BPF or equivalent.
678700
func (pi *ProgramInfo) JitedSize() (uint32, error) {
701+
if pi.restricted {
702+
return 0, ErrInfoRestricted
703+
}
704+
679705
if pi.jitedSize == 0 {
680706
return 0, fmt.Errorf("insufficient permissions, unsupported kernel, or JIT compiler disabled: %w", ErrNotSupported)
681707
}
@@ -687,6 +713,10 @@ func (pi *ProgramInfo) JitedSize() (uint32, error) {
687713
//
688714
// Available from 4.13. Reading this metadata requires CAP_BPF or equivalent.
689715
func (pi *ProgramInfo) TranslatedSize() (int, error) {
716+
if pi.restricted {
717+
return 0, ErrInfoRestricted
718+
}
719+
690720
insns := len(pi.insns)
691721
if insns == 0 {
692722
return 0, fmt.Errorf("insufficient permissions or unsupported kernel: %w", ErrNotSupported)
@@ -786,6 +816,10 @@ func (pi *ProgramInfo) JitedFuncLens() ([]uint32, bool) {
786816
// ErrNotSupported if the program was created without BTF or if the kernel
787817
// doesn't support the field.
788818
func (pi *ProgramInfo) FuncInfos() (btf.FuncOffsets, error) {
819+
if pi.restricted {
820+
return nil, ErrInfoRestricted
821+
}
822+
789823
if len(pi.funcInfos) == 0 {
790824
return nil, fmt.Errorf("insufficient permissions or unsupported kernel: %w", ErrNotSupported)
791825
}

internal/sys/ptr.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ type TypedPointer[T any] struct {
2828
ptr Pointer
2929
}
3030

31+
func (p TypedPointer[T]) IsNil() bool {
32+
return p.ptr.IsNil()
33+
}
34+
3135
// SlicePointer creates a [TypedPointer] from a slice.
3236
func SlicePointer[T comparable](s []T) TypedPointer[T] {
3337
return TypedPointer[T]{ptr: UnsafeSlicePointer(s)}

internal/sys/ptr_64.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,7 @@ type Pointer struct {
1313
structs.HostLayout
1414
ptr unsafe.Pointer
1515
}
16+
17+
func (p Pointer) IsNil() bool {
18+
return p.ptr == nil
19+
}

0 commit comments

Comments
 (0)