public inbox for libc-stable@sourceware.org
 help / color / mirror / Atom feed
From: Carlos O'Donell <carlos@redhat.com>
To: libc-stable@sourceware.org
Cc: Adhemerval Zanella <adhemerval.zanella@linaro.org>,
	Florian Weimer <fweimer@redhat.com>
Subject: [PATCH 18/27] elf: Issue audit la_objopen for vDSO
Date: Tue, 12 Apr 2022 14:41:56 -0400	[thread overview]
Message-ID: <20220412184205.3343677-19-carlos@redhat.com> (raw)
In-Reply-To: <20220412184205.3343677-1-carlos@redhat.com>

From: Adhemerval Zanella <adhemerval.zanella@linaro.org>

The vDSO is is listed in the link_map chain, but is never the subject of
an la_objopen call.  A new internal flag __RTLD_VDSO is added that
acts as __RTLD_OPENEXEC to allocate the required 'struct auditstate'
extra space for the 'struct link_map'.

The return value from the callback is currently ignored, since there
is no PLT call involved by glibc when using the vDSO, neither the vDSO
are exported directly.

Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu.

Reviewed-by: Florian Weimer <fweimer@redhat.com>
(cherry picked from commit f0e23d34a7bdf6b90fba954ee741419171ac41b2)

Resolved conflicts:
	elf/Makefile
---
 elf/Makefile         |   5 ++
 elf/dl-object.c      |  17 +++---
 elf/rtld.c           |   6 +++
 elf/setup-vdso.h     |   2 +-
 elf/tst-audit22.c    | 124 +++++++++++++++++++++++++++++++++++++++++++
 elf/tst-auditmod22.c |  51 ++++++++++++++++++
 include/dlfcn.h      |   2 +
 7 files changed, 199 insertions(+), 8 deletions(-)
 create mode 100644 elf/tst-audit22.c
 create mode 100644 elf/tst-auditmod22.c

diff --git a/elf/Makefile b/elf/Makefile
index 733b4c658d..b3ccd21872 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -355,6 +355,7 @@ tests += \
   tst-audit17 \
   tst-audit18 \
   tst-audit19b \
+  tst-audit22 \
   tst-auditmany \
   tst-auxobj \
   tst-auxobj-dlopen \
@@ -633,6 +634,7 @@ modules-names = \
   tst-auditmod18 \
   tst-auditmod19a \
   tst-auditmod19b \
+  tst-auditmod22 \
   tst-auxvalmod \
   tst-big-note-lib \
   tst-deep1mod1 \
@@ -1991,6 +1993,9 @@ $(objpfx)tst-audit19b.out: $(objpfx)tst-auditmod19b.so
 $(objpfx)tst-audit19b: $(objpfx)tst-audit19bmod.so
 tst-audit19b-ARGS = -- $(host-test-program-cmd)
 
+$(objpfx)tst-audit22.out: $(objpfx)tst-auditmod22.so
+tst-audit22-ARGS = -- $(host-test-program-cmd)
+
 # tst-sonamemove links against an older implementation of the library.
 LDFLAGS-tst-sonamemove-linkmod1.so = \
   -Wl,--version-script=tst-sonamemove-linkmod1.map \
