From patchwork Fri Nov 6 12:54:27 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 9578 Received: (qmail 17398 invoked by alias); 6 Nov 2015 12:54:35 -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 17385 invoked by uid 89); 6 Nov 2015 12:54:33 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.5 required=5.0 tests=AWL, BAYES_00, SPF_HELO_PASS, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com To: GNU C Library Cc: drepper@gmail.com From: Florian Weimer Subject: [PATCH] ld.so: Add original DSO name if overridden by audit module [BZ #18251] X-Enigmail-Draft-Status: N1110 Message-ID: <563CA303.6080404@redhat.com> Date: Fri, 6 Nov 2015 13:54:27 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.3.0 MIME-Version: 1.0 This is basically the patch from the bug, with whitespace changes removed, recommended headers in the test cases, and unreachable code removed from the test cases. I verified that the new tests are valid (they fail before the change to dl-load.c, and succeed afterwards). But I'm not familiar with ld.so, so I don't know if the patch is actually correct. I just want to move this forward. Thanks, Florian 2015-11-04 Ulrich Drepper * 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. 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; +} diff --git a/sysdeps/mach/hurd/dl-sysdep.c b/sysdeps/mach/hurd/dl-sysdep.c index 317605b..e446f15 100644 --- a/sysdeps/mach/hurd/dl-sysdep.c +++ b/sysdeps/mach/hurd/dl-sysdep.c @@ -186,7 +186,7 @@ unfmh(); /* XXX */ assert_perror (err); lastslash = strrchr (p, '/'); - l = _dl_map_object_from_fd (lastslash ? lastslash + 1 : p, + l = _dl_map_object_from_fd (lastslash ? lastslash + 1 : p, NULL, memobj, strdup (p), 0); /* Squirrel away the memory object port where it -- 2.4.3