BPF update
Subsystems (2)
cover BPF update
Two small BPF frontend updates.
The patchset is against your current net-next branch (pre master merge).
Thanks!
Daniel Borkmann (2):
tc, bpf: check section names and type everywhere tc, bpf: more header checks on loading elf
tc/tc_bpf.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 58 insertions(+), 6 deletions(-)
Signature · 1 line
1.9.3
PATCH 1/2 tc, bpf: check section names and type everywhere
When extracting sections, we better check for name and type. Noticed that some llvm versions emit .strtab and .shstrtab (e.g. saw it on pre 3.7), while more recent ones only seem to emit .strtab. Thus, make sure we get the right sections.
--- tc/tc_bpf.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-)
tc/tc_bpf.c +15 -6
@@ -1237,14 +1237,17 @@ static int bpf_fetch_ancillary(struct bpf_elf_ctx *ctx)if (ret <0 )continue ; -if (!strcmp (data.sec_name,ELF_SECTION_MAPS )) +if (data.sec_hdr.sh_type ==SHT_PROGBITS && + !strcmp (data.sec_name,ELF_SECTION_MAPS )) ret =bpf_fetch_maps (ctx, i, &data); -else if (!strcmp (data.sec_name,ELF_SECTION_LICENSE )) +else if (data.sec_hdr.sh_type ==SHT_PROGBITS && + !strcmp (data.sec_name,ELF_SECTION_LICENSE )) ret =bpf_fetch_license (ctx, i, &data); -else if (data.sec_hdr.sh_type ==SHT_SYMTAB ) +else if (data.sec_hdr.sh_type ==SHT_SYMTAB && + !strcmp (data.sec_name,".symtab" )) ret =bpf_fetch_symtab (ctx, i, &data);else if (data.sec_hdr.sh_type ==SHT_STRTAB && - i != ctx->elf_hdr.e_shstrndx) + !strcmp (data.sec_name,".strtab" )) ret =bpf_fetch_strtab (ctx, i, &data);if (ret <0 ) { fprintf(stderr, "Error parsing section %d! Perhaps"
@@ -1275,7 +1278,10 @@ static int bpf_fetch_prog(struct bpf_elf_ctx *ctx, const char *section)continue ; ret =bpf_fill_section_data (ctx, i, &data); -if (ret <0 ||strcmp (data.sec_name, section)) +if (ret <0 || + !(data.sec_hdr.sh_type ==SHT_PROGBITS && + data.sec_hdr.sh_flags &SHF_EXECINSTR && + !strcmp (data.sec_name, section)))continue ;memset (&prog,0 ,sizeof (prog));
@@ -1353,7 +1359,10 @@ static int bpf_fetch_prog_relo(struct bpf_elf_ctx *ctx, const char *section) idx = data_relo.sec_hdr.sh_info; ret =bpf_fill_section_data (ctx, idx, &data_insn); -if (ret <0 ||strcmp (data_insn.sec_name, section)) +if (ret <0 || + !(data_insn.sec_hdr.sh_type ==SHT_PROGBITS && + data_insn.sec_hdr.sh_flags &SHF_EXECINSTR && + !strcmp (data_insn.sec_name, section)))continue ; ret =bpf_apply_relo_data (ctx, &data_relo, &data_insn);
Signature · 1 line
1.9.3
PATCH 2/2 tc, bpf: more header checks on loading elf
In reply to Daniel BorkmanneBPF llvm backend can support different BPF formats, make sure the object we're trying to load matches with regards to endiannes and while at it, also check for other attributes related to BPF ELFs.
# llc --version LLVM (http://llvm.org/): LLVM version 3.8.0svn Optimized build. Built Jan 9 2016 (02:08:10). Default target: x86_64-unknown-linux-gnu Host CPU: ivybridge
Registered Targets:
bpf - BPF (host endian)
bpfeb - BPF (big endian)
bpfel - BPF (little endian)
[...]
--- tc/tc_bpf.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+)
tc/tc_bpf.c +43 -0
@@ -39,6 +39,8 @@#include <linux/filter.h> #include <linux/if_alg.h> +#include <arpa/inet.h> +#include "utils.h" #include "bpf_elf.h"
@@ -1564,6 +1566,38 @@ static void bpf_hash_destroy(struct bpf_elf_ctx *ctx) } } +static int bpf_elf_check_ehdr (const struct bpf_elf_ctx *ctx) +{ +if (ctx->elf_hdr.e_type !=ET_REL || + ctx->elf_hdr.e_machine !=0 || + ctx->elf_hdr.e_version !=EV_CURRENT ) { +fprintf (stderr,"ELF format error, ELF file not for eBPF?\n" ); +return -EINVAL ; + } + +switch (ctx->elf_hdr.e_ident[EI_DATA ]) { +default : +fprintf (stderr,"ELF format error, wrong endianness info?\n" ); +return -EINVAL ; +case ELFDATA2LSB : +if (htons (1 ) ==1 ) { +fprintf (stderr, +"We are big endian, eBPF object is little endian!\n" ); +return -EIO ; + } +break ; +case ELFDATA2MSB : +if (htons (1 ) !=1 ) { +fprintf (stderr, +"We are little endian, eBPF object is big endian!\n" ); +return -EIO ; + } +break ; + } + +return 0 ; +} +static int bpf_elf_ctx_init (struct bpf_elf_ctx *ctx,const char *pathname,enum bpf_prog_type type,bool verbose) {
@@ -1587,12 +1621,21 @@ static int bpf_elf_ctx_init(struct bpf_elf_ctx *ctx, const char *pathname, goto out_fd; } +if (elf_kind (ctx->elf_fd) !=ELF_K_ELF ) { + ret = -EINVAL ; + goto out_fd; + } +if (gelf_getehdr (ctx->elf_fd, &ctx->elf_hdr) != &ctx->elf_hdr) { ret = -EIO ; goto out_elf; } + ret =bpf_elf_check_ehdr (ctx); +if (ret <0 ) + goto out_elf; + ctx->sec_done =calloc (ctx->elf_hdr.e_shnum,sizeof (*(ctx->sec_done)));if (!ctx->sec_done) {
Signature · 1 line
1.9.3
Quoted 4 lines · On Tue, 12 Jan 2016 02:03:06 +0100 Daniel Borkmann <[email protected]> wrote:
Two small BPF frontend updates.
The patchset is against your current net-next branch (pre master merge).
Quoted 8 lines
Thanks!
Daniel Borkmann (2):
tc, bpf: check section names and type everywhere tc, bpf: more header checks on loading elftc/tc_bpf.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 58 insertions(+), 6 deletions(-)
This applies fine to master. Accepted.