Skip to content

Commit 1027b30

Browse files
committed
elf: refuse references to strings
Strings in BPF have to be stack allocated, so trying to reference a string that is allocated in a dedicated section doesn't work. The current error message is a bit confusing: load: .L.str: unsupported binding: STB_LOCAL The most common case for this is a call to bpf_trace_printk: bpf_trace_printk("foo", sizeof("foo")); Detect this case and return a better error.
1 parent 0a5ea64 commit 1027b30

File tree

7 files changed

+47
-11
lines changed

7 files changed

+47
-11
lines changed

elf_reader.go

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ func (ec *elfCode) loadPrograms(progSections map[elf.SectionIndex]*elf.Section,
190190

191191
insns, length, err := ec.loadInstructions(sec, syms, relocations[idx])
192192
if err != nil {
193-
return nil, fmt.Errorf("program %s: can't unmarshal instructions: %w", funcSym.Name, err)
193+
return nil, fmt.Errorf("program %s: %w", funcSym.Name, err)
194194
}
195195

196196
progType, attachType, attachTo := getProgType(sec.Name)
@@ -271,15 +271,15 @@ func (ec *elfCode) relocateInstruction(ins *asm.Instruction, rel elf.Symbol) err
271271
name = rel.Name
272272
)
273273

274+
if int(rel.Section) > len(ec.Sections) {
275+
return errors.New("out-of-bounds section index")
276+
}
277+
278+
section := ec.Sections[int(rel.Section)]
274279
if typ == elf.STT_SECTION {
275280
// Symbols with section type do not have a name set. Get it
276281
// from the section itself.
277-
idx := int(rel.Section)
278-
if idx > len(ec.Sections) {
279-
return errors.New("out-of-bounds section index")
280-
}
281-
282-
name = ec.Sections[idx].Name
282+
name = section.Name
283283
}
284284

285285
outer:
@@ -323,6 +323,10 @@ outer:
323323
fallthrough
324324

325325
case elf.STT_OBJECT:
326+
if section.Flags&elf.SHF_STRINGS > 0 {
327+
return fmt.Errorf("load: %s: string is not stack allocated: %w", name, ErrNotSupported)
328+
}
329+
326330
if bind != elf.STB_GLOBAL {
327331
return fmt.Errorf("load: %s: unsupported binding: %s", name, bind)
328332
}

elf_reader_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,16 @@ func TestLoadInitializedBTFMap(t *testing.T) {
203203
})
204204
}
205205

206+
func TestStringSection(t *testing.T) {
207+
testutils.TestFiles(t, "testdata/strings-*.elf", func(t *testing.T, file string) {
208+
_, err := LoadCollectionSpec(file)
209+
t.Log(err)
210+
if !errors.Is(err, ErrNotSupported) {
211+
t.Error("References to a string section should be unsupported")
212+
}
213+
})
214+
}
215+
206216
func TestLoadRawTracepoint(t *testing.T) {
207217
testutils.SkipOnOldKernel(t, "4.17", "BPF_RAW_TRACEPOINT API")
208218

testdata/Makefile

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
1-
LLVM_PREFIX ?= /usr/bin
2-
CLANG ?= $(LLVM_PREFIX)/clang
1+
CLANG ?= clang
32
CFLAGS := -target bpf -O2 -g -Wall -Werror $(CFLAGS)
43

4+
TARGETS := loader-clang-6.0 \
5+
loader-clang-7 \
6+
loader-clang-8 \
7+
loader-clang-9 \
8+
invalid_map \
9+
raw_tracepoint \
10+
invalid_map_static \
11+
initialized_btf_map \
12+
strings
13+
514
.PHONY: all clean
6-
all: loader-clang-6.0-el.elf loader-clang-7-el.elf loader-clang-8-el.elf loader-clang-9-el.elf invalid_map-el.elf raw_tracepoint-el.elf invalid_map_static-el.elf initialized_btf_map-el.elf \
7-
loader-clang-6.0-eb.elf loader-clang-7-eb.elf loader-clang-8-eb.elf loader-clang-9-eb.elf invalid_map-eb.elf raw_tracepoint-eb.elf invalid_map_static-eb.elf initialized_btf_map-eb.elf
15+
all: $(addsuffix -el.elf,$(TARGETS)) $(addsuffix -eb.elf,$(TARGETS))
816

917
clean:
1018
-$(RM) *.elf

testdata/common.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ struct bpf_map_def {
2626

2727
static void *(*map_lookup_elem)(const void *map, const void *key) = (void *)1;
2828

29+
static long (*trace_printk)(const char *fmt, uint32_t fmt_size, ...) = (void *)6;
30+
2931
static int (*perf_event_output)(const void *ctx, const void *map, uint64_t index, const void *data, uint64_t size) = (void *)25;
3032

3133
static uint32_t (*get_smp_processor_id)(void) = (void *)8;

testdata/strings-eb.elf

3.73 KB
Binary file not shown.

testdata/strings-el.elf

3.73 KB
Binary file not shown.

testdata/strings.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#include "common.h"
2+
3+
char __license[] __section("license") = "MIT";
4+
5+
#define STR1 "This string is allocated in the string section\n"
6+
#define STR2 "This one too\n"
7+
8+
__section("socket") int filter() {
9+
trace_printk(STR1, sizeof(STR1));
10+
trace_printk(STR2, sizeof(STR2));
11+
return 0;
12+
}

0 commit comments

Comments
 (0)