Print this page
smatch clean rtld
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/sgs/rtld/common/audit.c
+++ new/usr/src/cmd/sgs/rtld/common/audit.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) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 * Copyright (c) 2012, Joyent, Inc. All rights reserved.
25 25 *
26 26 * Audit interfaces. Auditing can be enabled in two ways:
27 27 *
28 28 * - Using the LD_AUDIT environment variable
29 29 *
30 30 * - From individual objects containing a DT_DEPAUDIT entry
31 31 * (see ld(1) -P/-p options).
32 32 *
33 33 * The former establishes a global set of audit libraries which can inspect all
34 34 * objects from a given process. The latter establishes a local set of audit
35 35 * libraries which can inspect the immediate dependencies of the caller.
36 36 *
37 37 * Audit library capabilities are indicated by flags within the link-map list
38 38 * header (for global auditing), see LML_TFLG_AUD_* flags, or by the same flags
39 39 * within the individual link-map (for local auditing). Although both sets of
40 40 * flags can occur in different data items they are defined as one to simplify
41 41 * audit interface requirements. The basic test for all audit interfaces is:
42 42 *
43 43 * if ((lml->lm_tflags | AFLAGS(lmp)) & LML_TFLG_AUD_MASK)
44 44 *
45 45 * Note. Auditors themselves are identified with the LML_TFLG_NOAUDIT link-map
46 46 * list flag, and no LML_TFLG_AUD_MASK flags. These flags get propagated from
47 47 * a callers link-map list to any new link-map lists created. Thus, standard
48 48 * link-maps lists have the LML_TFLG_AUD_MASK flags propagated, and should a
49 49 * new link-map list be created by an auditor, that list gets tagged as
50 50 * LML_TFLG_NOAUDIT.
51 51 *
52 52 * The latter link-map list equivalence test insures that auditors themselves
53 53 * (invoked through DT_DEPAUDIT) are not audited.
54 54 *
55 55 * The history of version changes:
56 56 *
57 57 * LAV_VERSION1 (Solaris 2.6)
58 58 * Auditing implementation added.
59 59 *
60 60 * LAV_VERSION2 (Solaris 2.6)
61 61 * LA_SYMB_ALTVALUE support added.
62 62 *
63 63 * LAV_VERSION3 (Solaris 9 update 7)
64 64 * ld_objfilter() added.
65 65 *
66 66 * LAV_VERSION4 (Solaris 10 update 5)
67 67 * Correction of activity calls for local auditors, and introduction of
68 68 * -z globalaudit concept.
69 69 *
70 70 * LAV_VERSION5 (Solaris 11)
71 71 * Under this version, preinit and activity events are enabled from local
72 72 * auditors. The la_preinit and la_activity interfaces require a cookie
73 73 * that represents the head of the link-map list being audited. If a
74 74 * local preinit or activity interface is detected, the local auditors
75 75 * la_objopen() routine is called with a cookie that represents the object
76 76 * that heads the link-map list of the object being audited.
77 77 *
78 78 * A local auditor is loaded through adding a new dependency that requests
79 79 * auditing, and therefore an la_activity(ADD) event is already in effect.
80 80 * Regardless, the local auditors la_activity() routine is called with the
81 81 * cookie that represents the object that heads the link-map list of the
82 82 * object being audited.
83 83 *
84 84 * A local auditor can be loaded prior to the preinit event. In this case,
85 85 * the local auditors la_preinit() routine is called with the cookie that
86 86 * represents the object that heads the link-map list of the object being
87 87 * audited. After the preinit event, any la_preinit() routine within a
88 88 * local auditor will not be called.
89 89 *
90 90 * These events are intended to follow the expected sequence of events
91 91 * received by global auditors, ie:
92 92 *
93 93 * - la_objopen(main)
94 94 * - la_activity(ADD)
95 95 * - la_objopen(dependency)
96 96 * - la_activity(CONSISTENT)
97 97 * - la_preinit(main)
98 98 */
99 99
100 100 #include <stdio.h>
101 101 #include <sys/types.h>
102 102 #include <sys/lwp.h>
103 103 #include <stdio.h>
104 104 #include <stdarg.h>
105 105 #include <dlfcn.h>
106 106 #include <string.h>
107 107 #include <debug.h>
108 108 #include "_rtld.h"
109 109 #include "_audit.h"
110 110 #include "_elf.h"
111 111 #include "msg.h"
112 112
113 113 uint_t audit_flags = 0; /* Copy of specific audit flags to */
114 114 /* simplify boot_elf.s access. */
115 115
116 116 /*
117 117 * Obtain a head link-map cookie. Local auditors can provide la_preinit() and
118 118 * la_activity() routines, and these routines require a cookie that represents
119 119 * the object that heads the link-map of the object being audited. A list of
120 120 * these cookies is maintained on the link-map list. This list allows multiple
121 121 * local objects to specify the same auditor, and to obtain the same cookie
122 122 * for the link-map that heads the link-map list.
123 123 *
124 124 * The initial cookie is created by _audit_create_head_client() which is called
125 125 * from _audit_add_head(). This cookies address is then passed to the local
126 126 * auditors ld_objopen() and la_activity() routines. Subsequent preinit and
127 127 * activity events use _audit_get_head_client() to dynamically retrieve the
128 128 * cookies address.
129 129 */
130 130 static Audit_client *
131 131 _audit_get_head_client(Rt_map *hlmp, Rt_map *almp)
132 132 {
133 133 Audit_client *acp;
134 134 Aliste idx;
135 135 Lm_list *hlml = LIST(hlmp);
136 136
137 137 for (ALIST_TRAVERSE(hlml->lm_aud_cookies, idx, acp)) {
138 138 if (acp->ac_lmp == almp)
139 139 return (acp);
140 140 }
141 141 return (NULL);
142 142 }
143 143
144 144 static Audit_client *
145 145 _audit_create_head_client(Rt_map *hlmp, Rt_map *almp)
146 146 {
147 147 Audit_client ac, *acp;
148 148 Lm_list *hlml = LIST(hlmp);
149 149
150 150 ac.ac_lmp = almp;
151 151 ac.ac_cookie = (uintptr_t)hlmp;
152 152 ac.ac_flags = 0;
153 153
154 154 if ((acp = alist_append(&(hlml->lm_aud_cookies), &ac,
155 155 sizeof (Audit_client), AL_CNT_COOKIES)) == NULL)
156 156 return (NULL);
157 157
158 158 return (acp);
159 159 }
160 160
161 161 /*
162 162 * Determine the appropriate client. Each client structure identifies the
163 163 * link-map of the auditor it is associated with. From the client structure,
164 164 * the address of the associated cookie, that represents the object being
165 165 * audited, is retrieved so that the address can be passed to any audit call.
166 166 *
167 167 * Note, objects that are being locally audited, can provide la_preinit() and
168 168 * la_activity() routines. These routines must be passed cookies that represent
169 169 * the object that heads the link-map list of the object being audited. These
170 170 * cookies are not maintained on this objects Audit_client structure, but are
171 171 * obtained from the associated link-map lists lm_cookies alist.
172 172 */
173 173 static Audit_client *
174 174 _audit_client(Audit_info *aip, Rt_map *almp)
175 175 {
176 176 int ndx;
177 177
178 178 if (aip == NULL)
179 179 return (NULL);
180 180
181 181 for (ndx = 0; ndx < aip->ai_cnt; ndx++) {
182 182 if (aip->ai_clients[ndx].ac_lmp == almp)
183 183 return (&(aip->ai_clients[ndx]));
184 184 }
185 185 return (NULL);
186 186 }
187 187
188 188 /*
189 189 * la_filter() caller. Traverse through all audit libraries and call any
190 190 * la_filter() entry points found. A zero return from an auditor indicates
191 191 * that the filtee should be ignored.
192 192 */
193 193 static int
194 194 _audit_objfilter(APlist *list, Rt_map *frlmp, const char *ref, Rt_map *felmp,
195 195 uint_t flags)
196 196 {
197 197 Audit_list *alp;
198 198 Aliste idx;
199 199 Lm_list *frlml = LIST(frlmp);
200 200
201 201 for (APLIST_TRAVERSE(list, idx, alp)) {
202 202 Audit_client *fracp, *feacp;
203 203 Rt_map *almp = alp->al_lmp;
204 204 Lm_list *alml = LIST(almp);
205 205 int ret;
206 206
207 207 if (alp->al_objfilter == NULL)
208 208 continue;
209 209 if ((fracp = _audit_client(AUDINFO(frlmp), almp)) == NULL)
210 210 continue;
211 211 if ((feacp = _audit_client(AUDINFO(felmp), almp)) == NULL)
212 212 continue;
213 213
214 214 DBG_CALL(Dbg_audit_objfilter(frlml, DBG_AUD_CALL,
215 215 alp->al_libname, NAME(frlmp), NAME(felmp), ref));
216 216
217 217 leave(alml, thr_flg_reenter);
218 218 ret = (*alp->al_objfilter)(&(fracp->ac_cookie), ref,
219 219 &(feacp->ac_cookie), flags);
220 220 (void) enter(thr_flg_reenter);
221 221
222 222 if (ret == 0) {
223 223 DBG_CALL(Dbg_audit_objfilter(frlml, DBG_AUD_RET,
224 224 alp->al_libname, NAME(frlmp), NULL, NULL));
225 225 return (0);
226 226 }
227 227 }
228 228 return (1);
229 229 }
230 230
231 231 int
232 232 audit_objfilter(Rt_map *frlmp, const char *ref, Rt_map *felmp, uint_t flags)
233 233 {
234 234 uint_t rtldflags;
235 235 int respond = 1;
236 236
237 237 if (rt_critical())
238 238 return (respond);
239 239
240 240 APPLICATION_ENTER(rtldflags);
241 241
242 242 if (auditors && (auditors->ad_flags & LML_TFLG_AUD_OBJFILTER))
243 243 respond = _audit_objfilter(auditors->ad_list, frlmp,
244 244 ref, felmp, flags);
245 245 if (respond && AUDITORS(frlmp) &&
246 246 (AUDITORS(frlmp)->ad_flags & LML_TFLG_AUD_OBJFILTER))
247 247 respond = _audit_objfilter(AUDITORS(frlmp)->ad_list, frlmp,
248 248 ref, felmp, flags);
249 249
250 250 APPLICATION_RETURN(rtldflags);
251 251
252 252 return (respond);
253 253 }
254 254
255 255 /*
256 256 * la_objsearch() caller. Traverse through all audit libraries and call any
257 257 * la_objsearch() entry points found.
258 258 *
259 259 * Effectively any audit library can change the name we're working with, so we
260 260 * continue to propagate the new name to each audit library. Any 0 return
261 261 * terminates the search.
262 262 */
263 263 static char *
264 264 _audit_objsearch(APlist *list, char *oname, Rt_map *clmp, uint_t flags)
265 265 {
266 266 Audit_list *alp;
267 267 Aliste idx;
268 268 Lm_list *clml = LIST(clmp);
269 269
270 270 for (APLIST_TRAVERSE(list, idx, alp)) {
271 271 Audit_client *acp;
272 272 Rt_map *almp = alp->al_lmp;
273 273 Lm_list *alml = LIST(almp);
274 274 char *nname = oname;
275 275
276 276 if (alp->al_objsearch == NULL)
277 277 continue;
278 278 if ((acp = _audit_client(AUDINFO(clmp), almp)) == NULL)
279 279 continue;
280 280
281 281 DBG_CALL(Dbg_audit_objsearch(clml, DBG_AUD_CALL,
282 282 alp->al_libname, nname, flags, NULL));
283 283
284 284 leave(alml, thr_flg_reenter);
285 285 nname = (*alp->al_objsearch)(nname, &(acp->ac_cookie), flags);
286 286 (void) enter(thr_flg_reenter);
287 287
288 288 /*
289 289 * Diagnose any return name that differs from the original name
290 290 * passed to the auditor.
291 291 */
292 292 if (nname && (nname[0] == '\0'))
293 293 nname = NULL;
294 294 if ((nname != oname) || strcmp(nname, oname))
295 295 DBG_CALL(Dbg_audit_objsearch(clml, DBG_AUD_RET,
296 296 alp->al_libname, oname, flags, nname));
297 297
298 298 if ((oname = nname) == NULL)
299 299 break;
300 300
301 301 }
302 302 return (oname);
303 303 }
304 304
305 305 char *
306 306 audit_objsearch(Rt_map *clmp, const char *name, uint_t flags)
307 307 {
308 308 char *nname = (char *)name;
309 309 uint_t rtldflags;
310 310
311 311 if (rt_critical())
312 312 return (nname);
313 313
314 314 APPLICATION_ENTER(rtldflags);
315 315
316 316 if (auditors && (auditors->ad_flags & LML_TFLG_AUD_OBJSEARCH))
317 317 nname = _audit_objsearch(auditors->ad_list, nname,
318 318 clmp, flags);
319 319 if (nname && AUDITORS(clmp) &&
320 320 (AUDITORS(clmp)->ad_flags & LML_TFLG_AUD_OBJSEARCH))
321 321 nname = _audit_objsearch(AUDITORS(clmp)->ad_list, nname,
322 322 clmp, flags);
323 323
324 324 APPLICATION_RETURN(rtldflags);
325 325
326 326 DBG_CALL(Dbg_libs_audit(LIST(clmp), name, nname));
327 327 return (nname);
328 328 }
329 329
330 330 /*
331 331 * la_activity() caller. Traverse through all audit libraries and call any
332 332 * la_activity() entry points found.
333 333 */
334 334 static void
335 335 _audit_activity(APlist *list, Rt_map *clmp, uint_t flags, Boolean client)
336 336 {
337 337 Audit_list *alp;
338 338 Aliste idx;
339 339 Lm_list *clml = LIST(clmp);
340 340
341 341 for (APLIST_TRAVERSE(list, idx, alp)) {
342 342 Audit_client *acp;
343 343 Rt_map *almp = alp->al_lmp;
344 344 Lm_list *alml = LIST(almp);
345 345 uintptr_t *cookie;
346 346
347 347 if (alp->al_activity == 0)
348 348 continue;
349 349
350 350 /*
351 351 * Determine what cookie is required. Any auditing that
352 352 * originates from the object that heads the link-map list has
353 353 * its own cookie. Local auditors must obtain the cookie that
354 354 * represents the object that heads the link-map list.
355 355 */
356 356 if (client)
357 357 acp = _audit_client(AUDINFO(clmp), almp);
358 358 else
359 359 acp = _audit_get_head_client(clml->lm_head, almp);
360 360
361 361 if (acp == NULL)
362 362 continue;
363 363 cookie = &(acp->ac_cookie);
364 364
365 365 /*
366 366 * Make sure the audit library only sees one addition/deletion
367 367 * at a time. This ensures the library doesn't see numerous
368 368 * events from lazy loading a series of libraries. Keep track
369 369 * of this caller having called an auditor, so that the
370 370 * appropriate "consistent" event can be supplied on leaving
371 371 * ld.so.1.
372 372 */
373 373 if ((flags == LA_ACT_ADD) || (flags == LA_ACT_DELETE)) {
374 374 if (alml->lm_flags & LML_FLG_AUDITNOTIFY)
375 375 continue;
376 376
377 377 alml->lm_flags |= LML_FLG_AUDITNOTIFY;
378 378 clml->lm_flags |= LML_FLG_ACTAUDIT;
379 379 } else {
380 380 if ((alml->lm_flags & LML_FLG_AUDITNOTIFY) == 0)
381 381 continue;
382 382
383 383 alml->lm_flags &= ~LML_FLG_AUDITNOTIFY;
384 384 }
385 385
386 386 DBG_CALL(Dbg_audit_activity(clml, alp->al_libname,
387 387 NAME(clml->lm_head), flags));
388 388
389 389 leave(alml, thr_flg_reenter);
390 390 (*alp->al_activity)(cookie, flags);
391 391 (void) enter(thr_flg_reenter);
392 392 }
393 393 }
394 394
395 395 void
396 396 audit_activity(Rt_map *clmp, uint_t flags)
397 397 {
398 398 Rt_map *lmp;
399 399 Aliste idx;
400 400 uint_t rtldflags;
401 401
402 402 if (rt_critical())
403 403 return;
404 404
405 405 APPLICATION_ENTER(rtldflags);
406 406
407 407 if (auditors && (auditors->ad_flags & LML_TFLG_AUD_ACTIVITY))
408 408 _audit_activity(auditors->ad_list, clmp, flags, TRUE);
409 409 if (AUDITORS(clmp) &&
410 410 (AUDITORS(clmp)->ad_flags & LML_TFLG_AUD_ACTIVITY))
411 411 _audit_activity(AUDITORS(clmp)->ad_list, clmp, flags, TRUE);
412 412
413 413 for (APLIST_TRAVERSE(aud_activity, idx, lmp)) {
414 414 if ((clmp != lmp) && AUDITORS(lmp) &&
415 415 (AUDITORS(lmp)->ad_flags & LML_TFLG_AUD_ACTIVITY)) {
416 416 _audit_activity(AUDITORS(lmp)->ad_list, lmp, flags,
417 417 FALSE);
418 418 }
419 419 }
420 420
421 421 APPLICATION_RETURN(rtldflags);
422 422 }
423 423
424 424 /*
425 425 * Determine whether an auditor is in use by the head link-map object.
426 426 */
427 427 static int
428 428 _audit_used_by_head(Rt_map *hlmp, Rt_map *almp)
429 429 {
430 430 Audit_list *alp;
431 431 Aliste idx;
432 432
433 433 for (APLIST_TRAVERSE(AUDITORS(hlmp)->ad_list, idx, alp)) {
434 434 if (alp->al_lmp == almp)
435 435 return (1);
436 436 }
437 437 return (0);
438 438 }
439 439
440 440 /*
441 441 * la_objopen() caller for the head link-map. Global auditors, or an auditor
442 442 * started from the object that heads a link-map list (typically the dynamic
443 443 * executable), are passed to la_objopen(). However, local auditors can
444 444 * provide activity and preinit events, and for these events, a cookie
445 445 * representing the head link-map list object is expected. This routine obtains
446 446 * these cookies from the link-map list lm_cookies element. This element
447 447 * ensures all clients of the same auditor use the same cookie.
448 448 *
449 449 * Although a local auditor will get an la_objopen() call for the object that
450 450 * heads the link-map list of the object being audited, the auditor is not
451 451 * permitted to request binding information for this head object. The head
452 452 * object has already been in existence, and bindings may have been resolved
453 453 * with it. This local auditor is coming into existence too late, and thus we
454 454 * don't allow any bindings to be caught at all.
455 455 */
456 456 static int
457 457 _audit_add_head(Rt_map *clmp, Rt_map *hlmp, int preinit, int activity)
458 458 {
459 459 Lm_list *clml = LIST(clmp);
460 460 Lmid_t lmid = get_linkmap_id(clml);
461 461 Audit_list *alp;
462 462 Aliste idx;
463 463 int save = 0;
464 464
465 465 for (APLIST_TRAVERSE(AUDITORS(clmp)->ad_list, idx, alp)) {
466 466 Audit_client *acp;
467 467 Rt_map *almp = alp->al_lmp;
468 468 Lm_list *alml = LIST(almp);
469 469 uintptr_t *cookie;
470 470 uint_t rtldflags;
471 471
472 472 /*
473 473 * Ensure this local auditor isn't already in existence as an
474 474 * auditor for the head of the link-map list. If it is, then
475 475 * this auditor will have already receive preinit and activity
476 476 * events.
477 477 */
478 478 if (AUDITORS(hlmp) && _audit_used_by_head(hlmp, almp))
479 479 continue;
480 480
481 481 /*
482 482 * Create a cookie that represents the object that heads the
483 483 * link-map list. If the cookie already exists, then this
484 484 * auditor has already been established for another objects
485 485 * local auditing. In this case, do not issue a la_objopen()
486 486 * or la_activity() event, as these will have already occurred.
487 487 */
488 488 if ((acp = _audit_get_head_client(clml->lm_head, almp)) != NULL)
489 489 continue;
490 490 if ((acp =
491 491 _audit_create_head_client(clml->lm_head, almp)) == NULL)
492 492 return (0);
493 493
494 494 cookie = &(acp->ac_cookie);
495 495 save++;
496 496
497 497 /*
498 498 * Call the la_objopen() if available.
499 499 */
500 500 if (alp->al_objopen) {
501 501 uint_t flags;
502 502
503 503 DBG_CALL(Dbg_audit_objopen(clml, DBG_AUD_CALL,
504 504 alp->al_libname, NAME(hlmp), 0, FALSE));
505 505
506 506 APPLICATION_ENTER(rtldflags);
507 507 leave(alml, thr_flg_reenter);
508 508 flags = (*alp->al_objopen)((Link_map *)hlmp, lmid,
509 509 cookie);
510 510 (void) enter(thr_flg_reenter);
511 511 APPLICATION_RETURN(rtldflags);
512 512
513 513 if (flags) {
514 514 DBG_CALL(Dbg_audit_objopen(clml, DBG_AUD_RET,
515 515 alp->al_libname, NAME(hlmp), flags, TRUE));
516 516 }
517 517 }
518 518
519 519 /*
520 520 * Call the la_activity() if available.
521 521 */
522 522 if (alp->al_activity) {
523 523 alml->lm_flags |= LML_FLG_AUDITNOTIFY;
524 524 clml->lm_flags |= LML_FLG_ACTAUDIT;
525 525
526 526 DBG_CALL(Dbg_audit_activity(clml, alp->al_libname,
527 527 NAME(clml->lm_head), LA_ACT_ADD));
528 528
529 529 APPLICATION_ENTER(rtldflags);
530 530 leave(alml, thr_flg_reenter);
531 531 (*alp->al_activity)(cookie, LA_ACT_ADD);
532 532 (void) enter(thr_flg_reenter);
533 533 APPLICATION_RETURN(rtldflags);
534 534 }
535 535 }
536 536
537 537 /*
538 538 * If new head link-map cookies have been generated, then maintain
539 539 * any preinit and/or activity requirements.
540 540 */
541 541 if (save) {
542 542 if (preinit && (aplist_append(&aud_preinit, clmp,
543 543 AL_CNT_AUDITORS) == NULL))
544 544 return (0);
545 545 if (activity && (aplist_append(&aud_activity, clmp,
546 546 AL_CNT_AUDITORS) == NULL))
547 547 return (0);
548 548 }
549 549 return (1);
550 550 }
551 551
552 552 /*
553 553 * la_objopen() caller. Create an audit information structure for the indicated
554 554 * link-map, regardless of an la_objopen() entry point. This structure is used
555 555 * to supply information to various audit interfaces (see LML_MSK_AUDINFO).
556 556 * Traverse through all audit libraries and call any la_objopen() entry points
557 557 * found.
558 558 */
559 559 static int
560 560 _audit_objopen(APlist *list, Rt_map *nlmp, Lmid_t lmid, Audit_info *aip,
561 561 int *ndx)
562 562 {
563 563 Lm_list *nlml = LIST(nlmp);
564 564 Audit_list *alp;
565 565 Aliste idx;
566 566
567 567 for (APLIST_TRAVERSE(list, idx, alp)) {
568 568 uint_t flags;
569 569 Audit_client *acp;
570 570 Rt_map *almp = alp->al_lmp;
571 571 Lm_list *alml = LIST(almp);
572 572
573 573 /*
574 574 * Associate a cookie with the audit library, and assign the
575 575 * initial cookie as the present link-map.
576 576 */
577 577 acp = &aip->ai_clients[(*ndx)++];
578 578 acp->ac_lmp = alp->al_lmp;
579 579 acp->ac_cookie = (uintptr_t)nlmp;
580 580
581 581 if (alp->al_objopen == NULL)
582 582 continue;
583 583
584 584 DBG_CALL(Dbg_audit_objopen(nlml, DBG_AUD_CALL, alp->al_libname,
585 585 NAME(nlmp), 0, FALSE));
586 586
587 587 leave(alml, thr_flg_reenter);
588 588 flags = (*alp->al_objopen)((Link_map *)nlmp, lmid,
589 589 &(acp->ac_cookie));
590 590 (void) enter(thr_flg_reenter);
591 591
592 592 /*
593 593 * Diagnose any flags returned by the auditor.
594 594 */
595 595 if (flags) {
596 596 DBG_CALL(Dbg_audit_objopen(nlml, DBG_AUD_RET,
597 597 alp->al_libname, NAME(nlmp), flags, FALSE));
598 598 }
599 599
600 600 if (flags & LA_FLG_BINDTO)
601 601 acp->ac_flags |= FLG_AC_BINDTO;
602 602
603 603 if (flags & LA_FLG_BINDFROM) {
604 604 ulong_t pltcnt;
605 605
606 606 acp->ac_flags |= FLG_AC_BINDFROM;
607 607
608 608 /*
609 609 * We only need dynamic plt's if a pltenter and/or a
610 610 * pltexit() entry point exist in one of our auditing
611 611 * libraries.
612 612 */
613 613 if (aip->ai_dynplts || (JMPREL(nlmp) == 0) ||
614 614 ((audit_flags & (AF_PLTENTER | AF_PLTEXIT)) == 0))
615 615 continue;
616 616
617 617 /*
618 618 * Create one dynplt for every 'PLT' that exists in the
619 619 * object.
620 620 */
621 621 pltcnt = PLTRELSZ(nlmp) / RELENT(nlmp);
622 622 if ((aip->ai_dynplts = calloc(pltcnt,
623 623 dyn_plt_ent_size)) == NULL)
624 624 return (0);
625 625 }
626 626 }
627 627 return (1);
628 628 }
629 629
630 630 int
631 631 audit_objopen(Rt_map *clmp, Rt_map *nlmp)
632 632 {
633 633 Lmid_t lmid = get_linkmap_id(LIST(nlmp));
634 634 int respond = 1, ndx = 0;
635 635 uint_t rtldflags;
636 636 uint_t clients = 0;
637 637 Audit_info *aip;
638 638
639 639 if (rt_critical())
640 640 return (respond);
641 641
642 642 /*
643 643 * Determine the number of auditors that can receive information
644 644 * regarding this object. This provides the number of client
645 645 * structures required for this object.
646 646 */
647 647 if (auditors)
648 648 clients = auditors->ad_cnt;
649 649 if (AUDITORS(clmp))
650 650 clients += AUDITORS(clmp)->ad_cnt;
651 651 if ((nlmp != clmp) && AUDITORS(nlmp))
652 652 clients += AUDITORS(nlmp)->ad_cnt;
653 653
654 654 /*
655 655 * Allocate an audit information structure. Each audited object
656 656 * maintains a AUDINFO() structure. As this structure can only be
657 657 * created once all auditors are loaded, a client count can now be
658 658 * computed.
659 659 *
660 660 * The allocation of the audit information structure includes an array
661 661 * of audit clients, 1 per audit library that has been loaded.
662 662 *
663 663 * ---------------
664 664 * | ai_cnt |
665 665 * Audit_info | ai_clients |-------
666 666 * | ai_dynplts | |
667 667 * |---------------| |
668 668 * Audit_client | 1 |<------
669 669 * |---------------|
670 670 * | 2 |
671 671 * .........
672 672 */
673 673 if ((AUDINFO(nlmp) = aip = calloc(1, sizeof (Audit_info) +
674 674 (sizeof (Audit_client) * clients))) == NULL)
675 675 return (0);
676 676
677 677 aip->ai_cnt = clients;
678 678 aip->ai_clients = (Audit_client *)((uintptr_t)aip +
679 679 sizeof (Audit_info));
680 680
681 681 APPLICATION_ENTER(rtldflags);
682 682
683 683 if (auditors)
684 684 respond = _audit_objopen(auditors->ad_list, nlmp,
685 685 lmid, aip, &ndx);
686 686 if (respond && AUDITORS(clmp))
687 687 respond = _audit_objopen(AUDITORS(clmp)->ad_list, nlmp,
688 688 lmid, aip, &ndx);
689 689 if (respond && (nlmp != clmp) && AUDITORS(nlmp))
690 690 respond = _audit_objopen(AUDITORS(nlmp)->ad_list, nlmp,
691 691 lmid, aip, &ndx);
692 692
693 693 APPLICATION_RETURN(rtldflags);
694 694
695 695 return (respond);
696 696 }
697 697
698 698 /*
699 699 * la_objclose() caller. Traverse through all audit libraries and call any
700 700 * la_objclose() entry points found.
701 701 */
702 702 void
703 703 _audit_objclose(APlist *list, Rt_map *lmp)
704 704 {
705 705 Audit_list *alp;
706 706 Aliste idx;
707 707 Lm_list *lml = LIST(lmp);
708 708
709 709 for (APLIST_TRAVERSE(list, idx, alp)) {
710 710 Audit_client *acp;
711 711 Rt_map *almp = alp->al_lmp;
↓ open down ↓ |
711 lines elided |
↑ open up ↑ |
712 712 Lm_list *alml = LIST(almp);
713 713
714 714 if (alp->al_objclose == NULL)
715 715 continue;
716 716 if ((acp = _audit_client(AUDINFO(lmp), almp)) == NULL)
717 717 continue;
718 718
719 719 DBG_CALL(Dbg_audit_objclose(lml, alp->al_libname, NAME(lmp)));
720 720
721 721 leave(alml, thr_flg_reenter);
722 - (*alp->al_objclose)(&(acp->ac_cookie));
722 + (void) (*alp->al_objclose)(&(acp->ac_cookie));
723 723 (void) enter(thr_flg_reenter);
724 724 }
725 725 }
726 726
727 727 /*
728 728 * Determine any la_objclose() requirements. An object that is about to be
729 729 * deleted needs to trigger an la_objclose() event to any associated auditors.
730 730 * In the case of local auditing, a deleted object may have a number of callers,
731 731 * and each of these callers may have their own auditing requirements. To
732 732 * ensure only one la_objclose() event is sent to each auditor, collect the
733 733 * auditors from any callers and make sure there's no duplication.
734 734 */
735 735 inline static void
736 736 add_objclose_list(Rt_map *lmp, APlist **alpp)
737 737 {
738 738 if (AFLAGS(lmp) & LML_TFLG_AUD_OBJCLOSE) {
739 739 Audit_list *alp;
740 740 Aliste idx;
741 741
742 742 for (APLIST_TRAVERSE(AUDITORS(lmp)->ad_list, idx, alp)) {
743 743 if (aplist_test(alpp, alp, AL_CNT_AUDITORS) == 0)
744 744 return;
745 745 }
746 746 }
747 747 }
748 748
749 749 void
750 750 audit_objclose(Rt_map *lmp, Rt_map *clmp)
751 751 {
752 752 APlist *alp = NULL;
753 753 uint_t rtldflags;
754 754
755 755 if (rt_critical())
756 756 return;
757 757
758 758 APPLICATION_ENTER(rtldflags);
759 759
760 760 if (auditors && (auditors->ad_flags & LML_TFLG_AUD_OBJCLOSE))
761 761 _audit_objclose(auditors->ad_list, lmp);
762 762
763 763 /*
764 764 * If this link-map list contains local auditors, determine if this
765 765 * object, or any of this objects CALLERS have instantiated auditors
766 766 * that need to know of la_objclose() events.
767 767 */
768 768 if (LIST(lmp)->lm_flags & LML_FLG_LOCAUDIT) {
769 769 Bnd_desc *bdp;
770 770 Aliste idx;
771 771
772 772 add_objclose_list(lmp, &alp);
773 773
774 774 for (APLIST_TRAVERSE(CALLERS(lmp), idx, bdp))
775 775 add_objclose_list(bdp->b_caller, &alp);
776 776 }
777 777
778 778 /*
779 779 * If this close originated from dlclose(), determine whether the caller
780 780 * requires a la_objclose() event.
781 781 */
782 782 if (clmp)
783 783 add_objclose_list(clmp, &alp);
784 784
785 785 if (alp) {
786 786 _audit_objclose(alp, lmp);
787 787 free((void *)alp);
788 788 }
789 789
790 790 APPLICATION_RETURN(rtldflags);
791 791 }
792 792
793 793 /*
794 794 * la_pltenter() caller. Traverse through all audit libraries and call any
795 795 * la_pltenter() entry points found. NOTE: this routine is called via the
796 796 * glue code established in elf_plt_trace_write(), the symbol descriptor is
797 797 * created as part of the glue and for 32bit environments the st_name is a
798 798 * pointer to the real symbol name (ie. it's already been adjusted with the
799 799 * objects base offset). For 64bit environments the st_name remains the
800 800 * original symbol offset and in this case it is used to compute the real name
801 801 * pointer and pass as a separate argument to the auditor.
802 802 */
803 803 static void
804 804 _audit_pltenter(APlist *list, Rt_map *rlmp, Rt_map *dlmp, Sym *sym,
805 805 uint_t ndx, void *regs, uint_t *flags)
806 806 {
807 807 Audit_list *alp;
808 808 Aliste idx;
809 809 Lm_list *rlml = LIST(rlmp);
810 810 #if defined(_ELF64)
811 811 const char *name = (const char *)(sym->st_name + STRTAB(dlmp));
812 812 #else
813 813 const char *name = (const char *)(sym->st_name);
814 814 #endif
815 815
816 816 for (APLIST_TRAVERSE(list, idx, alp)) {
817 817 Audit_client *racp, *dacp;
818 818 Rt_map *almp = alp->al_lmp;
819 819 Lm_list *alml = LIST(almp);
820 820 Addr ovalue = sym->st_value;
821 821
822 822 if (alp->al_pltenter == 0)
823 823 continue;
824 824 if ((racp = _audit_client(AUDINFO(rlmp), almp)) == NULL)
825 825 continue;
826 826 if ((dacp = _audit_client(AUDINFO(dlmp), almp)) == NULL)
827 827 continue;
828 828 if (((racp->ac_flags & FLG_AC_BINDFROM) == 0) ||
829 829 ((dacp->ac_flags & FLG_AC_BINDTO) == 0))
830 830 continue;
831 831
832 832 DBG_CALL(Dbg_audit_pltenter(rlml, DBG_AUD_CALL,
833 833 alp->al_libname, name, ovalue));
834 834
835 835 leave(alml, thr_flg_reenter);
836 836 sym->st_value = (Addr)(*alp->al_pltenter)(sym, ndx,
837 837 &(racp->ac_cookie), &(dacp->ac_cookie), regs,
838 838 /* BEGIN CSTYLED */
839 839 #if defined(_ELF64)
840 840 flags, name);
841 841 #else
842 842 flags);
843 843 #endif
844 844 /* END CSTYLED */
845 845 (void) enter(thr_flg_reenter);
846 846
847 847 if (ovalue != sym->st_value) {
848 848 DBG_CALL(Dbg_audit_pltenter(rlml, DBG_AUD_RET,
849 849 alp->al_libname, name, sym->st_value));
850 850 }
851 851 }
852 852 }
853 853
854 854 Addr
855 855 audit_pltenter(Rt_map *rlmp, Rt_map *dlmp, Sym *sym, uint_t ndx,
856 856 void *regs, uint_t *flags)
857 857 {
858 858 Sym nsym = *sym;
859 859 uint_t rtldflags;
860 860
861 861 if (rt_critical())
862 862 return (nsym.st_value);
863 863
864 864 /*
865 865 * We're effectively entering ld.so.1 from user (glue) code.
866 866 */
867 867 (void) enter(0);
868 868 APPLICATION_ENTER(rtldflags);
869 869
870 870 if (auditors && (auditors->ad_flags & LML_TFLG_AUD_PLTENTER))
871 871 _audit_pltenter(auditors->ad_list, rlmp, dlmp, &nsym,
872 872 ndx, regs, flags);
873 873 if (AUDITORS(rlmp) &&
874 874 (AUDITORS(rlmp)->ad_flags & LML_TFLG_AUD_PLTENTER))
875 875 _audit_pltenter(AUDITORS(rlmp)->ad_list, rlmp, dlmp, &nsym,
876 876 ndx, regs, flags);
877 877
878 878 APPLICATION_RETURN(rtldflags);
879 879 leave(LIST(rlmp), 0);
880 880
881 881 return (nsym.st_value);
882 882 }
883 883
884 884 /*
885 885 * la_pltexit() caller. Traverse through all audit libraries and call any
886 886 * la_pltexit() entry points found. See notes above (_audit_pltenter) for
887 887 * discussion on st_name.
888 888 */
889 889 static Addr
890 890 _audit_pltexit(APlist *list, uintptr_t retval, Rt_map *rlmp, Rt_map *dlmp,
891 891 Sym *sym, uint_t ndx)
892 892 {
893 893 Audit_list *alp;
894 894 Aliste idx;
895 895 #if defined(_ELF64)
896 896 const char *name = (const char *)(sym->st_name + STRTAB(dlmp));
897 897 #else
898 898 const char *name = (const char *)(sym->st_name);
899 899 #endif
900 900 Lm_list *rlml = LIST(rlmp);
901 901
902 902 for (APLIST_TRAVERSE(list, idx, alp)) {
903 903 Audit_client *racp, *dacp;
904 904 Rt_map *almp = alp->al_lmp;
905 905 Lm_list *alml = LIST(almp);
906 906
907 907 if (alp->al_pltexit == 0)
908 908 continue;
909 909 if ((racp = _audit_client(AUDINFO(rlmp), almp)) == NULL)
910 910 continue;
911 911 if ((dacp = _audit_client(AUDINFO(dlmp), almp)) == NULL)
912 912 continue;
913 913 if (((racp->ac_flags & FLG_AC_BINDFROM) == 0) ||
914 914 ((dacp->ac_flags & FLG_AC_BINDTO) == 0))
915 915 continue;
916 916
917 917 DBG_CALL(Dbg_audit_pltexit(rlml, alp->al_libname, name));
918 918
919 919 leave(alml, thr_flg_reenter);
920 920 retval = (*alp->al_pltexit)(sym, ndx,
921 921 &(racp->ac_cookie), &(dacp->ac_cookie),
922 922 /* BEGIN CSTYLED */
923 923 #if defined(_ELF64)
924 924 retval, name);
925 925 #else
926 926 retval);
927 927 #endif
928 928 /* END CSTYLED */
929 929 (void) enter(thr_flg_reenter);
930 930 }
931 931 return (retval);
932 932 }
933 933
934 934 Addr
935 935 audit_pltexit(uintptr_t retval, Rt_map *rlmp, Rt_map *dlmp, Sym *sym,
936 936 uint_t ndx)
937 937 {
938 938 uintptr_t _retval = retval;
939 939 uint_t rtldflags;
940 940
941 941 if (rt_critical())
942 942 return (_retval);
943 943
944 944 /*
945 945 * We're effectively entering ld.so.1 from user (glue) code.
946 946 */
947 947 (void) enter(0);
948 948 APPLICATION_ENTER(rtldflags);
949 949
950 950 if (auditors && (auditors->ad_flags & LML_TFLG_AUD_PLTEXIT))
951 951 _retval = _audit_pltexit(auditors->ad_list, _retval,
952 952 rlmp, dlmp, sym, ndx);
953 953 if (AUDITORS(rlmp) && (AUDITORS(rlmp)->ad_flags & LML_TFLG_AUD_PLTEXIT))
954 954 _retval = _audit_pltexit(AUDITORS(rlmp)->ad_list, _retval,
955 955 rlmp, dlmp, sym, ndx);
956 956
957 957 APPLICATION_RETURN(rtldflags);
958 958 leave(LIST(rlmp), 0);
959 959
960 960 return (_retval);
961 961 }
962 962
963 963
964 964 /*
965 965 * la_symbind() caller. Traverse through all audit libraries and call any
966 966 * la_symbind() entry points found.
967 967 */
968 968 static Addr
969 969 _audit_symbind(APlist *list, Rt_map *rlmp, Rt_map *dlmp, Sym *sym, uint_t ndx,
970 970 uint_t *flags, int *called)
971 971 {
972 972 Audit_list *alp;
973 973 Aliste idx;
974 974 Lm_list *rlml = LIST(rlmp);
975 975 #if defined(_ELF64)
976 976 const char *name = (const char *)(sym->st_name + STRTAB(dlmp));
977 977 #else
978 978 const char *name = (const char *)(sym->st_name);
979 979 #endif
980 980
981 981 for (APLIST_TRAVERSE(list, idx, alp)) {
982 982 Audit_client *racp, *dacp;
983 983 Rt_map *almp = alp->al_lmp;
984 984 Lm_list *alml = LIST(almp);
985 985 Addr ovalue = sym->st_value;
986 986 uint_t lflags, oflags = *flags;
987 987
988 988 if (alp->al_symbind == 0)
989 989 continue;
990 990
991 991 if ((racp = _audit_client(AUDINFO(rlmp), almp)) != NULL &&
992 992 (racp->ac_flags & FLG_AC_BINDFROM) == 0)
993 993 continue;
994 994
995 995 if ((dacp = _audit_client(AUDINFO(dlmp), almp)) == NULL)
996 996 continue;
997 997
998 998 if ((dacp->ac_flags & FLG_AC_BINDTO) == 0)
999 999 continue;
1000 1000
1001 1001 /*
1002 1002 * The la_symbind interface is only called when the destination
1003 1003 * object has been identified as BINDTO and either the
1004 1004 * destination object is being locally audited or the calling
1005 1005 * object has been identified as BINDFROM. Use a local version
1006 1006 * of the flags, so that any user update can be collected.
1007 1007 */
1008 1008 (*called)++;
1009 1009 lflags = (oflags & ~(LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT));
1010 1010
1011 1011 DBG_CALL(Dbg_audit_symbind(rlml, DBG_AUD_CALL,
1012 1012 alp->al_libname, name, ovalue, oflags));
1013 1013
1014 1014 leave(alml, thr_flg_reenter);
1015 1015 sym->st_value = (*alp->al_symbind)(sym, ndx, racp == NULL ?
1016 1016 NULL : &(racp->ac_cookie), &(dacp->ac_cookie),
1017 1017 /* BEGIN CSTYLED */
1018 1018 #if defined(_ELF64)
1019 1019 &lflags, name);
1020 1020 #else
1021 1021 &lflags);
1022 1022 #endif
1023 1023 /* END CSTYLED */
1024 1024 (void) enter(thr_flg_reenter);
1025 1025
1026 1026 /*
1027 1027 * If the auditor indicated that they did not want to process
1028 1028 * pltenter, or pltexit audits for this symbol, retain this
1029 1029 * information. Also retain whether an alternative symbol value
1030 1030 * has been supplied.
1031 1031 */
1032 1032 *flags |= (lflags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT));
1033 1033 if ((ovalue != sym->st_value) &&
1034 1034 (alp->al_vernum >= LAV_VERSION2))
1035 1035 *flags |= LA_SYMB_ALTVALUE;
1036 1036
1037 1037 if ((ovalue != sym->st_value) || (oflags != *flags)) {
1038 1038 DBG_CALL(Dbg_audit_symbind(rlml, DBG_AUD_RET,
1039 1039 alp->al_libname, name, sym->st_value, *flags));
1040 1040 }
1041 1041 }
1042 1042 return (sym->st_value);
1043 1043 }
1044 1044
1045 1045 Addr
1046 1046 audit_symbind(Rt_map *rlmp, Rt_map *dlmp, Sym *sym, uint_t ndx, Addr value,
1047 1047 uint_t *flags)
1048 1048 {
1049 1049 Sym nsym;
1050 1050 int called = 0;
1051 1051 uint_t rtldflags;
1052 1052
1053 1053 /*
1054 1054 * Construct a new symbol from that supplied but with the real address.
1055 1055 * In the 64-bit world the st_name field is only 32-bits which isn't
1056 1056 * big enough to hold a character pointer. We pass this pointer as a
1057 1057 * separate parameter for 64-bit audit libraries.
1058 1058 */
1059 1059 nsym = *sym;
1060 1060 nsym.st_value = value;
1061 1061
1062 1062 if (rt_critical())
1063 1063 return (nsym.st_value);
1064 1064
1065 1065 #if !defined(_ELF64)
1066 1066 nsym.st_name += (Word)STRTAB(dlmp);
1067 1067 #endif
1068 1068 APPLICATION_ENTER(rtldflags);
1069 1069
1070 1070 if (auditors && (auditors->ad_flags & LML_TFLG_AUD_SYMBIND))
1071 1071 nsym.st_value = _audit_symbind(auditors->ad_list,
1072 1072 rlmp, dlmp, &nsym, ndx, flags, &called);
1073 1073
1074 1074 if (AUDITORS(rlmp) && (AUDITORS(rlmp)->ad_flags & LML_TFLG_AUD_SYMBIND))
1075 1075 nsym.st_value = _audit_symbind(AUDITORS(rlmp)->ad_list,
1076 1076 rlmp, dlmp, &nsym, ndx, flags, &called);
1077 1077
1078 1078 if (dlmp != rlmp && AUDITORS(dlmp) &&
1079 1079 (AUDITORS(dlmp)->ad_flags & LML_TFLG_AUD_SYMBIND)) {
1080 1080 nsym.st_value = _audit_symbind(AUDITORS(dlmp)->ad_list,
1081 1081 rlmp, dlmp, &nsym, ndx, flags, &called);
1082 1082 }
1083 1083
1084 1084 /*
1085 1085 * If no la_symbind() was called for this interface, fabricate that no
1086 1086 * la_pltenter, or la_pltexit is required. This helps reduce the glue
1087 1087 * code created for further auditing.
1088 1088 */
1089 1089 if (called == 0)
1090 1090 *flags |= (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT);
1091 1091
1092 1092 APPLICATION_RETURN(rtldflags);
1093 1093
1094 1094 return (nsym.st_value);
1095 1095 }
1096 1096
1097 1097 /*
1098 1098 * la_preinit() caller. Traverse through all audit libraries and call any
1099 1099 * la_preinit() entry points found.
1100 1100 */
1101 1101 static void
1102 1102 _audit_preinit(APlist *list, Rt_map *clmp, Boolean client)
1103 1103 {
1104 1104 Audit_list *alp;
1105 1105 Aliste idx;
1106 1106 Lm_list *clml = LIST(clmp);
1107 1107
1108 1108 for (APLIST_TRAVERSE(list, idx, alp)) {
1109 1109 Audit_client *acp;
1110 1110 Rt_map *almp = alp->al_lmp;
1111 1111 Lm_list *alml = LIST(almp);
1112 1112 uintptr_t *cookie;
1113 1113
1114 1114 if (alp->al_preinit == 0)
1115 1115 continue;
1116 1116
1117 1117 /*
1118 1118 * Determine what cookie is required. Any auditing that
1119 1119 * originates from the object that heads the link-map list has
1120 1120 * its own cookie. Local auditors must obtain the cookie that
1121 1121 * represents the object that heads the link-map list.
1122 1122 */
1123 1123 if (client)
1124 1124 acp = _audit_client(AUDINFO(clmp), almp);
1125 1125 else
1126 1126 acp = _audit_get_head_client(clml->lm_head, almp);
1127 1127
1128 1128 if (acp == NULL)
1129 1129 continue;
1130 1130 cookie = &(acp->ac_cookie);
1131 1131
1132 1132 DBG_CALL(Dbg_audit_preinit(clml, alp->al_libname,
1133 1133 NAME(clml->lm_head)));
1134 1134
1135 1135 leave(alml, thr_flg_reenter);
1136 1136 (*alp->al_preinit)(cookie);
1137 1137 (void) enter(thr_flg_reenter);
1138 1138 }
1139 1139 }
1140 1140
1141 1141 void
1142 1142 audit_preinit(Rt_map *mlmp)
1143 1143 {
1144 1144 Rt_map *clmp;
1145 1145 Aliste idx;
1146 1146 uint_t rtldflags;
1147 1147
1148 1148 if (rt_critical())
1149 1149 return;
1150 1150
1151 1151 APPLICATION_ENTER(rtldflags);
1152 1152
1153 1153 if (auditors && (auditors->ad_flags & LML_TFLG_AUD_PREINIT))
1154 1154 _audit_preinit(auditors->ad_list, mlmp, TRUE);
1155 1155
1156 1156 if (AUDITORS(mlmp) && (AUDITORS(mlmp)->ad_flags & LML_TFLG_AUD_PREINIT))
1157 1157 _audit_preinit(AUDITORS(mlmp)->ad_list, mlmp, TRUE);
1158 1158
1159 1159 for (APLIST_TRAVERSE(aud_preinit, idx, clmp)) {
1160 1160 if (AUDITORS(clmp) &&
1161 1161 (AUDITORS(clmp)->ad_flags & LML_TFLG_AUD_PREINIT))
1162 1162 _audit_preinit(AUDITORS(clmp)->ad_list, clmp, FALSE);
1163 1163 }
1164 1164
1165 1165 APPLICATION_RETURN(rtldflags);
1166 1166 }
1167 1167
1168 1168 /*
1169 1169 * Clean up (free) an audit descriptor. First, gather a list of all handles,
1170 1170 * and then close each one down. This is done rather than using the handles
1171 1171 * directly from the auditors, as the audit list can be torn down as a result
1172 1172 * of the dlclose. In other words, what you're pointing at can be removed
1173 1173 * while you're still pointing at it.
1174 1174 */
1175 1175 void
1176 1176 audit_desc_cleanup(Rt_map *clmp)
1177 1177 {
1178 1178 Audit_desc *adp = AUDITORS(clmp);
1179 1179 Audit_list *alp;
1180 1180 Aliste idx;
1181 1181 APlist *ghalp = NULL;
1182 1182
1183 1183 if (adp == NULL)
1184 1184 return;
1185 1185 if (adp->ad_name)
1186 1186 free(adp->ad_name);
1187 1187
1188 1188 for (APLIST_TRAVERSE(adp->ad_list, idx, alp))
1189 1189 (void) aplist_append(&ghalp, alp->al_ghp, AL_CNT_GROUPS);
1190 1190
1191 1191 free(adp->ad_list);
1192 1192 adp->ad_list = NULL;
1193 1193
1194 1194 free(adp);
1195 1195
1196 1196 /*
1197 1197 * Indicate that the caller is no longer being audited.
1198 1198 */
1199 1199 AUDITORS(clmp) = NULL;
1200 1200 AFLAGS(clmp) &= ~LML_TFLG_AUD_MASK;
1201 1201
1202 1202 if (ghalp) {
1203 1203 Grp_hdl *ghp;
1204 1204 Aliste idx;
1205 1205
1206 1206 for (APLIST_TRAVERSE(ghalp, idx, ghp)) {
1207 1207 (void) dlclose_intn(ghp, clmp);
1208 1208 }
1209 1209 free(ghalp);
1210 1210 }
1211 1211 }
1212 1212
1213 1213 /*
1214 1214 * Objects that establish local auditors may have been added to preinit or
1215 1215 * activity lists. Remove the object from this list if it is present.
1216 1216 */
1217 1217 static void
1218 1218 remove_auditor(APlist *alp, Rt_map *clmp)
1219 1219 {
1220 1220 Rt_map *lmp;
1221 1221 Aliste idx;
1222 1222
1223 1223 for (APLIST_TRAVERSE(alp, idx, lmp)) {
1224 1224 if (lmp == clmp) {
1225 1225 aplist_delete(alp, &idx);
1226 1226 return;
1227 1227 }
1228 1228 }
1229 1229 }
1230 1230
1231 1231 /*
1232 1232 * Clean up (free) an audit information structure.
1233 1233 */
1234 1234 void
1235 1235 audit_info_cleanup(Rt_map *clmp)
1236 1236 {
1237 1237 Audit_info *aip = AUDINFO(clmp);
1238 1238
1239 1239 if (aip == NULL)
1240 1240 return;
1241 1241
1242 1242 if (aip->ai_dynplts)
1243 1243 free(aip->ai_dynplts);
1244 1244
1245 1245 if (aud_preinit)
1246 1246 remove_auditor(aud_preinit, clmp);
1247 1247 if (aud_activity)
1248 1248 remove_auditor(aud_activity, clmp);
1249 1249
1250 1250 free(aip);
1251 1251 }
1252 1252
1253 1253 /*
1254 1254 * Create a data structure of symbol lookup names and associated flags to help
1255 1255 * simplify audit_symget() use.
1256 1256 */
1257 1257 typedef struct {
1258 1258 Msg sname;
1259 1259 uint_t alflag;
1260 1260 uint_t auflag;
1261 1261 } Aud_info;
1262 1262
1263 1263 static const Aud_info aud_info[] = {
1264 1264 { MSG_SYM_LAVERSION, 0, 0 }, /* MSG_ORIG(MSG_SYM_LAVERSION) */
1265 1265 { MSG_SYM_LAPREINIT, /* MSG_ORIG(MSG_SYM_LAPREINIT) */
1266 1266 LML_TFLG_AUD_PREINIT, 0 },
1267 1267 { MSG_SYM_LAOBJSEARCH, /* MSG_ORIG(MSG_SYM_LAOBJSEARCH) */
1268 1268 LML_TFLG_AUD_OBJSEARCH, 0 },
1269 1269 { MSG_SYM_LAOBJOPEN, /* MSG_ORIG(MSG_SYM_LAOBJOPEN) */
1270 1270 LML_TFLG_AUD_OBJOPEN, 0 },
1271 1271 { MSG_SYM_LAOBJFILTER, /* MSG_ORIG(MSG_SYM_LAOBJFILTER */
1272 1272 LML_TFLG_AUD_OBJFILTER, 0 },
1273 1273 { MSG_SYM_LAOBJCLOSE, /* MSG_ORIG(MSG_SYM_LAOBJCLOSE) */
1274 1274 LML_TFLG_AUD_OBJCLOSE, 0 },
1275 1275 { MSG_SYM_LAACTIVITY, /* MSG_ORIG(MSG_SYM_LAACTIVITY) */
1276 1276 LML_TFLG_AUD_ACTIVITY, 0 },
1277 1277
1278 1278 #if defined(_ELF64)
1279 1279 { MSG_SYM_LASYMBIND_64, /* MSG_ORIG(MSG_SYM_LASYMBIND_64) */
1280 1280 #else
1281 1281 { MSG_SYM_LASYMBIND, /* MSG_ORIG(MSG_SYM_LASYMBIND) */
1282 1282 #endif
1283 1283 LML_TFLG_AUD_SYMBIND, 0 },
1284 1284
1285 1285 #if defined(__sparcv9)
1286 1286 { MSG_SYM_LAV9PLTENTER, /* MSG_ORIG(MSG_SYM_LAV9PLTENTER) */
1287 1287 #elif defined(__sparc)
1288 1288 { MSG_SYM_LAV8PLTENTER, /* MSG_ORIG(MSG_SYM_LAV8PLTENTER) */
1289 1289 #elif defined(__amd64)
1290 1290 { MSG_SYM_LAAMD64PLTENTER, /* MSG_ORIG(MSG_SYM_LAAMD64PLTENTER) */
1291 1291 #elif defined(__i386)
1292 1292 { MSG_SYM_LAX86PLTENTER, /* MSG_ORIG(MSG_SYM_LAX86PLTENTER) */
1293 1293 #else
1294 1294 #error platform not defined!
1295 1295 #endif
1296 1296 LML_TFLG_AUD_PLTENTER, AF_PLTENTER },
1297 1297
1298 1298 #if defined(_ELF64)
1299 1299 { MSG_SYM_LAPLTEXIT_64, /* MSG_ORIG(MSG_SYM_LAPLTEXIT_64) */
1300 1300 #else
1301 1301 { MSG_SYM_LAPLTEXIT, /* MSG_ORIG(MSG_SYM_LAPLTEXIT) */
1302 1302 #endif
1303 1303 LML_TFLG_AUD_PLTEXIT, AF_PLTEXIT }
1304 1304 };
1305 1305
1306 1306 #define AI_LAVERSION 0
1307 1307 #define AI_LAPREINIT 1
1308 1308 #define AI_LAOBJSEARCH 2
1309 1309 #define AI_LAOBJOPEN 3
1310 1310 #define AI_LAOBJFILTER 4
1311 1311 #define AI_LAOBJCLOSE 5
1312 1312 #define AI_LAACTIVITY 6
1313 1313 #define AI_LASYMBIND 7
1314 1314 #define AI_LAPLTENTER 8
1315 1315 #define AI_LAPLTEXIT 9
1316 1316
1317 1317 static Addr
1318 1318 audit_symget(Audit_list *alp, int info, int *in_nfavl)
1319 1319 {
1320 1320 Rt_map *lmp = alp->al_lmp;
1321 1321 const char *sname = MSG_ORIG(aud_info[info].sname);
1322 1322 uint_t alflag = aud_info[info].alflag;
1323 1323 uint_t auflag = aud_info[info].auflag;
1324 1324 uint_t binfo;
1325 1325 Slookup sl;
1326 1326 Sresult sr;
1327 1327
1328 1328 /*
1329 1329 * Initialize the symbol lookup, and symbol result, data structures.
1330 1330 */
1331 1331 SLOOKUP_INIT(sl, sname, lml_rtld.lm_head, lmp, ld_entry_cnt,
1332 1332 0, 0, 0, 0, (LKUP_FIRST | LKUP_DLSYM));
1333 1333 SRESULT_INIT(sr, sname);
1334 1334
1335 1335 if (LM_LOOKUP_SYM(lmp)(&sl, &sr, &binfo, in_nfavl)) {
1336 1336 Addr addr = sr.sr_sym->st_value;
1337 1337
1338 1338 if (!(FLAGS(lmp) & FLG_RT_FIXED))
1339 1339 addr += ADDR(lmp);
1340 1340
1341 1341 if (alflag)
1342 1342 alp->al_flags |= alflag;
1343 1343 if (auflag)
1344 1344 audit_flags |= auflag;
1345 1345
1346 1346 /*
1347 1347 * Note, unlike most other diagnostics, where we wish to
1348 1348 * identify the lmid of the caller, here we use the lmid of
1349 1349 * the auditor itself to show the association of the auditor
1350 1350 * and the interfaces it provides.
1351 1351 */
1352 1352 DBG_CALL(Dbg_audit_interface(LIST(alp->al_lmp),
1353 1353 alp->al_libname, sr.sr_name));
1354 1354 return (addr);
1355 1355 }
1356 1356 return (0);
1357 1357 }
1358 1358
1359 1359 /*
1360 1360 * Centralize cleanup routines.
1361 1361 */
1362 1362 static int
1363 1363 audit_disable(char *name, Rt_map *clmp, Grp_hdl *ghp, Audit_list *alp)
1364 1364 {
1365 1365 eprintf(LIST(clmp), ERR_FATAL, MSG_INTL(MSG_AUD_DISABLED), name);
1366 1366 if (ghp)
1367 1367 (void) dlclose_intn(ghp, clmp);
1368 1368 if (alp)
1369 1369 free(alp);
1370 1370
1371 1371 return (0);
1372 1372 }
1373 1373
1374 1374 /*
1375 1375 * Given a list of one or more audit libraries, open each one and establish a
1376 1376 * a descriptor representing the entry points it provides.
1377 1377 */
1378 1378 int
1379 1379 audit_setup(Rt_map *clmp, Audit_desc *adp, uint_t orig, int *in_nfavl)
1380 1380 {
1381 1381 char *ptr, *next;
1382 1382 Lm_list *clml = LIST(clmp);
1383 1383 Rt_map *hlmp;
1384 1384 int error = 1, activity = 0, preinit = 0;
1385 1385 uint_t rtldflags;
1386 1386
1387 1387 /*
1388 1388 * Determine the type of auditing for diagnostics.
1389 1389 */
1390 1390 if (DBG_ENABLED) {
1391 1391 int type;
1392 1392
1393 1393 if (orig & PD_FLG_EXTLOAD)
1394 1394 type = DBG_AUD_PRELOAD;
1395 1395 else if (FLAGS1(clmp) & FL1_RT_GLOBAUD)
1396 1396 type = DBG_AUD_GLOBAL;
1397 1397 else
1398 1398 type = DBG_AUD_LOCAL;
1399 1399
1400 1400 DBG_CALL(Dbg_audit_lib(clmp, adp->ad_name, type));
1401 1401 }
1402 1402
1403 1403 /*
1404 1404 * Mark that we have at least one auditing link map
1405 1405 */
1406 1406 rtld_flags2 |= RT_FL2_HASAUDIT;
1407 1407
1408 1408 /*
1409 1409 * The audit definitions may be a list (which will already have been
1410 1410 * dupped) so split it into individual tokens.
1411 1411 */
1412 1412 for (ptr = strtok_r(adp->ad_name, MSG_ORIG(MSG_STR_DELIMIT), &next);
1413 1413 ptr; ptr = strtok_r(NULL, MSG_ORIG(MSG_STR_DELIMIT), &next)) {
1414 1414 Grp_hdl *ghp;
1415 1415 Rt_map *lmp;
1416 1416 Lm_list *lml;
1417 1417 Rt_map **tobj;
1418 1418 Audit_list *alp;
1419 1419
1420 1420 DBG_CALL(Dbg_util_nl(clml, DBG_NL_STD));
1421 1421
1422 1422 /*
1423 1423 * Open the audit library on its own link-map.
1424 1424 */
1425 1425 if ((ghp = dlmopen_intn((Lm_list *)LM_ID_NEWLM, ptr,
1426 1426 (RTLD_FIRST | RTLD_GLOBAL | RTLD_WORLD), clmp,
1427 1427 FLG_RT_AUDIT, orig)) == NULL) {
1428 1428 error = audit_disable(ptr, clmp, 0, 0);
1429 1429 continue;
1430 1430 }
1431 1431 lmp = ghp->gh_ownlmp;
1432 1432 lml = LIST(lmp);
1433 1433
1434 1434 /*
1435 1435 * If this auditor has already been loaded, reuse it.
1436 1436 */
1437 1437 if ((alp = lml->lm_alp) != NULL) {
1438 1438 if (aplist_append(&(adp->ad_list), alp,
1439 1439 AL_CNT_AUDITORS) == NULL)
1440 1440 return (audit_disable(ptr, clmp, ghp, alp));
1441 1441
1442 1442 adp->ad_cnt++;
1443 1443 adp->ad_flags |= alp->al_flags;
1444 1444
1445 1445 /*
1446 1446 * If this existing auditor provides preinit or
1447 1447 * activity routines, track their existence. The
1448 1448 * instantiation of a local auditor requires a cookie
1449 1449 * be created that represents the object that heads
1450 1450 * the link-map list of the object being audited.
1451 1451 */
1452 1452 if (alp->al_preinit)
1453 1453 preinit++;
1454 1454 if (alp->al_activity)
1455 1455 activity++;
1456 1456
1457 1457 continue;
1458 1458 }
1459 1459
1460 1460 /*
1461 1461 * Prior to the Unified Process Model (UPM) environment, an
1462 1462 * rtld lock had to be held upon leave(). However, even within
1463 1463 * a UPM environment, an old auditor, that has a lazy dependency
1464 1464 * on libc, is still a possibility. As libc isn't loaded, we
1465 1465 * don't know the process model, and will determine this later.
1466 1466 * Refer to external.c:get_lcinterface().
1467 1467 */
1468 1468 if ((rtld_flags2 & RT_FL2_UNIFPROC) == 0)
1469 1469 lml->lm_flags |= LML_FLG_HOLDLOCK;
1470 1470
1471 1471 /*
1472 1472 * Allocate an audit list descriptor for this object and
1473 1473 * search for all known entry points.
1474 1474 */
1475 1475 if ((alp = calloc(1, sizeof (Audit_list))) == NULL)
1476 1476 return (audit_disable(ptr, clmp, ghp, 0));
1477 1477
1478 1478 alp->al_libname = NAME(lmp);
1479 1479 alp->al_lmp = lmp;
1480 1480 alp->al_ghp = ghp;
1481 1481
1482 1482 /*
1483 1483 * All audit libraries must handshake through la_version().
1484 1484 * Determine that the symbol exists, finish initializing the
1485 1485 * object, and then call the function.
1486 1486 */
1487 1487 if ((alp->al_version = (uint_t(*)())audit_symget(alp,
1488 1488 AI_LAVERSION, in_nfavl)) == 0) {
1489 1489 eprintf(lml, ERR_FATAL, MSG_INTL(MSG_GEN_NOSYM),
1490 1490 MSG_ORIG(MSG_SYM_LAVERSION));
1491 1491 error = audit_disable(ptr, clmp, ghp, alp);
1492 1492 continue;
1493 1493 }
1494 1494
1495 1495 if ((tobj = tsort(lmp, lml->lm_init, RT_SORT_REV)) ==
1496 1496 (Rt_map **)S_ERROR)
1497 1497 return (audit_disable(ptr, clmp, ghp, alp));
1498 1498
1499 1499 if (tobj)
1500 1500 call_init(tobj, DBG_INIT_SORT);
1501 1501
1502 1502 APPLICATION_ENTER(rtldflags);
1503 1503 leave(lml, thr_flg_reenter);
1504 1504 alp->al_vernum = (*alp->al_version)(LAV_CURRENT);
1505 1505 (void) enter(thr_flg_reenter);
1506 1506 APPLICATION_RETURN(rtldflags);
1507 1507
1508 1508 DBG_CALL(Dbg_audit_version(clml, alp->al_libname,
1509 1509 LAV_CURRENT, alp->al_vernum));
1510 1510
1511 1511 if ((alp->al_vernum < LAV_VERSION1) ||
1512 1512 (alp->al_vernum > LAV_CURRENT)) {
1513 1513 eprintf(lml, ERR_FATAL, MSG_INTL(MSG_AUD_BADVERS),
1514 1514 LAV_CURRENT, alp->al_vernum);
1515 1515 error = audit_disable(ptr, clmp, ghp, alp);
1516 1516 continue;
1517 1517 }
1518 1518
1519 1519 if (aplist_append(&(adp->ad_list), alp,
1520 1520 AL_CNT_AUDITORS) == NULL)
1521 1521 return (audit_disable(ptr, clmp, ghp, alp));
1522 1522
1523 1523 adp->ad_cnt++;
1524 1524
1525 1525 /*
1526 1526 * Collect any remaining entry points.
1527 1527 */
1528 1528 alp->al_objsearch = (char *(*)())audit_symget(alp,
1529 1529 AI_LAOBJSEARCH, in_nfavl);
1530 1530 alp->al_objopen = (uint_t(*)())audit_symget(alp,
1531 1531 AI_LAOBJOPEN, in_nfavl);
1532 1532 alp->al_objfilter = (int(*)())audit_symget(alp,
1533 1533 AI_LAOBJFILTER, in_nfavl);
1534 1534 alp->al_objclose = (uint_t(*)())audit_symget(alp,
1535 1535 AI_LAOBJCLOSE, in_nfavl);
1536 1536 alp->al_symbind = (uintptr_t(*)())audit_symget(alp,
1537 1537 AI_LASYMBIND, in_nfavl);
1538 1538 alp->al_pltenter = (uintptr_t(*)())audit_symget(alp,
1539 1539 AI_LAPLTENTER, in_nfavl);
1540 1540 alp->al_pltexit = (uintptr_t(*)())audit_symget(alp,
1541 1541 AI_LAPLTEXIT, in_nfavl);
1542 1542
1543 1543 if ((alp->al_preinit = (void(*)())audit_symget(alp,
1544 1544 AI_LAPREINIT, in_nfavl)) != NULL)
1545 1545 preinit++;
1546 1546 if ((alp->al_activity = (void(*)())audit_symget(alp,
1547 1547 AI_LAACTIVITY, in_nfavl)) != NULL)
1548 1548 activity++;
1549 1549
1550 1550 /*
1551 1551 * Collect the individual object flags, and assign this audit
1552 1552 * list descriptor to its associated link-map list.
1553 1553 */
1554 1554 adp->ad_flags |= alp->al_flags;
1555 1555 lml->lm_alp = alp;
1556 1556 }
1557 1557
1558 1558 /*
1559 1559 * If the caller isn't the head of its own link-map list, then any
1560 1560 * preinit or activity entry points need to be tracked separately.
1561 1561 * These "events" are not associated with a particular link-map, and
1562 1562 * thus a traversal of any existing preinit and activity clients is
1563 1563 * required.
1564 1564 *
1565 1565 * If either of these events are required, establish a cookie for the
1566 1566 * object at the head of the link-map list, and make an initial ADD
1567 1567 * activity for these local auditors.
1568 1568 */
1569 1569 if ((preinit || activity) && ((hlmp = clml->lm_head) != clmp) &&
1570 1570 (_audit_add_head(clmp, hlmp, preinit, activity) == 0))
1571 1571 return (0);
1572 1572
1573 1573 /*
1574 1574 * Free the original audit string, as this descriptor may be used again
1575 1575 * to add additional auditing.
1576 1576 */
1577 1577 free(adp->ad_name);
1578 1578 adp->ad_name = NULL;
1579 1579
1580 1580 return (error);
1581 1581 }
↓ open down ↓ |
849 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX