2024-01-02 02:12:26 +08:00
|
|
|
/* Copyright (C) 2011-2024 Free Software Foundation, Inc.
|
2011-06-09 19:06:21 +08:00
|
|
|
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
|
2012-02-10 07:18:22 +08:00
|
|
|
License along with the GNU C Library; if not, see
|
Prefer https to http for gnu.org and fsf.org URLs
Also, change sources.redhat.com to sourceware.org.
This patch was automatically generated by running the following shell
script, which uses GNU sed, and which avoids modifying files imported
from upstream:
sed -ri '
s,(http|ftp)(://(.*\.)?(gnu|fsf|sourceware)\.org($|[^.]|\.[^a-z])),https\2,g
s,(http|ftp)(://(.*\.)?)sources\.redhat\.com($|[^.]|\.[^a-z]),https\2sourceware.org\4,g
' \
$(find $(git ls-files) -prune -type f \
! -name '*.po' \
! -name 'ChangeLog*' \
! -path COPYING ! -path COPYING.LIB \
! -path manual/fdl-1.3.texi ! -path manual/lgpl-2.1.texi \
! -path manual/texinfo.tex ! -path scripts/config.guess \
! -path scripts/config.sub ! -path scripts/install-sh \
! -path scripts/mkinstalldirs ! -path scripts/move-if-change \
! -path INSTALL ! -path locale/programs/charmap-kw.h \
! -path po/libc.pot ! -path sysdeps/gnu/errlist.c \
! '(' -name configure \
-execdir test -f configure.ac -o -f configure.in ';' ')' \
! '(' -name preconfigure \
-execdir test -f preconfigure.ac ';' ')' \
-print)
and then by running 'make dist-prepare' to regenerate files built
from the altered files, and then executing the following to cleanup:
chmod a+x sysdeps/unix/sysv/linux/riscv/configure
# Omit irrelevant whitespace and comment-only changes,
# perhaps from a slightly-different Autoconf version.
git checkout -f \
sysdeps/csky/configure \
sysdeps/hppa/configure \
sysdeps/riscv/configure \
sysdeps/unix/sysv/linux/csky/configure
# Omit changes that caused a pre-commit check to fail like this:
# remote: *** error: sysdeps/powerpc/powerpc64/ppc-mcount.S: trailing lines
git checkout -f \
sysdeps/powerpc/powerpc64/ppc-mcount.S \
sysdeps/unix/sysv/linux/s390/s390-64/syscall.S
# Omit change that caused a pre-commit check to fail like this:
# remote: *** error: sysdeps/sparc/sparc64/multiarch/memcpy-ultra3.S: last line does not end in newline
git checkout -f sysdeps/sparc/sparc64/multiarch/memcpy-ultra3.S
2019-09-07 13:40:42 +08:00
|
|
|
<https://www.gnu.org/licenses/>. */
|
2011-06-09 19:06:21 +08:00
|
|
|
|
|
|
|
#define E(name) E_(name, CLASS)
|
|
|
|
#define E_(name, cl) E__(name, cl)
|
|
|
|
#define E__(name, cl) name##cl
|
|
|
|
#define EW(type) EW_(Elf, CLASS, type)
|
|
|
|
#define EW_(e, w, t) EW__(e, w, _##t)
|
|
|
|
#define EW__(e, w, t) e##w##t
|
|
|
|
|
2022-01-30 02:56:45 +08:00
|
|
|
#include <dl-r_debug.h>
|
|
|
|
|
2011-06-09 19:06:21 +08:00
|
|
|
struct E(link_map)
|
|
|
|
{
|
|
|
|
EW(Addr) l_addr;
|
|
|
|
EW(Addr) l_name;
|
|
|
|
EW(Addr) l_ld;
|
|
|
|
EW(Addr) l_next;
|
|
|
|
EW(Addr) l_prev;
|
|
|
|
EW(Addr) l_real;
|
|
|
|
Lmid_t l_ns;
|
|
|
|
EW(Addr) l_libname;
|
|
|
|
};
|
|
|
|
#if CLASS == __ELF_NATIVE_CLASS
|
elf: Fix pldd (BZ#18035)
Since 9182aa67994 (Fix vDSO l_name for GDB's, BZ#387) the initial link_map
for executable itself and loader will have both l_name and l_libname->name
holding the same value due:
elf/dl-object.c
95 new->l_name = *realname ? realname : (char *) newname->name + libname_len - 1;
Since newname->name points to new->l_libname->name.
This leads to pldd to an infinite call at:
elf/pldd-xx.c
203 again:
204 while (1)
205 {
206 ssize_t n = pread64 (memfd, tmpbuf.data, tmpbuf.length, name_offset);
228 /* Try the l_libname element. */
229 struct E(libname_list) ln;
230 if (pread64 (memfd, &ln, sizeof (ln), m.l_libname) == sizeof (ln))
231 {
232 name_offset = ln.name;
233 goto again;
234 }
Since the value at ln.name (l_libname->name) will be the same as previously
read. The straightforward fix is just avoid the check and read the new list
entry.
I checked also against binaries issues with old loaders with fix for BZ#387,
and pldd could dump the shared objects.
Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu, and
powerpc64le-linux-gnu.
[BZ #18035]
* elf/Makefile (tests-container): Add tst-pldd.
* elf/pldd-xx.c: Use _Static_assert in of pldd_assert.
(E(find_maps)): Avoid use alloca, use default read file operations
instead of explicit LFS names, and fix infinite loop.
* elf/pldd.c: Explicit set _FILE_OFFSET_BITS, cleanup headers.
(get_process_info): Use _Static_assert instead of assert, use default
directory operations instead of explicit LFS names, and free some
leadek pointers.
* elf/tst-pldd.c: New file.
2019-04-12 05:12:00 +08:00
|
|
|
_Static_assert (offsetof (struct link_map, l_addr)
|
|
|
|
== offsetof (struct E(link_map), l_addr), "l_addr");
|
|
|
|
_Static_assert (offsetof (struct link_map, l_name)
|
|
|
|
== offsetof (struct E(link_map), l_name), "l_name");
|
|
|
|
_Static_assert (offsetof (struct link_map, l_next)
|
|
|
|
== offsetof (struct E(link_map), l_next), "l_next");
|
2011-06-09 19:06:21 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
struct E(libname_list)
|
|
|
|
{
|
|
|
|
EW(Addr) name;
|
|
|
|
EW(Addr) next;
|
|
|
|
};
|
|
|
|
#if CLASS == __ELF_NATIVE_CLASS
|
elf: Fix pldd (BZ#18035)
Since 9182aa67994 (Fix vDSO l_name for GDB's, BZ#387) the initial link_map
for executable itself and loader will have both l_name and l_libname->name
holding the same value due:
elf/dl-object.c
95 new->l_name = *realname ? realname : (char *) newname->name + libname_len - 1;
Since newname->name points to new->l_libname->name.
This leads to pldd to an infinite call at:
elf/pldd-xx.c
203 again:
204 while (1)
205 {
206 ssize_t n = pread64 (memfd, tmpbuf.data, tmpbuf.length, name_offset);
228 /* Try the l_libname element. */
229 struct E(libname_list) ln;
230 if (pread64 (memfd, &ln, sizeof (ln), m.l_libname) == sizeof (ln))
231 {
232 name_offset = ln.name;
233 goto again;
234 }
Since the value at ln.name (l_libname->name) will be the same as previously
read. The straightforward fix is just avoid the check and read the new list
entry.
I checked also against binaries issues with old loaders with fix for BZ#387,
and pldd could dump the shared objects.
Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu, and
powerpc64le-linux-gnu.
[BZ #18035]
* elf/Makefile (tests-container): Add tst-pldd.
* elf/pldd-xx.c: Use _Static_assert in of pldd_assert.
(E(find_maps)): Avoid use alloca, use default read file operations
instead of explicit LFS names, and fix infinite loop.
* elf/pldd.c: Explicit set _FILE_OFFSET_BITS, cleanup headers.
(get_process_info): Use _Static_assert instead of assert, use default
directory operations instead of explicit LFS names, and free some
leadek pointers.
* elf/tst-pldd.c: New file.
2019-04-12 05:12:00 +08:00
|
|
|
_Static_assert (offsetof (struct libname_list, name)
|
|
|
|
== offsetof (struct E(libname_list), name), "name");
|
|
|
|
_Static_assert (offsetof (struct libname_list, next)
|
|
|
|
== offsetof (struct E(libname_list), next), "next");
|
2011-06-09 19:06:21 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
struct E(r_debug)
|
|
|
|
{
|
|
|
|
int r_version;
|
2011-08-17 22:31:15 +08:00
|
|
|
#if CLASS == 64
|
|
|
|
int pad;
|
|
|
|
#endif
|
2011-06-09 19:06:21 +08:00
|
|
|
EW(Addr) r_map;
|
|
|
|
};
|
|
|
|
#if CLASS == __ELF_NATIVE_CLASS
|
elf: Fix pldd (BZ#18035)
Since 9182aa67994 (Fix vDSO l_name for GDB's, BZ#387) the initial link_map
for executable itself and loader will have both l_name and l_libname->name
holding the same value due:
elf/dl-object.c
95 new->l_name = *realname ? realname : (char *) newname->name + libname_len - 1;
Since newname->name points to new->l_libname->name.
This leads to pldd to an infinite call at:
elf/pldd-xx.c
203 again:
204 while (1)
205 {
206 ssize_t n = pread64 (memfd, tmpbuf.data, tmpbuf.length, name_offset);
228 /* Try the l_libname element. */
229 struct E(libname_list) ln;
230 if (pread64 (memfd, &ln, sizeof (ln), m.l_libname) == sizeof (ln))
231 {
232 name_offset = ln.name;
233 goto again;
234 }
Since the value at ln.name (l_libname->name) will be the same as previously
read. The straightforward fix is just avoid the check and read the new list
entry.
I checked also against binaries issues with old loaders with fix for BZ#387,
and pldd could dump the shared objects.
Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu, and
powerpc64le-linux-gnu.
[BZ #18035]
* elf/Makefile (tests-container): Add tst-pldd.
* elf/pldd-xx.c: Use _Static_assert in of pldd_assert.
(E(find_maps)): Avoid use alloca, use default read file operations
instead of explicit LFS names, and fix infinite loop.
* elf/pldd.c: Explicit set _FILE_OFFSET_BITS, cleanup headers.
(get_process_info): Use _Static_assert instead of assert, use default
directory operations instead of explicit LFS names, and free some
leadek pointers.
* elf/tst-pldd.c: New file.
2019-04-12 05:12:00 +08:00
|
|
|
_Static_assert (offsetof (struct r_debug, r_version)
|
|
|
|
== offsetof (struct E(r_debug), r_version), "r_version");
|
|
|
|
_Static_assert (offsetof (struct r_debug, r_map)
|
|
|
|
== offsetof (struct E(r_debug), r_map), "r_map");
|
2011-06-09 19:06:21 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2011-08-17 22:31:15 +08:00
|
|
|
|
elf: Fix pldd (BZ#18035)
Since 9182aa67994 (Fix vDSO l_name for GDB's, BZ#387) the initial link_map
for executable itself and loader will have both l_name and l_libname->name
holding the same value due:
elf/dl-object.c
95 new->l_name = *realname ? realname : (char *) newname->name + libname_len - 1;
Since newname->name points to new->l_libname->name.
This leads to pldd to an infinite call at:
elf/pldd-xx.c
203 again:
204 while (1)
205 {
206 ssize_t n = pread64 (memfd, tmpbuf.data, tmpbuf.length, name_offset);
228 /* Try the l_libname element. */
229 struct E(libname_list) ln;
230 if (pread64 (memfd, &ln, sizeof (ln), m.l_libname) == sizeof (ln))
231 {
232 name_offset = ln.name;
233 goto again;
234 }
Since the value at ln.name (l_libname->name) will be the same as previously
read. The straightforward fix is just avoid the check and read the new list
entry.
I checked also against binaries issues with old loaders with fix for BZ#387,
and pldd could dump the shared objects.
Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu, and
powerpc64le-linux-gnu.
[BZ #18035]
* elf/Makefile (tests-container): Add tst-pldd.
* elf/pldd-xx.c: Use _Static_assert in of pldd_assert.
(E(find_maps)): Avoid use alloca, use default read file operations
instead of explicit LFS names, and fix infinite loop.
* elf/pldd.c: Explicit set _FILE_OFFSET_BITS, cleanup headers.
(get_process_info): Use _Static_assert instead of assert, use default
directory operations instead of explicit LFS names, and free some
leadek pointers.
* elf/tst-pldd.c: New file.
2019-04-12 05:12:00 +08:00
|
|
|
E(find_maps) (const char *exe, int memfd, pid_t pid, void *auxv,
|
|
|
|
size_t auxv_size)
|
2011-06-09 19:06:21 +08:00
|
|
|
{
|
|
|
|
EW(Addr) phdr = 0;
|
|
|
|
unsigned int phnum = 0;
|
|
|
|
unsigned int phent = 0;
|
|
|
|
|
|
|
|
EW(auxv_t) *auxvXX = (EW(auxv_t) *) auxv;
|
|
|
|
for (int i = 0; i < auxv_size / sizeof (EW(auxv_t)); ++i)
|
|
|
|
switch (auxvXX[i].a_type)
|
|
|
|
{
|
|
|
|
case AT_PHDR:
|
|
|
|
phdr = auxvXX[i].a_un.a_val;
|
|
|
|
break;
|
|
|
|
case AT_PHNUM:
|
|
|
|
phnum = auxvXX[i].a_un.a_val;
|
|
|
|
break;
|
|
|
|
case AT_PHENT:
|
|
|
|
phent = auxvXX[i].a_un.a_val;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (phdr == 0 || phnum == 0 || phent == 0)
|
|
|
|
error (EXIT_FAILURE, 0, gettext ("cannot find program header of process"));
|
|
|
|
|
elf: Fix pldd (BZ#18035)
Since 9182aa67994 (Fix vDSO l_name for GDB's, BZ#387) the initial link_map
for executable itself and loader will have both l_name and l_libname->name
holding the same value due:
elf/dl-object.c
95 new->l_name = *realname ? realname : (char *) newname->name + libname_len - 1;
Since newname->name points to new->l_libname->name.
This leads to pldd to an infinite call at:
elf/pldd-xx.c
203 again:
204 while (1)
205 {
206 ssize_t n = pread64 (memfd, tmpbuf.data, tmpbuf.length, name_offset);
228 /* Try the l_libname element. */
229 struct E(libname_list) ln;
230 if (pread64 (memfd, &ln, sizeof (ln), m.l_libname) == sizeof (ln))
231 {
232 name_offset = ln.name;
233 goto again;
234 }
Since the value at ln.name (l_libname->name) will be the same as previously
read. The straightforward fix is just avoid the check and read the new list
entry.
I checked also against binaries issues with old loaders with fix for BZ#387,
and pldd could dump the shared objects.
Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu, and
powerpc64le-linux-gnu.
[BZ #18035]
* elf/Makefile (tests-container): Add tst-pldd.
* elf/pldd-xx.c: Use _Static_assert in of pldd_assert.
(E(find_maps)): Avoid use alloca, use default read file operations
instead of explicit LFS names, and fix infinite loop.
* elf/pldd.c: Explicit set _FILE_OFFSET_BITS, cleanup headers.
(get_process_info): Use _Static_assert instead of assert, use default
directory operations instead of explicit LFS names, and free some
leadek pointers.
* elf/tst-pldd.c: New file.
2019-04-12 05:12:00 +08:00
|
|
|
EW(Phdr) *p = xmalloc (phnum * phent);
|
|
|
|
if (pread (memfd, p, phnum * phent, phdr) != phnum * phent)
|
|
|
|
error (EXIT_FAILURE, 0, gettext ("cannot read program header"));
|
2011-06-09 19:06:21 +08:00
|
|
|
|
|
|
|
/* Determine the load offset. We need this for interpreting the
|
|
|
|
other program header entries so we do this in a separate loop.
|
|
|
|
Fortunately it is the first time unless someone does something
|
|
|
|
stupid when linking the application. */
|
|
|
|
EW(Addr) offset = 0;
|
|
|
|
for (unsigned int i = 0; i < phnum; ++i)
|
|
|
|
if (p[i].p_type == PT_PHDR)
|
|
|
|
{
|
|
|
|
offset = phdr - p[i].p_vaddr;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
EW(Addr) list = 0;
|
|
|
|
char *interp = NULL;
|
|
|
|
for (unsigned int i = 0; i < phnum; ++i)
|
|
|
|
if (p[i].p_type == PT_DYNAMIC)
|
|
|
|
{
|
|
|
|
EW(Dyn) *dyn = xmalloc (p[i].p_filesz);
|
elf: Fix pldd (BZ#18035)
Since 9182aa67994 (Fix vDSO l_name for GDB's, BZ#387) the initial link_map
for executable itself and loader will have both l_name and l_libname->name
holding the same value due:
elf/dl-object.c
95 new->l_name = *realname ? realname : (char *) newname->name + libname_len - 1;
Since newname->name points to new->l_libname->name.
This leads to pldd to an infinite call at:
elf/pldd-xx.c
203 again:
204 while (1)
205 {
206 ssize_t n = pread64 (memfd, tmpbuf.data, tmpbuf.length, name_offset);
228 /* Try the l_libname element. */
229 struct E(libname_list) ln;
230 if (pread64 (memfd, &ln, sizeof (ln), m.l_libname) == sizeof (ln))
231 {
232 name_offset = ln.name;
233 goto again;
234 }
Since the value at ln.name (l_libname->name) will be the same as previously
read. The straightforward fix is just avoid the check and read the new list
entry.
I checked also against binaries issues with old loaders with fix for BZ#387,
and pldd could dump the shared objects.
Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu, and
powerpc64le-linux-gnu.
[BZ #18035]
* elf/Makefile (tests-container): Add tst-pldd.
* elf/pldd-xx.c: Use _Static_assert in of pldd_assert.
(E(find_maps)): Avoid use alloca, use default read file operations
instead of explicit LFS names, and fix infinite loop.
* elf/pldd.c: Explicit set _FILE_OFFSET_BITS, cleanup headers.
(get_process_info): Use _Static_assert instead of assert, use default
directory operations instead of explicit LFS names, and free some
leadek pointers.
* elf/tst-pldd.c: New file.
2019-04-12 05:12:00 +08:00
|
|
|
if (pread (memfd, dyn, p[i].p_filesz, offset + p[i].p_vaddr)
|
2011-06-09 19:06:21 +08:00
|
|
|
!= p[i].p_filesz)
|
elf: Fix pldd (BZ#18035)
Since 9182aa67994 (Fix vDSO l_name for GDB's, BZ#387) the initial link_map
for executable itself and loader will have both l_name and l_libname->name
holding the same value due:
elf/dl-object.c
95 new->l_name = *realname ? realname : (char *) newname->name + libname_len - 1;
Since newname->name points to new->l_libname->name.
This leads to pldd to an infinite call at:
elf/pldd-xx.c
203 again:
204 while (1)
205 {
206 ssize_t n = pread64 (memfd, tmpbuf.data, tmpbuf.length, name_offset);
228 /* Try the l_libname element. */
229 struct E(libname_list) ln;
230 if (pread64 (memfd, &ln, sizeof (ln), m.l_libname) == sizeof (ln))
231 {
232 name_offset = ln.name;
233 goto again;
234 }
Since the value at ln.name (l_libname->name) will be the same as previously
read. The straightforward fix is just avoid the check and read the new list
entry.
I checked also against binaries issues with old loaders with fix for BZ#387,
and pldd could dump the shared objects.
Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu, and
powerpc64le-linux-gnu.
[BZ #18035]
* elf/Makefile (tests-container): Add tst-pldd.
* elf/pldd-xx.c: Use _Static_assert in of pldd_assert.
(E(find_maps)): Avoid use alloca, use default read file operations
instead of explicit LFS names, and fix infinite loop.
* elf/pldd.c: Explicit set _FILE_OFFSET_BITS, cleanup headers.
(get_process_info): Use _Static_assert instead of assert, use default
directory operations instead of explicit LFS names, and free some
leadek pointers.
* elf/tst-pldd.c: New file.
2019-04-12 05:12:00 +08:00
|
|
|
error (EXIT_FAILURE, 0, gettext ("cannot read dynamic section"));
|
2011-06-09 19:06:21 +08:00
|
|
|
|
2022-01-30 02:56:45 +08:00
|
|
|
/* Search for the struct r_debug. */
|
2011-06-09 19:06:21 +08:00
|
|
|
for (unsigned int j = 0; j < p[i].p_filesz / sizeof (EW(Dyn)); ++j)
|
2022-01-30 02:56:45 +08:00
|
|
|
{
|
|
|
|
EW(Addr) off = offset + p[i].p_vaddr + sizeof (EW(Dyn)) * j;
|
|
|
|
off = E(r_debug_offset) (&dyn[j], memfd, off);
|
|
|
|
if (off != 0)
|
|
|
|
{
|
|
|
|
struct E(r_debug) r;
|
|
|
|
if (pread (memfd, &r, sizeof (r), off)
|
|
|
|
!= sizeof (r))
|
|
|
|
error (EXIT_FAILURE, 0, gettext ("cannot read r_debug"));
|
|
|
|
|
|
|
|
if (r.r_map != 0)
|
|
|
|
{
|
|
|
|
list = r.r_map;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-06-09 19:06:21 +08:00
|
|
|
|
|
|
|
free (dyn);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if (p[i].p_type == PT_INTERP)
|
|
|
|
{
|
elf: Fix pldd (BZ#18035)
Since 9182aa67994 (Fix vDSO l_name for GDB's, BZ#387) the initial link_map
for executable itself and loader will have both l_name and l_libname->name
holding the same value due:
elf/dl-object.c
95 new->l_name = *realname ? realname : (char *) newname->name + libname_len - 1;
Since newname->name points to new->l_libname->name.
This leads to pldd to an infinite call at:
elf/pldd-xx.c
203 again:
204 while (1)
205 {
206 ssize_t n = pread64 (memfd, tmpbuf.data, tmpbuf.length, name_offset);
228 /* Try the l_libname element. */
229 struct E(libname_list) ln;
230 if (pread64 (memfd, &ln, sizeof (ln), m.l_libname) == sizeof (ln))
231 {
232 name_offset = ln.name;
233 goto again;
234 }
Since the value at ln.name (l_libname->name) will be the same as previously
read. The straightforward fix is just avoid the check and read the new list
entry.
I checked also against binaries issues with old loaders with fix for BZ#387,
and pldd could dump the shared objects.
Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu, and
powerpc64le-linux-gnu.
[BZ #18035]
* elf/Makefile (tests-container): Add tst-pldd.
* elf/pldd-xx.c: Use _Static_assert in of pldd_assert.
(E(find_maps)): Avoid use alloca, use default read file operations
instead of explicit LFS names, and fix infinite loop.
* elf/pldd.c: Explicit set _FILE_OFFSET_BITS, cleanup headers.
(get_process_info): Use _Static_assert instead of assert, use default
directory operations instead of explicit LFS names, and free some
leadek pointers.
* elf/tst-pldd.c: New file.
2019-04-12 05:12:00 +08:00
|
|
|
interp = xmalloc (p[i].p_filesz);
|
|
|
|
if (pread (memfd, interp, p[i].p_filesz, offset + p[i].p_vaddr)
|
2011-06-09 19:06:21 +08:00
|
|
|
!= p[i].p_filesz)
|
elf: Fix pldd (BZ#18035)
Since 9182aa67994 (Fix vDSO l_name for GDB's, BZ#387) the initial link_map
for executable itself and loader will have both l_name and l_libname->name
holding the same value due:
elf/dl-object.c
95 new->l_name = *realname ? realname : (char *) newname->name + libname_len - 1;
Since newname->name points to new->l_libname->name.
This leads to pldd to an infinite call at:
elf/pldd-xx.c
203 again:
204 while (1)
205 {
206 ssize_t n = pread64 (memfd, tmpbuf.data, tmpbuf.length, name_offset);
228 /* Try the l_libname element. */
229 struct E(libname_list) ln;
230 if (pread64 (memfd, &ln, sizeof (ln), m.l_libname) == sizeof (ln))
231 {
232 name_offset = ln.name;
233 goto again;
234 }
Since the value at ln.name (l_libname->name) will be the same as previously
read. The straightforward fix is just avoid the check and read the new list
entry.
I checked also against binaries issues with old loaders with fix for BZ#387,
and pldd could dump the shared objects.
Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu, and
powerpc64le-linux-gnu.
[BZ #18035]
* elf/Makefile (tests-container): Add tst-pldd.
* elf/pldd-xx.c: Use _Static_assert in of pldd_assert.
(E(find_maps)): Avoid use alloca, use default read file operations
instead of explicit LFS names, and fix infinite loop.
* elf/pldd.c: Explicit set _FILE_OFFSET_BITS, cleanup headers.
(get_process_info): Use _Static_assert instead of assert, use default
directory operations instead of explicit LFS names, and free some
leadek pointers.
* elf/tst-pldd.c: New file.
2019-04-12 05:12:00 +08:00
|
|
|
error (EXIT_FAILURE, 0, gettext ("cannot read program interpreter"));
|
2011-06-09 19:06:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (list == 0)
|
|
|
|
{
|
|
|
|
if (interp == NULL)
|
|
|
|
{
|
|
|
|
// XXX check whether the executable itself is the loader
|
elf: Fix pldd (BZ#18035)
Since 9182aa67994 (Fix vDSO l_name for GDB's, BZ#387) the initial link_map
for executable itself and loader will have both l_name and l_libname->name
holding the same value due:
elf/dl-object.c
95 new->l_name = *realname ? realname : (char *) newname->name + libname_len - 1;
Since newname->name points to new->l_libname->name.
This leads to pldd to an infinite call at:
elf/pldd-xx.c
203 again:
204 while (1)
205 {
206 ssize_t n = pread64 (memfd, tmpbuf.data, tmpbuf.length, name_offset);
228 /* Try the l_libname element. */
229 struct E(libname_list) ln;
230 if (pread64 (memfd, &ln, sizeof (ln), m.l_libname) == sizeof (ln))
231 {
232 name_offset = ln.name;
233 goto again;
234 }
Since the value at ln.name (l_libname->name) will be the same as previously
read. The straightforward fix is just avoid the check and read the new list
entry.
I checked also against binaries issues with old loaders with fix for BZ#387,
and pldd could dump the shared objects.
Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu, and
powerpc64le-linux-gnu.
[BZ #18035]
* elf/Makefile (tests-container): Add tst-pldd.
* elf/pldd-xx.c: Use _Static_assert in of pldd_assert.
(E(find_maps)): Avoid use alloca, use default read file operations
instead of explicit LFS names, and fix infinite loop.
* elf/pldd.c: Explicit set _FILE_OFFSET_BITS, cleanup headers.
(get_process_info): Use _Static_assert instead of assert, use default
directory operations instead of explicit LFS names, and free some
leadek pointers.
* elf/tst-pldd.c: New file.
2019-04-12 05:12:00 +08:00
|
|
|
exit (EXIT_FAILURE);
|
2011-06-09 19:06:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// XXX perhaps try finding ld.so and _r_debug in it
|
elf: Fix pldd (BZ#18035)
Since 9182aa67994 (Fix vDSO l_name for GDB's, BZ#387) the initial link_map
for executable itself and loader will have both l_name and l_libname->name
holding the same value due:
elf/dl-object.c
95 new->l_name = *realname ? realname : (char *) newname->name + libname_len - 1;
Since newname->name points to new->l_libname->name.
This leads to pldd to an infinite call at:
elf/pldd-xx.c
203 again:
204 while (1)
205 {
206 ssize_t n = pread64 (memfd, tmpbuf.data, tmpbuf.length, name_offset);
228 /* Try the l_libname element. */
229 struct E(libname_list) ln;
230 if (pread64 (memfd, &ln, sizeof (ln), m.l_libname) == sizeof (ln))
231 {
232 name_offset = ln.name;
233 goto again;
234 }
Since the value at ln.name (l_libname->name) will be the same as previously
read. The straightforward fix is just avoid the check and read the new list
entry.
I checked also against binaries issues with old loaders with fix for BZ#387,
and pldd could dump the shared objects.
Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu, and
powerpc64le-linux-gnu.
[BZ #18035]
* elf/Makefile (tests-container): Add tst-pldd.
* elf/pldd-xx.c: Use _Static_assert in of pldd_assert.
(E(find_maps)): Avoid use alloca, use default read file operations
instead of explicit LFS names, and fix infinite loop.
* elf/pldd.c: Explicit set _FILE_OFFSET_BITS, cleanup headers.
(get_process_info): Use _Static_assert instead of assert, use default
directory operations instead of explicit LFS names, and free some
leadek pointers.
* elf/tst-pldd.c: New file.
2019-04-12 05:12:00 +08:00
|
|
|
exit (EXIT_FAILURE);
|
2011-06-09 19:06:21 +08:00
|
|
|
}
|
|
|
|
|
elf: Fix pldd (BZ#18035)
Since 9182aa67994 (Fix vDSO l_name for GDB's, BZ#387) the initial link_map
for executable itself and loader will have both l_name and l_libname->name
holding the same value due:
elf/dl-object.c
95 new->l_name = *realname ? realname : (char *) newname->name + libname_len - 1;
Since newname->name points to new->l_libname->name.
This leads to pldd to an infinite call at:
elf/pldd-xx.c
203 again:
204 while (1)
205 {
206 ssize_t n = pread64 (memfd, tmpbuf.data, tmpbuf.length, name_offset);
228 /* Try the l_libname element. */
229 struct E(libname_list) ln;
230 if (pread64 (memfd, &ln, sizeof (ln), m.l_libname) == sizeof (ln))
231 {
232 name_offset = ln.name;
233 goto again;
234 }
Since the value at ln.name (l_libname->name) will be the same as previously
read. The straightforward fix is just avoid the check and read the new list
entry.
I checked also against binaries issues with old loaders with fix for BZ#387,
and pldd could dump the shared objects.
Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu, and
powerpc64le-linux-gnu.
[BZ #18035]
* elf/Makefile (tests-container): Add tst-pldd.
* elf/pldd-xx.c: Use _Static_assert in of pldd_assert.
(E(find_maps)): Avoid use alloca, use default read file operations
instead of explicit LFS names, and fix infinite loop.
* elf/pldd.c: Explicit set _FILE_OFFSET_BITS, cleanup headers.
(get_process_info): Use _Static_assert instead of assert, use default
directory operations instead of explicit LFS names, and free some
leadek pointers.
* elf/tst-pldd.c: New file.
2019-04-12 05:12:00 +08:00
|
|
|
free (p);
|
|
|
|
free (interp);
|
|
|
|
|
2011-06-09 19:06:21 +08:00
|
|
|
/* Print the PID and program name first. */
|
|
|
|
printf ("%lu:\t%s\n", (unsigned long int) pid, exe);
|
|
|
|
|
|
|
|
/* Iterate over the list of objects and print the information. */
|
2015-04-09 01:11:21 +08:00
|
|
|
struct scratch_buffer tmpbuf;
|
|
|
|
scratch_buffer_init (&tmpbuf);
|
|
|
|
int status = 0;
|
2011-06-09 19:06:21 +08:00
|
|
|
do
|
|
|
|
{
|
|
|
|
struct E(link_map) m;
|
elf: Fix pldd (BZ#18035)
Since 9182aa67994 (Fix vDSO l_name for GDB's, BZ#387) the initial link_map
for executable itself and loader will have both l_name and l_libname->name
holding the same value due:
elf/dl-object.c
95 new->l_name = *realname ? realname : (char *) newname->name + libname_len - 1;
Since newname->name points to new->l_libname->name.
This leads to pldd to an infinite call at:
elf/pldd-xx.c
203 again:
204 while (1)
205 {
206 ssize_t n = pread64 (memfd, tmpbuf.data, tmpbuf.length, name_offset);
228 /* Try the l_libname element. */
229 struct E(libname_list) ln;
230 if (pread64 (memfd, &ln, sizeof (ln), m.l_libname) == sizeof (ln))
231 {
232 name_offset = ln.name;
233 goto again;
234 }
Since the value at ln.name (l_libname->name) will be the same as previously
read. The straightforward fix is just avoid the check and read the new list
entry.
I checked also against binaries issues with old loaders with fix for BZ#387,
and pldd could dump the shared objects.
Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu, and
powerpc64le-linux-gnu.
[BZ #18035]
* elf/Makefile (tests-container): Add tst-pldd.
* elf/pldd-xx.c: Use _Static_assert in of pldd_assert.
(E(find_maps)): Avoid use alloca, use default read file operations
instead of explicit LFS names, and fix infinite loop.
* elf/pldd.c: Explicit set _FILE_OFFSET_BITS, cleanup headers.
(get_process_info): Use _Static_assert instead of assert, use default
directory operations instead of explicit LFS names, and free some
leadek pointers.
* elf/tst-pldd.c: New file.
2019-04-12 05:12:00 +08:00
|
|
|
if (pread (memfd, &m, sizeof (m), list) != sizeof (m))
|
|
|
|
error (EXIT_FAILURE, 0, gettext ("cannot read link map"));
|
2011-06-09 19:06:21 +08:00
|
|
|
|
|
|
|
EW(Addr) name_offset = m.l_name;
|
|
|
|
while (1)
|
|
|
|
{
|
elf: Fix pldd (BZ#18035)
Since 9182aa67994 (Fix vDSO l_name for GDB's, BZ#387) the initial link_map
for executable itself and loader will have both l_name and l_libname->name
holding the same value due:
elf/dl-object.c
95 new->l_name = *realname ? realname : (char *) newname->name + libname_len - 1;
Since newname->name points to new->l_libname->name.
This leads to pldd to an infinite call at:
elf/pldd-xx.c
203 again:
204 while (1)
205 {
206 ssize_t n = pread64 (memfd, tmpbuf.data, tmpbuf.length, name_offset);
228 /* Try the l_libname element. */
229 struct E(libname_list) ln;
230 if (pread64 (memfd, &ln, sizeof (ln), m.l_libname) == sizeof (ln))
231 {
232 name_offset = ln.name;
233 goto again;
234 }
Since the value at ln.name (l_libname->name) will be the same as previously
read. The straightforward fix is just avoid the check and read the new list
entry.
I checked also against binaries issues with old loaders with fix for BZ#387,
and pldd could dump the shared objects.
Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu, and
powerpc64le-linux-gnu.
[BZ #18035]
* elf/Makefile (tests-container): Add tst-pldd.
* elf/pldd-xx.c: Use _Static_assert in of pldd_assert.
(E(find_maps)): Avoid use alloca, use default read file operations
instead of explicit LFS names, and fix infinite loop.
* elf/pldd.c: Explicit set _FILE_OFFSET_BITS, cleanup headers.
(get_process_info): Use _Static_assert instead of assert, use default
directory operations instead of explicit LFS names, and free some
leadek pointers.
* elf/tst-pldd.c: New file.
2019-04-12 05:12:00 +08:00
|
|
|
ssize_t n = pread (memfd, tmpbuf.data, tmpbuf.length, name_offset);
|
2011-06-09 19:06:21 +08:00
|
|
|
if (n == -1)
|
elf: Fix pldd (BZ#18035)
Since 9182aa67994 (Fix vDSO l_name for GDB's, BZ#387) the initial link_map
for executable itself and loader will have both l_name and l_libname->name
holding the same value due:
elf/dl-object.c
95 new->l_name = *realname ? realname : (char *) newname->name + libname_len - 1;
Since newname->name points to new->l_libname->name.
This leads to pldd to an infinite call at:
elf/pldd-xx.c
203 again:
204 while (1)
205 {
206 ssize_t n = pread64 (memfd, tmpbuf.data, tmpbuf.length, name_offset);
228 /* Try the l_libname element. */
229 struct E(libname_list) ln;
230 if (pread64 (memfd, &ln, sizeof (ln), m.l_libname) == sizeof (ln))
231 {
232 name_offset = ln.name;
233 goto again;
234 }
Since the value at ln.name (l_libname->name) will be the same as previously
read. The straightforward fix is just avoid the check and read the new list
entry.
I checked also against binaries issues with old loaders with fix for BZ#387,
and pldd could dump the shared objects.
Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu, and
powerpc64le-linux-gnu.
[BZ #18035]
* elf/Makefile (tests-container): Add tst-pldd.
* elf/pldd-xx.c: Use _Static_assert in of pldd_assert.
(E(find_maps)): Avoid use alloca, use default read file operations
instead of explicit LFS names, and fix infinite loop.
* elf/pldd.c: Explicit set _FILE_OFFSET_BITS, cleanup headers.
(get_process_info): Use _Static_assert instead of assert, use default
directory operations instead of explicit LFS names, and free some
leadek pointers.
* elf/tst-pldd.c: New file.
2019-04-12 05:12:00 +08:00
|
|
|
error (EXIT_FAILURE, 0, gettext ("cannot read object name"));
|
2011-06-09 19:06:21 +08:00
|
|
|
|
2015-04-09 01:11:21 +08:00
|
|
|
if (memchr (tmpbuf.data, '\0', n) != NULL)
|
2011-06-09 19:06:21 +08:00
|
|
|
break;
|
|
|
|
|
2015-04-09 01:11:21 +08:00
|
|
|
if (!scratch_buffer_grow (&tmpbuf))
|
elf: Fix pldd (BZ#18035)
Since 9182aa67994 (Fix vDSO l_name for GDB's, BZ#387) the initial link_map
for executable itself and loader will have both l_name and l_libname->name
holding the same value due:
elf/dl-object.c
95 new->l_name = *realname ? realname : (char *) newname->name + libname_len - 1;
Since newname->name points to new->l_libname->name.
This leads to pldd to an infinite call at:
elf/pldd-xx.c
203 again:
204 while (1)
205 {
206 ssize_t n = pread64 (memfd, tmpbuf.data, tmpbuf.length, name_offset);
228 /* Try the l_libname element. */
229 struct E(libname_list) ln;
230 if (pread64 (memfd, &ln, sizeof (ln), m.l_libname) == sizeof (ln))
231 {
232 name_offset = ln.name;
233 goto again;
234 }
Since the value at ln.name (l_libname->name) will be the same as previously
read. The straightforward fix is just avoid the check and read the new list
entry.
I checked also against binaries issues with old loaders with fix for BZ#387,
and pldd could dump the shared objects.
Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu, and
powerpc64le-linux-gnu.
[BZ #18035]
* elf/Makefile (tests-container): Add tst-pldd.
* elf/pldd-xx.c: Use _Static_assert in of pldd_assert.
(E(find_maps)): Avoid use alloca, use default read file operations
instead of explicit LFS names, and fix infinite loop.
* elf/pldd.c: Explicit set _FILE_OFFSET_BITS, cleanup headers.
(get_process_info): Use _Static_assert instead of assert, use default
directory operations instead of explicit LFS names, and free some
leadek pointers.
* elf/tst-pldd.c: New file.
2019-04-12 05:12:00 +08:00
|
|
|
error (EXIT_FAILURE, 0,
|
|
|
|
gettext ("cannot allocate buffer for object name"));
|
2011-06-09 19:06:21 +08:00
|
|
|
}
|
|
|
|
|
elf: Fix pldd (BZ#18035)
Since 9182aa67994 (Fix vDSO l_name for GDB's, BZ#387) the initial link_map
for executable itself and loader will have both l_name and l_libname->name
holding the same value due:
elf/dl-object.c
95 new->l_name = *realname ? realname : (char *) newname->name + libname_len - 1;
Since newname->name points to new->l_libname->name.
This leads to pldd to an infinite call at:
elf/pldd-xx.c
203 again:
204 while (1)
205 {
206 ssize_t n = pread64 (memfd, tmpbuf.data, tmpbuf.length, name_offset);
228 /* Try the l_libname element. */
229 struct E(libname_list) ln;
230 if (pread64 (memfd, &ln, sizeof (ln), m.l_libname) == sizeof (ln))
231 {
232 name_offset = ln.name;
233 goto again;
234 }
Since the value at ln.name (l_libname->name) will be the same as previously
read. The straightforward fix is just avoid the check and read the new list
entry.
I checked also against binaries issues with old loaders with fix for BZ#387,
and pldd could dump the shared objects.
Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu, and
powerpc64le-linux-gnu.
[BZ #18035]
* elf/Makefile (tests-container): Add tst-pldd.
* elf/pldd-xx.c: Use _Static_assert in of pldd_assert.
(E(find_maps)): Avoid use alloca, use default read file operations
instead of explicit LFS names, and fix infinite loop.
* elf/pldd.c: Explicit set _FILE_OFFSET_BITS, cleanup headers.
(get_process_info): Use _Static_assert instead of assert, use default
directory operations instead of explicit LFS names, and free some
leadek pointers.
* elf/tst-pldd.c: New file.
2019-04-12 05:12:00 +08:00
|
|
|
/* The m.l_name and m.l_libname.name for loader linkmap points to same
|
|
|
|
values (since BZ#387 fix). Trying to use l_libname name as the
|
|
|
|
shared object name might lead to an infinite loop (BZ#18035). */
|
2011-06-09 19:06:21 +08:00
|
|
|
|
|
|
|
/* Skip over the executable. */
|
2015-04-09 01:11:21 +08:00
|
|
|
if (((char *)tmpbuf.data)[0] != '\0')
|
|
|
|
printf ("%s\n", (char *)tmpbuf.data);
|
2011-06-09 19:06:21 +08:00
|
|
|
|
|
|
|
list = m.l_next;
|
|
|
|
}
|
|
|
|
while (list != 0);
|
|
|
|
|
2015-04-09 01:11:21 +08:00
|
|
|
scratch_buffer_free (&tmpbuf);
|
|
|
|
return status;
|
2011-06-09 19:06:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#undef CLASS
|