From patchwork Fri Nov 5 13:59:14 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 47113 X-Patchwork-Delegate: hjl.tools@gmail.com Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 608703858411 for ; Fri, 5 Nov 2021 14:02:17 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 608703858411 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1636120937; bh=XHrr4OBW+Si5/+k7TR36XSbIcxsOtQuiy19XbHBuEAE=; h=To:Subject:In-Reply-To:References:Date:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=e7aa2DccAhOk0eDjFAaMgGjrmaxNqHEQmujl3ihmGmgmUVu8KdGXQj5p+CsH9QehL u2qb6J+22Wm/py3c0HN5whqpx2Ii6xuZLrr8JSLEReJBlb4ng2Rk3u7I3reYOqX9a5 TDXHI+ktn/CK52CEBras229kO25TEoYJC5QtRNB0= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (usb-smtp-delivery-124.mimecast.com [170.10.153.124]) by sourceware.org (Postfix) with ESMTPS id 4427D3858436 for ; Fri, 5 Nov 2021 14:00:43 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 4427D3858436 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-4-_Fm9mgdtNGamAa2SpXjtAw-1; Fri, 05 Nov 2021 10:00:40 -0400 X-MC-Unique: _Fm9mgdtNGamAa2SpXjtAw-1 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id D58F8100F966 for ; Fri, 5 Nov 2021 13:59:16 +0000 (UTC) Received: from oldenburg.str.redhat.com (unknown [10.39.192.25]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 415155D6D7 for ; Fri, 5 Nov 2021 13:59:16 +0000 (UTC) To: libc-alpha@sourceware.org Subject: [PATCH 1/2] Use sysdeps/posix/dl-fileid.h as the generic and only implementation In-Reply-To: References: X-From-Line: 8abecf436b4e0575a514aaacbf4be69c73823cd5 Mon Sep 17 00:00:00 2001 Message-Id: <8abecf436b4e0575a514aaacbf4be69c73823cd5.1636120354.git.fweimer@redhat.com> Date: Fri, 05 Nov 2021 14:59:14 +0100 User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux) MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-12.3 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Florian Weimer via Libc-alpha From: Florian Weimer Reply-To: Florian Weimer Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" --- sysdeps/generic/dl-fileid.h | 30 ++++++++++++---------- sysdeps/posix/dl-fileid.h | 50 ------------------------------------- 2 files changed, 17 insertions(+), 63 deletions(-) delete mode 100644 sysdeps/posix/dl-fileid.h diff --git a/sysdeps/generic/dl-fileid.h b/sysdeps/generic/dl-fileid.h index fb1e1c788b..bf437f3d71 100644 --- a/sysdeps/generic/dl-fileid.h +++ b/sysdeps/generic/dl-fileid.h @@ -1,4 +1,4 @@ -/* File identity for the dynamic linker. Stub version. +/* File identity for the dynamic linker. Generic POSIX.1 version. Copyright (C) 2015-2021 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -17,30 +17,34 @@ . */ #include +#include -/* This type stores whatever information is fetched by _dl_get_file_id - and compared by _dl_file_id_match_p. */ +/* For POSIX.1 systems, the pair of st_dev and st_ino constitute + a unique identifier for a file. */ struct r_file_id { - /* In the stub version, we don't record anything at all. */ + dev_t dev; + ino64_t ino; }; /* Sample FD to fill in *ID. Returns true on success. On error, returns false, with errno set. */ static inline bool -_dl_get_file_id (int fd __attribute__ ((unused)), - struct r_file_id *id __attribute__ ((unused))) +_dl_get_file_id (int fd, struct r_file_id *id) { + struct __stat64_t64 st; + + if (__glibc_unlikely (__fstat64_time64 (fd, &st) < 0)) + return false; + + id->dev = st.st_dev; + id->ino = st.st_ino; return true; } -/* Compare two results from _dl_get_file_id for equality. - It's crucial that this never return false-positive matches. - It's ideal that it never return false-negative mismatches either, - but lack of matches is survivable. */ +/* Compare two results from _dl_get_file_id for equality. */ static inline bool -_dl_file_id_match_p (const struct r_file_id *a __attribute__ ((unused)), - const struct r_file_id *b __attribute__ ((unused))) +_dl_file_id_match_p (const struct r_file_id *a, const struct r_file_id *b) { - return false; + return a->dev == b->dev && a->ino == b->ino; } diff --git a/sysdeps/posix/dl-fileid.h b/sysdeps/posix/dl-fileid.h deleted file mode 100644 index bf437f3d71..0000000000 --- a/sysdeps/posix/dl-fileid.h +++ /dev/null @@ -1,50 +0,0 @@ -/* File identity for the dynamic linker. Generic POSIX.1 version. - Copyright (C) 2015-2021 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#include -#include - -/* For POSIX.1 systems, the pair of st_dev and st_ino constitute - a unique identifier for a file. */ -struct r_file_id - { - dev_t dev; - ino64_t ino; - }; - -/* Sample FD to fill in *ID. Returns true on success. - On error, returns false, with errno set. */ -static inline bool -_dl_get_file_id (int fd, struct r_file_id *id) -{ - struct __stat64_t64 st; - - if (__glibc_unlikely (__fstat64_time64 (fd, &st) < 0)) - return false; - - id->dev = st.st_dev; - id->ino = st.st_ino; - return true; -} - -/* Compare two results from _dl_get_file_id for equality. */ -static inline bool -_dl_file_id_match_p (const struct r_file_id *a, const struct r_file_id *b) -{ - return a->dev == b->dev && a->ino == b->ino; -} From patchwork Fri Nov 5 13:59:18 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 47112 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 9EE413858411 for ; Fri, 5 Nov 2021 14:01:34 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 9EE413858411 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1636120894; bh=FNh59/FyM3CgVJ5wtBnNOusiAgAAO03Cv7hqgCYY2FU=; h=To:Subject:In-Reply-To:References:Date:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=U8n0S0mCn1ygsdbIvCgVrMXNen7u3KDEzFoemfbARvZlsPpZwhmKyrCW/n7H5RC+U E1F5P3T079J0FX92oT59xB4uPnqYUYO1Ki4GOlOC/5LSU39Cd6VPKTIiObQYwnW1Nx gPxaf5mRo1Tr8wU0ZhKHlg2bxnjFQlXwYNNnZac4= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by sourceware.org (Postfix) with ESMTPS id D180A3858428 for ; Fri, 5 Nov 2021 14:00:35 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org D180A3858428 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-437-U6Rct4VKMfeTB6J8PryFcA-1; Fri, 05 Nov 2021 10:00:33 -0400 X-MC-Unique: U6Rct4VKMfeTB6J8PryFcA-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 7546A80670A for ; Fri, 5 Nov 2021 13:59:22 +0000 (UTC) Received: from oldenburg.str.redhat.com (unknown [10.39.192.25]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 4D38817A89 for ; Fri, 5 Nov 2021 13:59:20 +0000 (UTC) To: libc-alpha@sourceware.org Subject: [PATCH 2/2] elf: Detect PT_LOAD segments that extend beyond EOF and refuse loading In-Reply-To: References: X-From-Line: 27f078539ae2a5b390705ac6fa1a7437ae8ce97c Mon Sep 17 00:00:00 2001 Message-Id: <27f078539ae2a5b390705ac6fa1a7437ae8ce97c.1636120354.git.fweimer@redhat.com> Date: Fri, 05 Nov 2021 14:59:18 +0100 User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux) MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-12.6 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Florian Weimer via Libc-alpha From: Florian Weimer Reply-To: Florian Weimer Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" We occasionally see elf/tst-debug1 failing with a SIGBUS error with some toolchain versions (recently on aarch64 only). This test tries to emulate loading separated debuginfo, but whether the test object triggers the crash depends on many factors. Accurately rejected separated debuginfo in dlopen probably needs ELF markup, at least if this is to be done efficiently using program headers only. But this change still improves user experience slightly. We already obtain the file size from the kernel in most cases, so no additional system call is added. Based on earlier downstream-only patch by Jeff Law. --- elf/dl-load.c | 78 +++++++++++++++++++++---------------- sysdeps/generic/dl-fileid.h | 7 ++-- 2 files changed, 49 insertions(+), 36 deletions(-) diff --git a/elf/dl-load.c b/elf/dl-load.c index a1f1682188..a758bed9af 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -953,47 +953,48 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, struct r_debug *r = _dl_debug_update (nsid); bool make_consistent = false; - /* Get file information. To match the kernel behavior, do not fill - in this information for the executable in case of an explicit - loader invocation. */ + /* Get file information. */ struct r_file_id id; + off64_t file_size; + if (__glibc_unlikely (!_dl_get_file_id (fd, &id, &file_size))) + { + errstring = N_("cannot stat shared object"); + lose_errno: + errval = errno; + lose: + /* The file might already be closed. */ + if (fd != -1) + __close_nocancel (fd); + if (l != NULL && l->l_map_start != 0) + _dl_unmap_segments (l); + if (l != NULL && l->l_origin != (char *) -1l) + free ((char *) l->l_origin); + if (l != NULL && !l->l_libname->dont_free) + free (l->l_libname); + if (l != NULL && l->l_phdr_allocated) + free ((void *) l->l_phdr); + free (l); + free (realname); + + if (make_consistent && r != NULL) + { + r->r_state = RT_CONSISTENT; + _dl_debug_state (); + LIBC_PROBE (map_failed, 2, nsid, r); + } + + _dl_signal_error (errval, name, NULL, errstring); + } + if (mode & __RTLD_OPENEXEC) { assert (nsid == LM_ID_BASE); + /* To match the kernel behavior, do not fill in this information + for the executable in case of an explicit loader invocation. */ memset (&id, 0, sizeof (id)); } else { - if (__glibc_unlikely (!_dl_get_file_id (fd, &id))) - { - errstring = N_("cannot stat shared object"); - lose_errno: - errval = errno; - lose: - /* The file might already be closed. */ - if (fd != -1) - __close_nocancel (fd); - if (l != NULL && l->l_map_start != 0) - _dl_unmap_segments (l); - if (l != NULL && l->l_origin != (char *) -1l) - free ((char *) l->l_origin); - if (l != NULL && !l->l_libname->dont_free) - free (l->l_libname); - if (l != NULL && l->l_phdr_allocated) - free ((void *) l->l_phdr); - free (l); - free (realname); - - if (make_consistent && r != NULL) - { - r->r_state = RT_CONSISTENT; - _dl_debug_state (); - LIBC_PROBE (map_failed, 2, nsid, r); - } - - _dl_signal_error (errval, name, NULL, errstring); - } - /* Look again to see if the real name matched another already loaded. */ for (l = GL(dl_ns)[nsid]._ns_loaded; l != NULL; l = l->l_next) if (!l->l_removed && _dl_file_id_match_p (&l->l_file_id, &id)) @@ -1177,6 +1178,17 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, = N_("ELF load command address/offset not properly aligned"); goto lose; } + if (__glibc_unlikely (ph->p_offset + ph->p_filesz > file_size)) + { + /* If the segment is not fully backed by the file, + accessing memory beyond the last full page results in + SIGBUS. This often happens with non-loadable ELF + objects containing separated debugging information + (which have load segments that match the original ELF + file). */ + errstring = N_("ELF load command past end of file"); + goto lose; + } struct loadcmd *c = &loadcmds[nloadcmds++]; c->mapstart = ALIGN_DOWN (ph->p_vaddr, GLRO(dl_pagesize)); diff --git a/sysdeps/generic/dl-fileid.h b/sysdeps/generic/dl-fileid.h index bf437f3d71..c59627429c 100644 --- a/sysdeps/generic/dl-fileid.h +++ b/sysdeps/generic/dl-fileid.h @@ -27,10 +27,10 @@ struct r_file_id ino64_t ino; }; -/* Sample FD to fill in *ID. Returns true on success. - On error, returns false, with errno set. */ +/* Sample FD to fill in *ID, *SIZE. Returns true on success. On + error, returns false, with errno set. */ static inline bool -_dl_get_file_id (int fd, struct r_file_id *id) +_dl_get_file_id (int fd, struct r_file_id *id, off64_t *size) { struct __stat64_t64 st; @@ -39,6 +39,7 @@ _dl_get_file_id (int fd, struct r_file_id *id) id->dev = st.st_dev; id->ino = st.st_ino; + *size = st.st_size; return true; }