Skip to content

Commit 9f42ce1

Browse files
committed
fix: query xlated_prog_insns separately
As described in the comment, querying both xlated_prog_insns and other fields can cause some information to be missing. Make a separate syscall for this field to avoid missing information.
1 parent d362715 commit 9f42ce1

File tree

1 file changed

+21
-21
lines changed

1 file changed

+21
-21
lines changed

info.go

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -416,9 +416,22 @@ func newProgramInfoFromFd(fd *sys.FD) (*ProgramInfo, error) {
416416

417417
if info.XlatedProgLen > 0 {
418418
pi.insns = make([]byte, info.XlatedProgLen)
419+
var info2 sys.ProgInfo
419420
info2.XlatedProgLen = info.XlatedProgLen
420421
info2.XlatedProgInsns = sys.SlicePointer(pi.insns)
421-
makeSecondCall = true
422+
423+
// Linux kernel has a bug(?): if xlated_prog_len is specified and access is denied
424+
// by kernel.kptr_restrict or net.core.bpf_jit_harden sysctls, the syscall doesn't only
425+
// skip the xlated program's bytes, but other information as well.
426+
// See handling of xlated_prog_insns in bpf_prog_get_info_by_fd in kernel/bpf/syscall.c.
427+
// To avoid skipping other information, we specify xlated_prog_len in a separate syscall.
428+
if err := sys.ObjInfo(fd, &info2); err != nil {
429+
return nil, err
430+
}
431+
if info2.XlatedProgInsns.IsNil() {
432+
pi.restricted = true
433+
pi.insns = nil
434+
}
422435
}
423436

424437
if info.NrLineInfo > 0 {
@@ -477,14 +490,13 @@ func newProgramInfoFromFd(fd *sys.FD) (*ProgramInfo, error) {
477490
if err := sys.ObjInfo(fd, &info2); err != nil {
478491
return nil, err
479492
}
480-
}
481-
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{}
493+
if info.JitedProgLen > 0 && info2.JitedProgInsns.IsNil() {
494+
// JIT information is not available due to kernel.kptr_restrict
495+
pi.jitedInfo.lineInfos = nil
496+
pi.jitedInfo.ksyms = nil
497+
pi.jitedInfo.insns = nil
498+
pi.jitedInfo.funcLens = nil
499+
}
488500
}
489501

490502
return &pi, nil
@@ -581,10 +593,6 @@ var ErrRestrictedKernel = internal.ErrRestrictedKernel
581593
// ErrNotSupported if the program was created without BTF or if the kernel
582594
// doesn't support the field.
583595
func (pi *ProgramInfo) LineInfos() (btf.LineOffsets, error) {
584-
if pi.restricted {
585-
return nil, fmt.Errorf("line infos: %w", ErrRestrictedKernel)
586-
}
587-
588596
if len(pi.lineInfos) == 0 {
589597
return nil, fmt.Errorf("insufficient permissions or unsupported kernel: %w", ErrNotSupported)
590598
}
@@ -708,10 +716,6 @@ func (pi *ProgramInfo) Instructions() (asm.Instructions, error) {
708716
//
709717
// Available from 4.13. Reading this metadata requires CAP_BPF or equivalent.
710718
func (pi *ProgramInfo) JitedSize() (uint32, error) {
711-
if pi.restricted {
712-
return 0, fmt.Errorf("jited size: %w", ErrRestrictedKernel)
713-
}
714-
715719
if pi.jitedSize == 0 {
716720
return 0, fmt.Errorf("insufficient permissions, unsupported kernel, or JIT compiler disabled: %w", ErrNotSupported)
717721
}
@@ -832,10 +836,6 @@ func (pi *ProgramInfo) JitedFuncLens() ([]uint32, bool) {
832836
// ErrNotSupported if the program was created without BTF or if the kernel
833837
// doesn't support the field.
834838
func (pi *ProgramInfo) FuncInfos() (btf.FuncOffsets, error) {
835-
if pi.restricted {
836-
return nil, fmt.Errorf("func infos: %w", ErrRestrictedKernel)
837-
}
838-
839839
if len(pi.funcInfos) == 0 {
840840
return nil, fmt.Errorf("insufficient permissions or unsupported kernel: %w", ErrNotSupported)
841841
}

0 commit comments

Comments
 (0)