lib/39649: dlsym(3) does not follow dependencies Pull across code from FreeBSD to do a search of the passed object and it's NEEDED objects (dependencies). Reviewed by gimpy.diff -r1.121 -r1.122 src/libexec/ld.elf_so/rtld.c
(skrll)
--- src/libexec/ld.elf_so/rtld.c 2008/09/27 03:52:05 1.121
+++ src/libexec/ld.elf_so/rtld.c 2008/10/04 09:37:12 1.122
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: rtld.c,v 1.121 2008/09/27 03:52:05 macallan Exp $ */ | 1 | /* $NetBSD: rtld.c,v 1.122 2008/10/04 09:37:12 skrll Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright 1996 John D. Polstra. | 4 | * Copyright 1996 John D. Polstra. | |
5 | * Copyright 1996 Matt Thomas <matt@3am-software.com> | 5 | * Copyright 1996 Matt Thomas <matt@3am-software.com> | |
6 | * Copyright 2002 Charles M. Hannum <root@ihack.net> | 6 | * Copyright 2002 Charles M. Hannum <root@ihack.net> | |
7 | * All rights reserved. | 7 | * All rights reserved. | |
8 | * | 8 | * | |
9 | * Redistribution and use in source and binary forms, with or without | 9 | * Redistribution and use in source and binary forms, with or without | |
10 | * modification, are permitted provided that the following conditions | 10 | * modification, are permitted provided that the following conditions | |
11 | * are met: | 11 | * are met: | |
12 | * 1. Redistributions of source code must retain the above copyright | 12 | * 1. Redistributions of source code must retain the above copyright | |
13 | * notice, this list of conditions and the following disclaimer. | 13 | * notice, this list of conditions and the following disclaimer. | |
14 | * 2. Redistributions in binary form must reproduce the above copyright | 14 | * 2. Redistributions in binary form must reproduce the above copyright | |
@@ -30,27 +30,27 @@ | @@ -30,27 +30,27 @@ | |||
30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
32 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 32 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
33 | */ | 33 | */ | |
34 | 34 | |||
35 | /* | 35 | /* | |
36 | * Dynamic linker for ELF. | 36 | * Dynamic linker for ELF. | |
37 | * | 37 | * | |
38 | * John Polstra <jdp@polstra.com>. | 38 | * John Polstra <jdp@polstra.com>. | |
39 | */ | 39 | */ | |
40 | 40 | |||
41 | #include <sys/cdefs.h> | 41 | #include <sys/cdefs.h> | |
42 | #ifndef lint | 42 | #ifndef lint | |
43 | __RCSID("$NetBSD: rtld.c,v 1.121 2008/09/27 03:52:05 macallan Exp $"); | 43 | __RCSID("$NetBSD: rtld.c,v 1.122 2008/10/04 09:37:12 skrll Exp $"); | |
44 | #endif /* not lint */ | 44 | #endif /* not lint */ | |
45 | 45 | |||
46 | #include <err.h> | 46 | #include <err.h> | |
47 | #include <errno.h> | 47 | #include <errno.h> | |
48 | #include <fcntl.h> | 48 | #include <fcntl.h> | |
49 | #include <stdarg.h> | 49 | #include <stdarg.h> | |
50 | #include <stdio.h> | 50 | #include <stdio.h> | |
51 | #include <stdlib.h> | 51 | #include <stdlib.h> | |
52 | #include <string.h> | 52 | #include <string.h> | |
53 | #include <unistd.h> | 53 | #include <unistd.h> | |
54 | #include <sys/param.h> | 54 | #include <sys/param.h> | |
55 | #include <sys/mman.h> | 55 | #include <sys/mman.h> | |
56 | #include <dirent.h> | 56 | #include <dirent.h> | |
@@ -879,32 +879,34 @@ dlsym(void *handle, const char *name) | @@ -879,32 +879,34 @@ dlsym(void *handle, const char *name) | |||
879 | abort(); | 879 | abort(); | |
880 | } | 880 | } | |
881 | break; | 881 | break; | |
882 | 882 | |||
883 | default: | 883 | default: | |
884 | if ((obj = _rtld_dlcheck(handle)) == NULL) | 884 | if ((obj = _rtld_dlcheck(handle)) == NULL) | |
885 | return NULL; | 885 | return NULL; | |
886 | 886 | |||
887 | if (obj->mainprog) { | 887 | if (obj->mainprog) { | |
888 | /* Search main program and all libraries loaded by it */ | 888 | /* Search main program and all libraries loaded by it */ | |
889 | def = _rtld_symlook_list(name, hash, &_rtld_list_main, | 889 | def = _rtld_symlook_list(name, hash, &_rtld_list_main, | |
890 | &defobj, false); | 890 | &defobj, false); | |
891 | } else { | 891 | } else { | |
892 | /* | 892 | Needed_Entry fake; | |
893 | * XXX - This isn't correct. The search should include | 893 | ||
894 | * the whole DAG rooted at the given object. | 894 | /* Search the object and all the libraries loaded by it. */ | |
895 | */ | 895 | fake.next = NULL; | |
896 | def = _rtld_symlook_obj(name, hash, obj, false); | 896 | fake.obj = (Obj_Entry *)obj; | |
897 | defobj = obj; | 897 | fake.name = 0; | |
898 | def = _rtld_symlook_needed(name, hash, &fake, &defobj, | |||
899 | false); | |||
898 | } | 900 | } | |
899 | break; | 901 | break; | |
900 | } | 902 | } | |
901 | 903 | |||
902 | if (def != NULL) { | 904 | if (def != NULL) { | |
903 | #ifdef __HAVE_FUNCTION_DESCRIPTORS | 905 | #ifdef __HAVE_FUNCTION_DESCRIPTORS | |
904 | if (ELF_ST_TYPE(def->st_info) == STT_FUNC) | 906 | if (ELF_ST_TYPE(def->st_info) == STT_FUNC) | |
905 | return (void *)_rtld_function_descriptor_alloc(defobj, | 907 | return (void *)_rtld_function_descriptor_alloc(defobj, | |
906 | def, 0); | 908 | def, 0); | |
907 | #endif /* __HAVE_FUNCTION_DESCRIPTORS */ | 909 | #endif /* __HAVE_FUNCTION_DESCRIPTORS */ | |
908 | return defobj->relocbase + def->st_value; | 910 | return defobj->relocbase + def->st_value; | |
909 | } | 911 | } | |
910 | 912 |
--- src/libexec/ld.elf_so/rtld.h 2008/06/03 19:32:32 1.78
+++ src/libexec/ld.elf_so/rtld.h 2008/10/04 09:37:12 1.79
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: rtld.h,v 1.78 2008/06/03 19:32:32 ad Exp $ */ | 1 | /* $NetBSD: rtld.h,v 1.79 2008/10/04 09:37:12 skrll Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright 1996 John D. Polstra. | 4 | * Copyright 1996 John D. Polstra. | |
5 | * Copyright 1996 Matt Thomas <matt@3am-software.com> | 5 | * Copyright 1996 Matt Thomas <matt@3am-software.com> | |
6 | * All rights reserved. | 6 | * All rights reserved. | |
7 | * | 7 | * | |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without | |
9 | * modification, are permitted provided that the following conditions | 9 | * modification, are permitted provided that the following conditions | |
10 | * are met: | 10 | * are met: | |
11 | * 1. Redistributions of source code must retain the above copyright | 11 | * 1. Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer. | 12 | * notice, this list of conditions and the following disclaimer. | |
13 | * 2. Redistributions in binary form must reproduce the above copyright | 13 | * 2. Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in the | 14 | * notice, this list of conditions and the following disclaimer in the | |
@@ -264,26 +264,28 @@ void _rtld_setup_pltgot(const Obj_Entry | @@ -264,26 +264,28 @@ void _rtld_setup_pltgot(const Obj_Entry | |||
264 | /* search.c */ | 264 | /* search.c */ | |
265 | Obj_Entry *_rtld_load_library(const char *, const Obj_Entry *, int); | 265 | Obj_Entry *_rtld_load_library(const char *, const Obj_Entry *, int); | |
266 | 266 | |||
267 | /* symbol.c */ | 267 | /* symbol.c */ | |
268 | unsigned long _rtld_elf_hash(const char *); | 268 | unsigned long _rtld_elf_hash(const char *); | |
269 | const Elf_Sym *_rtld_symlook_obj(const char *, unsigned long, | 269 | const Elf_Sym *_rtld_symlook_obj(const char *, unsigned long, | |
270 | const Obj_Entry *, bool); | 270 | const Obj_Entry *, bool); | |
271 | const Elf_Sym *_rtld_find_symdef(unsigned long, const Obj_Entry *, | 271 | const Elf_Sym *_rtld_find_symdef(unsigned long, const Obj_Entry *, | |
272 | const Obj_Entry **, bool); | 272 | const Obj_Entry **, bool); | |
273 | const Elf_Sym *_rtld_symlook_list(const char *, unsigned long, | 273 | const Elf_Sym *_rtld_symlook_list(const char *, unsigned long, | |
274 | const Objlist *, const Obj_Entry **, bool); | 274 | const Objlist *, const Obj_Entry **, bool); | |
275 | const Elf_Sym *_rtld_symlook_default(const char *, unsigned long, | 275 | const Elf_Sym *_rtld_symlook_default(const char *, unsigned long, | |
276 | const Obj_Entry *, const Obj_Entry **, bool); | 276 | const Obj_Entry *, const Obj_Entry **, bool); | |
277 | const Elf_Sym *_rtld_symlook_needed(const char *, unsigned long, | |||
278 | const Needed_Entry *, const Obj_Entry **, bool); | |||
277 | 279 | |||
278 | /* map_object.c */ | 280 | /* map_object.c */ | |
279 | Obj_Entry *_rtld_map_object(const char *, int, const struct stat *); | 281 | Obj_Entry *_rtld_map_object(const char *, int, const struct stat *); | |
280 | void _rtld_obj_free(Obj_Entry *); | 282 | void _rtld_obj_free(Obj_Entry *); | |
281 | Obj_Entry *_rtld_obj_new(void); | 283 | Obj_Entry *_rtld_obj_new(void); | |
282 | 284 | |||
283 | /* function descriptors */ | 285 | /* function descriptors */ | |
284 | #ifdef __HAVE_FUNCTION_DESCRIPTORS | 286 | #ifdef __HAVE_FUNCTION_DESCRIPTORS | |
285 | Elf_Addr _rtld_function_descriptor_alloc(const Obj_Entry *, | 287 | Elf_Addr _rtld_function_descriptor_alloc(const Obj_Entry *, | |
286 | const Elf_Sym *, Elf_Addr); | 288 | const Elf_Sym *, Elf_Addr); | |
287 | const void *_rtld_function_descriptor_function(const void *); | 289 | const void *_rtld_function_descriptor_function(const void *); | |
288 | #endif /* __HAVE_FUNCTION_DESCRIPTORS */ | 290 | #endif /* __HAVE_FUNCTION_DESCRIPTORS */ | |
289 | 291 |
--- src/libexec/ld.elf_so/symbol.c 2008/07/24 04:39:25 1.46
+++ src/libexec/ld.elf_so/symbol.c 2008/10/04 09:37:12 1.47
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: symbol.c,v 1.46 2008/07/24 04:39:25 matt Exp $ */ | 1 | /* $NetBSD: symbol.c,v 1.47 2008/10/04 09:37:12 skrll Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright 1996 John D. Polstra. | 4 | * Copyright 1996 John D. Polstra. | |
5 | * Copyright 1996 Matt Thomas <matt@3am-software.com> | 5 | * Copyright 1996 Matt Thomas <matt@3am-software.com> | |
6 | * Copyright 2002 Charles M. Hannum <root@ihack.net> | 6 | * Copyright 2002 Charles M. Hannum <root@ihack.net> | |
7 | * All rights reserved. | 7 | * All rights reserved. | |
8 | * | 8 | * | |
9 | * Redistribution and use in source and binary forms, with or without | 9 | * Redistribution and use in source and binary forms, with or without | |
10 | * modification, are permitted provided that the following conditions | 10 | * modification, are permitted provided that the following conditions | |
11 | * are met: | 11 | * are met: | |
12 | * 1. Redistributions of source code must retain the above copyright | 12 | * 1. Redistributions of source code must retain the above copyright | |
13 | * notice, this list of conditions and the following disclaimer. | 13 | * notice, this list of conditions and the following disclaimer. | |
14 | * 2. Redistributions in binary form must reproduce the above copyright | 14 | * 2. Redistributions in binary form must reproduce the above copyright | |
@@ -30,27 +30,27 @@ | @@ -30,27 +30,27 @@ | |||
30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
32 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 32 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
33 | */ | 33 | */ | |
34 | 34 | |||
35 | /* | 35 | /* | |
36 | * Dynamic linker for ELF. | 36 | * Dynamic linker for ELF. | |
37 | * | 37 | * | |
38 | * John Polstra <jdp@polstra.com>. | 38 | * John Polstra <jdp@polstra.com>. | |
39 | */ | 39 | */ | |
40 | 40 | |||
41 | #include <sys/cdefs.h> | 41 | #include <sys/cdefs.h> | |
42 | #ifndef lint | 42 | #ifndef lint | |
43 | __RCSID("$NetBSD: symbol.c,v 1.46 2008/07/24 04:39:25 matt Exp $"); | 43 | __RCSID("$NetBSD: symbol.c,v 1.47 2008/10/04 09:37:12 skrll Exp $"); | |
44 | #endif /* not lint */ | 44 | #endif /* not lint */ | |
45 | 45 | |||
46 | #include <err.h> | 46 | #include <err.h> | |
47 | #include <errno.h> | 47 | #include <errno.h> | |
48 | #include <fcntl.h> | 48 | #include <fcntl.h> | |
49 | #include <stdarg.h> | 49 | #include <stdarg.h> | |
50 | #include <stdio.h> | 50 | #include <stdio.h> | |
51 | #include <stdlib.h> | 51 | #include <stdlib.h> | |
52 | #include <string.h> | 52 | #include <string.h> | |
53 | #include <unistd.h> | 53 | #include <unistd.h> | |
54 | #include <sys/types.h> | 54 | #include <sys/types.h> | |
55 | #include <sys/mman.h> | 55 | #include <sys/mman.h> | |
56 | #include <dirent.h> | 56 | #include <dirent.h> | |
@@ -126,26 +126,76 @@ _rtld_symlook_list(const char *name, uns | @@ -126,26 +126,76 @@ _rtld_symlook_list(const char *name, uns | |||
126 | def = symp; | 126 | def = symp; | |
127 | defobj = elm->obj; | 127 | defobj = elm->obj; | |
128 | if (ELF_ST_BIND(def->st_info) != STB_WEAK) | 128 | if (ELF_ST_BIND(def->st_info) != STB_WEAK) | |
129 | break; | 129 | break; | |
130 | } | 130 | } | |
131 | } | 131 | } | |
132 | } | 132 | } | |
133 | if (def != NULL) | 133 | if (def != NULL) | |
134 | *defobj_out = defobj; | 134 | *defobj_out = defobj; | |
135 | return def; | 135 | return def; | |
136 | } | 136 | } | |
137 | 137 | |||
138 | /* | 138 | /* | |
139 | * Search the symbol table of a shared object and all objects needed by it for | |||
140 | * a symbol of the given name. Search order is breadth-first. Returns a pointer | |||
141 | * to the symbol, or NULL if no definition was found. | |||
142 | */ | |||
143 | const Elf_Sym * | |||
144 | _rtld_symlook_needed(const char *name, unsigned long hash, | |||
145 | const Needed_Entry *needed, const Obj_Entry **defobj_out, bool inplt) | |||
146 | { | |||
147 | const Elf_Sym *def, *def_w; | |||
148 | const Needed_Entry *n; | |||
149 | const Obj_Entry *obj, *defobj, *defobj1; | |||
150 | ||||
151 | def = def_w = NULL; | |||
152 | defobj = NULL; | |||
153 | for (n = needed; n != NULL; n = n->next) { | |||
154 | if ((obj = n->obj) == NULL || | |||
155 | (def = _rtld_symlook_obj(name, hash, obj, inplt)) == NULL) | |||
156 | continue; | |||
157 | defobj = obj; | |||
158 | if (ELF_ST_BIND(def->st_info) != STB_WEAK) { | |||
159 | *defobj_out = defobj; | |||
160 | ||||
161 | return (def); | |||
162 | } | |||
163 | } | |||
164 | /* | |||
165 | * Either the symbol definition has not been found in directly needed | |||
166 | * objects, or the found symbol is weak. | |||
167 | */ | |||
168 | for (n = needed; n != NULL; n = n->next) { | |||
169 | if ((obj = n->obj) == NULL) | |||
170 | continue; | |||
171 | def_w = _rtld_symlook_needed(name, hash, obj->needed, &defobj1, | |||
172 | inplt); | |||
173 | if (def_w == NULL) | |||
174 | continue; | |||
175 | if (def == NULL || ELF_ST_BIND(def_w->st_info) != STB_WEAK) { | |||
176 | def = def_w; | |||
177 | defobj = defobj1; | |||
178 | if (ELF_ST_BIND(def_w->st_info) != STB_WEAK) | |||
179 | break; | |||
180 | } | |||
181 | } | |||
182 | if (def != NULL) | |||
183 | *defobj_out = defobj; | |||
184 | ||||
185 | return def; | |||
186 | } | |||
187 | ||||
188 | /* | |||
139 | * Search the symbol table of a single shared object for a symbol of | 189 | * Search the symbol table of a single shared object for a symbol of | |
140 | * the given name. Returns a pointer to the symbol, or NULL if no | 190 | * the given name. Returns a pointer to the symbol, or NULL if no | |
141 | * definition was found. | 191 | * definition was found. | |
142 | * | 192 | * | |
143 | * The symbol's hash value is passed in for efficiency reasons; that | 193 | * The symbol's hash value is passed in for efficiency reasons; that | |
144 | * eliminates many recomputations of the hash value. | 194 | * eliminates many recomputations of the hash value. | |
145 | */ | 195 | */ | |
146 | const Elf_Sym * | 196 | const Elf_Sym * | |
147 | _rtld_symlook_obj(const char *name, unsigned long hash, | 197 | _rtld_symlook_obj(const char *name, unsigned long hash, | |
148 | const Obj_Entry *obj, bool in_plt) | 198 | const Obj_Entry *obj, bool in_plt) | |
149 | { | 199 | { | |
150 | unsigned long symnum; | 200 | unsigned long symnum; | |
151 | 201 |