kern/135468: broken detection of Linux binaries via ".note.ABI-tag"
section.
Petr Salinger
Petr.Salinger at seznam.cz
Thu Jun 11 08:50:02 UTC 2009
>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:
More information about the freebsd-bugs
mailing list