From a1b85ae88b1a664e93ca0182c82f7763dd5a1754 Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Mon, 9 Nov 2015 16:52:31 +0100 Subject: ld.so: Add original DSO name if overridden by audit module [BZ #18251] * elf/dl-load.c (_dl_map_object_from_fd): Add additional parameter for original name of the DSO. Add it to the name list of the DSO if it is actually given. (_dl_map_object): Keep track of whether an audit module rewrote the file name. If yes, pass the original name to _dl_map_object_from_fd in a new parameter, otherwise NULL. When debugging is enabled, log the change of the file name. * sysdeps/mach/hur/dl-sysdep.c: Adjust commented-out call to _dl_map_object_from_fd. * elf/Makefile: Build and run tst-audit11 and tst-audit12. * elf/tst-audit11.c: New file * elf/tst-auditmod11.c: New file. * elf/tst-audit11mod1.c: New file. * elf/tst-audit11mod2.c: New file. * elf/tst-audit11mod2.map: New file. * elf/tst-audit12.c: New file * elf/tst-auditmod12.c: New file. * elf/tst-audit12mod1.c: New file. * elf/tst-audit12mod2.c: New file. * elf/tst-audit12mod2.map: New file. * elf/tst-audit12mod3.c: New file. --- elf/Makefile | 18 ++++++++++++++++-- elf/dl-load.c | 33 ++++++++++++++++++++++++++++----- elf/tst-audit11.c | 36 ++++++++++++++++++++++++++++++++++++ elf/tst-audit11mod1.c | 24 ++++++++++++++++++++++++ elf/tst-audit11mod2.c | 23 +++++++++++++++++++++++ elf/tst-audit11mod2.map | 22 ++++++++++++++++++++++ elf/tst-audit12.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ elf/tst-audit12mod1.c | 24 ++++++++++++++++++++++++ elf/tst-audit12mod2.c | 23 +++++++++++++++++++++++ elf/tst-audit12mod2.map | 22 ++++++++++++++++++++++ elf/tst-audit12mod3.c | 23 +++++++++++++++++++++++ elf/tst-auditmod11.c | 39 +++++++++++++++++++++++++++++++++++++++ elf/tst-auditmod12.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 13 files changed, 372 insertions(+), 7 deletions(-) create mode 100644 elf/tst-audit11.c create mode 100644 elf/tst-audit11mod1.c create mode 100644 elf/tst-audit11mod2.c create mode 100644 elf/tst-audit11mod2.map create mode 100644 elf/tst-audit12.c create mode 100644 elf/tst-audit12mod1.c create mode 100644 elf/tst-audit12mod2.c create mode 100644 elf/tst-audit12mod2.map create mode 100644 elf/tst-audit12mod3.c create mode 100644 elf/tst-auditmod11.c create mode 100644 elf/tst-auditmod12.c (limited to 'elf') diff --git a/elf/Makefile b/elf/Makefile index 546c8eb..76985cc 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -149,7 +149,7 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \ tst-nodelete) \ tst-initorder tst-initorder2 tst-relsort1 tst-null-argv \ tst-ptrguard1 tst-tlsalign tst-tlsalign-extern tst-nodelete-opened \ - tst-nodelete2 + tst-nodelete2 tst-audit11 tst-audit12 # reldep9 ifeq ($(build-hardcoded-path-in-tests),yes) tests += tst-dlopen-aout @@ -219,7 +219,9 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ tst-initorder2d \ tst-relsort1mod1 tst-relsort1mod2 tst-array2dep \ tst-array5dep tst-null-argv-lib \ - tst-tlsalign-lib tst-nodelete-opened-lib tst-nodelete2mod + tst-tlsalign-lib tst-nodelete-opened-lib tst-nodelete2mod \ + tst-audit11mod1 tst-audit11mod2 tst-auditmod11 \ + tst-audit12mod1 tst-audit12mod2 tst-audit12mod3 tst-auditmod12 ifeq (yes,$(have-protected-data)) modules-names += tst-protected1moda tst-protected1modb tests += tst-protected1a tst-protected1b @@ -1220,3 +1222,15 @@ $(objpfx)tst-unused-dep.out: $(objpfx)testobj1.so $(objpfx)tst-unused-dep-cmp.out: $(objpfx)tst-unused-dep.out cmp $< /dev/null > $@; \ $(evaluate-test) + +$(objpfx)tst-audit11.out: $(objpfx)tst-auditmod11.so $(objpfx)tst-audit11mod1.so +$(objpfx)tst-audit11: $(libdl) +tst-audit11-ENV = LD_AUDIT=$(objpfx)tst-auditmod11.so +$(objpfx)tst-audit11mod1.so: $(objpfx)tst-audit11mod2.so +LDFLAGS-tst-audit11mod2.so = -Wl,--version-script=tst-audit11mod2.map,-soname,tst-audit11mod2.so + +$(objpfx)tst-audit12.out: $(objpfx)tst-auditmod12.so $(objpfx)tst-audit12mod1.so $(objpfx)tst-audit12mod3.so +$(objpfx)tst-audit12: $(libdl) +tst-audit12-ENV = LD_AUDIT=$(objpfx)tst-auditmod12.so +$(objpfx)tst-audit12mod1.so: $(objpfx)tst-audit12mod2.so +LDFLAGS-tst-audit12mod2.so = -Wl,--version-script=tst-audit12mod2.map diff --git a/elf/dl-load.c b/elf/dl-load.c index 993a419..c5e948e 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -863,9 +863,10 @@ lose (int code, int fd, const char *name, char *realname, struct link_map *l, static #endif struct link_map * -_dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp, - char *realname, struct link_map *loader, int l_type, - int mode, void **stack_endp, Lmid_t nsid) +_dl_map_object_from_fd (const char *name, const char *origname, int fd, + struct filebuf *fbp, char *realname, + struct link_map *loader, int l_type, int mode, + void **stack_endp, Lmid_t nsid) { struct link_map *l = NULL; const ElfW(Ehdr) *header; @@ -1391,6 +1392,17 @@ cannot enable executable stack as shared object requires"); /* Finally the file information. */ l->l_file_id = id; +#ifdef SHARED + /* When auditing is used the recorded names might not include the + name by which the DSO is actually known. Add that as well. */ + if (__glibc_unlikely (origname != NULL)) + add_name_to_object (l, origname); +#else + /* Audit modules only exist when linking is dynamic so ORIGNAME + cannot be non-NULL. */ + assert (origname == NULL); +#endif + /* When we profile the SONAME might be needed for something else but loading. Add it right away. */ if (__glibc_unlikely (GLRO(dl_profile) != NULL) @@ -1904,6 +1916,7 @@ _dl_map_object (struct link_map *loader, const char *name, int type, int trace_mode, int mode, Lmid_t nsid) { int fd; + const char *origname = NULL; char *realname; char *name_copy; struct link_map *l; @@ -1961,6 +1974,7 @@ _dl_map_object (struct link_map *loader, const char *name, { if (afct->objsearch != NULL) { + const char *before = name; name = afct->objsearch (name, &loader->l_audit[cnt].cookie, LA_SER_ORIG); if (name == NULL) @@ -1969,6 +1983,15 @@ _dl_map_object (struct link_map *loader, const char *name, fd = -1; goto no_file; } + if (before != name && strcmp (before, name) != 0) + { + if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) + _dl_debug_printf ("audit changed filename %s -> %s\n", + before, name); + + if (origname == NULL) + origname = before; + } } afct = afct->next; @@ -2183,8 +2206,8 @@ _dl_map_object (struct link_map *loader, const char *name, } void *stack_end = __libc_stack_end; - return _dl_map_object_from_fd (name, fd, &fb, realname, loader, type, mode, - &stack_end, nsid); + return _dl_map_object_from_fd (name, origname, fd, &fb, realname, loader, + type, mode, &stack_end, nsid); } struct add_path_state diff --git a/elf/tst-audit11.c b/elf/tst-audit11.c new file mode 100644 index 0000000..15a44f9 --- /dev/null +++ b/elf/tst-audit11.c @@ -0,0 +1,36 @@ +/* Test version symbol binding can find a DSO replaced by la_objsearch. + Copyright (C) 2015 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 + +int +do_test (void) +{ + puts ("Start"); + if (dlopen ("$ORIGIN/tst-audit11mod1.so", RTLD_LAZY) == NULL) + { + printf ("module not loaded: %s\n", dlerror ()); + return 1; + } + puts ("OK"); + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/elf/tst-audit11mod1.c b/elf/tst-audit11mod1.c new file mode 100644 index 0000000..32df01f --- /dev/null +++ b/elf/tst-audit11mod1.c @@ -0,0 +1,24 @@ +/* DSO directly opened by tst-audit11. + Copyright (C) 2015 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 + . */ + +extern int f2 (void); +int +f1 (void) +{ + return f2 (); +} diff --git a/elf/tst-audit11mod2.c b/elf/tst-audit11mod2.c new file mode 100644 index 0000000..211456f --- /dev/null +++ b/elf/tst-audit11mod2.c @@ -0,0 +1,23 @@ +/* DSO indirectly opened by tst-audit11, with symbol versioning. + Copyright (C) 2015 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 + . */ + +int +f2 (void) +{ + return 42; +} diff --git a/elf/tst-audit11mod2.map b/elf/tst-audit11mod2.map new file mode 100644 index 0000000..76d4d5b --- /dev/null +++ b/elf/tst-audit11mod2.map @@ -0,0 +1,22 @@ +/* Symbol versioning for the DSO indirectly opened by tst-audit11. + Copyright (C) 2015 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 + . */ + +V1 { + global: f2; + local: *; +}; diff --git a/elf/tst-audit12.c b/elf/tst-audit12.c new file mode 100644 index 0000000..cd026bd --- /dev/null +++ b/elf/tst-audit12.c @@ -0,0 +1,49 @@ +/* Test that symbol is bound to a DSO replaced by la_objsearch. + Copyright (C) 2015 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 + +int +do_test (void) +{ + puts ("Start"); + void *h = dlopen ("$ORIGIN/tst-audit12mod1.so", RTLD_LAZY); + if (h == NULL) + { + printf ("module not loaded: %s\n", dlerror ()); + return 1; + } + int (*fp) (void) = (int (*) (void)) dlsym (h, "f1"); + if (fp == NULL) + { + printf ("function f1 not found: %s\n", dlerror ()); + return 1; + } + int res = fp (); + if (res != 43) + { + puts ("incorrect function f2 called"); + return 1; + } + printf ("%d is OK\n", res); + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/elf/tst-audit12mod1.c b/elf/tst-audit12mod1.c new file mode 100644 index 0000000..9ad73b6 --- /dev/null +++ b/elf/tst-audit12mod1.c @@ -0,0 +1,24 @@ +/* DSO directly opened by tst-audit12. + Copyright (C) 2015 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 + . */ + +extern int f2 (void); +int +f1 (void) +{ + return f2 (); +} diff --git a/elf/tst-audit12mod2.c b/elf/tst-audit12mod2.c new file mode 100644 index 0000000..de48b6a --- /dev/null +++ b/elf/tst-audit12mod2.c @@ -0,0 +1,23 @@ +/* Replaced DSO referenced by tst-audit12mod1.so, for tst-audit12. + Copyright (C) 2015 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 + . */ + +int +f2 (void) +{ + return 42; +} diff --git a/elf/tst-audit12mod2.map b/elf/tst-audit12mod2.map new file mode 100644 index 0000000..1030ac6 --- /dev/null +++ b/elf/tst-audit12mod2.map @@ -0,0 +1,22 @@ +/* Symbol versioning for tst-audit12mod2.so used by tst-audit12. + Copyright (C) 2015 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 + . */ + +V1 { + global: f2; + local: *; +}; diff --git a/elf/tst-audit12mod3.c b/elf/tst-audit12mod3.c new file mode 100644 index 0000000..e4e9d4b --- /dev/null +++ b/elf/tst-audit12mod3.c @@ -0,0 +1,23 @@ +/* Replacement DSO loaded by the audit module, for tst-audit12. + Copyright (C) 2015 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 + . */ + +int +f2 (void) +{ + return 43; +} diff --git a/elf/tst-auditmod11.c b/elf/tst-auditmod11.c new file mode 100644 index 0000000..cfcb34f --- /dev/null +++ b/elf/tst-auditmod11.c @@ -0,0 +1,39 @@ +/* Audit module for tst-audit11. + Copyright (C) 2015 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 +#include +#include +#include + +unsigned int +la_version (unsigned int version) +{ + return version; +} + +char * +la_objsearch (const char *name, uintptr_t *cookie, unsigned int flag) +{ + if (strcmp (name, "tst-audit11mod2.so") == 0) + { + return (char *) "$ORIGIN/tst-audit11mod2.so"; + } + return (char *) name; +} diff --git a/elf/tst-auditmod12.c b/elf/tst-auditmod12.c new file mode 100644 index 0000000..0c532bd --- /dev/null +++ b/elf/tst-auditmod12.c @@ -0,0 +1,43 @@ +/* Audit module for tst-audit12. + Copyright (C) 2015 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 +#include +#include +#include + +unsigned int +la_version (unsigned int version) +{ + return version; +} + +char * +la_objsearch (const char *name, uintptr_t *cookie, unsigned int flag) +{ + const char target[] = "tst-audit12mod2.so"; + + size_t namelen = strlen (name); + if (namelen >= sizeof (target) - 1 + && strcmp (name + namelen - (sizeof (target) - 1), target) == 0) + { + return (char *) "$ORIGIN/tst-audit12mod3.so"; + } + return (char *) name; +} -- cgit v1.1