Blob Blame History Raw
From 9348ded117d05ba1d54a748173db009d473c707c Mon Sep 17 00:00:00 2001
From: Andrea Claudi <aclaudi@redhat.com>
Date: Thu, 13 Jun 2019 14:37:57 +0200
Subject: [PATCH] bpf: initialise map symbol before retrieving and comparing
 its type

Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1716361
Upstream Status: iproute2.git commit 1a7d3ad8a5862

commit 1a7d3ad8a5862ca9ce9dd19326faeea77e5e6142
Author: Quentin Monnet <quentin.monnet@netronome.com>
Date:   Tue Nov 20 01:26:27 2018 +0000

    bpf: initialise map symbol before retrieving and comparing its type

    In order to compare BPF map symbol type correctly in regard to the
    latest LLVM, commit 7a04dd84a7f9 ("bpf: check map symbol type properly
    with newer llvm compiler") compares map symbol type to both NOTYPE and
    OBJECT. To do so, it first retrieves the type from "sym.st_info" and
    stores it into a temporary variable.

    However, the type is collected from the symbol "sym" before this latter
    symbol is actually updated. gelf_getsym() is called after that and
    updates "sym", and when comparison with OBJECT or NOTYPE happens it is
    done on the type of the symbol collected in the previous passage of the
    loop (or on an uninitialised symbol on the first passage). This may
    eventually break map collection from the ELF file.

    Fix this by assigning the type to the temporary variable only after the
    call to gelf_getsym().

    Fixes: 7a04dd84a7f9 ("bpf: check map symbol type properly with newer llvm compiler")
    Reported-by: Ron Philip <ron.philip@netronome.com>
    Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com>
    Reviewed-by: Jiong Wang <jiong.wang@netronome.com>
    Acked-by: Yonghong Song <yhs@fb.com>
    Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 lib/bpf.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/lib/bpf.c b/lib/bpf.c
index 45f279fa4a416..6aff8f7bad7fb 100644
--- a/lib/bpf.c
+++ b/lib/bpf.c
@@ -1758,11 +1758,12 @@ static const char *bpf_map_fetch_name(struct bpf_elf_ctx *ctx, int which)
 	int i;
 
 	for (i = 0; i < ctx->sym_num; i++) {
-		int type = GELF_ST_TYPE(sym.st_info);
+		int type;
 
 		if (gelf_getsym(ctx->sym_tab, i, &sym) != &sym)
 			continue;
 
+		type = GELF_ST_TYPE(sym.st_info);
 		if (GELF_ST_BIND(sym.st_info) != STB_GLOBAL ||
 		    (type != STT_NOTYPE && type != STT_OBJECT) ||
 		    sym.st_shndx != ctx->sec_maps ||
@@ -1851,11 +1852,12 @@ static int bpf_map_num_sym(struct bpf_elf_ctx *ctx)
 	GElf_Sym sym;
 
 	for (i = 0; i < ctx->sym_num; i++) {
-		int type = GELF_ST_TYPE(sym.st_info);
+		int type;
 
 		if (gelf_getsym(ctx->sym_tab, i, &sym) != &sym)
 			continue;
 
+		type = GELF_ST_TYPE(sym.st_info);
 		if (GELF_ST_BIND(sym.st_info) != STB_GLOBAL ||
 		    (type != STT_NOTYPE && type != STT_OBJECT) ||
 		    sym.st_shndx != ctx->sec_maps)
@@ -1931,10 +1933,12 @@ static int bpf_map_verify_all_offs(struct bpf_elf_ctx *ctx, int end)
 		 * the table again.
 		 */
 		for (i = 0; i < ctx->sym_num; i++) {
-			int type = GELF_ST_TYPE(sym.st_info);
+			int type;
 
 			if (gelf_getsym(ctx->sym_tab, i, &sym) != &sym)
 				continue;
+
+			type = GELF_ST_TYPE(sym.st_info);
 			if (GELF_ST_BIND(sym.st_info) != STB_GLOBAL ||
 			    (type != STT_NOTYPE && type != STT_OBJECT) ||
 			    sym.st_shndx != ctx->sec_maps)
-- 
2.20.1