diff --git a/elf/dl-object.c b/elf/dl-object.c
index 1875599eb2..dee49a32d4 100644
--- a/elf/dl-object.c
+++ b/elf/dl-object.c
@@ -59,16 +59,19 @@ _dl_new_object (char *realname, const char *libname, int type,
 {
 #ifdef SHARED
   unsigned int naudit;
-  if (__glibc_unlikely ((mode & __RTLD_OPENEXEC) != 0))
+  if (__glibc_unlikely ((mode & (__RTLD_OPENEXEC | __RTLD_VDSO)) != 0))
     {
-      assert (type == lt_executable);
-      assert (nsid == LM_ID_BASE);
+      if (mode & __RTLD_OPENEXEC)
+	{
+	  assert (type == lt_executable);
+	  assert (nsid == LM_ID_BASE);
 
-      /* Ignore the specified libname for the main executable.  It is
-	 only known with an explicit loader invocation.  */
-      libname = "";
+	  /* Ignore the specified libname for the main executable.  It is
+	     only known with an explicit loader invocation.  */
+	  libname = "";
+	}
 
-      /* We create the map for the executable before we know whether
+      /* We create the map for the executable and vDSO before we know whether
 	 we have auditing libraries and if yes, how many.  Assume the
 	 worst.  */
       naudit = DL_NNS;
diff --git a/elf/rtld.c b/elf/rtld.c
index 5e5d3001a4..83c12f8b8b 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -1885,6 +1885,12 @@ dl_main (const ElfW(Phdr) *phdr,
       assert (i == npreloads);
     }
 
+#ifdef NEED_DL_SYSINFO_DSO
+  /* Now that the audit modules are opened, call la_objopen for the vDSO.  */
+  if (GLRO(dl_sysinfo_map) != NULL)
+    _dl_audit_objopen (GLRO(dl_sysinfo_map), LM_ID_BASE);
+#endif
+
   /* Load all the libraries specified by DT_NEEDED entries.  If LD_PRELOAD
      specified some libraries to load, these are inserted before the actual
      dependencies in the executable's searchlist for symbol resolution.  */
diff --git a/elf/setup-vdso.h b/elf/setup-vdso.h
index 3f20578046..2b013d974a 100644
--- a/elf/setup-vdso.h
+++ b/elf/setup-vdso.h
@@ -30,7 +30,7 @@ setup_vdso (struct link_map *main_map __attribute__ ((unused)),
      We just want our data structures to describe it as if we had just
      mapped and relocated it normally.  */
   struct link_map *l = _dl_new_object ((char *) "", "", lt_library, NULL,
-				       0, LM_ID_BASE);
+				       __RTLD_VDSO, LM_ID_BASE);
   if (__glibc_likely (l != NULL))
     {
       l->l_phdr = ((const void *) GLRO(dl_sysinfo_dso)
diff --git a/elf/tst-audit22.c b/elf/tst-audit22.c
new file mode 100644
index 0000000000..18fd22a760
--- /dev/null
+++ b/elf/tst-audit22.c
@@ -0,0 +1,124 @@
+/* Check DTAUDIT and vDSO interaction.
+   Copyright (C) 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <getopt.h>
+#include <limits.h>
+#include <inttypes.h>
+#include <string.h>
+#include <stdlib.h>
+#include <support/capture_subprocess.h>
+#include <support/check.h>
+#include <support/xstdio.h>
+#include <support/support.h>
+#include <sys/auxv.h>
+
+static int restart;
+#define CMDLINE_OPTIONS \
+  { "restart", no_argument, &restart, 1 },
+
+static uintptr_t vdso_addr;
+
+static int
+handle_restart (void)
+{
+  fprintf (stderr, "vdso: %p\n", (void*) vdso_addr);
+  return 0;
+}
+
+static uintptr_t
+parse_address (const char *str)
+{
+  void *r;
+  TEST_COMPARE (sscanf (str, "%p\n", &r), 1);
+  return (uintptr_t) r;
+}
+
+static inline bool
+startswith (const char *str, const char *pre)
+{
+  size_t lenpre = strlen (pre);
+  size_t lenstr = strlen (str);
+  return lenstr >= lenpre && memcmp (pre, str, lenpre) == 0;
+}
+
+static int
+do_test (int argc, char *argv[])
+{
+  vdso_addr = getauxval (AT_SYSINFO_EHDR);
+  if (vdso_addr == 0)
+    FAIL_UNSUPPORTED ("getauxval (AT_SYSINFO_EHDR) returned 0");
+
+  /* We must have either:
+     - One our fource parameters left if called initially:
+       + path to ld.so         optional
+       + "--library-path"      optional
+       + the library path      optional
+       + the application name  */
+  if (restart)
+    return handle_restart ();
+
+  char *spargv[9];
+  int i = 0;
+  for (; i < argc - 1; i++)
+    spargv[i] = argv[i + 1];
+  spargv[i++] = (char *) "--direct";
+  spargv[i++] = (char *) "--restart";
+  spargv[i] = NULL;
+
+  setenv ("LD_AUDIT", "tst-auditmod22.so", 0);
+  struct support_capture_subprocess result
+    = support_capture_subprogram (spargv[0], spargv);
+  support_capture_subprocess_check (&result, "tst-audit22", 0, sc_allow_stderr);
+
+  /* The respawned process should always print the vDSO address (otherwise it
+     will fails as unsupported).  However, on some architectures the audit
+     module might see the vDSO with l_addr being 0, meaning a fixed mapping
+     (linux-gate.so).  In this case we don't check its value against
+     AT_SYSINFO_EHDR one.  */
+  uintptr_t vdso_process = 0;
+  bool vdso_audit_found = false;
+  uintptr_t vdso_audit = 0;
+
+  FILE *out = fmemopen (result.err.buffer, result.err.length, "r");
+  TEST_VERIFY (out != NULL);
+  char *buffer = NULL;
+  size_t buffer_length = 0;
+  while (xgetline (&buffer, &buffer_length, out))
+    {
+      if (startswith (buffer, "vdso: "))
+	vdso_process = parse_address (buffer + strlen ("vdso: "));
+      else if (startswith (buffer, "vdso found: "))
+	{
+	  vdso_audit = parse_address (buffer + strlen ("vdso found: "));
+          vdso_audit_found = true;
+	}
+    }
+
+  TEST_COMPARE (vdso_audit_found, true);
+  if (vdso_audit != 0)
+    TEST_COMPARE (vdso_process, vdso_audit);
+
+  free (buffer);
+  xfclose (out);
+
+  return 0;
+}
+
+#define TEST_FUNCTION_ARGV do_test
+#include <support/test-driver.c>
diff --git a/elf/tst-auditmod22.c b/elf/tst-auditmod22.c
new file mode 100644
index 0000000000..8e05ce8cbb
--- /dev/null
+++ b/elf/tst-auditmod22.c
@@ -0,0 +1,51 @@
+/* Check DTAUDIT and vDSO interaction.
+   Copyright (C) 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <link.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/auxv.h>
+
+static inline bool
+startswith (const char *str, const char *pre)
+{
+  size_t lenpre = strlen (pre);
+  size_t lenstr = strlen (str);
+  return lenstr < lenpre ? false : memcmp (pre, str, lenpre) == 0;
+}
+
+unsigned int
+la_version (unsigned int version)
+{
+  return LAV_CURRENT;
+}
+
+unsigned int
+la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
+{
+  /* The linux-gate.so is placed at a fixed address, thus l_addr being 0,
+     and it might be the value reported as the AT_SYSINFO_EHDR.  */
+  if (map->l_addr == 0 && startswith (map->l_name, "linux-gate.so"))
+    fprintf (stderr, "vdso found: %p\n", NULL);
+  else if (map->l_addr == getauxval (AT_SYSINFO_EHDR))
+    fprintf (stderr, "vdso found: %p\n", (void*) map->l_addr);
+
+  return 0;
+}
diff --git a/include/dlfcn.h b/include/dlfcn.h
index a4c283728f..e73294b0af 100644
--- a/include/dlfcn.h
+++ b/include/dlfcn.h
@@ -12,6 +12,8 @@
 #define __RTLD_AUDIT	0x08000000
 #define __RTLD_SECURE	0x04000000 /* Apply additional security checks.  */
 #define __RTLD_NOIFUNC	0x02000000 /* Suppress calling ifunc functions.  */
+#define __RTLD_VDSO	0x01000000 /* Tell _dl_new_object the object is
+				      system-loaded.  */
 
 #define __LM_ID_CALLER	-2
 
-- 
2.35.1


  parent reply	other threads:[~2022-04-12 18:42 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-04-12 18:41 [PATCH 00/27] Improve LD_AUDIT support in glibc 2.34 Carlos O'Donell
2022-04-12 18:41 ` [PATCH 01/27] powerpc: Delete unneeded ELF_MACHINE_BEFORE_RTLD_RELOC Carlos O'Donell
2022-04-12 18:41 ` [PATCH 02/27] elf: Avoid nested functions in the loader [BZ #27220] Carlos O'Donell
2022-04-12 18:41 ` [PATCH 03/27] elf: Fix elf_get_dynamic_info definition Carlos O'Donell
2022-04-12 18:41 ` [PATCH 04/27] elf: Fix dynamic-link.h usage on rtld.c Carlos O'Donell
2022-04-12 18:41 ` [PATCH 05/27] elf: Fix elf_get_dynamic_info() for bootstrap Carlos O'Donell
2022-04-12 18:41 ` [PATCH 06/27] elf: Move LAV_CURRENT to link_lavcurrent.h Carlos O'Donell
2022-04-12 18:41 ` [PATCH 07/27] elf: Move la_activity (LA_ACT_ADD) after _dl_add_to_namespace_list() (BZ #28062) Carlos O'Donell
2022-04-12 18:41 ` [PATCH 08/27] elf: Add _dl_audit_objopen Carlos O'Donell
2022-04-12 18:41 ` [PATCH 09/27] elf: Add _dl_audit_activity_map and _dl_audit_activity_nsid Carlos O'Donell
2022-04-12 18:41 ` [PATCH 10/27] elf: Add _dl_audit_objsearch Carlos O'Donell
2022-04-12 18:41 ` [PATCH 11/27] elf: Add _dl_audit_objclose Carlos O'Donell
2022-04-12 18:41 ` [PATCH 12/27] elf: Add _dl_audit_symbind_alt and _dl_audit_symbind Carlos O'Donell
2022-04-12 18:41 ` [PATCH 13/27] elf: Add _dl_audit_preinit Carlos O'Donell
2022-04-12 18:41 ` [PATCH 14/27] elf: Add _dl_audit_pltenter Carlos O'Donell
2022-04-12 18:41 ` [PATCH 15/27] elf: Add _dl_audit_pltexit Carlos O'Donell
2022-04-12 18:41 ` [PATCH 16/27] elf: Avoid unnecessary slowdown from profiling with audit (BZ#15533) Carlos O'Donell
2022-04-12 18:41 ` [PATCH 17/27] elf: Add audit tests for modules with TLSDESC Carlos O'Donell
2022-04-12 18:41 ` Carlos O'Donell [this message]
2022-04-12 18:41 ` [PATCH 19/27] elf: Do not fail for failed dlmopen on audit modules (BZ #28061) Carlos O'Donell
2022-04-12 18:41 ` [PATCH 20/27] elf: Add la_activity during application exit Carlos O'Donell
2022-04-12 18:41 ` [PATCH 21/27] elf: Fix initial-exec TLS access on audit modules (BZ #28096) Carlos O'Donell
2022-04-12 18:42 ` [PATCH 22/27] elf: Issue la_symbind for bind-now (BZ #23734) Carlos O'Donell
2022-04-12 18:42 ` [PATCH 23/27] elf: Fix runtime linker auditing on aarch64 (BZ #26643) Carlos O'Donell
2022-04-12 18:42 ` [PATCH 24/27] Fix elf/tst-audit25a with default bind now toolchains Carlos O'Donell
2022-04-12 18:42 ` [PATCH 25/27] elf: Replace tst-audit24bmod2.so with tst-audit24bmod2 Carlos O'Donell
2022-04-12 18:42 ` [PATCH 26/27] hppa: Fix bind-now audit (BZ #28857) Carlos O'Donell
2022-04-12 18:42 ` [PATCH 27/27] NEWS: Update fixed bug list for LD_AUDIT backports Carlos O'Donell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220412184205.3343677-19-carlos@redhat.com \
    --to=carlos@redhat.com \
    --cc=adhemerval.zanella@linaro.org \
    --cc=fweimer@redhat.com \
    --cc=libc-stable@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).