From patchwork Tue Jan 26 19:19:11 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnaldo Carvalho de Melo X-Patchwork-Id: 60546 Delivered-To: patch@linaro.org Received: by 10.112.130.2 with SMTP id oa2csp2157667lbb; Tue, 26 Jan 2016 11:20:03 -0800 (PST) X-Received: by 10.98.8.28 with SMTP id c28mr36314666pfd.56.1453836001212; Tue, 26 Jan 2016 11:20:01 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id fe1si3618983pac.200.2016.01.26.11.20.00; Tue, 26 Jan 2016 11:20:01 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752573AbcAZTTx (ORCPT + 30 others); Tue, 26 Jan 2016 14:19:53 -0500 Received: from bombadil.infradead.org ([198.137.202.9]:47669 "EHLO bombadil.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752458AbcAZTTq (ORCPT ); Tue, 26 Jan 2016 14:19:46 -0500 Received: from [179.235.167.117] (helo=zoo.infradead.org) by bombadil.infradead.org with esmtpsa (Exim 4.80.1 #2 (Red Hat Linux)) id 1aO99B-00046f-Pn; Tue, 26 Jan 2016 19:19:26 +0000 Received: by zoo.infradead.org (Postfix, from userid 1000) id E64062209D1; Tue, 26 Jan 2016 16:19:17 -0300 (BRT) From: Arnaldo Carvalho de Melo To: Ingo Molnar Cc: linux-kernel@vger.kernel.org, Wang Nan , "David S. Miller" , Brendan Gregg , Daniel Borkmann , He Kuang , Jiri Olsa , Li Zefan , Masami Hiramatsu , Namhyung Kim , Peter Zijlstra , Will Deacon , pi3orama@163.com, Arnaldo Carvalho de Melo Subject: [PATCH 22/26] perf bpf: Check relocation target section Date: Tue, 26 Jan 2016 16:19:11 -0300 Message-Id: <1453835955-14224-23-git-send-email-acme@kernel.org> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1453835955-14224-1-git-send-email-acme@kernel.org> References: <1453835955-14224-1-git-send-email-acme@kernel.org> X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org See http://www.infradead.org/rpr.html Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Wang Nan Libbpf should check the target section before doing relocation to ensure the relocation is correct. If not, a bug in LLVM causes an error. See [1]. Also, if an incorrect BPF script uses both global variable and map, global variable whould be treated as map and be relocated without error. This patch saves the id of the map section into obj->efile and compare target section of a relocation symbol against it during relocation. Previous patch introduces a test case about this problem. After this patch: # ~/perf test BPF 37: Test BPF filter : 37.1: Test basic BPF filtering : Ok 37.2: Test BPF prologue generation : Ok 37.3: Test BPF relocation checker : Ok # perf test -v BPF ... 37.3: Test BPF relocation checker : ... libbpf: loading object '[bpf_relocation_test]' from buffer libbpf: section .strtab, size 126, link 0, flags 0, type=3 libbpf: section .text, size 0, link 0, flags 6, type=1 libbpf: section .data, size 0, link 0, flags 3, type=1 libbpf: section .bss, size 0, link 0, flags 3, type=8 libbpf: section func=sys_write, size 104, link 0, flags 6, type=1 libbpf: found program func=sys_write libbpf: section .relfunc=sys_write, size 16, link 10, flags 0, type=9 libbpf: section maps, size 16, link 0, flags 3, type=1 libbpf: maps in [bpf_relocation_test]: 16 bytes libbpf: section license, size 4, link 0, flags 3, type=1 libbpf: license of [bpf_relocation_test] is GPL libbpf: section version, size 4, link 0, flags 3, type=1 libbpf: kernel version of [bpf_relocation_test] is 40400 libbpf: section .symtab, size 144, link 1, flags 0, type=2 libbpf: map 0 is "my_table" libbpf: collecting relocating info for: 'func=sys_write' libbpf: Program 'func=sys_write' contains non-map related relo data pointing to section 65522 bpf: failed to load buffer Compile BPF program failed. test child finished with 0 ---- end ---- Test BPF filter subtest 2: Ok [1] https://llvm.org/bugs/show_bug.cgi?id=26243 Signed-off-by: Wang Nan Acked-by: Alexei Starovoitov Tested-by: Arnaldo Carvalho de Melo Cc: "David S. Miller" Cc: Brendan Gregg Cc: Daniel Borkmann Cc: He Kuang Cc: Jiri Olsa Cc: Li Zefan Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Will Deacon Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1453715801-7732-3-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/bpf/libbpf.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) -- 2.5.0 diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 8334a5a9d5d7..7e543c3102d4 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -201,6 +201,7 @@ struct bpf_object { Elf_Data *data; } *reloc; int nr_reloc; + int maps_shndx; } efile; /* * All loaded bpf_object is linked in a list, which is @@ -350,6 +351,7 @@ static struct bpf_object *bpf_object__new(const char *path, */ obj->efile.obj_buf = obj_buf; obj->efile.obj_buf_sz = obj_buf_sz; + obj->efile.maps_shndx = -1; obj->loaded = false; @@ -529,12 +531,12 @@ bpf_object__init_maps(struct bpf_object *obj, void *data, } static int -bpf_object__init_maps_name(struct bpf_object *obj, int maps_shndx) +bpf_object__init_maps_name(struct bpf_object *obj) { int i; Elf_Data *symbols = obj->efile.symbols; - if (!symbols || maps_shndx < 0) + if (!symbols || obj->efile.maps_shndx < 0) return -EINVAL; for (i = 0; i < symbols->d_size / sizeof(GElf_Sym); i++) { @@ -544,7 +546,7 @@ bpf_object__init_maps_name(struct bpf_object *obj, int maps_shndx) if (!gelf_getsym(symbols, i, &sym)) continue; - if (sym.st_shndx != maps_shndx) + if (sym.st_shndx != obj->efile.maps_shndx) continue; map_name = elf_strptr(obj->efile.elf, @@ -572,7 +574,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj) Elf *elf = obj->efile.elf; GElf_Ehdr *ep = &obj->efile.ehdr; Elf_Scn *scn = NULL; - int idx = 0, err = 0, maps_shndx = -1; + int idx = 0, err = 0; /* Elf is corrupted/truncated, avoid calling elf_strptr. */ if (!elf_rawdata(elf_getscn(elf, ep->e_shstrndx), NULL)) { @@ -625,7 +627,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj) else if (strcmp(name, "maps") == 0) { err = bpf_object__init_maps(obj, data->d_buf, data->d_size); - maps_shndx = idx; + obj->efile.maps_shndx = idx; } else if (sh.sh_type == SHT_SYMTAB) { if (obj->efile.symbols) { pr_warning("bpf: multiple SYMTAB in %s\n", @@ -674,8 +676,8 @@ static int bpf_object__elf_collect(struct bpf_object *obj) pr_warning("Corrupted ELF file: index of strtab invalid\n"); return LIBBPF_ERRNO__FORMAT; } - if (maps_shndx >= 0) - err = bpf_object__init_maps_name(obj, maps_shndx); + if (obj->efile.maps_shndx >= 0) + err = bpf_object__init_maps_name(obj); out: return err; } @@ -697,7 +699,8 @@ bpf_object__find_prog_by_idx(struct bpf_object *obj, int idx) static int bpf_program__collect_reloc(struct bpf_program *prog, size_t nr_maps, GElf_Shdr *shdr, - Elf_Data *data, Elf_Data *symbols) + Elf_Data *data, Elf_Data *symbols, + int maps_shndx) { int i, nrels; @@ -724,9 +727,6 @@ bpf_program__collect_reloc(struct bpf_program *prog, return -LIBBPF_ERRNO__FORMAT; } - insn_idx = rel.r_offset / sizeof(struct bpf_insn); - pr_debug("relocation: insn_idx=%u\n", insn_idx); - if (!gelf_getsym(symbols, GELF_R_SYM(rel.r_info), &sym)) { @@ -735,6 +735,15 @@ bpf_program__collect_reloc(struct bpf_program *prog, return -LIBBPF_ERRNO__FORMAT; } + if (sym.st_shndx != maps_shndx) { + pr_warning("Program '%s' contains non-map related relo data pointing to section %u\n", + prog->section_name, sym.st_shndx); + return -LIBBPF_ERRNO__RELOC; + } + + insn_idx = rel.r_offset / sizeof(struct bpf_insn); + pr_debug("relocation: insn_idx=%u\n", insn_idx); + if (insns[insn_idx].code != (BPF_LD | BPF_IMM | BPF_DW)) { pr_warning("bpf: relocation: invalid relo for insns[%d].code 0x%x\n", insn_idx, insns[insn_idx].code); @@ -863,7 +872,8 @@ static int bpf_object__collect_reloc(struct bpf_object *obj) err = bpf_program__collect_reloc(prog, nr_maps, shdr, data, - obj->efile.symbols); + obj->efile.symbols, + obj->efile.maps_shndx); if (err) return err; }