Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions btf/ext_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -642,9 +642,15 @@ func parseLineInfoRecords(r io.Reader, bo binary.ByteOrder, recordSize uint32, r
return nil, fmt.Errorf("expected LineInfo record size %d, but BTF blob contains %d", exp, got)
}

out := make([]bpfLineInfo, recordNum)
if err := binary.Read(r, bo, out); err != nil {
return nil, fmt.Errorf("can't read line info: %v", err)
out := make([]bpfLineInfo, 0)
chunk := make([]bpfLineInfo, min(1024, recordNum))
for remaining := recordNum; remaining > 0; {
n := min(uint32(1024), remaining)
if err := binary.Read(r, bo, chunk[:n]); err != nil {
return nil, fmt.Errorf("can't read line info: %v", err)
}
out = append(out, chunk[:n]...)
remaining -= n
}
Comment thread
dylandreimerink marked this conversation as resolved.

if offsetInBytes {
Expand Down
4 changes: 2 additions & 2 deletions btf/ext_info_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ func TestParseLineInfoRecordsAllocations(t *testing.T) {
parseLineInfoRecords(bytes.NewReader(buf), internal.NativeEndian, size, count, true)
})

// 7 is the number of allocations on go 1.22
// 9 is the number of allocations on go 1.26
// what we want to test is that we are not allocating
// once per record
qt.Assert(t, qt.IsTrue(allocs <= 7))
qt.Assert(t, qt.IsTrue(allocs <= 9))
}
45 changes: 45 additions & 0 deletions elf_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,10 @@ func (ec *elfCode) loadProgramSections() (map[string]*ProgramSpec, error) {
return nil, fmt.Errorf("section %v: missing symbols", sec.Name)
}

if sec.ReaderAt == nil {
return nil, fmt.Errorf("compressed program section is not supported")
}

funcs, err := ec.loadFunctions(sec)
if err != nil {
return nil, fmt.Errorf("section %v: %w", sec.Name, err)
Expand Down Expand Up @@ -452,6 +456,13 @@ func (ec *elfCode) loadFunctions(sec *elfSection) (map[string]asm.Instructions,
return nil, fmt.Errorf("duplicate symbol %s in section %s", sym.Name, sec.Name)
}

if sym.Value > math.MaxUint32 || sym.Size > math.MaxUint32 {
return nil, fmt.Errorf("symbol %s: offset or size exceeds 32 bits in section %s", sym.Name, sec.Name)
}
if sym.Value+sym.Size > sec.Size {
return nil, fmt.Errorf("symbol %s: size goes out of bounds of section %s", sym.Name, sec.Name)
}

// Decode the symbol's instruction stream, limited to its size.
sr := internal.NewBufferedSectionReader(sec, int64(sym.Value), int64(sym.Size))
insns := make(asm.Instructions, 0, sym.Size/asm.InstructionSize)
Expand Down Expand Up @@ -803,6 +814,10 @@ func (ec *elfCode) loadMaps() error {
return fmt.Errorf("section %v: no symbols", sec.Name)
}

if sec.ReaderAt == nil {
return fmt.Errorf("compressed map section is not supported")
}

vars, err := ec.sectionVars(ec.btf, sec.Name)
if err != nil {
return fmt.Errorf("section %v: loading map variable BTF: %w", sec.Name, err)
Expand All @@ -814,6 +829,13 @@ func (ec *elfCode) loadMaps() error {
return fmt.Errorf("duplicate symbol %s in section %s", name, sec.Name)
}

if sym.Value > math.MaxUint32 || sym.Size > math.MaxUint32 {
return fmt.Errorf("symbol %s: offset or size exceeds 32 bits in section %s", sym.Name, sec.Name)
}
if sym.Value+sym.Size > sec.Size {
return fmt.Errorf("symbol %s: size goes out of bounds of section %s", name, sec.Name)
}

sr := internal.NewBufferedSectionReader(sec, int64(sym.Value), int64(sym.Size))

spec := MapSpec{
Expand Down Expand Up @@ -889,6 +911,10 @@ func (ec *elfCode) loadBTFMaps() error {
return fmt.Errorf("missing BTF")
}

if sec.ReaderAt == nil {
return fmt.Errorf("compressed BTF map section is not supported")
}

vars, err := ec.sectionVars(ec.btf, sec.Name)
if err != nil {
return fmt.Errorf("section %v: loading map variable BTF: %w", sec.Name, err)
Expand All @@ -912,6 +938,13 @@ func (ec *elfCode) loadBTFMaps() error {
return fmt.Errorf("section %v: missing symbol for map %s", sec.Name, name)
}

if sym.Value > math.MaxUint32 || sym.Size > math.MaxUint32 {
return fmt.Errorf("symbol %s: offset or size exceeds 32 bits in section %s", sym.Name, sec.Name)
}
if sym.Value+sym.Size > sec.Size {
return fmt.Errorf("section %v: symbol %s: size goes out of bounds of section", sec.Name, name)
}

sr := internal.NewBufferedSectionReader(sec, int64(sym.Value), int64(sym.Size))

// The BTF metadata for each Var contains the full length of the map
Expand Down Expand Up @@ -1245,6 +1278,10 @@ func resolveBTFValuesContents(es *elfSection, sym elf.Symbol, member btf.Member)
return nil, fmt.Errorf("member offset %d exceeds symbol size %d", member.Offset.Bytes(), sym.Size)
}

if es.Addralign == 0 {
return nil, fmt.Errorf("section has no address alignment, can't resolve .values contents")
}

for i, sym := range valuesRelocations(es, sym, member) {
// Emit a value stub based on the type of relocation to be replaced by a
// real fd later in the pipeline before populating the Map.
Expand Down Expand Up @@ -1354,6 +1391,10 @@ func (ec *elfCode) loadDataSections() error {
return fmt.Errorf("data section %s: variable %s offset %d exceeds maximum", sec.Name, sym.Name, off)
}

if sym.Size > math.MaxUint32 {
return fmt.Errorf("data section %s: variable %s size %d exceeds maximum", sec.Name, sym.Name, sym.Size)
}

ec.vars[sym.Name] = &VariableSpec{
SectionName: sec.Name,
Name: sym.Name,
Expand Down Expand Up @@ -1487,6 +1528,10 @@ func (ec *elfCode) associateStructOpsRelocs(progs map[string]*ProgramSpec) error
return fmt.Errorf("failed to read section data: %w", err)
}

if ec.btf == nil {
return fmt.Errorf("struct_ops section %s: missing BTF", sec.Name)
}

// Resolve the BTF datasec describing variables in this section.
var ds *btf.Datasec
if err := ec.btf.TypeByName(sec.Name, &ds); err != nil {
Expand Down
Loading