Date: Thu, 11 Jun 2009 08:48:00 GMT From: Petr Salinger <Petr.Salinger@seznam.cz> To: freebsd-gnats-submit@FreeBSD.org Subject: kern/135468: broken detection of Linux binaries via ".note.ABI-tag" section. Message-ID: <200906110848.n5B8m0V1016019@www.freebsd.org> Resent-Message-ID: <200906110850.n5B8o1HG087162@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 135468 >Category: kern >Synopsis: broken detection of Linux binaries via ".note.ABI-tag" section. >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Thu Jun 11 08:50:01 UTC 2009 >Closed-Date: >Last-Modified: >Originator: Petr Salinger >Release: >Organization: >Environment: >Description: The current (7.2, 8.0) code tries to detect Linux binaries by parsing".note.ABI-tag" section. The layout of this note is different compared to layout of native FreeBSD one. >From http://www.netbsd.org/docs/kernel/elf-notes.html: Starting with glibc 2.1, the GNU project will be using a single ELF Note to indicate which GNU operating system and which version of that system a binary was built for. The format of that note is: Name Size 4 Desc Size 16 Type 4-byte integer containing the value 0x01 Name "GNU\0" Desc Four 4-byte integers containing, in order: 1. OS (0 = Linux, 1 = Hurd, 2 = Solaris) 2. Major 3. Minor 4. Teeny So linux emulation should be used only when Name is "GNU" AND first 4-byte integer in Desc is zero. The current code breaks libc environment compiled with native FreeBSD calling convention - Desc = 3. >How-To-Repeat: >Fix: Correct solution would be to provide a "brand checker" function which would return: 1 for unknown brand, osreldate for know brand with OSREL capability, 0 for know brand without OSREL capability. Alternatively is possible to use fact, that in current both cases exactly 8 bytes have to be checked, see attached patch. Patch attached with submission follows: Upstream checks the .note.ABI-tag in a bad way. They should not only check the "GNU", but also whether OS field matches. In both cases they should check 8 bytes, we can use it for current hack. http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=532627 Index: src/sys/amd64/linux32/linux32_sysvec.c =================================================================== --- src.orig/sys/amd64/linux32/linux32_sysvec.c +++ src/sys/amd64/linux32/linux32_sysvec.c @@ -1047,10 +1047,10 @@ .sv_maxssiz = &linux32_maxssiz, }; -static char GNULINUX_ABI_VENDOR[] = "GNU"; +static char GNULINUX_ABI_VENDOR[] = "GNU\0\0\0\0\0"; static Elf_Brandnote linux32_brandnote = { - .hdr.n_namesz = sizeof(GNULINUX_ABI_VENDOR), + .hdr.n_namesz = 4, .hdr.n_descsz = 16, .hdr.n_type = 1, .vendor = GNULINUX_ABI_VENDOR, Index: src/sys/i386/linux/linux_sysvec.c =================================================================== --- src.orig/sys/i386/linux/linux_sysvec.c +++ src/sys/i386/linux/linux_sysvec.c @@ -1017,10 +1017,10 @@ .sv_maxssiz = NULL }; -static char GNULINUX_ABI_VENDOR[] = "GNU"; +static char GNULINUX_ABI_VENDOR[] = "GNU\0\0\0\0\0"; static Elf_Brandnote linux_brandnote = { - .hdr.n_namesz = sizeof(GNULINUX_ABI_VENDOR), + .hdr.n_namesz = 4, .hdr.n_descsz = 16, .hdr.n_type = 1, .vendor = GNULINUX_ABI_VENDOR, Index: src/sys/kern/imgact_elf.c =================================================================== --- src.orig/sys/kern/imgact_elf.c +++ src/sys/kern/imgact_elf.c @@ -112,10 +112,10 @@ #define round_page_ps(va, ps) (((va) + (ps - 1)) & ~(ps - 1)) #define aligned(a, t) (trunc_page_ps((u_long)(a), sizeof(t)) == (u_long)(a)) -static const char FREEBSD_ABI_VENDOR[] = "FreeBSD"; +static const char FREEBSD_ABI_VENDOR[] = "FreeBSD\0"; Elf_Brandnote __elfN(freebsd_brandnote) = { - .hdr.n_namesz = sizeof(FREEBSD_ABI_VENDOR), + .hdr.n_namesz = 8, .hdr.n_descsz = sizeof(int32_t), .hdr.n_type = 1, .vendor = FREEBSD_ABI_VENDOR, @@ -1393,8 +1393,7 @@ note->n_type != checknote->hdr.n_type) goto nextnote; note_name = (const char *)(note + 1); - if (strncmp(checknote->vendor, note_name, - checknote->hdr.n_namesz) != 0) + if (memcmp(checknote->vendor, note_name, 8) != 0) goto nextnote; /* >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200906110848.n5B8m0V1016019>