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