From patchwork Wed Dec 2 23:22:42 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aurelien Jarno X-Patchwork-Id: 9863 Received: (qmail 70623 invoked by alias); 2 Dec 2015 23:23:06 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 70606 invoked by uid 89); 2 Dec 2015 23:23:06 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.9 required=5.0 tests=BAYES_00, KAM_LAZY_DOMAIN_SECURITY, T_RP_MATCHES_RCVD autolearn=no version=3.3.2 X-HELO: hall.aurel32.net From: Aurelien Jarno To: libc-alpha@sourceware.org Cc: Aurelien Jarno Subject: [PATCH] linux: add support for uname26 personality Date: Thu, 3 Dec 2015 00:22:42 +0100 Message-Id: <1449098562-9513-1-git-send-email-aurelien@aurel32.net> When the kernel is running under the uname26 personality (for programs that cannot handle "Linux 3.0"), it maps version 3.x to 2.6.40+x and 4.x to 2.6.60+x. When the GNU libc is configured with --enable-kernel=3.x or 4.x and uname26 personality is enabled, binaries get abort with a "FATAL: kernel too old message", even if the kernel actually supports such a binary. This patch fixes the issue by converting the value in 2.6.x format back to the 3.x or 4.X format. --- ChangeLog | 6 ++++++ sysdeps/unix/sysv/linux/dl-sysdep.c | 26 +++++++++++++++++++++++--- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index c7c4c25..593cfad 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2015-12-03 Aurelien Jarno + + * sysdeps/unix/sysv/linux/dl-sysdep.c (convert_from_uname26): New. + (_dl_discover_osversion): Call convert_from_uname26 before returning + the version. + 2015-12-01 H.J. Lu [BZ #19313] diff --git a/sysdeps/unix/sysv/linux/dl-sysdep.c b/sysdeps/unix/sysv/linux/dl-sysdep.c index a4c32f6..4fca8d1 100644 --- a/sysdeps/unix/sysv/linux/dl-sysdep.c +++ b/sysdeps/unix/sysv/linux/dl-sysdep.c @@ -38,6 +38,25 @@ frob_brk (void) # include #endif +/* When the kernel is running under the uname26 personality (for programs + that cannot handle "Linux 3.0"), it maps version 3.x to 2.6.40+x and + 4.x to 2.6.60+x. We need to convert that back to the standard version + numbering to be able to compare versions. */ +static int +convert_from_uname26 (int version) +{ + if ((version & 0xffff00) == 0x020600) + { + /* 2.6.40+x to 3.x */ + if ((version & 0xff) >= 60) + version += 0x020000 - 60; + /* 2.6.60+x to 4.x */ + else if ((version & 0xff) >= 40) + version += 0x010000 - 40; + } + + return version; +} int attribute_hidden @@ -65,8 +84,9 @@ _dl_discover_osversion (void) while ((ElfW(Addr)) (note + 1) - start < phdr[i].p_memsz) { if (!memcmp (note, &expected_note, sizeof expected_note)) - return *(const ElfW(Word) *) ((const void *) note - + sizeof expected_note); + return convert_from_uname26( + *(const ElfW(Word) *) ((const void *) note + + sizeof expected_note)); #define ROUND(len) (((len) + sizeof note->n_type - 1) & -sizeof note->n_type) note = ((const void *) (note + 1) + ROUND (note->n_namesz) + ROUND (note->n_descsz)); @@ -128,5 +148,5 @@ _dl_discover_osversion (void) if (parts < 3) version <<= 8 * (3 - parts); - return version; + return convert_from_uname26(version); }