Print this page
smatch clean rtld
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/sgs/rtld/common/analyze.c
+++ new/usr/src/cmd/sgs/rtld/common/analyze.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 */
25 25
26 26 /*
27 27 * Copyright (c) 1988 AT&T
28 28 * All Rights Reserved
29 29 */
30 30
31 31 #include <string.h>
32 32 #include <stdio.h>
33 33 #include <unistd.h>
34 34 #include <sys/stat.h>
35 35 #include <sys/mman.h>
36 36 #include <sys/debug.h>
37 37 #include <fcntl.h>
38 38 #include <limits.h>
39 39 #include <dlfcn.h>
40 40 #include <errno.h>
41 41 #include <link.h>
42 42 #include <debug.h>
43 43 #include <conv.h>
44 44 #include "_rtld.h"
45 45 #include "_audit.h"
46 46 #include "_elf.h"
47 47 #include "_a.out.h"
48 48 #include "_inline_gen.h"
49 49 #include "msg.h"
50 50
51 51 /*
52 52 * If a load filter flag is in effect, and this object is a filter, trigger the
53 53 * loading of all its filtees. The load filter flag is in effect when creating
54 54 * configuration files, or when under the control of ldd(1), or the LD_LOADFLTR
55 55 * environment variable is set, or this object was built with the -zloadfltr
56 56 * flag. Otherwise, filtee loading is deferred until triggered by a relocation.
57 57 */
58 58 static void
59 59 load_filtees(Rt_map *lmp, int *in_nfavl)
60 60 {
61 61 if ((FLAGS1(lmp) & MSK_RT_FILTER) &&
62 62 ((FLAGS(lmp) & FLG_RT_LOADFLTR) ||
63 63 (LIST(lmp)->lm_tflags & LML_TFLG_LOADFLTR))) {
64 64 Dyninfo *dip = DYNINFO(lmp);
65 65 uint_t cnt, max = DYNINFOCNT(lmp);
66 66 Slookup sl;
67 67
68 68 /*
69 69 * Initialize the symbol lookup data structure. Note, no symbol
70 70 * name is supplied. This NULL name causes filters to be loaded
71 71 * but no symbol to be searched for.
72 72 */
73 73 SLOOKUP_INIT(sl, 0, lmp, lmp, ld_entry_cnt, 0, 0, 0, 0, 0);
74 74
75 75 for (cnt = 0; cnt < max; cnt++, dip++) {
76 76 uint_t binfo;
77 77 Sresult sr;
78 78
79 79 SRESULT_INIT(sr, NULL);
80 80
81 81 if (((dip->di_flags & MSK_DI_FILTER) == 0) ||
82 82 ((dip->di_flags & FLG_DI_AUXFLTR) &&
83 83 (rtld_flags & RT_FL_NOAUXFLTR)))
84 84 continue;
85 85 (void) elf_lookup_filtee(&sl, &sr, &binfo, cnt,
86 86 in_nfavl);
87 87 }
88 88 }
89 89 }
90 90
91 91 /*
92 92 * Analyze one or more link-maps of a link map control list. This routine is
93 93 * called at startup to continue the processing of the main executable. It is
94 94 * also called each time a new set of objects are loaded, ie. from filters,
95 95 * lazy-loaded objects, or dlopen().
96 96 *
97 97 * In each instance we traverse the link-map control list starting with the
98 98 * initial object. As dependencies are analyzed they are added to the link-map
99 99 * control list. Thus the list grows as we traverse it - this results in the
100 100 * breadth first ordering of all needed objects.
101 101 *
102 102 * Return the initial link-map from which analysis starts for relocate_lmc().
103 103 */
104 104 Rt_map *
105 105 analyze_lmc(Lm_list *lml, Aliste nlmco, Rt_map *nlmp, Rt_map *clmp,
106 106 int *in_nfavl)
107 107 {
108 108 Rt_map *lmp;
109 109 Lm_cntl *nlmc;
110 110
111 111 /*
112 112 * If this link-map control list is being analyzed, return. The object
113 113 * that has just been added will be picked up by the existing analysis
114 114 * thread. Note, this is only really meaningful during process init-
115 115 * ialization, as objects are added to the main link-map control list.
116 116 * Following this initialization, each family of objects that are loaded
117 117 * are added to a new link-map control list.
118 118 */
119 119 /* LINTED */
120 120 nlmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, nlmco);
121 121 if (nlmc->lc_flags & LMC_FLG_ANALYZING)
122 122 return (nlmp);
123 123
124 124 /*
125 125 * If this object doesn't belong to the present link-map control list
126 126 * then it must already have been analyzed, or it is in the process of
127 127 * being analyzed prior to us recursing into this analysis. In either
128 128 * case, ignore the object as it's already being taken care of.
129 129 */
130 130 if (nlmco != CNTL(nlmp))
131 131 return (nlmp);
132 132
133 133 nlmc->lc_flags |= LMC_FLG_ANALYZING;
134 134
135 135 for (lmp = nlmp; lmp; lmp = NEXT_RT_MAP(lmp)) {
136 136 if (FLAGS(lmp) &
137 137 (FLG_RT_ANALZING | FLG_RT_ANALYZED | FLG_RT_DELETE))
138 138 continue;
139 139
140 140 /*
141 141 * Indicate that analyzing is under way.
142 142 */
143 143 FLAGS(lmp) |= FLG_RT_ANALZING;
144 144
145 145 /*
146 146 * If this link map represents a relocatable object, then we
147 147 * need to finish the link-editing of the object at this point.
148 148 */
149 149 if (FLAGS(lmp) & FLG_RT_OBJECT) {
150 150 Rt_map *olmp;
151 151
152 152 if ((olmp = elf_obj_fini(lml, lmp, clmp,
153 153 in_nfavl)) == NULL) {
154 154 if (lml->lm_flags & LML_FLG_TRC_ENABLE)
155 155 continue;
156 156 nlmp = NULL;
157 157 break;
158 158 }
159 159
160 160 /*
161 161 * The original link-map that captured a relocatable
162 162 * object is a temporary link-map, that basically acts
163 163 * as a place holder in the link-map list. On
164 164 * completion of relocatable object processing, a new
165 165 * link-map is created, and switched with the place
166 166 * holder. Therefore, reassign both the present
167 167 * link-map pointer and the return link-map pointer.
168 168 * The former resets this routines link-map processing,
169 169 * while the latter provides for later functions, like
170 170 * relocate_lmc(), to start processing from this new
171 171 * link-map.
172 172 */
173 173 if (nlmp == lmp)
174 174 nlmp = olmp;
175 175 lmp = olmp;
176 176 }
177 177
178 178 DBG_CALL(Dbg_file_analyze(lmp));
179 179
180 180 /*
181 181 * Establish any dependencies this object requires.
182 182 */
183 183 if (LM_NEEDED(lmp)(lml, nlmco, lmp, in_nfavl) == 0) {
184 184 if (lml->lm_flags & LML_FLG_TRC_ENABLE)
185 185 continue;
186 186 nlmp = NULL;
187 187 break;
188 188 }
189 189
190 190 FLAGS(lmp) &= ~FLG_RT_ANALZING;
191 191 FLAGS(lmp) |= FLG_RT_ANALYZED;
192 192
193 193 /*
194 194 * If we're building a configuration file, determine if this
195 195 * object is a filter and if so load its filtees. This
196 196 * traversal is only necessary for crle(1), as typical use of
197 197 * an object will load filters as part of relocation processing.
198 198 */
199 199 if (MODE(nlmp) & RTLD_CONFGEN)
200 200 load_filtees(lmp, in_nfavl);
201 201
202 202 /*
203 203 * If an interposer has been added, it will have been inserted
204 204 * in the link-map before the link we're presently analyzing.
205 205 * Break out of this analysis loop and return to the head of
206 206 * the link-map control list to analyze the interposer. Note
207 207 * that this rescan preserves the breadth first loading of
208 208 * dependencies.
209 209 */
210 210 /* LINTED */
211 211 nlmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, nlmco);
212 212 if (nlmc->lc_flags & LMC_FLG_REANALYZE) {
213 213 nlmc->lc_flags &= ~LMC_FLG_REANALYZE;
214 214 lmp = nlmc->lc_head;
215 215 }
216 216 }
217 217
218 218 /* LINTED */
219 219 nlmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, nlmco);
220 220 nlmc->lc_flags &= ~LMC_FLG_ANALYZING;
221 221
222 222 return (nlmp);
223 223 }
224 224
225 225 /*
226 226 * Determine whether a symbol represents zero, .bss, bits. Most commonly this
227 227 * function is used to determine whether the data for a copy relocation refers
228 228 * to initialized data or .bss. If the data definition is within .bss, then the
229 229 * data is zero filled, and as the copy destination within the executable is
230 230 * .bss, we can skip copying zero's to zero's.
231 231 *
232 232 * However, if the defining object has MOVE data, it's .bss might contain
233 233 * non-zero data, in which case copy the definition regardless.
234 234 *
235 235 * For backward compatibility copy relocation processing, this routine can be
236 236 * used to determine precisely if a copy destination is a move record recipient.
237 237 */
238 238 static int
239 239 are_bits_zero(Rt_map *dlmp, Sym *dsym, int dest)
240 240 {
241 241 mmapobj_result_t *mpp;
242 242 caddr_t daddr = (caddr_t)dsym->st_value;
243 243
244 244 if ((FLAGS(dlmp) & FLG_RT_FIXED) == 0)
245 245 daddr += ADDR(dlmp);
246 246
247 247 /*
248 248 * Determine the segment that contains the copy definition. Given that
249 249 * the copy relocation records have already been captured and verified,
250 250 * a segment must be found (but we add an escape clause never the less).
251 251 */
252 252 if ((mpp = find_segment(daddr, dlmp)) == NULL)
253 253 return (1);
254 254
255 255 /*
256 256 * If the definition is not within .bss, indicate this is not zero data.
257 257 */
258 258 if (daddr < (mpp->mr_addr + mpp->mr_offset + mpp->mr_fsize))
259 259 return (0);
260 260
261 261 /*
262 262 * If the definition is within .bss, make sure the definition isn't the
263 263 * recipient of a move record. Note, we don't precisely analyze whether
264 264 * the address is a move record recipient, as the infrastructure to
265 265 * prepare for, and carry out this analysis, is probably more costly
266 266 * than just copying the bytes regardless.
267 267 */
268 268 if ((FLAGS(dlmp) & FLG_RT_MOVE) == 0)
269 269 return (1);
270 270
271 271 /*
272 272 * However, for backward compatibility copy relocation processing, we
273 273 * can afford to work a little harder. Here, determine precisely
274 274 * whether the destination in the executable is a move record recipient.
275 275 * See comments in lookup_sym_interpose(), below.
276 276 */
277 277 if (dest && is_move_data(daddr))
278 278 return (0);
279 279
280 280 return (1);
281 281 }
282 282
283 283 /*
284 284 * Relocate an individual object.
285 285 */
286 286 static int
287 287 relocate_so(Lm_list *lml, Rt_map *lmp, int *relocated, int now, int *in_nfavl)
288 288 {
289 289 APlist *textrel = NULL;
290 290 int ret = 1;
291 291
292 292 /*
293 293 * If we're running under ldd(1), and haven't been asked to trace any
294 294 * warnings, skip any actual relocation processing.
295 295 */
296 296 if (((lml->lm_flags & LML_FLG_TRC_ENABLE) == 0) ||
297 297 (lml->lm_flags & LML_FLG_TRC_WARN)) {
298 298
299 299 if (relocated)
300 300 (*relocated)++;
301 301
302 302 if ((LM_RELOC(lmp)(lmp, now, in_nfavl, &textrel) == 0) &&
303 303 ((lml->lm_flags & LML_FLG_TRC_ENABLE) == 0))
304 304 ret = 0;
305 305
306 306 /*
307 307 * Finally process any move data. Note, this is carried out
308 308 * with ldd(1) under relocation processing too, as it can flush
309 309 * out move errors, and enables lari(1) to provide a true
310 310 * representation of the runtime bindings.
311 311 */
312 312 if ((FLAGS(lmp) & FLG_RT_MOVE) &&
313 313 (move_data(lmp, &textrel) == 0) &&
314 314 ((lml->lm_flags & LML_FLG_TRC_ENABLE) == 0))
315 315 ret = 0;
316 316 }
317 317
318 318 /*
319 319 * If a text segment was write enabled to perform any relocations or
320 320 * move records, then re-protect the segment by disabling writes.
321 321 */
322 322 if (textrel) {
323 323 mmapobj_result_t *mpp;
324 324 Aliste idx;
325 325
326 326 for (APLIST_TRAVERSE(textrel, idx, mpp))
327 327 (void) set_prot(lmp, mpp, 0);
328 328 free(textrel);
329 329 }
330 330
331 331 return (ret);
332 332 }
333 333
334 334 /*
335 335 * Relocate the objects on a link-map control list.
336 336 */
337 337 static int
338 338 _relocate_lmc(Lm_list *lml, Aliste lmco, Rt_map *nlmp, int *relocated,
339 339 int *in_nfavl)
340 340 {
341 341 Rt_map *lmp;
342 342
343 343 for (lmp = nlmp; lmp; lmp = NEXT_RT_MAP(lmp)) {
344 344 /*
345 345 * If this object has already been relocated, we're done. If
346 346 * this object is being deleted, skip it, there's probably a
347 347 * relocation error somewhere that's causing this deletion.
348 348 */
349 349 if (FLAGS(lmp) &
350 350 (FLG_RT_RELOCING | FLG_RT_RELOCED | FLG_RT_DELETE))
351 351 continue;
352 352
353 353 /*
354 354 * Indicate that relocation processing is under way.
355 355 */
356 356 FLAGS(lmp) |= FLG_RT_RELOCING;
357 357
358 358 /*
359 359 * Relocate the object.
360 360 */
361 361 if (relocate_so(lml, lmp, relocated, 0, in_nfavl) == 0)
362 362 return (0);
363 363
364 364 /*
365 365 * Indicate that the objects relocation is complete.
366 366 */
367 367 FLAGS(lmp) &= ~FLG_RT_RELOCING;
368 368 FLAGS(lmp) |= FLG_RT_RELOCED;
369 369
370 370 /*
371 371 * If this object is being relocated on the main link-map list
372 372 * indicate that this object's init is available for harvesting.
373 373 * Objects that are being collected on other link-map lists
374 374 * will have there init availability tagged when the objects
375 375 * are move to the main link-map list (ie, after we know they,
376 376 * and their dependencies, are fully relocated and ready for
377 377 * use).
378 378 *
379 379 * Note, even under ldd(1) this init identification is necessary
380 380 * for -i (tsort) gathering.
381 381 */
382 382 if (lmco == ALIST_OFF_DATA) {
383 383 lml->lm_init++;
384 384 lml->lm_flags |= LML_FLG_OBJADDED;
385 385 }
386 386
387 387 /*
388 388 * Determine if this object is a filter, and if a load filter
389 389 * flag is in effect, trigger the loading of all its filtees.
390 390 */
391 391 load_filtees(lmp, in_nfavl);
392 392 }
393 393
394 394 /*
395 395 * Perform special copy relocations. These are only meaningful for
396 396 * dynamic executables (fixed and head of their link-map list). If
397 397 * this ever has to change then the infrastructure of COPY() has to
398 398 * change. Presently, a given link map can only have a receiver or
399 399 * supplier of copy data, so a union is used to overlap the storage
400 400 * for the COPY_R() and COPY_S() lists. These lists would need to
401 401 * be separated.
402 402 */
403 403 if ((FLAGS(nlmp) & FLG_RT_FIXED) && (nlmp == LIST(nlmp)->lm_head) &&
404 404 (((lml->lm_flags & LML_FLG_TRC_ENABLE) == 0) ||
405 405 (lml->lm_flags & LML_FLG_TRC_WARN))) {
406 406 Rt_map *lmp;
407 407 Aliste idx1;
408 408 Word tracing;
409 409
410 410 #if defined(__i386)
411 411 if (elf_copy_gen(nlmp) == 0)
412 412 return (0);
413 413 #endif
414 414 if (COPY_S(nlmp) == NULL)
415 415 return (1);
416 416
417 417 if ((LIST(nlmp)->lm_flags & LML_FLG_TRC_ENABLE) &&
418 418 (((rtld_flags & RT_FL_SILENCERR) == 0) ||
419 419 (LIST(nlmp)->lm_flags & LML_FLG_TRC_VERBOSE)))
420 420 tracing = 1;
421 421 else
422 422 tracing = 0;
423 423
424 424 DBG_CALL(Dbg_util_nl(lml, DBG_NL_STD));
425 425
426 426 for (APLIST_TRAVERSE(COPY_S(nlmp), idx1, lmp)) {
427 427 Rel_copy *rcp;
428 428 Aliste idx2;
429 429
430 430 for (ALIST_TRAVERSE(COPY_R(lmp), idx2, rcp)) {
431 431 int zero;
432 432
433 433 /*
434 434 * Only copy the data if the data is from
435 435 * a non-zero definition (ie. not .bss).
436 436 */
437 437 zero = are_bits_zero(rcp->r_dlmp,
438 438 rcp->r_dsym, 0);
439 439 DBG_CALL(Dbg_reloc_copy(rcp->r_dlmp, nlmp,
440 440 rcp->r_name, zero));
441 441 if (zero)
442 442 continue;
443 443
444 444 (void) memcpy(rcp->r_radd, rcp->r_dadd,
445 445 rcp->r_size);
446 446
447 447 if ((tracing == 0) || ((FLAGS1(rcp->r_dlmp) &
448 448 FL1_RT_DISPREL) == 0))
449 449 continue;
450 450
451 451 (void) printf(MSG_INTL(MSG_LDD_REL_CPYDISP),
452 452 demangle(rcp->r_name), NAME(rcp->r_dlmp));
453 453 }
454 454 }
455 455
456 456 DBG_CALL(Dbg_util_nl(lml, DBG_NL_STD));
457 457
458 458 free(COPY_S(nlmp));
459 459 COPY_S(nlmp) = NULL;
460 460 }
461 461 return (1);
462 462 }
463 463
464 464 int
465 465 relocate_lmc(Lm_list *lml, Aliste nlmco, Rt_map *clmp, Rt_map *nlmp,
466 466 int *in_nfavl)
467 467 {
468 468 int lret = 1, pret = 1;
469 469 APlist *alp;
470 470 Aliste plmco;
471 471 Lm_cntl *plmc, *nlmc;
472 472
473 473 /*
474 474 * If this link-map control list is being relocated, return. The object
475 475 * that has just been added will be picked up by the existing relocation
476 476 * thread. Note, this is only really meaningful during process init-
477 477 * ialization, as objects are added to the main link-map control list.
478 478 * Following this initialization, each family of objects that are loaded
479 479 * are added to a new link-map control list.
480 480 */
481 481 /* LINTED */
482 482 nlmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, nlmco);
483 483
484 484 if (nlmc->lc_flags & LMC_FLG_RELOCATING)
485 485 return (1);
486 486
487 487 nlmc->lc_flags |= LMC_FLG_RELOCATING;
488 488
489 489 /*
490 490 * Relocate one or more link-maps of a link map control list. If this
491 491 * object doesn't belong to the present link-map control list then it
492 492 * must already have been relocated, or it is in the process of being
493 493 * relocated prior to us recursing into this relocation. In either
494 494 * case, ignore the object as it's already being taken care of, however,
495 495 * fall through and capture any relocation promotions that might have
496 496 * been established from the reference mode of this object.
497 497 *
498 498 * If we're generating a configuration file using crle(1), two passes
499 499 * may be involved. Under the first pass, RTLD_CONFGEN is set. Under
500 500 * this pass, crle() loads objects into the process address space. No
501 501 * relocation is necessary at this point, we simply need to analyze the
502 502 * objects to ensure any directly bound dependencies, filtees, etc.
503 503 * get loaded. Although we skip the relocation, fall through to ensure
504 504 * any control lists are maintained appropriately.
505 505 *
506 506 * If objects are to be dldump(3c)'ed, crle(1) makes a second pass,
507 507 * using RTLD_NOW and RTLD_CONFGEN. The RTLD_NOW effectively carries
508 508 * out the relocations of all loaded objects.
509 509 */
510 510 if ((nlmco == CNTL(nlmp)) &&
511 511 ((MODE(nlmp) & (RTLD_NOW | RTLD_CONFGEN)) != RTLD_CONFGEN)) {
512 512 int relocated = 0;
513 513
514 514 /*
515 515 * Determine whether the initial link-map control list has
516 516 * started relocation. From this point, should any interposing
517 517 * objects be added to this link-map control list, the objects
518 518 * are demoted to standard objects. Their interposition can't
519 519 * be guaranteed once relocations have been carried out.
520 520 */
521 521 if (nlmco == ALIST_OFF_DATA)
522 522 lml->lm_flags |= LML_FLG_STARTREL;
523 523
524 524 /*
525 525 * Relocate the link-map control list. Should this relocation
526 526 * fail, clean up this link-map list. Relocations within this
527 527 * list may have required relocation promotions on other lists,
528 528 * so before acting upon these, and possibly adding more objects
529 529 * to the present link-map control list, try and clean up any
530 530 * failed objects now.
531 531 */
532 532 lret = _relocate_lmc(lml, nlmco, nlmp, &relocated, in_nfavl);
533 533 if ((lret == 0) && (nlmco != ALIST_OFF_DATA))
534 534 remove_lmc(lml, clmp, nlmco, NAME(nlmp));
535 535 }
536 536
537 537 /*
538 538 * Determine the new, and previous link-map control lists.
539 539 */
540 540 /* LINTED */
541 541 nlmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, nlmco);
542 542 if (nlmco == ALIST_OFF_DATA) {
543 543 plmco = nlmco;
544 544 plmc = nlmc;
545 545 } else {
546 546 plmco = nlmco - lml->lm_lists->al_size;
547 547 /* LINTED */
548 548 plmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, plmco);
549 549 }
550 550
551 551 /*
552 552 * Having completed this control list of objects, they can now be bound
553 553 * to from other objects. Move this control list to the control list
554 554 * that precedes it. Although this control list may have only bound to
555 555 * controls lists much higher up the control list stack, it must only
556 556 * be moved up one control list so as to preserve the link-map order
557 557 * that may have already been traversed in search of symbols.
558 558 */
559 559 if (lret && (nlmco != ALIST_OFF_DATA) && nlmc->lc_head)
560 560 lm_move(lml, nlmco, plmco, nlmc, plmc);
561 561
562 562 /*
563 563 * Determine whether existing objects that have already been relocated,
564 564 * need any additional relocations performed. This can occur when new
565 565 * objects are loaded with RTLD_NOW, and these new objects have
566 566 * dependencies on objects that are already loaded. Note, that we peel
567 567 * any relocation promotions off of one control list at a time. This
568 568 * prevents relocations from being bound to objects that might yet fail
569 569 * to relocate themselves.
570 570 */
571 571 while ((alp = plmc->lc_now) != NULL) {
572 572 Aliste idx;
573 573 Rt_map *lmp;
574 574
575 575 /*
576 576 * Remove the relocation promotion list, as performing more
577 577 * relocations may result in discovering more objects that need
578 578 * promotion.
579 579 */
580 580 plmc->lc_now = NULL;
581 581
582 582 for (APLIST_TRAVERSE(alp, idx, lmp)) {
583 583 /*
584 584 * If the original relocation of the link-map control
585 585 * list failed, or one of the relocation promotions of
586 586 * this loop has failed, demote any pending objects
587 587 * relocation mode.
588 588 */
589 589 if ((lret == 0) || (pret == 0)) {
590 590 MODE(lmp) &= ~RTLD_NOW;
591 591 MODE(lmp) |= RTLD_LAZY;
592 592 continue;
593 593 }
594 594
595 595 /*
596 596 * If a relocation fails, save the error condition.
597 597 * It's possible that all new objects on the original
598 598 * link-map control list have been relocated
599 599 * successfully, but if the user request requires
600 600 * promoting objects that have already been loaded, we
601 601 * have to indicate that this operation couldn't be
602 602 * performed. The unrelocated objects are in use on
603 603 * another control list, and may continue to be used.
604 604 * If the .plt that resulted in the error is called,
605 605 * then the process will receive a fatal error at that
606 606 * time. But, the .plt may never be called.
607 607 */
608 608 if (relocate_so(lml, lmp, 0, 1, in_nfavl) == 0)
609 609 pret = 0;
610 610 }
611 611
612 612 /*
613 613 * Having promoted any objects, determine whether additional
614 614 * dependencies were added, and if so move them to the previous
615 615 * link-map control list.
616 616 */
617 617 /* LINTED */
618 618 nlmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, nlmco);
619 619 /* LINTED */
620 620 plmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, plmco);
621 621 if ((nlmco != ALIST_OFF_DATA) && nlmc->lc_head)
622 622 lm_move(lml, nlmco, plmco, nlmc, plmc);
623 623 free(alp);
624 624 }
625 625
626 626 /*
627 627 * If relocations have been successful, indicate that relocations are
628 628 * no longer active for this control list. Otherwise, leave the
629 629 * relocation flag, as this flag is used to determine the style of
630 630 * cleanup (see remove_lmc()).
631 631 */
632 632 if (lret && pret) {
633 633 /* LINTED */
634 634 nlmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, nlmco);
635 635 nlmc->lc_flags &= ~LMC_FLG_RELOCATING;
636 636
637 637 return (1);
638 638 }
639 639
640 640 return (0);
641 641 }
642 642
643 643 /*
644 644 * Inherit the first rejection message for possible later diagnostics.
645 645 *
646 646 * Any attempt to process a file that is unsuccessful, should be accompanied
647 647 * with an error diagnostic. However, some operations like searching for a
648 648 * simple filename, involve trying numerous paths, and an error message for each
649 649 * lookup is not required. Although a multiple search can fail, it's possible
650 650 * that a file was found, but was rejected because it was the wrong type.
651 651 * To satisfy these possibilities, the first failure is recorded as a rejection
652 652 * message, and this message is used later for a more specific diagnostic.
653 653 *
654 654 * File searches are focused at load_one(), and from here a rejection descriptor
655 655 * is passed down to various child routines. If these child routines can
656 656 * process multiple files, then they will maintain their own rejection desc-
657 657 * riptor. This is filled in for any failures, and a diagnostic produced to
658 658 * reflect the failure. The child routines then employ rejection_inherit() to
659 659 * pass the first rejection message back to load_one().
660 660 *
661 661 * Note that the name, and rejection string must be duplicated, as the name
662 662 * buffer and error string buffer (see conv_ routines) may be reused for
663 663 * additional processing or rejection messages.
664 664 */
665 665 void
666 666 rejection_inherit(Rej_desc *rej1, Rej_desc *rej2)
667 667 {
668 668 if (rej2->rej_type && (rej1->rej_type == 0)) {
669 669 rej1->rej_type = rej2->rej_type;
670 670 rej1->rej_info = rej2->rej_info;
671 671 rej1->rej_flags = rej2->rej_flags;
672 672 if (rej2->rej_name)
673 673 rej1->rej_name = stravl_insert(rej2->rej_name, 0, 0, 0);
674 674 if ((rej2->rej_str) && ((rej1->rej_str =
675 675 stravl_insert(rej2->rej_str, 0, 0, 0)) == NULL))
676 676 rej1->rej_str = MSG_ORIG(MSG_EMG_ENOMEM);
677 677 }
678 678 }
679 679
680 680 /*
681 681 * Helper routine for is_so_matched() that consolidates matching a path name,
682 682 * or file name component of a link-map name.
683 683 */
684 684 inline static int
685 685 _is_so_matched(const char *name, const char *str, int path)
686 686 {
687 687 const char *_str;
688 688
689 689 if ((path == 0) && ((_str = strrchr(str, '/')) != NULL))
690 690 _str++;
691 691 else
692 692 _str = str;
693 693
694 694 return (strcmp(name, _str));
695 695 }
696 696
697 697 /*
698 698 * Determine whether a search name matches one of the names associated with a
699 699 * link-map. A link-map contains several names:
700 700 *
701 701 * - a NAME() - this is the basename of the dynamic executable that started
702 702 * the process, and the path name of any dependencies used by the process.
703 703 * Most executables are received as full path names, as exec() prepends a
704 704 * search $PATH to locate the executable. However, simple file names can
705 705 * be received from exec() if the file is executed from the present working
706 706 * directory. Regardless, ld.so.1 maintains NAME() as the basename, as
707 707 * this has always been the name used in diagnostics and error messages.
708 708 * Most dependencies are full path names, as the typical search for a
709 709 * dependency, say "libx.so.1", results in search paths being prepended to
710 710 * the name, which eventually open "/lib/libx.so.1". However, relative
711 711 * path names can be supplied as dependencies, e.g. dlopen("../libx.so.1").
712 712 *
713 713 * - a PATHNAME() - this is the fully resolved path name of the object. This
714 714 * name will differ from NAME() for all dynamic executables, and may differ
715 715 * from the NAME() of dependencies, if the dependency is not a full path
716 716 * name, or the dependency resolves to a symbolic link.
717 717 *
718 718 * - an ALIAS() name - these are alternative names by which the object has
719 719 * been found, ie. when dependencies are loaded through a variety of
720 720 * different symbolic links.
721 721 *
722 722 * The name pattern matching can differ depending on whether we are looking
723 723 * for a full path name (path != 0), or a simple file name (path == 0). Full
724 724 * path names typically match NAME() or PATHNAME() entries.
725 725 *
726 726 * For all full path name searches, the link-map names are taken as is. For
727 727 * simple file name searches, only the file name component of any link-map
728 728 * names are used for comparison.
729 729 */
730 730 inline static Rt_map *
731 731 is_so_matched(Rt_map *lmp, const char *name, int path)
732 732 {
733 733 Aliste idx;
734 734 const char *cp;
735 735
736 736 if (_is_so_matched(name, NAME(lmp), path) == 0)
737 737 return (lmp);
738 738
739 739 if (PATHNAME(lmp) != NAME(lmp)) {
740 740 if (_is_so_matched(name, PATHNAME(lmp), path) == 0)
741 741 return (lmp);
742 742 }
743 743
744 744 for (APLIST_TRAVERSE(ALIAS(lmp), idx, cp)) {
745 745 if (_is_so_matched(name, cp, path) == 0)
746 746 return (lmp);
747 747 }
748 748
749 749 return (NULL);
750 750 }
751 751
752 752 /*
753 753 * Files are opened by ld.so.1 to satisfy dependencies, filtees and dlopen()
754 754 * requests. Each request investigates the file based upon the callers
755 755 * environment. Once a full path name has been established, the following
756 756 * checks are made:
757 757 *
758 758 * - does the path exist in the link-map lists FullPathNode AVL tree? if
759 759 * so, the file is already loaded, and its associated link-map pointer
760 760 * is returned.
761 761 * - does the path exist in the not-found AVL tree? if so, this path has
762 762 * already been determined to not exist, and a failure is returned.
763 763 * - a device/inode check, to ensure the same file isn't mapped multiple
764 764 * times through different paths. See file_open().
765 765 *
766 766 * However, there are cases where a test for an existing file name needs to be
767 767 * carried out, such as dlopen(NOLOAD) requests, dldump() requests, and as a
768 768 * final fallback to dependency loading. These requests are handled by
769 769 * is_so_loaded().
770 770 *
771 771 * A traversal through the callers link-map list is carried out, and from each
772 772 * link-map, a comparison is made against all of the various names by which the
773 773 * object has been referenced. is_so_matched() is used to compare the link-map
774 774 * names against the name being searched for. Whether the search name is a full
775 775 * path name or a simple file name, governs what comparisons are made.
776 776 *
777 777 * A full path name, which is a fully resolved path name that starts with a "/"
778 778 * character, or a relative path name that includes a "/" character, must match
779 779 * the link-map names exactly. A simple file name, which is any name *not*
780 780 * containing a "/" character, are matched against the file name component of
781 781 * any link-map names.
782 782 */
783 783 Rt_map *
784 784 is_so_loaded(Lm_list *lml, const char *name, int *in_nfavl)
785 785 {
786 786 Rt_map *lmp;
787 787 avl_index_t where;
788 788 Lm_cntl *lmc;
789 789 Aliste idx;
790 790 int path = 0;
791 791
792 792 /*
793 793 * If the name is a full path name, first determine if the path name is
794 794 * registered on the FullPathNode AVL, or not-found AVL trees.
795 795 */
796 796 if (name[0] == '/') {
797 797 uint_t hash = sgs_str_hash(name);
798 798
799 799 if (((lmp = fpavl_recorded(lml, name, hash, &where)) != NULL) &&
800 800 ((FLAGS(lmp) & (FLG_RT_OBJECT | FLG_RT_DELETE)) == 0))
801 801 return (lmp);
802 802
803 803 if (pnavl_recorded(&nfavl, name, hash, NULL)) {
804 804 /*
805 805 * For dlopen() and dlsym() fall backs, indicate that
806 806 * a registered not-found path has indicated that this
807 807 * object does not exist.
808 808 */
809 809 if (in_nfavl)
810 810 (*in_nfavl)++;
811 811 return (NULL);
812 812 }
813 813 }
814 814
815 815 /*
816 816 * Determine whether the name is a simple file name, or a path name.
817 817 */
818 818 if (strchr(name, '/'))
819 819 path++;
820 820
821 821 /*
822 822 * Loop through the callers link-map lists.
823 823 */
824 824 for (ALIST_TRAVERSE(lml->lm_lists, idx, lmc)) {
825 825 for (lmp = lmc->lc_head; lmp; lmp = NEXT_RT_MAP(lmp)) {
826 826 if (FLAGS(lmp) & (FLG_RT_OBJECT | FLG_RT_DELETE))
827 827 continue;
828 828
829 829 if (is_so_matched(lmp, name, path))
830 830 return (lmp);
831 831 }
832 832 }
833 833 return (NULL);
834 834 }
835 835
836 836 /*
837 837 * Tracing is enabled by the LD_TRACE_LOADED_OPTIONS environment variable which
838 838 * is normally set from ldd(1). For each link map we load, print the load name
839 839 * and the full pathname of the associated object.
840 840 */
841 841 /* ARGSUSED4 */
842 842 static void
843 843 trace_so(Rt_map *clmp, Rej_desc *rej, const char *name, const char *path,
844 844 int alter, const char *nfound)
845 845 {
846 846 const char *str = MSG_ORIG(MSG_STR_EMPTY);
847 847 const char *reject = MSG_ORIG(MSG_STR_EMPTY);
848 848 char _reject[PATH_MAX];
849 849
850 850 /*
851 851 * The first time through trace_so() will only have lddstub on the
852 852 * link-map list and the preloaded shared object is supplied as "path".
853 853 * As we don't want to print this shared object as a dependency, but
854 854 * instead inspect *its* dependencies, return.
855 855 */
856 856 if (FLAGS1(clmp) & FL1_RT_LDDSTUB)
857 857 return;
858 858
859 859 /*
860 860 * Without any rejection info, this is a supplied not-found condition.
861 861 */
862 862 if (rej && (rej->rej_type == 0)) {
863 863 (void) printf(nfound, name);
864 864 return;
865 865 }
866 866
867 867 /*
868 868 * If rejection information exists then establish what object was
869 869 * found and the reason for its rejection.
870 870 */
871 871 if (rej) {
872 872 Conv_reject_desc_buf_t rej_buf;
873 873
874 874 /* LINTED */
875 875 (void) snprintf(_reject, PATH_MAX,
876 876 MSG_INTL(ldd_reject[rej->rej_type]),
877 877 conv_reject_desc(rej, &rej_buf, M_MACH));
878 878 if (rej->rej_name)
879 879 path = rej->rej_name;
880 880 reject = (char *)_reject;
881 881
882 882 /*
883 883 * Was an alternative pathname defined (from a configuration
884 884 * file).
885 885 */
886 886 if (rej->rej_flags & FLG_REJ_ALTER)
887 887 str = MSG_INTL(MSG_LDD_FIL_ALTER);
888 888 } else {
889 889 if (alter)
890 890 str = MSG_INTL(MSG_LDD_FIL_ALTER);
891 891 }
892 892
893 893 /*
894 894 * If the load name isn't a full pathname print its associated pathname
895 895 * together with all the other information we've gathered.
896 896 */
897 897 if (*name == '/')
898 898 (void) printf(MSG_ORIG(MSG_LDD_FIL_PATH), path, str, reject);
899 899 else
900 900 (void) printf(MSG_ORIG(MSG_LDD_FIL_EQUIV), name, path, str,
901 901 reject);
902 902 }
903 903
904 904 /*
905 905 * Establish a link-map mode, initializing it if it has just been loaded, or
906 906 * potentially updating it if it already exists.
907 907 */
908 908 int
909 909 update_mode(Rt_map *lmp, int omode, int nmode)
910 910 {
911 911 Lm_list *lml = LIST(lmp);
912 912 int pmode = 0;
913 913
914 914 /*
915 915 * A newly loaded object hasn't had its mode set yet. Modes are used to
916 916 * load dependencies, so don't propagate any parent or no-load flags, as
917 917 * these would adversely affect this objects ability to load any of its
918 918 * dependencies that aren't already loaded. RTLD_FIRST is applicable to
919 919 * this objects handle creation only, and should not be propagated.
920 920 */
921 921 if ((FLAGS(lmp) & FLG_RT_MODESET) == 0) {
922 922 MODE(lmp) |= nmode & ~(RTLD_PARENT | RTLD_NOLOAD | RTLD_FIRST);
923 923 FLAGS(lmp) |= FLG_RT_MODESET;
924 924 return (1);
925 925 }
926 926
927 927 /*
928 928 * Establish any new overriding modes. RTLD_LAZY and RTLD_NOW should be
929 929 * represented individually (this is historic, as these two flags were
930 930 * the only flags originally available to dlopen()). Other flags are
931 931 * accumulative, but have a hierarchy of preference.
932 932 */
933 933 if ((omode & RTLD_LAZY) && (nmode & RTLD_NOW)) {
934 934 MODE(lmp) &= ~RTLD_LAZY;
935 935 pmode |= RTLD_NOW;
936 936 }
937 937
938 938 pmode |= ((~omode & nmode) &
939 939 (RTLD_GLOBAL | RTLD_WORLD | RTLD_NODELETE));
940 940 if (pmode) {
941 941 DBG_CALL(Dbg_file_mode_promote(lmp, pmode));
942 942 MODE(lmp) |= pmode;
943 943 }
944 944
945 945 /*
946 946 * If this load is an RTLD_NOW request and the object has already been
947 947 * loaded non-RTLD_NOW, append this object to the relocation-now list
948 948 * of the objects associated control list. Note, if the object hasn't
949 949 * yet been relocated, setting its MODE() to RTLD_NOW will establish
950 950 * full relocation processing when it eventually gets relocated.
951 951 */
952 952 if ((pmode & RTLD_NOW) &&
953 953 (FLAGS(lmp) & (FLG_RT_RELOCED | FLG_RT_RELOCING))) {
954 954 Lm_cntl *lmc;
955 955
956 956 /* LINTED */
957 957 lmc = (Lm_cntl *)alist_item_by_offset(LIST(lmp)->lm_lists,
958 958 CNTL(lmp));
959 959 (void) aplist_append(&lmc->lc_now, lmp, AL_CNT_LMNOW);
960 960 }
961 961
962 962 /*
963 963 * If this objects .init has been collected but has not yet been called,
964 964 * it may be necessary to reevaluate the object using tsort(). For
965 965 * example, a new dlopen() hierarchy may bind to uninitialized objects
966 966 * that are already loaded, or a dlopen(RTLD_NOW) can establish new
967 967 * bindings between already loaded objects that require the tsort()
968 968 * information be recomputed. If however, no new objects have been
969 969 * added to the process, and this object hasn't been promoted, don't
970 970 * bother reevaluating the .init. The present tsort() information is
971 971 * probably as accurate as necessary, and by not establishing a parallel
972 972 * tsort() we can help reduce the amount of recursion possible between
973 973 * .inits.
974 974 */
975 975 if (((FLAGS(lmp) &
976 976 (FLG_RT_INITCLCT | FLG_RT_INITCALL)) == FLG_RT_INITCLCT) &&
977 977 ((lml->lm_flags & LML_FLG_OBJADDED) || ((pmode & RTLD_NOW) &&
978 978 (FLAGS(lmp) & (FLG_RT_RELOCED | FLG_RT_RELOCING))))) {
979 979 FLAGS(lmp) &= ~FLG_RT_INITCLCT;
980 980 LIST(lmp)->lm_init++;
981 981 LIST(lmp)->lm_flags |= LML_FLG_OBJREEVAL;
982 982 }
983 983
984 984 return (pmode);
985 985 }
986 986
987 987 /*
988 988 * Determine whether an alias name already exists, and if not create one. This
989 989 * is typically used to retain dependency names, such as "libc.so.1", which
990 990 * would have been expanded to full path names when they were loaded. The
991 991 * full path names (NAME() and possibly PATHNAME()) are maintained on the
992 992 * FullPathNode AVL tree, and thus would have been matched by fpavl_loaded()
993 993 * during file_open().
994 994 */
995 995 int
996 996 append_alias(Rt_map *lmp, const char *str, int *added)
997 997 {
998 998 const char *cp;
999 999 Aliste idx;
1000 1000
1001 1001 /*
1002 1002 * Determine if this filename is already on the alias list.
1003 1003 */
1004 1004 for (APLIST_TRAVERSE(ALIAS(lmp), idx, cp)) {
1005 1005 if (strcmp(cp, str) == 0)
1006 1006 return (1);
1007 1007 }
1008 1008
1009 1009 /*
1010 1010 * This is a new alias, append it to the alias list.
1011 1011 */
1012 1012 if (((cp = stravl_insert(str, 0, 0, 0)) == NULL) ||
1013 1013 (aplist_append(&ALIAS(lmp), cp, AL_CNT_ALIAS) == NULL))
1014 1014 return (0);
1015 1015
1016 1016 if (added)
1017 1017 *added = 1;
1018 1018 return (1);
1019 1019 }
1020 1020
1021 1021 /*
1022 1022 * Determine whether a file is already loaded by comparing device and inode
1023 1023 * values.
1024 1024 */
1025 1025 static Rt_map *
1026 1026 is_devinode_loaded(rtld_stat_t *status, Lm_list *lml, const char *name,
1027 1027 uint_t flags)
1028 1028 {
1029 1029 Lm_cntl *lmc;
1030 1030 Aliste idx;
1031 1031
1032 1032 /*
1033 1033 * If this is an auditor, it will have been opened on a new link-map.
1034 1034 * To prevent multiple occurrences of the same auditor on multiple
1035 1035 * link-maps, search the head of each link-map list and see if this
1036 1036 * object is already loaded as an auditor.
1037 1037 */
1038 1038 if (flags & FLG_RT_AUDIT) {
1039 1039 Lm_list *lml;
1040 1040
1041 1041 for (APLIST_TRAVERSE(dynlm_list, idx, lml)) {
1042 1042 Rt_map *nlmp = lml->lm_head;
1043 1043
1044 1044 if (nlmp && ((FLAGS(nlmp) &
1045 1045 (FLG_RT_AUDIT | FLG_RT_DELETE)) == FLG_RT_AUDIT) &&
1046 1046 (STDEV(nlmp) == status->st_dev) &&
1047 1047 (STINO(nlmp) == status->st_ino))
1048 1048 return (nlmp);
1049 1049 }
1050 1050 return (NULL);
1051 1051 }
1052 1052
1053 1053 /*
1054 1054 * If the file has been found determine from the new files status
1055 1055 * information if this file is actually linked to one we already have
1056 1056 * mapped. This catches symlink names not caught by is_so_loaded().
1057 1057 */
1058 1058 for (ALIST_TRAVERSE(lml->lm_lists, idx, lmc)) {
1059 1059 Rt_map *nlmp;
1060 1060
1061 1061 for (nlmp = lmc->lc_head; nlmp; nlmp = NEXT_RT_MAP(nlmp)) {
1062 1062 if ((FLAGS(nlmp) & FLG_RT_DELETE) ||
1063 1063 (FLAGS1(nlmp) & FL1_RT_LDDSTUB))
1064 1064 continue;
1065 1065
1066 1066 if ((STDEV(nlmp) != status->st_dev) ||
1067 1067 (STINO(nlmp) != status->st_ino))
1068 1068 continue;
1069 1069
1070 1070 if (lml->lm_flags & LML_FLG_TRC_VERBOSE) {
1071 1071 /* BEGIN CSTYLED */
1072 1072 if (*name == '/')
1073 1073 (void) printf(MSG_ORIG(MSG_LDD_FIL_PATH),
1074 1074 name, MSG_ORIG(MSG_STR_EMPTY),
1075 1075 MSG_ORIG(MSG_STR_EMPTY));
1076 1076 else
1077 1077 (void) printf(MSG_ORIG(MSG_LDD_FIL_EQUIV),
1078 1078 name, NAME(nlmp),
1079 1079 MSG_ORIG(MSG_STR_EMPTY),
1080 1080 MSG_ORIG(MSG_STR_EMPTY));
1081 1081 /* END CSTYLED */
1082 1082 }
1083 1083 return (nlmp);
1084 1084 }
1085 1085 }
1086 1086 return (NULL);
1087 1087 }
1088 1088
1089 1089 /*
1090 1090 * Generate any error messages indicating a file could not be found. When
1091 1091 * preloading or auditing a secure application, it can be a little more helpful
1092 1092 * to indicate that a search of secure directories has failed, so adjust the
1093 1093 * messages accordingly.
1094 1094 */
1095 1095 void
1096 1096 file_notfound(Lm_list *lml, const char *name, Rt_map *clmp, uint_t flags,
1097 1097 Rej_desc *rej)
1098 1098 {
1099 1099 int secure = 0;
1100 1100
1101 1101 if ((rtld_flags & RT_FL_SECURE) &&
1102 1102 (flags & (FLG_RT_PRELOAD | FLG_RT_AUDIT)))
1103 1103 secure++;
1104 1104
1105 1105 if (lml->lm_flags & LML_FLG_TRC_ENABLE) {
1106 1106 /*
1107 1107 * Under ldd(1), auxiliary filtees that can't be loaded are
1108 1108 * ignored, unless verbose errors are requested.
1109 1109 */
1110 1110 if ((rtld_flags & RT_FL_SILENCERR) &&
1111 1111 ((lml->lm_flags & LML_FLG_TRC_VERBOSE) == 0))
1112 1112 return;
1113 1113
1114 1114 if (secure)
1115 1115 trace_so(clmp, rej, name, 0, 0,
1116 1116 MSG_INTL(MSG_LDD_SEC_NFOUND));
1117 1117 else
1118 1118 trace_so(clmp, rej, name, 0, 0,
1119 1119 MSG_INTL(MSG_LDD_FIL_NFOUND));
1120 1120 return;
1121 1121 }
1122 1122
1123 1123 if (rej->rej_type) {
1124 1124 Conv_reject_desc_buf_t rej_buf;
1125 1125
1126 1126 eprintf(lml, ERR_FATAL, MSG_INTL(err_reject[rej->rej_type]),
1127 1127 rej->rej_name ? rej->rej_name : MSG_INTL(MSG_STR_UNKNOWN),
1128 1128 conv_reject_desc(rej, &rej_buf, M_MACH));
1129 1129 return;
1130 1130 }
1131 1131
1132 1132 if (secure)
1133 1133 eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SEC_OPEN), name);
1134 1134 else
1135 1135 eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN), name,
1136 1136 strerror(ENOENT));
1137 1137 }
1138 1138
1139 1139 static int
1140 1140 file_open(int err, Lm_list *lml, Rt_map *clmp, uint_t flags, Fdesc *fdp,
1141 1141 Rej_desc *rej, int *in_nfavl)
1142 1142 {
1143 1143 rtld_stat_t status;
1144 1144 Rt_map *nlmp;
1145 1145 avl_index_t nfavlwhere = 0;
1146 1146 const char *oname = fdp->fd_oname, *nname = fdp->fd_nname;
1147 1147 uint_t hash = sgs_str_hash(nname);
1148 1148
1149 1149
1150 1150 if ((nname = stravl_insert(fdp->fd_nname, hash, 0, 0)) == NULL)
1151 1151 return (0);
1152 1152 fdp->fd_nname = nname;
1153 1153
1154 1154 if ((err == 0) && (fdp->fd_flags & FLG_FD_ALTER))
1155 1155 DBG_CALL(Dbg_file_config_obj(lml, oname, 0, nname));
1156 1156
1157 1157 /*
1158 1158 * If we're dealing with a full pathname, determine whether this
1159 1159 * pathname is already known. Other pathnames fall through to the
1160 1160 * dev/inode check, as even though the pathname may look the same as
1161 1161 * one previously used, the process may have changed directory.
1162 1162 */
1163 1163 if ((err == 0) && (nname[0] == '/')) {
1164 1164 if ((nlmp = fpavl_recorded(lml, nname, hash,
1165 1165 &(fdp->fd_avlwhere))) != NULL) {
1166 1166 fdp->fd_lmp = nlmp;
1167 1167 return (1);
1168 1168 }
1169 1169 if (pnavl_recorded(&nfavl, nname, hash, &nfavlwhere)) {
1170 1170 /*
1171 1171 * For dlopen() and dlsym() fall backs, indicate that
1172 1172 * a registered not-found path has indicated that this
1173 1173 * object does not exist. If this path has been
1174 1174 * constructed as part of expanding a CAPABILITY
1175 1175 * directory, this is a silent failure, where no
1176 1176 * rejection message is created.
1177 1177 */
1178 1178 if (in_nfavl)
1179 1179 (*in_nfavl)++;
1180 1180 return (0);
1181 1181 }
1182 1182 }
1183 1183
1184 1184 if ((err == 0) && ((rtld_stat(nname, &status)) != -1)) {
1185 1185 char path[PATH_MAX];
1186 1186 int fd, size, added;
1187 1187
1188 1188 /*
1189 1189 * If this path has been constructed as part of expanding a
1190 1190 * CAPABILITY directory, ignore any subdirectories. As this
1191 1191 * is a silent failure, no rejection message is created. For
1192 1192 * any other reference that expands to a directory, fall
1193 1193 * through to construct a meaningful rejection message.
1194 1194 */
1195 1195 if ((flags & FLG_RT_CAP) &&
1196 1196 ((status.st_mode & S_IFMT) == S_IFDIR))
1197 1197 return (0);
1198 1198
1199 1199 /*
1200 1200 * If this is a directory (which can't be mmap()'ed) generate a
1201 1201 * precise error message.
1202 1202 */
1203 1203 if ((status.st_mode & S_IFMT) == S_IFDIR) {
1204 1204 rej->rej_name = nname;
1205 1205 if (fdp->fd_flags & FLG_FD_ALTER)
1206 1206 rej->rej_flags = FLG_REJ_ALTER;
1207 1207 rej->rej_type = SGS_REJ_STR;
1208 1208 rej->rej_str = strerror(EISDIR);
1209 1209 DBG_CALL(Dbg_file_rejected(lml, rej, M_MACH));
1210 1210 return (0);
1211 1211 }
1212 1212
1213 1213 /*
1214 1214 * Resolve the filename and determine whether the resolved name
1215 1215 * is already known. Typically, the previous fpavl_loaded()
1216 1216 * will have caught this, as both NAME() and PATHNAME() for a
1217 1217 * link-map are recorded in the FullPathNode AVL tree. However,
1218 1218 * instances exist where a file can be replaced (loop-back
1219 1219 * mounts, bfu, etc.), and reference is made to the original
1220 1220 * file through a symbolic link. By checking the pathname here,
1221 1221 * we don't fall through to the dev/inode check and conclude
1222 1222 * that a new file should be loaded.
1223 1223 */
1224 1224 if ((nname[0] == '/') &&
1225 1225 ((size = resolvepath(nname, path, (PATH_MAX - 1))) > 0)) {
1226 1226 path[size] = '\0';
1227 1227
1228 1228 fdp->fd_flags |= FLG_FD_RESOLVED;
1229 1229
1230 1230 if (strcmp(nname, path)) {
1231 1231 if ((nlmp =
1232 1232 fpavl_recorded(lml, path, 0, 0)) != NULL) {
1233 1233 added = 0;
1234 1234
1235 1235 if (append_alias(nlmp, nname,
1236 1236 &added) == 0)
1237 1237 return (0);
1238 1238 /* BEGIN CSTYLED */
1239 1239 if (added)
1240 1240 DBG_CALL(Dbg_file_skip(LIST(clmp),
1241 1241 NAME(nlmp), nname));
1242 1242 /* END CSTYLED */
1243 1243 fdp->fd_lmp = nlmp;
1244 1244 return (1);
1245 1245 }
1246 1246
1247 1247 /*
1248 1248 * If this pathname hasn't been loaded, save
1249 1249 * the resolved pathname so that it doesn't
1250 1250 * have to be recomputed as part of fullpath()
1251 1251 * processing.
1252 1252 */
1253 1253 if ((fdp->fd_pname = stravl_insert(path, 0,
1254 1254 (size + 1), 0)) == NULL)
1255 1255 return (0);
1256 1256 }
1257 1257 }
1258 1258
1259 1259 if (nlmp = is_devinode_loaded(&status, lml, nname, flags)) {
1260 1260 if (flags & FLG_RT_AUDIT) {
1261 1261 /*
1262 1262 * If we've been requested to load an auditor,
1263 1263 * and an auditor of the same name already
1264 1264 * exists, then the original auditor is used.
1265 1265 */
1266 1266 DBG_CALL(Dbg_audit_skip(LIST(clmp),
1267 1267 NAME(nlmp), LIST(nlmp)->lm_lmidstr));
1268 1268 } else {
1269 1269 /*
1270 1270 * Otherwise, if an alternatively named file
1271 1271 * has been found for the same dev/inode, add
1272 1272 * a new name alias. Insert any alias full path
1273 1273 * name in the FullPathNode AVL tree.
1274 1274 */
1275 1275 added = 0;
1276 1276
1277 1277 if (append_alias(nlmp, nname, &added) == 0)
1278 1278 return (0);
1279 1279 if (added) {
1280 1280 if ((nname[0] == '/') &&
1281 1281 (fpavl_insert(lml, nlmp,
1282 1282 nname, 0) == 0))
1283 1283 return (0);
1284 1284 DBG_CALL(Dbg_file_skip(LIST(clmp),
1285 1285 NAME(nlmp), nname));
1286 1286 }
1287 1287 }
1288 1288
1289 1289 /*
1290 1290 * Record in the file descriptor the existing object
1291 1291 * that satisfies this open request.
1292 1292 */
1293 1293 fdp->fd_lmp = nlmp;
1294 1294 return (1);
1295 1295 }
1296 1296
1297 1297 if ((fd = open(nname, O_RDONLY, 0)) == -1) {
1298 1298 /*
1299 1299 * As the file must exist for the previous stat() to
1300 1300 * have succeeded, record the error condition.
1301 1301 */
1302 1302 rej->rej_type = SGS_REJ_STR;
1303 1303 rej->rej_str = strerror(errno);
1304 1304 } else {
1305 1305 /*
1306 1306 * Map the object. A successful return indicates that
1307 1307 * the object is appropriate for ld.so.1 processing.
1308 1308 */
1309 1309 fdp->fd_ftp = map_obj(lml, fdp, status.st_size, nname,
1310 1310 fd, rej);
1311 1311 (void) close(fd);
1312 1312
1313 1313 if (fdp->fd_ftp != NULL) {
1314 1314 fdp->fd_dev = status.st_dev;
1315 1315 fdp->fd_ino = status.st_ino;
1316 1316 return (1);
1317 1317 }
1318 1318 }
1319 1319
1320 1320 } else if (errno != ENOENT) {
1321 1321 /*
1322 1322 * If the open() failed for anything other than the file not
1323 1323 * existing, record the error condition.
1324 1324 */
1325 1325 rej->rej_type = SGS_REJ_STR;
1326 1326 rej->rej_str = strerror(errno);
1327 1327 }
1328 1328
1329 1329 /*
1330 1330 * Regardless of error, duplicate and record any full path names that
1331 1331 * can't be used on the "not-found" AVL tree.
1332 1332 */
1333 1333 if (nname[0] == '/')
1334 1334 nfavl_insert(nname, nfavlwhere);
1335 1335
1336 1336 /*
1337 1337 * Indicate any rejection.
1338 1338 */
1339 1339 if (rej->rej_type) {
1340 1340 rej->rej_name = nname;
1341 1341 if (fdp->fd_flags & FLG_FD_ALTER)
1342 1342 rej->rej_flags = FLG_REJ_ALTER;
1343 1343 DBG_CALL(Dbg_file_rejected(lml, rej, M_MACH));
1344 1344 }
1345 1345 return (0);
1346 1346 }
1347 1347
1348 1348 /*
1349 1349 * Find a full pathname (it contains a "/").
1350 1350 */
1351 1351 int
1352 1352 find_path(Lm_list *lml, Rt_map *clmp, uint_t flags, Fdesc *fdp, Rej_desc *rej,
1353 1353 int *in_nfavl)
1354 1354 {
1355 1355 const char *oname = fdp->fd_oname;
1356 1356 int err = 0;
1357 1357
1358 1358 /*
1359 1359 * If directory configuration exists determine if this path is known.
1360 1360 */
1361 1361 if (rtld_flags & RT_FL_DIRCFG) {
1362 1362 Rtc_obj *obj;
1363 1363 const char *aname;
1364 1364
1365 1365 if ((obj = elf_config_ent(oname, (Word)elf_hash(oname),
1366 1366 0, &aname)) != 0) {
1367 1367 /*
1368 1368 * If the configuration file states that this path is a
1369 1369 * directory, or the path is explicitly defined as
1370 1370 * non-existent (ie. a unused platform specific
1371 1371 * library), then go no further.
1372 1372 */
1373 1373 if (obj->co_flags & RTC_OBJ_DIRENT) {
1374 1374 err = EISDIR;
1375 1375 } else if ((obj->co_flags &
1376 1376 (RTC_OBJ_NOEXIST | RTC_OBJ_ALTER)) ==
1377 1377 RTC_OBJ_NOEXIST) {
1378 1378 err = ENOENT;
1379 1379 } else if ((obj->co_flags & RTC_OBJ_ALTER) &&
1380 1380 (rtld_flags & RT_FL_OBJALT) && (lml == &lml_main)) {
1381 1381 int ret;
1382 1382
1383 1383 fdp->fd_flags |= FLG_FD_ALTER;
1384 1384 fdp->fd_nname = aname;
1385 1385
1386 1386 /*
1387 1387 * Attempt to open the alternative path. If
1388 1388 * this fails, and the alternative is flagged
1389 1389 * as optional, fall through to open the
1390 1390 * original path.
1391 1391 */
1392 1392 DBG_CALL(Dbg_libs_found(lml, aname,
1393 1393 FLG_FD_ALTER));
1394 1394 ret = file_open(0, lml, clmp, flags, fdp,
1395 1395 rej, in_nfavl);
1396 1396 if (ret || ((obj->co_flags &
1397 1397 RTC_OBJ_OPTINAL) == 0))
1398 1398 return (ret);
1399 1399
1400 1400 fdp->fd_flags &= ~FLG_FD_ALTER;
1401 1401 }
1402 1402 }
1403 1403 }
1404 1404 DBG_CALL(Dbg_libs_found(lml, oname, 0));
1405 1405 fdp->fd_nname = oname;
1406 1406 return (file_open(err, lml, clmp, flags, fdp, rej, in_nfavl));
1407 1407 }
1408 1408
1409 1409 /*
1410 1410 * Find a simple filename (it doesn't contain a "/").
1411 1411 */
1412 1412 static int
1413 1413 _find_file(Lm_list *lml, Rt_map *clmp, uint_t flags, Fdesc *fdp, Rej_desc *rej,
1414 1414 Pdesc *pdp, int aflag, int *in_nfavl)
1415 1415 {
1416 1416 const char *nname = fdp->fd_nname;
1417 1417
1418 1418 DBG_CALL(Dbg_libs_found(lml, nname, aflag));
1419 1419 if ((lml->lm_flags & LML_FLG_TRC_SEARCH) &&
1420 1420 ((FLAGS1(clmp) & FL1_RT_LDDSTUB) == 0)) {
1421 1421 (void) printf(MSG_INTL(MSG_LDD_PTH_TRYING), nname, aflag ?
1422 1422 MSG_INTL(MSG_LDD_FIL_ALTER) : MSG_ORIG(MSG_STR_EMPTY));
1423 1423 }
1424 1424
1425 1425 /*
1426 1426 * If we're being audited tell the audit library of the file we're about
1427 1427 * to go search for. The audit library may offer an alternative
1428 1428 * dependency, or indicate that this dependency should be ignored.
1429 1429 */
1430 1430 if ((lml->lm_tflags | AFLAGS(clmp)) & LML_TFLG_AUD_OBJSEARCH) {
1431 1431 char *aname;
1432 1432
1433 1433 if ((aname = audit_objsearch(clmp, nname,
1434 1434 (pdp->pd_flags & LA_SER_MASK))) == NULL) {
1435 1435 DBG_CALL(Dbg_audit_terminate(lml, nname));
1436 1436 return (0);
1437 1437 }
1438 1438
1439 1439 if (aname != nname) {
1440 1440 fdp->fd_flags &= ~FLG_FD_SLASH;
1441 1441 fdp->fd_nname = aname;
1442 1442 }
1443 1443 }
1444 1444 return (file_open(0, lml, clmp, flags, fdp, rej, in_nfavl));
1445 1445 }
1446 1446
1447 1447 static int
1448 1448 find_file(Lm_list *lml, Rt_map *clmp, uint_t flags, Fdesc *fdp, Rej_desc *rej,
1449 1449 Pdesc *pdp, Word *strhash, int *in_nfavl)
1450 1450 {
1451 1451 static Rtc_obj Obj = { 0 };
1452 1452 Rtc_obj *dobj;
1453 1453 const char *oname = fdp->fd_oname;
1454 1454 size_t olen = strlen(oname);
1455 1455
1456 1456 if (pdp->pd_pname == NULL)
1457 1457 return (0);
1458 1458 if (pdp->pd_info) {
1459 1459 dobj = (Rtc_obj *)pdp->pd_info;
1460 1460 if ((dobj->co_flags &
1461 1461 (RTC_OBJ_NOEXIST | RTC_OBJ_ALTER)) == RTC_OBJ_NOEXIST)
1462 1462 return (0);
1463 1463 } else
1464 1464 dobj = NULL;
1465 1465
1466 1466 /*
1467 1467 * If configuration information exists see if this directory/file
1468 1468 * combination exists.
1469 1469 */
1470 1470 if ((rtld_flags & RT_FL_DIRCFG) &&
1471 1471 ((dobj == NULL) || (dobj->co_id != 0))) {
1472 1472 Rtc_obj *fobj;
1473 1473 const char *aname = NULL;
1474 1474
1475 1475 /*
1476 1476 * If this object descriptor has not yet been searched for in
1477 1477 * the configuration file go find it.
1478 1478 */
1479 1479 if (dobj == NULL) {
1480 1480 dobj = elf_config_ent(pdp->pd_pname,
1481 1481 (Word)elf_hash(pdp->pd_pname), 0, 0);
1482 1482 if (dobj == NULL)
1483 1483 dobj = &Obj;
1484 1484 pdp->pd_info = (void *)dobj;
1485 1485
1486 1486 if ((dobj->co_flags & (RTC_OBJ_NOEXIST |
1487 1487 RTC_OBJ_ALTER)) == RTC_OBJ_NOEXIST)
1488 1488 return (0);
1489 1489 }
1490 1490
1491 1491 /*
1492 1492 * If we found a directory search for the file.
1493 1493 */
1494 1494 if (dobj->co_id != 0) {
1495 1495 if (*strhash == NULL)
1496 1496 *strhash = (Word)elf_hash(oname);
1497 1497 fobj = elf_config_ent(oname, *strhash,
1498 1498 dobj->co_id, &aname);
1499 1499
1500 1500 /*
1501 1501 * If this object specifically does not exist, or the
1502 1502 * object can't be found in a know-all-entries
1503 1503 * directory, continue looking. If the object does
1504 1504 * exist determine if an alternative object exists.
1505 1505 */
1506 1506 if (fobj == NULL) {
1507 1507 if (dobj->co_flags & RTC_OBJ_ALLENTS)
1508 1508 return (0);
1509 1509 } else {
1510 1510 if ((fobj->co_flags & (RTC_OBJ_NOEXIST |
1511 1511 RTC_OBJ_ALTER)) == RTC_OBJ_NOEXIST)
1512 1512 return (0);
1513 1513
1514 1514 if ((fobj->co_flags & RTC_OBJ_ALTER) &&
1515 1515 (rtld_flags & RT_FL_OBJALT) &&
1516 1516 (lml == &lml_main)) {
1517 1517 int ret;
1518 1518
1519 1519 fdp->fd_flags |= FLG_FD_ALTER;
1520 1520 fdp->fd_nname = aname;
1521 1521
1522 1522 /*
1523 1523 * Attempt to open the alternative path.
1524 1524 * If this fails, and the alternative is
1525 1525 * flagged as optional, fall through to
1526 1526 * open the original path.
1527 1527 */
1528 1528 ret = _find_file(lml, clmp, flags, fdp,
1529 1529 rej, pdp, 1, in_nfavl);
1530 1530 if (ret || ((fobj->co_flags &
1531 1531 RTC_OBJ_OPTINAL) == 0))
1532 1532 return (ret);
1533 1533
1534 1534 fdp->fd_flags &= ~FLG_FD_ALTER;
1535 1535 }
↓ open down ↓ |
1535 lines elided |
↑ open up ↑ |
1536 1536 }
1537 1537 }
1538 1538 }
1539 1539
1540 1540 /*
1541 1541 * Protect ourselves from building an invalid pathname.
1542 1542 */
1543 1543 if ((olen + pdp->pd_plen + 1) >= PATH_MAX) {
1544 1544 eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN), oname,
1545 1545 strerror(ENAMETOOLONG));
1546 - return (0);
1546 + return (0);
1547 1547 }
1548 1548 if ((fdp->fd_nname = (LM_GET_SO(clmp)(pdp->pd_pname, oname,
1549 1549 pdp->pd_plen, olen))) == NULL)
1550 1550 return (0);
1551 1551
1552 1552 return (_find_file(lml, clmp, flags, fdp, rej, pdp, 0, in_nfavl));
1553 1553 }
1554 1554
1555 1555 static Fct *Vector[] = {
1556 1556 &elf_fct,
1557 1557 #ifdef A_OUT
1558 1558 &aout_fct,
1559 1559 #endif
1560 1560 0
1561 1561 };
1562 1562
1563 1563 /*
1564 1564 * Remap the first page of a file to provide a better diagnostic as to why
1565 1565 * an mmapobj(2) operation on this file failed. Sadly, mmapobj(), and all
1566 1566 * system calls for that matter, only pass back a generic failure in errno.
1567 1567 * Hopefully one day this will be improved, but in the mean time we repeat
1568 1568 * the kernels ELF verification to try and provide more detailed information.
1569 1569 */
1570 1570 static int
1571 1571 map_fail(Fdesc *fdp, size_t fsize, const char *name, int fd, Rej_desc *rej)
1572 1572 {
1573 1573 caddr_t addr;
1574 1574 int vnum;
1575 1575 size_t size;
1576 1576
1577 1577 /*
1578 1578 * Use the original file size to determine what to map, and catch the
1579 1579 * obvious error of a zero sized file.
1580 1580 */
1581 1581 if (fsize == 0) {
1582 1582 rej->rej_type = SGS_REJ_UNKFILE;
1583 1583 return (1);
1584 1584 } else if (fsize < syspagsz)
1585 1585 size = fsize;
1586 1586 else
1587 1587 size = syspagsz;
1588 1588
1589 1589 if ((addr = mmap(0, size, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED)
1590 1590 return (0);
1591 1591
1592 1592 rej->rej_type = 0;
1593 1593
1594 1594 /*
1595 1595 * Validate the file against each supported file type. Should a
1596 1596 * characteristic of the file be found invalid for this platform, a
1597 1597 * rejection message will have been recorded.
1598 1598 */
1599 1599 for (vnum = 0; Vector[vnum]; vnum++) {
1600 1600 if (((Vector[vnum]->fct_verify_file)(addr, size,
1601 1601 fdp, name, rej) == 0) && rej->rej_type)
1602 1602 break;
1603 1603 }
1604 1604
1605 1605 /*
1606 1606 * If no rejection message has been recorded, then this is simply an
1607 1607 * unknown file type.
1608 1608 */
1609 1609 if (rej->rej_type == 0)
1610 1610 rej->rej_type = SGS_REJ_UNKFILE;
1611 1611
1612 1612 (void) munmap(addr, size);
1613 1613 return (1);
1614 1614 }
1615 1615
1616 1616 /*
1617 1617 * Unmap a file.
1618 1618 */
1619 1619 void
1620 1620 unmap_obj(mmapobj_result_t *mpp, uint_t mapnum)
1621 1621 {
1622 1622 uint_t num;
1623 1623
1624 1624 for (num = 0; num < mapnum; num++) {
1625 1625 /* LINTED */
1626 1626 (void) munmap((void *)(uintptr_t)mpp[num].mr_addr,
1627 1627 mpp[num].mr_msize);
1628 1628 }
1629 1629 cnt_unmap++;
1630 1630 }
1631 1631
1632 1632 /*
1633 1633 * Map a file.
1634 1634 */
1635 1635 Fct *
1636 1636 map_obj(Lm_list *lml, Fdesc *fdp, size_t fsize, const char *name, int fd,
1637 1637 Rej_desc *rej)
1638 1638 {
1639 1639 static mmapobj_result_t *smpp = NULL;
1640 1640 static uint_t smapnum;
1641 1641 mmapobj_result_t *mpp;
1642 1642 uint_t mnum, mapnum, mflags;
1643 1643 void *padding;
1644 1644
1645 1645 /*
1646 1646 * Allocate an initial mapping array. The initial size should be large
1647 1647 * enough to handle the normal ELF objects we come across.
1648 1648 */
1649 1649 if (smpp == NULL) {
1650 1650 smpp = malloc(sizeof (mmapobj_result_t) * MMAPFD_NUM);
1651 1651 if (smpp == NULL)
1652 1652 return (NULL);
1653 1653 smapnum = MMAPFD_NUM;
1654 1654 }
1655 1655
1656 1656 /*
1657 1657 * If object padding is required, set the necessary flags.
1658 1658 */
1659 1659 if (r_debug.rtd_objpad) {
1660 1660 mflags = MMOBJ_INTERPRET | MMOBJ_PADDING;
1661 1661 padding = &r_debug.rtd_objpad;
1662 1662 } else {
1663 1663 mflags = MMOBJ_INTERPRET;
1664 1664 padding = NULL;
1665 1665 }
1666 1666
1667 1667 /*
1668 1668 * Map the file. If the number of mappings required by this file
1669 1669 * exceeds the present mapping structure, an error indicating the
1670 1670 * return data is too big is returned. Bail on any other error.
1671 1671 */
1672 1672 mapnum = smapnum;
1673 1673 if (mmapobj(fd, mflags, smpp, &mapnum, padding) == -1) {
1674 1674 if (errno != E2BIG) {
1675 1675 int err = errno;
1676 1676
1677 1677 /*
1678 1678 * An unsupported error indicates that there's something
1679 1679 * incompatible with this ELF file, and the process that
1680 1680 * is already running. Map the first page of the file
1681 1681 * and see if we can generate a better error message.
1682 1682 */
1683 1683 if ((errno == ENOTSUP) && map_fail(fdp, fsize, name,
1684 1684 fd, rej))
1685 1685 return (NULL);
1686 1686
1687 1687 rej->rej_type = SGS_REJ_STR;
1688 1688 rej->rej_str = strerror(err);
1689 1689 return (NULL);
1690 1690 }
1691 1691
1692 1692 /*
1693 1693 * The mapping requirement exceeds the present mapping
1694 1694 * structure, however the number of mapping required is
1695 1695 * available in the mapping number.
1696 1696 */
1697 1697 free((void *)smpp);
1698 1698 if ((smpp = malloc(sizeof (mmapobj_result_t) * mapnum)) == NULL)
1699 1699 return (NULL);
1700 1700 smapnum = mapnum;
1701 1701
1702 1702 /*
1703 1703 * With the appropriate mapping structure, try the mapping
1704 1704 * request again.
1705 1705 */
1706 1706 if (mmapobj(fd, mflags, smpp, &mapnum, padding) == -1) {
1707 1707 rej->rej_type = SGS_REJ_STR;
1708 1708 rej->rej_str = strerror(errno);
1709 1709 return (NULL);
1710 1710 }
1711 1711 }
1712 1712 ASSERT(mapnum != 0);
1713 1713
1714 1714 /*
1715 1715 * Traverse the mappings in search of a file type ld.so.1 can process.
1716 1716 * If the file type is verified as one ld.so.1 can process, retain the
1717 1717 * mapping information, and the number of mappings this object uses,
1718 1718 * and clear the static mapping pointer for the next map_obj() use of
1719 1719 * mmapobj().
1720 1720 */
1721 1721 DBG_CALL(Dbg_file_mmapobj(lml, name, smpp, mapnum));
1722 1722 cnt_map++;
1723 1723
1724 1724 for (mnum = 0, mpp = smpp; mnum < mapnum; mnum++, mpp++) {
1725 1725 uint_t flags = (mpp->mr_flags & MR_TYPE_MASK);
1726 1726 Fct *fptr = NULL;
1727 1727
1728 1728 if (flags == MR_HDR_ELF) {
1729 1729 fptr = elf_verify((mpp->mr_addr + mpp->mr_offset),
1730 1730 mpp->mr_fsize, fdp, name, rej);
1731 1731 }
1732 1732 #ifdef A_OUT
1733 1733 if (flags == MR_HDR_AOUT) {
1734 1734 fptr = aout_verify((mpp->mr_addr + mpp->mr_offset),
1735 1735 mpp->mr_fsize, fdp, name, rej);
1736 1736 }
1737 1737 #endif
1738 1738 if (fptr) {
1739 1739 fdp->fd_mapn = mapnum;
1740 1740 fdp->fd_mapp = smpp;
1741 1741
1742 1742 smpp = NULL;
1743 1743
1744 1744 return (fptr);
1745 1745 }
1746 1746 }
1747 1747
1748 1748 /*
1749 1749 * If the mapped file is inappropriate, indicate that the file type is
1750 1750 * unknown, and free the mapping.
1751 1751 */
1752 1752 if (rej->rej_type == 0)
1753 1753 rej->rej_type = SGS_REJ_UNKFILE;
1754 1754 unmap_obj(smpp, mapnum);
1755 1755
1756 1756 return (NULL);
1757 1757 }
1758 1758
1759 1759 /*
1760 1760 * A unique file has been opened. Create a link-map to represent it, and
1761 1761 * process the various names by which it can be referenced.
1762 1762 */
1763 1763 Rt_map *
1764 1764 load_file(Lm_list *lml, Aliste lmco, Rt_map *clmp, Fdesc *fdp, int *in_nfavl)
1765 1765 {
1766 1766 mmapobj_result_t *fpmpp = NULL, *fmpp = NULL, *lpmpp, *lmpp;
1767 1767 mmapobj_result_t *hmpp, *mpp, *ompp = fdp->fd_mapp;
1768 1768 uint_t mnum, omapnum = fdp->fd_mapn;
1769 1769 const char *nname = fdp->fd_nname;
1770 1770 Rt_map *nlmp;
1771 1771 Ehdr *ehdr = NULL;
1772 1772
1773 1773 /*
1774 1774 * Traverse the mappings for the input file to capture generic mapping
1775 1775 * information, and create a link-map to represent the file.
1776 1776 */
1777 1777 for (mnum = 0, mpp = ompp; mnum < omapnum; mnum++, mpp++) {
1778 1778 uint_t flags = (mpp->mr_flags & MR_TYPE_MASK);
1779 1779
1780 1780 /*
1781 1781 * Keep track of the first and last mappings that may include
1782 1782 * padding.
1783 1783 */
1784 1784 if (fpmpp == NULL)
1785 1785 fpmpp = mpp;
1786 1786 lpmpp = mpp;
1787 1787
1788 1788 /*
1789 1789 * Keep track of the first and last mappings that do not include
1790 1790 * padding.
1791 1791 */
1792 1792 if (flags != MR_PADDING) {
1793 1793 if (fmpp == NULL)
1794 1794 fmpp = mpp;
1795 1795 lmpp = mpp;
1796 1796 }
1797 1797 if (flags == MR_HDR_ELF) {
1798 1798 /* LINTED */
1799 1799 ehdr = (Ehdr *)(mpp->mr_addr + mpp->mr_offset);
1800 1800 hmpp = mpp;
1801 1801 } else if (flags == MR_HDR_AOUT)
1802 1802 hmpp = mpp;
1803 1803 }
1804 1804
1805 1805 /*
1806 1806 * The only ELF files we can handle are ET_EXEC, ET_DYN, and ET_REL.
1807 1807 *
1808 1808 * ET_REL must be processed by ld(1) to create an in-memory ET_DYN.
1809 1809 * The initial processing carried out by elf_obj_file() creates a
1810 1810 * temporary link-map, that acts as a place holder, until the objects
1811 1811 * processing is finished with elf_obj_fini().
1812 1812 */
1813 1813 if (ehdr && (ehdr->e_type == ET_REL)) {
1814 1814 if ((nlmp = elf_obj_file(lml, lmco, clmp, nname, hmpp, ompp,
1815 1815 omapnum)) == NULL)
1816 1816 return (nlmp);
1817 1817 } else {
1818 1818 Addr addr;
1819 1819 size_t msize;
1820 1820
1821 1821 /*
1822 1822 * The size of the total reservation, and the padding range,
1823 1823 * are a historic artifact required by debuggers. Although
1824 1824 * these values express the range of the associated mappings,
1825 1825 * there can be holes between segments (in which small objects
1826 1826 * could be mapped). Anyone who needs to verify offsets
1827 1827 * against segments should analyze all the object mappings,
1828 1828 * rather than relying on these address ranges.
1829 1829 */
1830 1830 addr = (Addr)(hmpp->mr_addr + hmpp->mr_offset);
1831 1831 msize = lmpp->mr_addr + lmpp->mr_msize - fmpp->mr_addr;
1832 1832
1833 1833 if ((nlmp = ((fdp->fd_ftp)->fct_new_lmp)(lml, lmco, fdp, addr,
1834 1834 msize, NULL, clmp, in_nfavl)) == NULL)
1835 1835 return (NULL);
1836 1836
1837 1837 /*
1838 1838 * Save generic mapping information.
1839 1839 */
1840 1840 MMAPS(nlmp) = ompp;
1841 1841 MMAPCNT(nlmp) = omapnum;
1842 1842 PADSTART(nlmp) = (ulong_t)fpmpp->mr_addr;
1843 1843 PADIMLEN(nlmp) = lpmpp->mr_addr + lpmpp->mr_msize -
1844 1844 fpmpp->mr_addr;
1845 1845 }
1846 1846
1847 1847 /*
1848 1848 * Save the dev/inode information for later comparisons, and identify
1849 1849 * this as a new object.
1850 1850 */
1851 1851 STDEV(nlmp) = fdp->fd_dev;
1852 1852 STINO(nlmp) = fdp->fd_ino;
1853 1853 FLAGS(nlmp) |= FLG_RT_NEWLOAD;
1854 1854
1855 1855 /*
1856 1856 * If this is ELF relocatable object, we're done for now.
1857 1857 */
1858 1858 if (ehdr && (ehdr->e_type == ET_REL))
1859 1859 return (nlmp);
1860 1860
1861 1861 /*
1862 1862 * Insert the names of this link-map into the FullPathNode AVL tree.
1863 1863 * Save both the NAME() and PATHNAME() if the names differ.
1864 1864 */
1865 1865 (void) fullpath(nlmp, fdp);
1866 1866
1867 1867 if ((NAME(nlmp)[0] == '/') && (fpavl_insert(lml, nlmp, NAME(nlmp),
1868 1868 fdp->fd_avlwhere) == 0)) {
1869 1869 remove_so(lml, nlmp, clmp);
1870 1870 return (NULL);
1871 1871 }
1872 1872 if (((NAME(nlmp)[0] != '/') || (NAME(nlmp) != PATHNAME(nlmp))) &&
1873 1873 (fpavl_insert(lml, nlmp, PATHNAME(nlmp), 0) == 0)) {
1874 1874 remove_so(lml, nlmp, clmp);
1875 1875 return (NULL);
1876 1876 }
1877 1877
1878 1878 /*
1879 1879 * If this is a secure application, record any full path name directory
1880 1880 * in which this dependency has been found. This directory can be
1881 1881 * deemed safe (as we've already found a dependency here). This
1882 1882 * recording provides a fall-back should another objects $ORIGIN
1883 1883 * definition expands to this directory, an expansion that would
1884 1884 * ordinarily be deemed insecure.
1885 1885 */
1886 1886 if (rtld_flags & RT_FL_SECURE) {
1887 1887 if (NAME(nlmp)[0] == '/')
1888 1888 spavl_insert(NAME(nlmp));
1889 1889 if ((NAME(nlmp) != PATHNAME(nlmp)) &&
1890 1890 (PATHNAME(nlmp)[0] == '/'))
1891 1891 spavl_insert(PATHNAME(nlmp));
1892 1892 }
1893 1893
1894 1894 /*
1895 1895 * If we're processing an alternative object reset the original name
1896 1896 * for possible $ORIGIN processing.
1897 1897 */
1898 1898 if (fdp->fd_flags & FLG_FD_ALTER) {
1899 1899 const char *odir, *ndir;
1900 1900 size_t olen;
1901 1901
1902 1902 FLAGS(nlmp) |= FLG_RT_ALTER;
1903 1903
1904 1904 /*
1905 1905 * If we were given a pathname containing a slash then the
1906 1906 * original name is still in oname. Otherwise the original
1907 1907 * directory is in dir->p_name (which is all we need for
1908 1908 * $ORIGIN).
1909 1909 */
1910 1910 if (fdp->fd_flags & FLG_FD_SLASH) {
1911 1911 char *ofil;
1912 1912
1913 1913 odir = fdp->fd_oname;
1914 1914 ofil = strrchr(fdp->fd_oname, '/');
1915 1915 olen = ofil - odir + 1;
1916 1916 } else {
1917 1917 odir = fdp->fd_odir;
1918 1918 olen = strlen(odir) + 1;
1919 1919 }
1920 1920 if ((ndir = stravl_insert(odir, 0, olen, 1)) == NULL) {
1921 1921 remove_so(lml, nlmp, clmp);
1922 1922 return (NULL);
1923 1923 }
1924 1924 ORIGNAME(nlmp) = ndir;
1925 1925 DIRSZ(nlmp) = --olen;
1926 1926 }
1927 1927
1928 1928 return (nlmp);
1929 1929 }
1930 1930
1931 1931 /*
1932 1932 * This function loads the named file and returns a pointer to its link map.
1933 1933 * It is assumed that the caller has already checked that the file is not
1934 1934 * already loaded before calling this function (refer is_so_loaded()).
1935 1935 * Find and open the file, map it into memory, add it to the end of the list
1936 1936 * of link maps and return a pointer to the new link map. Return 0 on error.
1937 1937 */
1938 1938 static Rt_map *
1939 1939 load_so(Lm_list *lml, Aliste lmco, Rt_map *clmp, uint_t flags,
1940 1940 Fdesc *fdp, Rej_desc *rej, int *in_nfavl)
1941 1941 {
1942 1942 const char *oname = fdp->fd_oname;
1943 1943 Pdesc *pdp;
1944 1944
1945 1945 /*
1946 1946 * If this path name hasn't already been identified as containing a
1947 1947 * slash, check the path name. Most paths have been constructed
1948 1948 * through appending a file name to a search path, and/or have been
1949 1949 * inspected by expand(), and thus have a slash. However, we can
1950 1950 * receive path names via auditors or configuration files, and thus
1951 1951 * an evaluation here catches these instances.
1952 1952 */
1953 1953 if ((fdp->fd_flags & FLG_FD_SLASH) == 0) {
1954 1954 const char *str;
1955 1955
1956 1956 for (str = oname; *str; str++) {
1957 1957 if (*str == '/') {
1958 1958 fdp->fd_flags |= FLG_FD_SLASH;
1959 1959 break;
1960 1960 }
1961 1961 }
1962 1962 }
1963 1963
1964 1964 /*
1965 1965 * If we are passed a 'null' link-map this means that this is the first
1966 1966 * object to be loaded on this link-map list. In that case we set the
1967 1967 * link-map to ld.so.1's link-map.
1968 1968 *
1969 1969 * This link-map is referenced to determine what lookup rules to use
1970 1970 * when searching for files. By using ld.so.1's we are defaulting to
1971 1971 * ELF look-up rules.
1972 1972 *
1973 1973 * Note: This case happens when loading the first object onto
1974 1974 * the plt_tracing link-map.
1975 1975 */
1976 1976 if (clmp == 0)
1977 1977 clmp = lml_rtld.lm_head;
1978 1978
1979 1979 /*
1980 1980 * If this path resulted from a $CAPABILITY specification, then the
1981 1981 * best capability object has already been establish, and is available
1982 1982 * in the calling file descriptor. Perform some minor book-keeping so
1983 1983 * that we can fall through into common code.
1984 1984 */
1985 1985 if (flags & FLG_RT_CAP) {
1986 1986 /*
1987 1987 * If this object is already loaded, we're done.
1988 1988 */
1989 1989 if (fdp->fd_lmp)
1990 1990 return (fdp->fd_lmp);
1991 1991
1992 1992 /*
1993 1993 * Obtain the avl index for this object.
1994 1994 */
1995 1995 (void) fpavl_recorded(lml, fdp->fd_nname, 0,
1996 1996 &(fdp->fd_avlwhere));
1997 1997
1998 1998 } else if (fdp->fd_flags & FLG_FD_SLASH) {
1999 1999 Rej_desc _rej = { 0 };
2000 2000
2001 2001 if (find_path(lml, clmp, flags, fdp, &_rej, in_nfavl) == 0) {
2002 2002 rejection_inherit(rej, &_rej);
2003 2003 return (NULL);
2004 2004 }
2005 2005
2006 2006 /*
2007 2007 * If this object is already loaded, we're done.
2008 2008 */
2009 2009 if (fdp->fd_lmp)
2010 2010 return (fdp->fd_lmp);
2011 2011
2012 2012 } else {
2013 2013 /*
2014 2014 * No '/' - for each directory on list, make a pathname using
2015 2015 * that directory and filename and try to open that file.
2016 2016 */
2017 2017 Spath_desc sd = { search_rules, NULL, 0 };
2018 2018 Word strhash = 0;
2019 2019 int found = 0;
2020 2020
2021 2021 /*
2022 2022 * Traverse the search path lists, creating full pathnames and
2023 2023 * attempt to load each path.
2024 2024 */
2025 2025 for (pdp = get_next_dir(&sd, clmp, flags); pdp;
2026 2026 pdp = get_next_dir(&sd, clmp, flags)) {
2027 2027 Rej_desc _rej = { 0 };
2028 2028 Fdesc fd = { 0 };
2029 2029
2030 2030 /*
2031 2031 * Under debugging, duplicate path name entries are
2032 2032 * tagged but remain part of the search path list so
2033 2033 * that they can be diagnosed under "unused" processing.
2034 2034 * Skip these entries, as this path would have already
2035 2035 * been attempted.
2036 2036 */
2037 2037 if (pdp->pd_flags & PD_FLG_DUPLICAT)
2038 2038 continue;
2039 2039
2040 2040 fd = *fdp;
2041 2041
2042 2042 /*
2043 2043 * Try and locate this file. Make sure to clean up
2044 2044 * any rejection information should the file have
2045 2045 * been found, but not appropriate.
2046 2046 */
2047 2047 if (find_file(lml, clmp, flags, &fd, &_rej, pdp,
2048 2048 &strhash, in_nfavl) == 0) {
2049 2049 rejection_inherit(rej, &_rej);
2050 2050 continue;
2051 2051 }
2052 2052
2053 2053 /*
2054 2054 * Indicate that this search path has been used. If
2055 2055 * this is an LD_LIBRARY_PATH setting, ignore any use
2056 2056 * by ld.so.1 itself.
2057 2057 */
2058 2058 if (((pdp->pd_flags & LA_SER_LIBPATH) == 0) ||
2059 2059 ((lml->lm_flags & LML_FLG_RTLDLM) == 0))
2060 2060 pdp->pd_flags |= PD_FLG_USED;
2061 2061
2062 2062 /*
2063 2063 * If this object is already loaded, we're done.
2064 2064 */
2065 2065 *fdp = fd;
2066 2066 if (fdp->fd_lmp)
2067 2067 return (fdp->fd_lmp);
2068 2068
2069 2069 fdp->fd_odir = pdp->pd_pname;
2070 2070 found = 1;
2071 2071 break;
2072 2072 }
2073 2073
2074 2074 /*
2075 2075 * If the file couldn't be loaded, do another comparison of
2076 2076 * loaded files using just the basename. This catches folks
2077 2077 * who may have loaded multiple full pathname files (possibly
2078 2078 * from setxid applications) to satisfy dependency relationships
2079 2079 * (i.e., a file might have a dependency on foo.so.1 which has
2080 2080 * already been opened using its full pathname).
2081 2081 */
2082 2082 if (found == 0)
2083 2083 return (is_so_loaded(lml, oname, in_nfavl));
2084 2084 }
2085 2085
2086 2086 /*
2087 2087 * Trace that this successfully opened file is about to be processed.
2088 2088 * Note, as part of processing a family of hardware capabilities filtees
2089 2089 * a number of candidates may have been opened and mapped to determine
2090 2090 * their capability requirements. At this point we've decided which
2091 2091 * of the candidates to use.
2092 2092 */
2093 2093 if (lml->lm_flags & LML_FLG_TRC_ENABLE) {
2094 2094 trace_so(clmp, 0, fdp->fd_oname, fdp->fd_nname,
2095 2095 (fdp->fd_flags & FLG_FD_ALTER), 0);
2096 2096 }
2097 2097
2098 2098 /*
2099 2099 * Finish mapping the file and return the link-map descriptor.
2100 2100 */
2101 2101 return (load_file(lml, lmco, clmp, fdp, in_nfavl));
2102 2102 }
2103 2103
2104 2104 /*
2105 2105 * Trace an attempt to load an object, and seed the originating name.
2106 2106 */
2107 2107 const char *
2108 2108 load_trace(Lm_list *lml, Pdesc *pdp, Rt_map *clmp, Fdesc *fdp)
2109 2109 {
2110 2110 const char *name = pdp->pd_pname;
2111 2111
2112 2112 DBG_CALL(Dbg_libs_find(lml, name));
2113 2113
2114 2114 /*
2115 2115 * First generate any ldd(1) diagnostics.
2116 2116 */
2117 2117 if ((lml->lm_flags & (LML_FLG_TRC_VERBOSE | LML_FLG_TRC_SEARCH)) &&
2118 2118 ((FLAGS1(clmp) & FL1_RT_LDDSTUB) == 0))
2119 2119 (void) printf(MSG_INTL(MSG_LDD_FIL_FIND), name, NAME(clmp));
2120 2120
2121 2121 /*
2122 2122 * Propagate any knowledge of a slash within the path name.
2123 2123 */
2124 2124 if (pdp->pd_flags & PD_FLG_PNSLASH)
2125 2125 fdp->fd_flags |= FLG_FD_SLASH;
2126 2126
2127 2127 /*
2128 2128 * If we're being audited tell any audit libraries of the file we're
2129 2129 * about to go search for.
2130 2130 */
2131 2131 if (aud_activity ||
2132 2132 ((lml->lm_tflags | AFLAGS(clmp)) & LML_TFLG_AUD_ACTIVITY))
2133 2133 audit_activity(clmp, LA_ACT_ADD);
2134 2134
2135 2135 if ((lml->lm_tflags | AFLAGS(clmp)) & LML_TFLG_AUD_OBJSEARCH) {
2136 2136 char *aname;
2137 2137
2138 2138 /*
2139 2139 * The auditor can indicate that this object should be ignored.
2140 2140 */
2141 2141 if ((aname =
2142 2142 audit_objsearch(clmp, name, LA_SER_ORIG)) == NULL) {
2143 2143 DBG_CALL(Dbg_audit_terminate(lml, name));
2144 2144 return (NULL);
2145 2145 }
2146 2146
2147 2147 if (name != aname) {
2148 2148 fdp->fd_flags &= ~FLG_FD_SLASH;
2149 2149 name = aname;
2150 2150 }
2151 2151 }
2152 2152 fdp->fd_oname = name;
2153 2153 return (name);
2154 2154 }
2155 2155
2156 2156 /*
2157 2157 * Having loaded an object and created a link-map to describe it, finish
2158 2158 * processing this stage, including verifying any versioning requirements,
2159 2159 * updating the objects mode, creating a handle if necessary, and adding this
2160 2160 * object to existing handles if required.
2161 2161 */
2162 2162 static int
2163 2163 load_finish(Lm_list *lml, const char *name, Rt_map *clmp, int nmode,
2164 2164 uint_t flags, Grp_hdl **hdl, Rt_map *nlmp)
2165 2165 {
2166 2166 Aliste idx1;
2167 2167 Grp_hdl *ghp;
2168 2168 int promote;
2169 2169 uint_t rdflags;
2170 2170
2171 2171 /*
2172 2172 * If this dependency is associated with a required version ensure that
2173 2173 * the version is present in the loaded file.
2174 2174 */
2175 2175 if (((rtld_flags & RT_FL_NOVERSION) == 0) && THIS_IS_ELF(clmp) &&
2176 2176 VERNEED(clmp) && (elf_verify_vers(name, clmp, nlmp) == 0))
2177 2177 return (0);
2178 2178
2179 2179 /*
2180 2180 * If this object has indicated that it should be isolated as a group
2181 2181 * (DT_FLAGS_1 contains DF_1_GROUP - object was built with -B group),
2182 2182 * or if the callers direct bindings indicate it should be isolated as
2183 2183 * a group (DYNINFO flags contains FLG_DI_GROUP - dependency following
2184 2184 * -zgroupperm), establish the appropriate mode.
2185 2185 *
2186 2186 * The intent of an object defining itself as a group is to isolate the
2187 2187 * relocation of the group within its own members, however, unless
2188 2188 * opened through dlopen(), in which case we assume dlsym() will be used
2189 2189 * to locate symbols in the new object, we still need to associate the
2190 2190 * new object with the caller so that the caller can bind to this new
2191 2191 * object. This is equivalent to a dlopen(RTLD_GROUP) and dlsym()
2192 2192 * using the returned handle.
2193 2193 */
2194 2194 if ((FLAGS(nlmp) | flags) & FLG_RT_SETGROUP) {
2195 2195 nmode &= ~RTLD_WORLD;
2196 2196 nmode |= RTLD_GROUP;
2197 2197
2198 2198 /*
2199 2199 * If the object wasn't explicitly dlopen()'ed, in which case a
2200 2200 * handle would have been requested, associate the object with
2201 2201 * the parent.
2202 2202 */
2203 2203 if ((flags & FLG_RT_PUBHDL) == 0)
2204 2204 nmode |= RTLD_PARENT;
2205 2205 }
2206 2206
2207 2207 /*
2208 2208 * Establish new mode and flags.
2209 2209 */
2210 2210 promote = update_mode(nlmp, MODE(nlmp), nmode);
2211 2211 FLAGS(nlmp) |= flags;
2212 2212
2213 2213 /*
2214 2214 * Establish the flags for any referenced dependency descriptors
2215 2215 * (Grp_desc).
2216 2216 *
2217 2217 * - The referenced object is available for dlsym().
2218 2218 * - The referenced object is available to relocate against.
2219 2219 * - The referenced object should have it's dependencies
2220 2220 * added to this handle
2221 2221 */
2222 2222 rdflags = (GPD_DLSYM | GPD_RELOC | GPD_ADDEPS);
2223 2223
2224 2224 /*
2225 2225 * If we've been asked to establish a handle create one for this object.
2226 2226 * Or, if this object has already been analyzed, but this reference
2227 2227 * requires that the mode of the object be promoted, create a private
2228 2228 * handle to propagate the new modes to all this objects dependencies.
2229 2229 */
2230 2230 if ((FLAGS(nlmp) & (FLG_RT_PUBHDL | FLG_RT_PRIHDL)) ||
2231 2231 (promote && (FLAGS(nlmp) & FLG_RT_ANALYZED))) {
2232 2232 uint_t oflags, hflags, cdflags = 0;
2233 2233
2234 2234 /*
2235 2235 * Establish any flags for the handle (Grp_hdl).
2236 2236 *
2237 2237 * - Public handles establish dependencies between objects
2238 2238 * that must be taken into account when dlclose()'ing
2239 2239 * objects. Private handles provide for collecting
2240 2240 * dependencies, but do not affect dlclose(). Note that
2241 2241 * a handle may already exist, but the public/private
2242 2242 * state is set to trigger the required propagation of the
2243 2243 * handle's flags and any dependency gathering.
2244 2244 * - Use of the RTLD_FIRST flag indicates that only the first
2245 2245 * dependency on the handle (the new object) can be used
2246 2246 * to satisfy dlsym() requests.
2247 2247 */
2248 2248 if (FLAGS(nlmp) & FLG_RT_PUBHDL)
2249 2249 hflags = GPH_PUBLIC;
2250 2250 else
2251 2251 hflags = GPH_PRIVATE;
2252 2252
2253 2253 if (nmode & RTLD_FIRST)
2254 2254 hflags |= GPH_FIRST;
2255 2255
2256 2256 /*
2257 2257 * Establish the flags for this callers dependency descriptor
2258 2258 * (Grp_desc).
2259 2259 *
2260 2260 * - The creation of a public handle creates a descriptor
2261 2261 * for the referenced object and the caller (parent).
2262 2262 * Typically, the handle is created for dlopen() or for
2263 2263 * filtering. A private handle does not need to maintain
2264 2264 * a descriptor to the parent.
2265 2265 * - Use of the RTLD_PARENT flag indicates that the parent
2266 2266 * can be relocated against.
2267 2267 */
2268 2268 if (FLAGS(nlmp) & FLG_RT_PUBHDL) {
2269 2269 cdflags |= GPD_PARENT;
2270 2270 if (nmode & RTLD_PARENT)
2271 2271 cdflags |= GPD_RELOC;
2272 2272 }
2273 2273
2274 2274 /*
2275 2275 * Now that the handle flags have been established, remove any
2276 2276 * handle definition from the referenced object so that the
2277 2277 * definitions don't mistakenly get inherited by a dependency.
2278 2278 */
2279 2279 oflags = FLAGS(nlmp);
2280 2280 FLAGS(nlmp) &= ~(FLG_RT_PUBHDL | FLG_RT_PRIHDL);
2281 2281
2282 2282 DBG_CALL(Dbg_file_hdl_title(DBG_HDL_ADD));
2283 2283 if ((ghp = hdl_create(lml, nlmp, clmp, hflags, rdflags,
2284 2284 cdflags)) == NULL)
2285 2285 return (0);
2286 2286
2287 2287 /*
2288 2288 * Add any dependencies that are already loaded, to the handle.
2289 2289 */
2290 2290 if (hdl_initialize(ghp, nlmp, nmode, promote) == 0)
2291 2291 return (0);
2292 2292
2293 2293 if (hdl)
2294 2294 *hdl = ghp;
2295 2295
2296 2296 /*
2297 2297 * If we were asked to create a public handle, we're done.
2298 2298 *
2299 2299 * If this is a private handle request, then the handle is left
2300 2300 * intact with a GPH_PRIVATE identifier. This handle is a
2301 2301 * convenience for processing the dependencies of this object,
2302 2302 * but does not affect how this object might be dlclose()'d.
2303 2303 * For a private handle, fall through to carry out any group
2304 2304 * processing.
2305 2305 */
2306 2306 if (oflags & FLG_RT_PUBHDL)
2307 2307 return (1);
2308 2308 }
2309 2309
2310 2310 /*
2311 2311 * If the caller isn't part of a group we're done.
2312 2312 */
2313 2313 if (GROUPS(clmp) == NULL)
2314 2314 return (1);
2315 2315
2316 2316 /*
2317 2317 * Determine if our caller is already associated with a handle, if so
2318 2318 * we need to add this object to any handles that already exist.
2319 2319 * Traverse the list of groups our caller is a member of and add this
2320 2320 * new link-map to those groups.
2321 2321 */
2322 2322 for (APLIST_TRAVERSE(GROUPS(clmp), idx1, ghp)) {
2323 2323 Aliste idx2;
2324 2324 Grp_desc *gdp;
2325 2325 int ale;
2326 2326 Rt_map *dlmp1;
2327 2327 APlist *lmalp = NULL;
2328 2328
2329 2329 DBG_CALL(Dbg_file_hdl_title(DBG_HDL_ADD));
2330 2330
2331 2331 /*
2332 2332 * If the caller doesn't indicate that its dependencies should
2333 2333 * be added to a handle, ignore it. This case identifies a
2334 2334 * parent of a dlopen(RTLD_PARENT) request.
2335 2335 */
2336 2336 for (ALIST_TRAVERSE(ghp->gh_depends, idx2, gdp)) {
2337 2337 if (gdp->gd_depend == clmp)
2338 2338 break;
2339 2339 }
2340 2340 if ((gdp->gd_flags & GPD_ADDEPS) == 0)
2341 2341 continue;
2342 2342
2343 2343 if ((gdp = hdl_add(ghp, nlmp, rdflags, &ale)) == NULL)
2344 2344 return (0);
2345 2345
2346 2346 /*
2347 2347 * If this member already exists then its dependencies will
2348 2348 * have already been processed.
2349 2349 */
2350 2350 if (ale == ALE_EXISTS)
2351 2351 continue;
2352 2352
2353 2353 /*
2354 2354 * If the object we've added has just been opened, it will not
2355 2355 * yet have been processed for its dependencies, these will be
2356 2356 * added on later calls to load_one(). If it doesn't have any
2357 2357 * dependencies we're also done.
2358 2358 */
2359 2359 if (((FLAGS(nlmp) & FLG_RT_ANALYZED) == 0) ||
2360 2360 (DEPENDS(nlmp) == NULL))
2361 2361 continue;
2362 2362
2363 2363 /*
2364 2364 * Otherwise, this object exists and has dependencies, so add
2365 2365 * all of its dependencies to the handle were operating on.
2366 2366 */
2367 2367 if (aplist_append(&lmalp, nlmp, AL_CNT_DEPCLCT) == NULL)
2368 2368 return (0);
2369 2369
2370 2370 for (APLIST_TRAVERSE(lmalp, idx2, dlmp1)) {
2371 2371 Aliste idx3;
2372 2372 Bnd_desc *bdp;
2373 2373
2374 2374 /*
2375 2375 * Add any dependencies of this dependency to the
2376 2376 * dynamic dependency list so they can be further
2377 2377 * processed.
2378 2378 */
2379 2379 for (APLIST_TRAVERSE(DEPENDS(dlmp1), idx3, bdp)) {
2380 2380 Rt_map *dlmp2 = bdp->b_depend;
2381 2381
2382 2382 if ((bdp->b_flags & BND_NEEDED) == 0)
2383 2383 continue;
2384 2384
2385 2385 if (aplist_test(&lmalp, dlmp2,
2386 2386 AL_CNT_DEPCLCT) == 0) {
2387 2387 free(lmalp);
2388 2388 return (0);
2389 2389 }
2390 2390 }
2391 2391
2392 2392 if (nlmp == dlmp1)
2393 2393 continue;
2394 2394
2395 2395 if ((gdp =
2396 2396 hdl_add(ghp, dlmp1, rdflags, &ale)) == NULL) {
2397 2397 free(lmalp);
2398 2398 return (0);
2399 2399 }
2400 2400
2401 2401 if (ale == ALE_CREATE)
2402 2402 (void) update_mode(dlmp1, MODE(dlmp1), nmode);
2403 2403 }
2404 2404 free(lmalp);
2405 2405 }
2406 2406 return (1);
2407 2407 }
2408 2408
2409 2409 /*
2410 2410 * The central routine for loading shared objects. Insures ldd() diagnostics,
2411 2411 * handle creation, and any other related additions are all done in one place.
2412 2412 */
2413 2413 Rt_map *
2414 2414 load_path(Lm_list *lml, Aliste lmco, Rt_map *clmp, int nmode, uint_t flags,
2415 2415 Grp_hdl **hdl, Fdesc *fdp, Rej_desc *rej, int *in_nfavl)
2416 2416 {
2417 2417 const char *name = fdp->fd_oname;
2418 2418 Rt_map *nlmp;
2419 2419
2420 2420 if ((nmode & RTLD_NOLOAD) == 0) {
2421 2421 int oin_nfavl;
2422 2422
2423 2423 /*
2424 2424 * Keep track of the number of not-found loads.
2425 2425 */
2426 2426 if (in_nfavl)
2427 2427 oin_nfavl = *in_nfavl;
2428 2428
2429 2429 /*
2430 2430 * If this isn't a noload request attempt to load the file.
2431 2431 */
2432 2432 if ((nlmp = load_so(lml, lmco, clmp, flags, fdp, rej,
2433 2433 in_nfavl)) == NULL)
2434 2434 return (NULL);
2435 2435
2436 2436 /*
2437 2437 * If this file has been found, reset the not-found load count.
2438 2438 * Although a search for this file might have inspected a number
2439 2439 * of non-existent path names, the file has been found so there
2440 2440 * is no need to accumulate a non-found count, as this may
2441 2441 * trigger unnecessary fall back (retry) processing.
2442 2442 */
2443 2443 if (in_nfavl)
2444 2444 *in_nfavl = oin_nfavl;
2445 2445
2446 2446 /*
2447 2447 * If we've loaded a library which identifies itself as not
2448 2448 * being dlopen()'able catch it here. Let non-dlopen()'able
2449 2449 * objects through under RTLD_CONFGEN as they're only being
2450 2450 * mapped to be dldump()'ed.
2451 2451 */
2452 2452 if ((rtld_flags & RT_FL_APPLIC) && ((FLAGS(nlmp) &
2453 2453 (FLG_RT_NOOPEN | FLG_RT_RELOCED)) == FLG_RT_NOOPEN) &&
2454 2454 ((nmode & RTLD_CONFGEN) == 0)) {
2455 2455 Rej_desc _rej = { 0 };
2456 2456
2457 2457 _rej.rej_name = name;
2458 2458 _rej.rej_type = SGS_REJ_STR;
2459 2459 _rej.rej_str = MSG_INTL(MSG_GEN_NOOPEN);
2460 2460 DBG_CALL(Dbg_file_rejected(lml, &_rej, M_MACH));
2461 2461 rejection_inherit(rej, &_rej);
2462 2462 remove_so(lml, nlmp, clmp);
2463 2463 return (NULL);
2464 2464 }
2465 2465 } else {
2466 2466 /*
2467 2467 * If it's a NOLOAD request - check to see if the object
2468 2468 * has already been loaded.
2469 2469 */
2470 2470 /* LINTED */
2471 2471 if (nlmp = is_so_loaded(lml, name, in_nfavl)) {
2472 2472 if ((lml->lm_flags & LML_FLG_TRC_VERBOSE) &&
2473 2473 ((FLAGS1(clmp) & FL1_RT_LDDSTUB) == 0)) {
2474 2474 (void) printf(MSG_INTL(MSG_LDD_FIL_FIND), name,
2475 2475 NAME(clmp));
2476 2476 /* BEGIN CSTYLED */
2477 2477 if (*name == '/')
2478 2478 (void) printf(MSG_ORIG(MSG_LDD_FIL_PATH),
2479 2479 name, MSG_ORIG(MSG_STR_EMPTY),
2480 2480 MSG_ORIG(MSG_STR_EMPTY));
2481 2481 else
2482 2482 (void) printf(MSG_ORIG(MSG_LDD_FIL_EQUIV),
2483 2483 name, NAME(nlmp),
2484 2484 MSG_ORIG(MSG_STR_EMPTY),
2485 2485 MSG_ORIG(MSG_STR_EMPTY));
2486 2486 /* END CSTYLED */
2487 2487 }
2488 2488 } else {
2489 2489 Rej_desc _rej = { 0 };
2490 2490
2491 2491 _rej.rej_name = name;
2492 2492 _rej.rej_type = SGS_REJ_STR;
2493 2493 _rej.rej_str = strerror(ENOENT);
2494 2494 DBG_CALL(Dbg_file_rejected(lml, &_rej, M_MACH));
2495 2495 rejection_inherit(rej, &_rej);
2496 2496 return (NULL);
2497 2497 }
2498 2498 }
2499 2499
2500 2500 /*
2501 2501 * Finish processing this loaded object.
2502 2502 */
2503 2503 if (load_finish(lml, name, clmp, nmode, flags, hdl, nlmp) == 0) {
2504 2504 FLAGS(nlmp) &= ~FLG_RT_NEWLOAD;
2505 2505
2506 2506 /*
2507 2507 * If this object has already been analyzed, then it is in use,
2508 2508 * so even though this operation has failed, it should not be
2509 2509 * torn down.
2510 2510 */
2511 2511 if ((FLAGS(nlmp) & FLG_RT_ANALYZED) == 0)
2512 2512 remove_so(lml, nlmp, clmp);
2513 2513 return (NULL);
2514 2514 }
2515 2515
2516 2516 /*
2517 2517 * If this object is new, and we're being audited, tell the audit
2518 2518 * libraries of the file we've just opened. Note, if the new link-map
2519 2519 * requires local auditing of its dependencies we also register its
2520 2520 * opening.
2521 2521 */
2522 2522 if (FLAGS(nlmp) & FLG_RT_NEWLOAD) {
2523 2523 FLAGS(nlmp) &= ~FLG_RT_NEWLOAD;
2524 2524
2525 2525 if ((lml->lm_tflags | AFLAGS(clmp) | AFLAGS(nlmp)) &
2526 2526 LML_TFLG_AUD_MASK) {
2527 2527 if (audit_objopen(clmp, nlmp) == 0) {
2528 2528 remove_so(lml, nlmp, clmp);
2529 2529 return (NULL);
2530 2530 }
2531 2531 }
2532 2532 }
2533 2533 return (nlmp);
2534 2534 }
2535 2535
2536 2536 /*
2537 2537 * Load one object from a possible list of objects. Typically, for requests
2538 2538 * such as NEEDED's, only one object is specified. However, this object could
2539 2539 * be specified using $ISALIST or $CAPABILITY, in which case only the first
2540 2540 * object that can be loaded is used (ie. the best).
2541 2541 */
2542 2542 Rt_map *
2543 2543 load_one(Lm_list *lml, Aliste lmco, Alist *palp, Rt_map *clmp, int mode,
2544 2544 uint_t flags, Grp_hdl **hdl, int *in_nfavl)
2545 2545 {
2546 2546 Rej_desc rej = { 0 };
2547 2547 Aliste idx;
2548 2548 Pdesc *pdp;
2549 2549 const char *name;
2550 2550
2551 2551 for (ALIST_TRAVERSE(palp, idx, pdp)) {
2552 2552 Rt_map *lmp = NULL;
2553 2553
2554 2554 /*
2555 2555 * A $CAPABILITY/$HWCAP requirement can expand into a number of
2556 2556 * candidates.
2557 2557 */
2558 2558 if (pdp->pd_flags & PD_TKN_CAP) {
2559 2559 lmp = load_cap(lml, lmco, pdp->pd_pname, clmp,
2560 2560 mode, (flags | FLG_RT_CAP), hdl, &rej, in_nfavl);
2561 2561 } else {
2562 2562 Fdesc fd = { 0 };
2563 2563
2564 2564 /*
2565 2565 * Trace the inspection of this file, determine any
2566 2566 * auditor substitution, and seed the file descriptor
2567 2567 * with the originating name.
2568 2568 */
2569 2569 if (load_trace(lml, pdp, clmp, &fd) == NULL)
2570 2570 continue;
2571 2571
2572 2572 /*
2573 2573 * Locate and load the file.
2574 2574 */
2575 2575 lmp = load_path(lml, lmco, clmp, mode, flags, hdl, &fd,
2576 2576 &rej, in_nfavl);
2577 2577 }
2578 2578 if (lmp)
2579 2579 return (lmp);
2580 2580 }
2581 2581
2582 2582 /*
2583 2583 * If no objects can be found, use the first path name from the Alist
2584 2584 * to provide a diagnostic. If this pathname originated from an
2585 2585 * expanded token, use the original name for any diagnostic output.
2586 2586 */
2587 2587 pdp = alist_item(palp, 0);
2588 2588
2589 2589 if ((name = pdp->pd_oname) == 0)
2590 2590 name = pdp->pd_pname;
2591 2591
2592 2592 file_notfound(lml, name, clmp, flags, &rej);
2593 2593 return (NULL);
2594 2594 }
2595 2595
2596 2596 /*
2597 2597 * Determine whether a symbol is defined as an interposer.
2598 2598 */
2599 2599 int
2600 2600 is_sym_interposer(Rt_map *lmp, Sym *sym)
2601 2601 {
2602 2602 Syminfo *sip = SYMINFO(lmp);
2603 2603
2604 2604 if (sip) {
2605 2605 ulong_t ndx;
2606 2606
2607 2607 ndx = (((ulong_t)sym - (ulong_t)SYMTAB(lmp)) / SYMENT(lmp));
2608 2608 /* LINTED */
2609 2609 sip = (Syminfo *)((char *)sip + (ndx * SYMINENT(lmp)));
2610 2610 if (sip->si_flags & SYMINFO_FLG_INTERPOSE)
2611 2611 return (1);
2612 2612 }
2613 2613 return (0);
2614 2614 }
2615 2615
2616 2616 /*
2617 2617 * While processing direct or group bindings, determine whether the object to
2618 2618 * which we've bound can be interposed upon. In this context, copy relocations
2619 2619 * are a form of interposition.
2620 2620 */
2621 2621 static int
2622 2622 lookup_sym_interpose(Slookup *slp, Sresult *srp, uint_t *binfo, int *in_nfavl)
2623 2623 {
2624 2624 Rt_map *lmp, *clmp, *dlmp = srp->sr_dmap;
2625 2625 Sym *osym = srp->sr_sym;
2626 2626 Slookup sl;
2627 2627 Lm_list *lml;
2628 2628
2629 2629 /*
2630 2630 * If we've bound to a copy relocation definition then we need to assign
2631 2631 * this binding to the original copy reference. Fabricate an inter-
2632 2632 * position diagnostic, as this is a legitimate form of interposition.
2633 2633 */
2634 2634 if (osym && (FLAGS1(dlmp) & FL1_RT_COPYTOOK)) {
2635 2635 Rel_copy *rcp;
2636 2636 Aliste idx;
2637 2637
2638 2638 for (ALIST_TRAVERSE(COPY_R(dlmp), idx, rcp)) {
2639 2639 if ((osym == rcp->r_dsym) || (osym->st_value &&
2640 2640 (osym->st_value == rcp->r_dsym->st_value))) {
2641 2641 srp->sr_dmap = rcp->r_rlmp;
2642 2642 srp->sr_sym = rcp->r_rsym;
2643 2643 *binfo |=
2644 2644 (DBG_BINFO_INTERPOSE | DBG_BINFO_COPYREF);
2645 2645 return (1);
2646 2646 }
2647 2647 }
2648 2648 }
2649 2649
2650 2650 /*
2651 2651 * If a symbol binding has been established, inspect the link-map list
2652 2652 * of the destination object, otherwise use the link-map list of the
2653 2653 * original caller.
2654 2654 */
2655 2655 if (osym)
2656 2656 clmp = dlmp;
2657 2657 else
2658 2658 clmp = slp->sl_cmap;
2659 2659
2660 2660 lml = LIST(clmp);
2661 2661 lmp = lml->lm_head;
2662 2662
2663 2663 /*
2664 2664 * Prior to Solaris 8, external references from an executable that were
2665 2665 * bound to an uninitialized variable (.bss) within a shared object did
2666 2666 * not establish a copy relocation. This was thought to be an
2667 2667 * optimization, to prevent copying zero's to zero's. Typically,
2668 2668 * interposition took its course, with the shared object binding to the
2669 2669 * executables data definition.
2670 2670 *
2671 2671 * This scenario can be broken when this old executable runs against a
2672 2672 * new shared object that is directly bound. With no copy-relocation
2673 2673 * record, ld.so.1 has no data to trigger the normal vectoring of the
2674 2674 * binding to the executable.
2675 2675 *
2676 2676 * Starting with Solaris 8, a DT_FLAGS entry is written to all objects,
2677 2677 * regardless of there being any DF_ flags entries. Therefore, an
2678 2678 * object without this dynamic tag is susceptible to the copy relocation
2679 2679 * issue. If the executable has no DT_FLAGS tag, and contains the same
2680 2680 * .bss symbol definition as has been directly bound to, redirect the
2681 2681 * binding to the executables data definition.
2682 2682 */
2683 2683 if (osym && ((FLAGS1(lmp) & FL1_RT_DTFLAGS) == 0) &&
2684 2684 (FCT(lmp) == &elf_fct) &&
2685 2685 (ELF_ST_TYPE(osym->st_info) != STT_FUNC) &&
2686 2686 are_bits_zero(dlmp, osym, 0)) {
2687 2687 Sresult sr;
2688 2688
2689 2689 /*
2690 2690 * Initialize a local symbol result descriptor, using the
2691 2691 * original symbol name. Initialize a local symbol lookup
2692 2692 * descriptor, using the original lookup information, and a
2693 2693 * new initial link-map.
2694 2694 */
2695 2695 SRESULT_INIT(sr, slp->sl_name);
2696 2696 sl = *slp;
2697 2697 sl.sl_imap = lmp;
2698 2698
2699 2699 /*
2700 2700 * Determine whether the same symbol name exists within the
2701 2701 * executable, that the size and type of symbol are the same,
2702 2702 * and that the symbol is also associated with .bss.
2703 2703 */
2704 2704 if (SYMINTP(lmp)(&sl, &sr, binfo, in_nfavl)) {
2705 2705 Sym *isym = sr.sr_sym;
2706 2706
2707 2707 if ((isym->st_size == osym->st_size) &&
2708 2708 (isym->st_info == osym->st_info) &&
2709 2709 are_bits_zero(lmp, isym, 1)) {
2710 2710 *srp = sr;
2711 2711 *binfo |=
2712 2712 (DBG_BINFO_INTERPOSE | DBG_BINFO_COPYREF);
2713 2713 return (1);
2714 2714 }
2715 2715 }
2716 2716 }
2717 2717
2718 2718 if ((lml->lm_flags & LML_FLG_INTRPOSE) == 0)
2719 2719 return (NULL);
2720 2720
2721 2721 /*
2722 2722 * Traverse the list of known interposers to determine whether any
2723 2723 * offer the same symbol. Note, the head of the link-map could be
2724 2724 * identified as an interposer. Otherwise, skip the head of the
2725 2725 * link-map, so that we don't bind to any .plt references, or
2726 2726 * copy-relocation destinations unintentionally.
2727 2727 */
2728 2728 lmp = lml->lm_head;
2729 2729 sl = *slp;
2730 2730
2731 2731 if (((FLAGS(lmp) & MSK_RT_INTPOSE) == 0) || (sl.sl_flags & LKUP_COPY))
2732 2732 lmp = NEXT_RT_MAP(lmp);
2733 2733
2734 2734 for (; lmp; lmp = NEXT_RT_MAP(lmp)) {
2735 2735 if (FLAGS(lmp) & FLG_RT_DELETE)
2736 2736 continue;
2737 2737 if ((FLAGS(lmp) & MSK_RT_INTPOSE) == 0)
2738 2738 break;
2739 2739
2740 2740 /*
2741 2741 * If we had already bound to this object, there's no point in
2742 2742 * searching it again, we're done.
2743 2743 */
2744 2744 if (lmp == dlmp)
2745 2745 break;
2746 2746
2747 2747 /*
2748 2748 * If this interposer can be inspected by the caller, look for
2749 2749 * the symbol within the interposer.
2750 2750 */
2751 2751 if (callable(clmp, lmp, 0, sl.sl_flags)) {
2752 2752 Sresult sr;
2753 2753
2754 2754 /*
2755 2755 * Initialize a local symbol result descriptor, using
2756 2756 * the original symbol name. Initialize a local symbol
2757 2757 * lookup descriptor, using the original lookup
2758 2758 * information, and a new initial link-map.
2759 2759 */
2760 2760 SRESULT_INIT(sr, slp->sl_name);
2761 2761 sl.sl_imap = lmp;
2762 2762
2763 2763 if (SYMINTP(lmp)(&sl, &sr, binfo, in_nfavl)) {
2764 2764 Sym *isym = sr.sr_sym;
2765 2765 Rt_map *ilmp = sr.sr_dmap;
2766 2766
2767 2767 /*
2768 2768 * If this object provides individual symbol
2769 2769 * interposers, make sure that the symbol we
2770 2770 * have found is tagged as an interposer.
2771 2771 */
2772 2772 if ((FLAGS(ilmp) & FLG_RT_SYMINTPO) &&
2773 2773 (is_sym_interposer(ilmp, isym) == 0))
2774 2774 continue;
2775 2775
2776 2776 /*
2777 2777 * Indicate this binding has occurred to an
2778 2778 * interposer, and return the symbol.
2779 2779 */
2780 2780 *srp = sr;
2781 2781 *binfo |= DBG_BINFO_INTERPOSE;
2782 2782 return (1);
2783 2783 }
2784 2784 }
2785 2785 }
2786 2786 return (0);
2787 2787 }
2788 2788
2789 2789 /*
2790 2790 * If an object specifies direct bindings (it contains a syminfo structure
2791 2791 * describing where each binding was established during link-editing, and the
2792 2792 * object was built -Bdirect), then look for the symbol in the specific object.
2793 2793 */
2794 2794 static int
2795 2795 lookup_sym_direct(Slookup *slp, Sresult *srp, uint_t *binfo, Syminfo *sip,
2796 2796 Rt_map *lmp, int *in_nfavl)
2797 2797 {
2798 2798 Rt_map *dlmp, *clmp = slp->sl_cmap;
2799 2799 int ret;
2800 2800 Slookup sl;
2801 2801
2802 2802 /*
2803 2803 * If a direct binding resolves to the definition of a copy relocated
2804 2804 * variable, it must be redirected to the copy (in the executable) that
2805 2805 * will eventually be made. Typically, this redirection occurs in
2806 2806 * lookup_sym_interpose(). But, there's an edge condition. If a
2807 2807 * directly bound executable contains pic code, there may be a
2808 2808 * reference to a definition that will eventually have a copy made.
2809 2809 * However, this copy relocation may not yet have occurred, because
2810 2810 * the relocation making this reference comes before the relocation
2811 2811 * that will create the copy.
2812 2812 * Under direct bindings, the syminfo indicates that a copy will be
2813 2813 * taken (SYMINFO_FLG_COPY). This can only be set in an executable.
2814 2814 * Thus, the caller must be the executable, so bind to the destination
2815 2815 * of the copy within the executable.
2816 2816 */
2817 2817 if (((slp->sl_flags & LKUP_COPY) == 0) &&
2818 2818 (sip->si_flags & SYMINFO_FLG_COPY)) {
2819 2819 slp->sl_imap = LIST(clmp)->lm_head;
2820 2820
2821 2821 if (ret = SYMINTP(clmp)(slp, srp, binfo, in_nfavl))
2822 2822 *binfo |= (DBG_BINFO_DIRECT | DBG_BINFO_COPYREF);
2823 2823 return (ret);
2824 2824 }
2825 2825
2826 2826 /*
2827 2827 * If we need to directly bind to our parent, start looking in each
2828 2828 * callers link map.
2829 2829 */
2830 2830 sl = *slp;
2831 2831 sl.sl_flags |= LKUP_DIRECT;
2832 2832 ret = 0;
2833 2833
2834 2834 if (sip->si_boundto == SYMINFO_BT_PARENT) {
2835 2835 Aliste idx1;
2836 2836 Bnd_desc *bdp;
2837 2837 Grp_hdl *ghp;
2838 2838
2839 2839 /*
2840 2840 * Determine the parent of this explicit dependency from its
2841 2841 * CALLERS()'s list.
2842 2842 */
2843 2843 for (APLIST_TRAVERSE(CALLERS(clmp), idx1, bdp)) {
2844 2844 sl.sl_imap = lmp = bdp->b_caller;
2845 2845 if (ret = SYMINTP(lmp)(&sl, srp, binfo, in_nfavl))
2846 2846 goto found;
2847 2847 }
2848 2848
2849 2849 /*
2850 2850 * A caller can also be defined as the parent of a dlopen()
2851 2851 * call. Determine whether this object has any handles. The
2852 2852 * dependencies maintained with the handle represent the
2853 2853 * explicit dependencies of the dlopen()'ed object, and the
2854 2854 * calling parent.
2855 2855 */
2856 2856 for (APLIST_TRAVERSE(HANDLES(clmp), idx1, ghp)) {
2857 2857 Grp_desc *gdp;
2858 2858 Aliste idx2;
2859 2859
2860 2860 for (ALIST_TRAVERSE(ghp->gh_depends, idx2, gdp)) {
2861 2861 if ((gdp->gd_flags & GPD_PARENT) == 0)
2862 2862 continue;
2863 2863 sl.sl_imap = lmp = gdp->gd_depend;
2864 2864 if (ret = SYMINTP(lmp)(&sl, srp, binfo,
2865 2865 in_nfavl))
2866 2866 goto found;
2867 2867 }
2868 2868 }
2869 2869 } else {
2870 2870 /*
2871 2871 * If we need to direct bind to anything else look in the
2872 2872 * link map associated with this symbol reference.
2873 2873 */
2874 2874 if (sip->si_boundto == SYMINFO_BT_SELF)
2875 2875 sl.sl_imap = lmp = clmp;
2876 2876 else
2877 2877 sl.sl_imap = lmp;
2878 2878
2879 2879 if (lmp)
2880 2880 ret = SYMINTP(lmp)(&sl, srp, binfo, in_nfavl);
2881 2881 }
2882 2882 found:
2883 2883 if (ret)
2884 2884 *binfo |= DBG_BINFO_DIRECT;
2885 2885
2886 2886 /*
2887 2887 * If a reference to a directly bound symbol can't be satisfied, then
2888 2888 * determine whether an interposer can provide the missing symbol. If
2889 2889 * a reference to a directly bound symbol is satisfied, then determine
2890 2890 * whether that object can be interposed upon for this symbol.
2891 2891 */
2892 2892 dlmp = srp->sr_dmap;
2893 2893 if ((ret == 0) || (dlmp && (LIST(dlmp)->lm_head != dlmp) &&
2894 2894 (LIST(dlmp) == LIST(clmp)))) {
2895 2895 if (lookup_sym_interpose(slp, srp, binfo, in_nfavl))
2896 2896 return (1);
2897 2897 }
2898 2898
2899 2899 return (ret);
2900 2900 }
2901 2901
2902 2902 static int
2903 2903 core_lookup_sym(Rt_map *ilmp, Slookup *slp, Sresult *srp, uint_t *binfo,
2904 2904 Aliste off, int *in_nfavl)
2905 2905 {
2906 2906 Rt_map *lmp;
2907 2907
2908 2908 /*
2909 2909 * Copy relocations should start their search after the head of the
2910 2910 * main link-map control list.
2911 2911 */
2912 2912 if ((off == ALIST_OFF_DATA) && (slp->sl_flags & LKUP_COPY) && ilmp)
2913 2913 lmp = NEXT_RT_MAP(ilmp);
2914 2914 else
2915 2915 lmp = ilmp;
2916 2916
2917 2917 for (; lmp; lmp = NEXT_RT_MAP(lmp)) {
2918 2918 if (callable(slp->sl_cmap, lmp, 0, slp->sl_flags)) {
2919 2919
2920 2920 slp->sl_imap = lmp;
2921 2921 if ((SYMINTP(lmp)(slp, srp, binfo, in_nfavl)) ||
2922 2922 (*binfo & BINFO_MSK_TRYAGAIN))
2923 2923 return (1);
2924 2924 }
2925 2925 }
2926 2926 return (0);
2927 2927 }
2928 2928
2929 2929 static int
2930 2930 rescan_lazy_find_sym(Rt_map *ilmp, Slookup *slp, Sresult *srp, uint_t *binfo,
2931 2931 int *in_nfavl)
2932 2932 {
2933 2933 Rt_map *lmp;
2934 2934
2935 2935 for (lmp = ilmp; lmp; lmp = NEXT_RT_MAP(lmp)) {
2936 2936 if (LAZY(lmp) == 0)
2937 2937 continue;
2938 2938 if (callable(slp->sl_cmap, lmp, 0, slp->sl_flags)) {
2939 2939
2940 2940 slp->sl_imap = lmp;
2941 2941 if (elf_lazy_find_sym(slp, srp, binfo, in_nfavl))
2942 2942 return (1);
2943 2943 }
2944 2944 }
2945 2945 return (0);
2946 2946 }
2947 2947
2948 2948 static int
2949 2949 _lookup_sym(Slookup *slp, Sresult *srp, uint_t *binfo, int *in_nfavl)
2950 2950 {
2951 2951 const char *name = slp->sl_name;
2952 2952 Rt_map *clmp = slp->sl_cmap;
2953 2953 Lm_list *lml = LIST(clmp);
2954 2954 Rt_map *ilmp = slp->sl_imap, *lmp;
2955 2955 ulong_t rsymndx;
2956 2956 int ret;
2957 2957 Syminfo *sip;
2958 2958 Slookup sl;
2959 2959
2960 2960 /*
2961 2961 * Search the initial link map for the required symbol (this category is
2962 2962 * selected by dlsym(), where individual link maps are searched for a
2963 2963 * required symbol. Therefore, we know we have permission to look at
2964 2964 * the link map).
2965 2965 */
2966 2966 if (slp->sl_flags & LKUP_FIRST)
2967 2967 return (SYMINTP(ilmp)(slp, srp, binfo, in_nfavl));
2968 2968
2969 2969 /*
2970 2970 * Determine whether this lookup can be satisfied by an objects direct,
2971 2971 * or lazy binding information. This is triggered by a relocation from
2972 2972 * the object (hence rsymndx is set).
2973 2973 */
2974 2974 if (((rsymndx = slp->sl_rsymndx) != 0) &&
2975 2975 ((sip = SYMINFO(clmp)) != NULL)) {
2976 2976 uint_t bound;
2977 2977
2978 2978 /*
2979 2979 * Find the corresponding Syminfo entry for the original
2980 2980 * referencing symbol.
2981 2981 */
2982 2982 /* LINTED */
2983 2983 sip = (Syminfo *)((char *)sip + (rsymndx * SYMINENT(clmp)));
2984 2984 bound = sip->si_boundto;
2985 2985
2986 2986 /*
2987 2987 * Identify any EXTERN or PARENT references for ldd(1).
2988 2988 */
2989 2989 if ((lml->lm_flags & LML_FLG_TRC_WARN) &&
2990 2990 (bound > SYMINFO_BT_LOWRESERVE)) {
2991 2991 if (bound == SYMINFO_BT_PARENT)
2992 2992 *binfo |= DBG_BINFO_REF_PARENT;
2993 2993 if (bound == SYMINFO_BT_EXTERN)
2994 2994 *binfo |= DBG_BINFO_REF_EXTERN;
2995 2995 }
2996 2996
2997 2997 /*
2998 2998 * If the symbol information indicates a direct binding,
2999 2999 * determine the link map that is required to satisfy the
3000 3000 * binding. Note, if the dependency can not be found, but a
3001 3001 * direct binding isn't required, we will still fall through
3002 3002 * to perform any default symbol search.
3003 3003 */
3004 3004 if (sip->si_flags & SYMINFO_FLG_DIRECT) {
3005 3005
3006 3006 lmp = 0;
3007 3007 if (bound < SYMINFO_BT_LOWRESERVE)
3008 3008 lmp = elf_lazy_load(clmp, slp, bound,
3009 3009 name, 0, NULL, in_nfavl);
3010 3010
3011 3011 /*
3012 3012 * If direct bindings have been disabled, and this isn't
3013 3013 * a translator, skip any direct binding now that we've
3014 3014 * ensured the resolving object has been loaded.
3015 3015 *
3016 3016 * If we need to direct bind to anything, we look in
3017 3017 * ourselves, our parent, or in the link map we've just
3018 3018 * loaded. Otherwise, even though we may have lazily
3019 3019 * loaded an object we still continue to search for
3020 3020 * symbols from the head of the link map list.
3021 3021 */
3022 3022 if (((FLAGS(clmp) & FLG_RT_TRANS) ||
3023 3023 (((lml->lm_tflags & LML_TFLG_NODIRECT) == 0) &&
3024 3024 ((slp->sl_flags & LKUP_SINGLETON) == 0))) &&
3025 3025 ((FLAGS1(clmp) & FL1_RT_DIRECT) ||
3026 3026 (sip->si_flags & SYMINFO_FLG_DIRECTBIND))) {
3027 3027 ret = lookup_sym_direct(slp, srp, binfo,
3028 3028 sip, lmp, in_nfavl);
3029 3029
3030 3030 /*
3031 3031 * Determine whether this direct binding has
3032 3032 * been rejected. If we've bound to a singleton
3033 3033 * without following a singleton search, then
3034 3034 * return. The caller detects this condition
3035 3035 * and will trigger a new singleton search.
3036 3036 *
3037 3037 * For any other rejection (such as binding to
3038 3038 * a symbol labeled as nodirect - presumably
3039 3039 * because the symbol definition has been
3040 3040 * changed since the referring object was last
3041 3041 * built), fall through to a standard symbol
3042 3042 * search.
3043 3043 */
3044 3044 if (((*binfo & BINFO_MSK_REJECTED) == 0) ||
3045 3045 (*binfo & BINFO_MSK_TRYAGAIN))
3046 3046 return (ret);
3047 3047
3048 3048 *binfo &= ~BINFO_MSK_REJECTED;
3049 3049 }
3050 3050 }
3051 3051 }
3052 3052
3053 3053 /*
3054 3054 * Duplicate the lookup information, as we'll need to modify this
3055 3055 * information for some of the following searches.
3056 3056 */
3057 3057 sl = *slp;
3058 3058
3059 3059 /*
3060 3060 * If the referencing object has the DF_SYMBOLIC flag set, look in the
3061 3061 * referencing object for the symbol first. Failing that, fall back to
3062 3062 * our generic search.
3063 3063 */
3064 3064 if ((FLAGS1(clmp) & FL1_RT_SYMBOLIC) &&
3065 3065 ((sl.sl_flags & LKUP_SINGLETON) == 0)) {
3066 3066
3067 3067 sl.sl_imap = clmp;
3068 3068 if (SYMINTP(clmp)(&sl, srp, binfo, in_nfavl)) {
3069 3069 Rt_map *dlmp = srp->sr_dmap;
3070 3070 ulong_t dsymndx = (((ulong_t)srp->sr_sym -
3071 3071 (ulong_t)SYMTAB(dlmp)) / SYMENT(dlmp));
3072 3072
3073 3073 /*
3074 3074 * Make sure this symbol hasn't explicitly been defined
3075 3075 * as nodirect.
3076 3076 */
3077 3077 if (((sip = SYMINFO(dlmp)) == 0) ||
3078 3078 /* LINTED */
3079 3079 ((sip = (Syminfo *)((char *)sip +
3080 3080 (dsymndx * SYMINENT(dlmp)))) == 0) ||
3081 3081 ((sip->si_flags & SYMINFO_FLG_NOEXTDIRECT) == 0))
3082 3082 return (1);
3083 3083 }
3084 3084 }
3085 3085
3086 3086 sl.sl_flags |= LKUP_STANDARD;
3087 3087
3088 3088 /*
3089 3089 * If this lookup originates from a standard relocation, then traverse
3090 3090 * all link-map control lists, inspecting any object that is available
3091 3091 * to this caller. Otherwise, traverse the link-map control list
3092 3092 * associated with the caller.
3093 3093 */
3094 3094 if (sl.sl_flags & LKUP_STDRELOC) {
3095 3095 Aliste off;
3096 3096 Lm_cntl *lmc;
3097 3097
3098 3098 ret = 0;
3099 3099
3100 3100 for (ALIST_TRAVERSE_BY_OFFSET(lml->lm_lists, off, lmc)) {
3101 3101 if (((ret = core_lookup_sym(lmc->lc_head, &sl, srp,
3102 3102 binfo, off, in_nfavl)) != 0) ||
3103 3103 (*binfo & BINFO_MSK_TRYAGAIN))
3104 3104 break;
3105 3105 }
3106 3106 } else
3107 3107 ret = core_lookup_sym(ilmp, &sl, srp, binfo, ALIST_OFF_DATA,
3108 3108 in_nfavl);
3109 3109
3110 3110 /*
3111 3111 * If a symbol binding should be retried, return so that the search can
3112 3112 * be repeated.
3113 3113 */
3114 3114 if (*binfo & BINFO_MSK_TRYAGAIN)
3115 3115 return (0);
3116 3116
3117 3117 /*
3118 3118 * To allow transitioning into a world of lazy loading dependencies see
3119 3119 * if this link map contains objects that have lazy dependencies still
3120 3120 * outstanding. If so, and we haven't been able to locate a non-weak
3121 3121 * symbol reference, start bringing in any lazy dependencies to see if
3122 3122 * the reference can be satisfied. Use of dlsym(RTLD_PROBE) sets the
3123 3123 * LKUP_NOFALLBACK flag, and this flag disables this fall back.
3124 3124 */
3125 3125 if ((ret == 0) && ((sl.sl_flags & LKUP_NOFALLBACK) == 0)) {
3126 3126 if ((lmp = ilmp) == 0)
3127 3127 lmp = LIST(clmp)->lm_head;
3128 3128
3129 3129 lml = LIST(lmp);
3130 3130 if ((sl.sl_flags & LKUP_WEAK) || (lml->lm_lazy == 0))
3131 3131 return (NULL);
3132 3132
3133 3133 DBG_CALL(Dbg_syms_lazy_rescan(lml, name));
3134 3134
3135 3135 /*
3136 3136 * If this request originated from a dlsym(RTLD_NEXT) then start
3137 3137 * looking for dependencies from the caller, otherwise use the
3138 3138 * initial link-map.
3139 3139 */
3140 3140 if (sl.sl_flags & LKUP_NEXT)
3141 3141 ret = rescan_lazy_find_sym(clmp, &sl, srp, binfo,
3142 3142 in_nfavl);
3143 3143 else {
3144 3144 Aliste idx;
3145 3145 Lm_cntl *lmc;
3146 3146
3147 3147 for (ALIST_TRAVERSE(lml->lm_lists, idx, lmc)) {
3148 3148 sl.sl_flags |= LKUP_NOFALLBACK;
3149 3149 if (ret = rescan_lazy_find_sym(lmc->lc_head,
3150 3150 &sl, srp, binfo, in_nfavl))
3151 3151 break;
3152 3152 }
3153 3153 }
3154 3154 }
3155 3155 return (ret);
3156 3156 }
3157 3157
3158 3158 /*
3159 3159 * Symbol lookup routine. Takes an ELF symbol name, and a list of link maps to
3160 3160 * search. If successful, return a pointer to the symbol table entry, a
3161 3161 * pointer to the link map of the enclosing object, and information relating
3162 3162 * to the type of binding. Else return a null pointer.
3163 3163 *
3164 3164 * To improve ELF performance, we first compute the ELF hash value and pass
3165 3165 * it to each _lookup_sym() routine. The ELF function will use this value to
3166 3166 * locate the symbol, the a.out function will simply ignore it.
3167 3167 */
3168 3168 int
3169 3169 lookup_sym(Slookup *slp, Sresult *srp, uint_t *binfo, int *in_nfavl)
3170 3170 {
3171 3171 Rt_map *clmp = slp->sl_cmap;
3172 3172 Sym *rsym = slp->sl_rsym;
3173 3173 uchar_t rtype = slp->sl_rtype, vis;
3174 3174 int ret, mode;
3175 3175
3176 3176 if (slp->sl_hash == 0)
3177 3177 slp->sl_hash = elf_hash(slp->sl_name);
3178 3178 *binfo = 0;
3179 3179
3180 3180 if (rsym) {
3181 3181 vis = ELF_ST_VISIBILITY(rsym->st_other);
3182 3182
3183 3183 /*
3184 3184 * Symbols that are defined as protected, or hidden, within an
3185 3185 * object usually have any relocation references from within
3186 3186 * the same object bound at link-edit time. Therefore, ld.so.1
3187 3187 * is not involved. However, if a reference is to a
3188 3188 * capabilities symbol, this reference must be resolved at
3189 3189 * runtime. In this case look directly within the calling
3190 3190 * object, and only within the calling object, for these
3191 3191 * symbols. Note, an object may still use dlsym() to search
3192 3192 * externally for a symbol which is defined as protected within
3193 3193 * the same object.
3194 3194 */
3195 3195 if ((rsym->st_shndx != SHN_UNDEF) &&
3196 3196 ((slp->sl_flags & LKUP_DLSYM) == 0) &&
3197 3197 ((vis == STV_PROTECTED) || (vis == STV_HIDDEN))) {
3198 3198 slp->sl_imap = clmp;
3199 3199 return (SYMINTP(clmp)(slp, srp, binfo, in_nfavl));
3200 3200 }
3201 3201
3202 3202 /*
3203 3203 * Establish any state that might be associated with a symbol
3204 3204 * reference.
3205 3205 */
3206 3206 if ((slp->sl_flags & LKUP_STDRELOC) &&
3207 3207 (ELF_ST_BIND(rsym->st_info) == STB_WEAK))
3208 3208 slp->sl_flags |= LKUP_WEAK;
3209 3209
3210 3210 if (vis == STV_SINGLETON)
3211 3211 slp->sl_flags |= LKUP_SINGLETON;
3212 3212 }
3213 3213
3214 3214 /*
3215 3215 * Establish any lookup state required for this type of relocation.
3216 3216 */
3217 3217 if ((slp->sl_flags & LKUP_STDRELOC) && rtype) {
3218 3218 if (rtype == M_R_COPY)
3219 3219 slp->sl_flags |= LKUP_COPY;
3220 3220
3221 3221 if (rtype != M_R_JMP_SLOT)
3222 3222 slp->sl_flags |= LKUP_SPEC;
3223 3223 }
3224 3224
3225 3225 /*
3226 3226 * Under ldd -w, any unresolved weak references are diagnosed. Set the
3227 3227 * symbol binding as global to trigger a relocation error if the symbol
3228 3228 * can not be found.
3229 3229 */
3230 3230 if (rsym) {
3231 3231 if (LIST(slp->sl_cmap)->lm_flags & LML_FLG_TRC_NOUNRESWEAK)
3232 3232 slp->sl_bind = STB_GLOBAL;
3233 3233 else if ((slp->sl_bind = ELF_ST_BIND(rsym->st_info)) ==
3234 3234 STB_WEAK)
3235 3235 slp->sl_flags |= LKUP_WEAK;
3236 3236 }
3237 3237
3238 3238 /*
3239 3239 * Save the callers MODE().
3240 3240 */
3241 3241 mode = MODE(clmp);
3242 3242
3243 3243 /*
3244 3244 * Carry out an initial symbol search. This search takes into account
3245 3245 * all the modes of the requested search.
3246 3246 */
3247 3247 if (((ret = _lookup_sym(slp, srp, binfo, in_nfavl)) == 0) &&
3248 3248 (*binfo & BINFO_MSK_TRYAGAIN)) {
3249 3249 Slookup sl = *slp;
3250 3250
3251 3251 /*
3252 3252 * Try the symbol search again. This retry can be necessary if:
3253 3253 *
3254 3254 * - a binding has been rejected because of binding to a
3255 3255 * singleton without going through a singleton search.
3256 3256 * - a group binding has resulted in binding to a symbol
3257 3257 * that indicates no-direct binding.
3258 3258 *
3259 3259 * Reset the lookup data, and try again.
3260 3260 */
3261 3261 sl.sl_imap = LIST(sl.sl_cmap)->lm_head;
3262 3262 sl.sl_flags &= ~(LKUP_FIRST | LKUP_SELF | LKUP_NEXT);
3263 3263 sl.sl_rsymndx = 0;
3264 3264
3265 3265 if (*binfo & BINFO_REJSINGLE)
3266 3266 sl.sl_flags |= LKUP_SINGLETON;
3267 3267 if (*binfo & BINFO_REJGROUP) {
3268 3268 sl.sl_flags |= LKUP_WORLD;
3269 3269 mode |= RTLD_WORLD;
3270 3270 }
3271 3271 *binfo &= ~BINFO_MSK_REJECTED;
3272 3272
3273 3273 ret = _lookup_sym(&sl, srp, binfo, in_nfavl);
3274 3274 }
3275 3275
3276 3276 /*
3277 3277 * If the caller is restricted to a symbol search within its group,
3278 3278 * determine if it is necessary to follow a binding from outside of
3279 3279 * the group.
3280 3280 */
3281 3281 if (((mode & (RTLD_GROUP | RTLD_WORLD)) == RTLD_GROUP) &&
3282 3282 (lookup_sym_interpose(slp, srp, binfo, in_nfavl)))
3283 3283 return (1);
3284 3284
3285 3285 return (ret);
3286 3286 }
3287 3287
3288 3288 /*
3289 3289 * Associate a binding descriptor with a caller and its dependency, or update
3290 3290 * an existing descriptor.
3291 3291 */
3292 3292 int
3293 3293 bind_one(Rt_map *clmp, Rt_map *dlmp, uint_t flags)
3294 3294 {
3295 3295 Bnd_desc *bdp;
3296 3296 Aliste idx;
3297 3297 int found = ALE_CREATE;
3298 3298
3299 3299 /*
3300 3300 * Determine whether a binding descriptor already exists between the
3301 3301 * two objects.
3302 3302 */
3303 3303 for (APLIST_TRAVERSE(DEPENDS(clmp), idx, bdp)) {
3304 3304 if (bdp->b_depend == dlmp) {
3305 3305 found = ALE_EXISTS;
3306 3306 break;
3307 3307 }
3308 3308 }
3309 3309
3310 3310 if (found == ALE_CREATE) {
3311 3311 /*
3312 3312 * Create a new binding descriptor.
3313 3313 */
3314 3314 if ((bdp = malloc(sizeof (Bnd_desc))) == NULL)
3315 3315 return (0);
3316 3316
3317 3317 bdp->b_caller = clmp;
3318 3318 bdp->b_depend = dlmp;
3319 3319 bdp->b_flags = 0;
3320 3320
3321 3321 /*
3322 3322 * Append the binding descriptor to the caller and the
3323 3323 * dependency.
3324 3324 */
3325 3325 if (aplist_append(&DEPENDS(clmp), bdp, AL_CNT_DEPENDS) == NULL)
3326 3326 return (0);
3327 3327
3328 3328 if (aplist_append(&CALLERS(dlmp), bdp, AL_CNT_CALLERS) == NULL)
3329 3329 return (0);
3330 3330 }
3331 3331
3332 3332 if ((found == ALE_CREATE) || ((bdp->b_flags & flags) != flags)) {
3333 3333 bdp->b_flags |= flags;
3334 3334
3335 3335 if (flags & BND_REFER)
3336 3336 FLAGS1(dlmp) |= FL1_RT_USED;
3337 3337
3338 3338 DBG_CALL(Dbg_file_bind_entry(LIST(clmp), bdp));
3339 3339 }
3340 3340 return (found);
3341 3341 }
3342 3342
3343 3343 /*
3344 3344 * Cleanup after relocation processing.
3345 3345 */
3346 3346 int
3347 3347 relocate_finish(Rt_map *lmp, APlist *bound, int ret)
3348 3348 {
3349 3349 DBG_CALL(Dbg_reloc_run(lmp, 0, ret, DBG_REL_FINISH));
3350 3350
3351 3351 /*
3352 3352 * Establish bindings to all objects that have been bound to.
3353 3353 */
3354 3354 if (bound) {
3355 3355 Rt_map *_lmp;
3356 3356 Word used;
3357 3357
3358 3358 /*
3359 3359 * Only create bindings if the callers relocation was
3360 3360 * successful (ret != 0), otherwise the object will eventually
3361 3361 * be torn down. Create these bindings if running under ldd(1)
3362 3362 * with the -U/-u options regardless of relocation errors, as
3363 3363 * the unused processing needs to traverse these bindings to
3364 3364 * diagnose unused objects.
3365 3365 */
3366 3366 used = LIST(lmp)->lm_flags &
3367 3367 (LML_FLG_TRC_UNREF | LML_FLG_TRC_UNUSED);
3368 3368
3369 3369 if (ret || used) {
3370 3370 Aliste idx;
3371 3371
3372 3372 for (APLIST_TRAVERSE(bound, idx, _lmp)) {
3373 3373 if (bind_one(lmp, _lmp, BND_REFER) || used)
3374 3374 continue;
3375 3375
3376 3376 ret = 0;
3377 3377 break;
3378 3378 }
3379 3379 }
3380 3380 free(bound);
3381 3381 }
3382 3382
3383 3383 return (ret);
3384 3384 }
3385 3385
3386 3386 /*
3387 3387 * Function to correct protection settings. Segments are all mapped initially
3388 3388 * with permissions as given in the segment header. We need to turn on write
3389 3389 * permissions on a text segment if there are any relocations against that
3390 3390 * segment, and then turn write permission back off again before returning
3391 3391 * control to the caller. This function turns the permission on or off
3392 3392 * depending on the value of the permission argument.
3393 3393 */
3394 3394 int
3395 3395 set_prot(Rt_map *lmp, mmapobj_result_t *mpp, int perm)
3396 3396 {
3397 3397 int prot;
3398 3398
3399 3399 /*
3400 3400 * If this is an allocated image (ie. a relocatable object) we can't
3401 3401 * mprotect() anything.
3402 3402 */
3403 3403 if (FLAGS(lmp) & FLG_RT_IMGALLOC)
3404 3404 return (1);
3405 3405
3406 3406 DBG_CALL(Dbg_file_prot(lmp, perm));
3407 3407
3408 3408 if (perm)
3409 3409 prot = mpp->mr_prot | PROT_WRITE;
3410 3410 else
3411 3411 prot = mpp->mr_prot & ~PROT_WRITE;
3412 3412
3413 3413 if (mprotect((void *)(uintptr_t)mpp->mr_addr,
3414 3414 mpp->mr_msize, prot) == -1) {
3415 3415 int err = errno;
3416 3416 eprintf(LIST(lmp), ERR_FATAL, MSG_INTL(MSG_SYS_MPROT),
3417 3417 NAME(lmp), strerror(err));
3418 3418 return (0);
3419 3419 }
3420 3420 mpp->mr_prot = prot;
3421 3421 return (1);
3422 3422 }
↓ open down ↓ |
1866 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX