Patch "tools/resolve_btfids: Fix cross-compilation to non-host endianness" has been added to the 6.6-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    tools/resolve_btfids: Fix cross-compilation to non-host endianness

to the 6.6-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     tools-resolve_btfids-fix-cross-compilation-to-non-ho.patch
and it can be found in the queue-6.6 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 0a1b836f3a2fc550a582c4e36b1c7a2713edc54c
Author: Viktor Malik <vmalik@xxxxxxxxxx>
Date:   Tue Feb 6 13:46:10 2024 +0100

    tools/resolve_btfids: Fix cross-compilation to non-host endianness
    
    [ Upstream commit 903fad4394666bc23975c93fb58f137ce64b5192 ]
    
    The .BTF_ids section is pre-filled with zeroed BTF ID entries during the
    build and afterwards patched by resolve_btfids with correct values.
    Since resolve_btfids always writes in host-native endianness, it relies
    on libelf to do the translation when the target ELF is cross-compiled to
    a different endianness (this was introduced in commit 61e8aeda9398
    ("bpf: Fix libelf endian handling in resolv_btfids")).
    
    Unfortunately, the translation will corrupt the flags fields of SET8
    entries because these were written during vmlinux compilation and are in
    the correct endianness already. This will lead to numerous selftests
    failures such as:
    
        $ sudo ./test_verifier 502 502
        #502/p sleepable fentry accept FAIL
        Failed to load prog 'Invalid argument'!
        bpf_fentry_test1 is not sleepable
        verification time 34 usec
        stack depth 0
        processed 0 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0
        Summary: 0 PASSED, 0 SKIPPED, 1 FAILED
    
    Since it's not possible to instruct libelf to translate just certain
    values, let's manually bswap the flags (both global and entry flags) in
    resolve_btfids when needed, so that libelf then translates everything
    correctly.
    
    Fixes: ef2c6f370a63 ("tools/resolve_btfids: Add support for 8-byte BTF sets")
    Signed-off-by: Viktor Malik <vmalik@xxxxxxxxxx>
    Signed-off-by: Andrii Nakryiko <andrii@xxxxxxxxxx>
    Link: https://lore.kernel.org/bpf/7b6bff690919555574ce0f13d2a5996cacf7bf69.1707223196.git.vmalik@xxxxxxxxxx
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/tools/bpf/resolve_btfids/main.c b/tools/bpf/resolve_btfids/main.c
index 32634f00abba4..d9520cb826b31 100644
--- a/tools/bpf/resolve_btfids/main.c
+++ b/tools/bpf/resolve_btfids/main.c
@@ -90,6 +90,14 @@
 
 #define ADDR_CNT	100
 
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# define ELFDATANATIVE	ELFDATA2LSB
+#elif __BYTE_ORDER == __BIG_ENDIAN
+# define ELFDATANATIVE	ELFDATA2MSB
+#else
+# error "Unknown machine endianness!"
+#endif
+
 struct btf_id {
 	struct rb_node	 rb_node;
 	char		*name;
@@ -117,6 +125,7 @@ struct object {
 		int		 idlist_shndx;
 		size_t		 strtabidx;
 		unsigned long	 idlist_addr;
+		int		 encoding;
 	} efile;
 
 	struct rb_root	sets;
@@ -320,6 +329,7 @@ static int elf_collect(struct object *obj)
 {
 	Elf_Scn *scn = NULL;
 	size_t shdrstrndx;
+	GElf_Ehdr ehdr;
 	int idx = 0;
 	Elf *elf;
 	int fd;
@@ -351,6 +361,13 @@ static int elf_collect(struct object *obj)
 		return -1;
 	}
 
+	if (gelf_getehdr(obj->efile.elf, &ehdr) == NULL) {
+		pr_err("FAILED cannot get ELF header: %s\n",
+			elf_errmsg(-1));
+		return -1;
+	}
+	obj->efile.encoding = ehdr.e_ident[EI_DATA];
+
 	/*
 	 * Scan all the elf sections and look for save data
 	 * from .BTF_ids section and symbols.
@@ -681,6 +698,24 @@ static int sets_patch(struct object *obj)
 			 */
 			BUILD_BUG_ON(set8->pairs != &set8->pairs[0].id);
 			qsort(set8->pairs, set8->cnt, sizeof(set8->pairs[0]), cmp_id);
+
+			/*
+			 * When ELF endianness does not match endianness of the
+			 * host, libelf will do the translation when updating
+			 * the ELF. This, however, corrupts SET8 flags which are
+			 * already in the target endianness. So, let's bswap
+			 * them to the host endianness and libelf will then
+			 * correctly translate everything.
+			 */
+			if (obj->efile.encoding != ELFDATANATIVE) {
+				int i;
+
+				set8->flags = bswap_32(set8->flags);
+				for (i = 0; i < set8->cnt; i++) {
+					set8->pairs[i].flags =
+						bswap_32(set8->pairs[i].flags);
+				}
+			}
 		}
 
 		pr_debug("sorting  addr %5lu: cnt %6d [%s]\n",




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux