Mercurial > illumos > illumos-gate
changeset 12889:69001e4756ae
6956152 dlclose() from an auditor can be fatal. Preinit/activity events should be more flexible.
line wrap: on
line diff
--- a/usr/src/cmd/sgs/include/conv.h Tue Jul 20 16:38:52 2010 -0400 +++ b/usr/src/cmd/sgs/include/conv.h Tue Jul 20 16:29:51 2010 -0700 @@ -126,6 +126,33 @@ } Conv_reject_desc_buf_t; /* + * conv_la_bind() + */ +#define CONV_LA_BIND_BUFSIZE 56 +typedef union { + Conv_inv_buf_t inv_buf; + char buf[CONV_LA_BIND_BUFSIZE]; +} Conv_la_bind_buf_t; + +/* + * conv_la_search() + */ +#define CONV_LA_SEARCH_BUFSIZE 111 +typedef union { + Conv_inv_buf_t inv_buf; + char buf[CONV_LA_SEARCH_BUFSIZE]; +} Conv_la_search_buf_t; + +/* + * conv_la_symbind() + */ +#define CONV_LA_SYMBIND_BUFSIZE 113 +typedef union { + Conv_inv_buf_t inv_buf; + char buf[CONV_LA_SYMBIND_BUFSIZE]; +} Conv_la_symbind_buf_t; + +/* * conv_cap_val_hw/sf() * * These sizes are based on the maximum number of capabilities that exist. @@ -843,6 +870,11 @@ extern const char *conv_ent_flags(ec_flags_t, Conv_ent_flags_buf_t *); extern const char *conv_ent_files_flags(Word, Conv_fmt_flags_t fmt_flags, Conv_ent_files_flags_buf_t *); +extern const char *conv_la_activity(uint_t, Conv_fmt_flags_t, + Conv_inv_buf_t *); +extern const char *conv_la_bind(uint_t, Conv_la_bind_buf_t *); +extern const char *conv_la_search(uint_t, Conv_la_search_buf_t *); +extern const char *conv_la_symbind(uint_t, Conv_la_symbind_buf_t *); extern const char *conv_grphdl_flags(uint_t, Conv_grphdl_flags_buf_t *); extern const char *conv_grpdesc_flags(uint_t, Conv_grpdesc_flags_buf_t *); extern Isa_desc *conv_isalist(void);
--- a/usr/src/cmd/sgs/include/debug.h Tue Jul 20 16:38:52 2010 -0400 +++ b/usr/src/cmd/sgs/include/debug.h Tue Jul 20 16:29:51 2010 -0700 @@ -93,6 +93,13 @@ #define DBG_SYM_REDUCE_GLOBAL 1 /* reporting global symbols to local */ #define DBG_SYM_REDUCE_RETAIN 2 /* reporting non reduced local syms */ +#define DBG_AUD_CALL 1 /* original call to auditor */ +#define DBG_AUD_RET 2 /* return from auditor diagnostic */ + +#define DBG_AUD_LOCAL 0 /* auditor is local */ +#define DBG_AUD_GLOBAL 1 /* auditor is global */ +#define DBG_AUD_PRELOAD 2 /* auditor is preloaded */ + /* * Group handle operations - passed to Dbg_file_hdl_title(). Indicate why * handle dependencies are being manipulated. @@ -759,15 +766,27 @@ extern void Dbg_args_option(Lm_list *, int, int, char *); extern void Dbg_args_str2chr(Lm_list *, int, const char *, int); extern void Dbg_args_Wldel(Lm_list *, int, const char *); +extern void Dbg_audit_activity(Lm_list *, const char *, const char *, + uint_t); extern void Dbg_audit_ignore(Rt_map *); extern void Dbg_audit_interface(Lm_list *, const char *, const char *); -extern void Dbg_audit_lib(Lm_list *, const char *); -extern void Dbg_audit_object(Lm_list *, const char *, const char *); -extern void Dbg_audit_symval(Lm_list *, const char *, const char *, - const char *, Addr, Addr); +extern void Dbg_audit_lib(Rt_map *, const char *, int); +extern void Dbg_audit_objclose(Lm_list *, const char *, const char *); +extern void Dbg_audit_objopen(Lm_list *, int, const char *, const char *, + uint_t, Boolean); +extern void Dbg_audit_objfilter(Lm_list *, int, const char *, const char *, + const char *, const char *); +extern void Dbg_audit_objsearch(Lm_list *, int, const char *, const char *, + uint_t, const char *); +extern void Dbg_audit_pltenter(Lm_list *, int, const char *, const char *, + Addr); +extern void Dbg_audit_pltexit(Lm_list *, const char *, const char *); +extern void Dbg_audit_preinit(Lm_list *, const char *, const char *); +extern void Dbg_audit_symbind(Lm_list *, int, const char *, const char *, + Addr, uint_t); extern void Dbg_audit_skip(Lm_list *, const char *, const char *); extern void Dbg_audit_terminate(Lm_list *, const char *); -extern void Dbg_audit_version(Lm_list *, const char *, ulong_t); +extern void Dbg_audit_version(Lm_list *, const char *, uint_t, uint_t); extern void Dbg_basic_collect(Lm_list *); extern void Dbg_basic_create(Lm_list *);
--- a/usr/src/cmd/sgs/include/rtld.h Tue Jul 20 16:38:52 2010 -0400 +++ b/usr/src/cmd/sgs/include/rtld.h Tue Jul 20 16:29:51 2010 -0700 @@ -303,7 +303,7 @@ uint_t lm_tls; /* new obj that require TLS */ uint_t lm_lmid; /* unique link-map list identifier, */ char *lm_lmidstr; /* and associated diagnostic string */ - APlist *lm_actaudit; /* list of pending audit activity */ + Alist *lm_aud_cookies; /* local auditor cookies */ Lc_desc lm_lcs[CI_MAX]; /* external libc functions */ }; @@ -330,7 +330,7 @@ uint_t lm_tls; uint_t lm_lmid; Elf32_Addr lm_lmidstr; - Elf32_Addr lm_actaudit; + Elf32_Addr lm_aud_cookies; Elf32_Addr lm_lcs[CI_MAX]; }; #endif /* _SYSCALL32 */ @@ -346,28 +346,27 @@ /* * END: Exposed to rtld_db - don't move, don't delete */ -#define LML_FLG_NOAUDIT 0x00000004 /* symbol auditing disabled */ +#define LML_FLG_ACTAUDIT 0x00000004 /* audit activity posted */ #define LML_FLG_PLTREL 0x00000008 /* deferred plt relocation */ - /* initialization */ - /* (ld.so.1 only) */ + /* initialization (ld.so.1 */ + /* only) */ #define LML_FLG_HOLDLOCK 0x00000010 /* hold the rtld mutex lock */ #define LML_FLG_ENVIRON 0x00000020 /* environ var initialized */ #define LML_FLG_INTRPOSE 0x00000040 /* interposing objs on list */ #define LML_FLG_LOCAUDIT 0x00000080 /* local auditors exists for */ - /* this link-map list */ + /* this link-map list */ #define LML_FLG_LOADAVAIL 0x00000100 /* load anything available */ #define LML_FLG_IGNRELERR 0x00000200 /* ignore relocation errors - */ - /* internal for crle(1) */ -#define LML_FLG_DBNOTIF 0x00000400 /* binding activity going on */ -#define LML_FLG_STARTREL 0x00000800 /* relocation started */ -#define LML_FLG_ATEXIT 0x00001000 /* atexit processing */ -#define LML_FLG_OBJADDED 0x00002000 /* object(s) added */ -#define LML_FLG_OBJDELETED 0x00004000 /* object(s) deleted */ -#define LML_FLG_OBJREEVAL 0x00008000 /* existing object(s) needs */ - /* tsort reevaluation */ -#define LML_FLG_INTRPOSETSORT 0x00020000 /* interpose tsorting done */ -#define LML_FLG_AUDITNOTIFY 0x00040000 /* audit consistent required */ -#define LML_FLG_GROUPSEXIST 0x00080000 /* local groups exist */ + /* internal for crle(1) */ +#define LML_FLG_STARTREL 0x00000400 /* relocation started */ +#define LML_FLG_ATEXIT 0x00000800 /* atexit processing */ +#define LML_FLG_OBJADDED 0x00001000 /* object(s) added */ +#define LML_FLG_OBJDELETED 0x00002000 /* object(s) deleted */ +#define LML_FLG_OBJREEVAL 0x00004000 /* existing object(s) needs */ + /* tsort reevaluation */ +#define LML_FLG_INTRPOSETSORT 0x00008000 /* interpose tsorting done */ +#define LML_FLG_AUDITNOTIFY 0x00010000 /* audit consistent required */ +#define LML_FLG_GROUPSEXIST 0x00020000 /* local groups exist */ #define LML_FLG_TRC_LDDSTUB 0x00100000 /* identify lddstub */ #define LML_FLG_TRC_ENABLE 0x00200000 /* tracing enabled (ldd) */ @@ -375,14 +374,14 @@ #define LML_FLG_TRC_VERBOSE 0x00800000 /* verbose (versioning) trace */ #define LML_FLG_TRC_SEARCH 0x01000000 /* trace search paths */ #define LML_FLG_TRC_UNREF 0x02000000 /* trace unreferenced */ - /* dependencies */ + /* dependencies */ #define LML_FLG_TRC_UNUSED 0x04000000 /* trace unused dependencies */ #define LML_FLG_TRC_INIT 0x08000000 /* print .init order */ #define LML_FLG_TRC_NOUNRESWEAK 0x10000000 /* unresolved weak references */ - /* are not allowed */ + /* are not allowed */ #define LML_FLG_TRC_NOPAREXT 0x20000000 /* unresolved PARENT/EXTERN */ - /* references are not */ - /* allowed */ + /* references are not */ + /* allowed */ #define LML_MSK_TRC 0xfff00000 /* tracing mask */ /* @@ -391,7 +390,7 @@ */ #define LML_TFLG_NOLAZYLD 0x00000001 /* lazy loading disabled */ #define LML_TFLG_NODIRECT 0x00000002 /* direct bindings disabled */ - +#define LML_TFLG_NOAUDIT 0x00000004 /* auditing disabled */ #define LML_TFLG_LOADFLTR 0x00000008 /* trigger filtee loading */ #define LML_TFLG_AUD_PREINIT 0x00001000 /* preinit (audit) exists */
--- a/usr/src/cmd/sgs/ldprof/common/profile.c Tue Jul 20 16:38:52 2010 -0400 +++ b/usr/src/cmd/sgs/ldprof/common/profile.c Tue Jul 20 16:29:51 2010 -0700 @@ -20,8 +20,7 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -405,7 +404,7 @@ * Don't even try to profile an object that does not have * auditing enabled on it's link-map. This catches 'ld.so.1'. */ - if (LIST(LINKMAP_TO_RTMAP(lmp))->lm_flags & LML_FLG_NOAUDIT) + if (LIST(LINKMAP_TO_RTMAP(lmp))->lm_tflags & LML_TFLG_NOAUDIT) return (LA_FLG_BINDFROM); if (profile_open(pname, lmp) == 0)
--- a/usr/src/cmd/sgs/libconv/Makefile.com Tue Jul 20 16:38:52 2010 -0400 +++ b/usr/src/cmd/sgs/libconv/Makefile.com Tue Jul 20 16:29:51 2010 -0700 @@ -20,8 +20,7 @@ # # -# Copyright 2010 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved. # LIBRARY = libconv.a @@ -34,7 +33,8 @@ globals_machelf64.o sections_machelf64.o \ symbols_machelf64.o symbols_sparc_machelf64.o -COMOBJS= arch.o c_literal.o \ +COMOBJS= arch.o audit.o \ + c_literal.o \ cap.o config.o \ corenote.o data.o \ deftag.o demangle.o \ @@ -55,7 +55,8 @@ ASOBJS= vernote.o -BLTOBJS= arch_msg.o c_literal_msg.o \ +BLTOBJS= arch_msg.o audit_msg.o \ + c_literal_msg.o \ cap_msg.o config_msg.o \ corenote_msg.o data_msg.o \ deftag_msg.o demangle_msg.o \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/sgs/libconv/common/audit.c Tue Jul 20 16:29:51 2010 -0700 @@ -0,0 +1,203 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + */ + +#include <string.h> +#include <link.h> +#include "_conv.h" +#include "audit_msg.h" + +#define BINDSZ CONV_EXPN_FIELD_DEF_PREFIX_SIZE + \ + MSG_LA_FLG_BINDTO_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ + MSG_LA_FLG_BINDFROM_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ + CONV_INV_BUFSIZE + CONV_EXPN_FIELD_DEF_SUFFIX_SIZE + +/* + * Ensure that Conv_la_bind_buf_t is large enough: + * + * BINDSZ is the real minimum size of the buffer required by conv_la_bind(). + * However, Conv_la_bind_buf_t uses CONV_LA_BIND_BUFSIZE to set the + * buffer size. We do things this way because the definition of BINDSZ uses + * information that is not available in the environment of other programs + * that include the conv.h header file. + */ +#if (CONV_LA_BIND_BUFSIZE != BINDSZ) && !defined(__lint) +#define REPORT_BUFSIZE BINDSZ +#include "report_bufsize.h" +#error "CONV_LA_BIND_BUFSIZE does not match BINDSZ" +#endif + +/* + * String conversion routine for la_objopen() return flags. + */ +const char * +conv_la_bind(uint_t bind, Conv_la_bind_buf_t *la_bind_buf) +{ + static const Val_desc vda[] = { + { LA_FLG_BINDTO, MSG_LA_FLG_BINDTO }, + { LA_FLG_BINDFROM, MSG_LA_FLG_BINDFROM }, + { 0, 0 } + }; + static CONV_EXPN_FIELD_ARG conv_arg = { + NULL, sizeof (la_bind_buf->buf), NULL }; + + if (bind == 0) + return (MSG_ORIG(MSG_GBL_ZERO)); + + conv_arg.buf = la_bind_buf->buf; + conv_arg.oflags = conv_arg.rflags = bind; + + (void) conv_expn_field(&conv_arg, vda, 0); + + return ((const char *)la_bind_buf->buf); +} + +#define SEARCHSZ CONV_EXPN_FIELD_DEF_PREFIX_SIZE + \ + MSG_LA_SER_ORIG_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ + MSG_LA_SER_LIBPATH_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ + MSG_LA_SER_RUNPATH_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ + MSG_LA_SER_DEFAULT_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ + MSG_LA_SER_CONFIG_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ + MSG_LA_SER_SECURE_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ + CONV_INV_BUFSIZE + CONV_EXPN_FIELD_DEF_SUFFIX_SIZE + +/* + * Ensure that Conv_la_search_buf_t is large enough: + * + * SEARCHSZ is the real minimum size of the buffer required by conv_la_search(). + * However, Conv_la_search_buf_t uses CONV_LA_SEARCH_BUFSIZE to set the + * buffer size. We do things this way because the definition of SEARCHSZ uses + * information that is not available in the environment of other programs + * that include the conv.h header file. + */ +#if (CONV_LA_SEARCH_BUFSIZE != SEARCHSZ) && !defined(__lint) +#define REPORT_BUFSIZE SEARCHSZ +#include "report_bufsize.h" +#error "CONV_LA_SEARCH_BUFSIZE does not match SEARCHSZ" +#endif + +/* + * String conversion routine for la_objsearch() flags. + */ +const char * +conv_la_search(uint_t search, Conv_la_search_buf_t *la_search_buf) +{ + static const Val_desc vda[] = { + { LA_SER_ORIG, MSG_LA_SER_ORIG }, + { LA_SER_LIBPATH, MSG_LA_SER_LIBPATH }, + { LA_SER_RUNPATH, MSG_LA_SER_RUNPATH }, + { LA_SER_DEFAULT, MSG_LA_SER_DEFAULT }, + { LA_SER_CONFIG, MSG_LA_SER_CONFIG }, + { LA_SER_SECURE, MSG_LA_SER_SECURE }, + { 0, 0 } + }; + static CONV_EXPN_FIELD_ARG conv_arg = { + NULL, sizeof (la_search_buf->buf), NULL }; + + if (search == 0) + return (MSG_ORIG(MSG_GBL_NULL)); + + conv_arg.buf = la_search_buf->buf; + conv_arg.oflags = conv_arg.rflags = search; + + (void) conv_expn_field(&conv_arg, vda, 0); + + return ((const char *)la_search_buf->buf); +} + +/* + * String conversion routine for la_objopen() return flags. + */ + +/* + * String conversion routine for la_activity() flags. + */ +const char * +conv_la_activity(uint_t request, Conv_fmt_flags_t fmt_flags, + Conv_inv_buf_t *inv_buf) +{ + static const Msg requests[LA_ACT_MAX] = { + MSG_LA_ACT_CONSISTENT, /* MSG_ORIG(MSG_LA_ACT_CONSISTENT) */ + MSG_LA_ACT_ADD, /* MSG_ORIG(MSG_LA_ACT_ADD) */ + MSG_LA_ACT_DELETE /* MSG_ORIG(MSG_LA_ACT_DELETE) */ + }; + static const conv_ds_msg_t ds_requests = { + CONV_DS_MSG_INIT(LA_ACT_CONSISTENT, requests) }; + + static const conv_ds_t *ds[] = { CONV_DS_ADDR(ds_requests), NULL }; + + return (conv_map_ds(ELFOSABI_NONE, EM_NONE, request, ds, fmt_flags, + inv_buf)); +} + +#define SYMBSZ CONV_EXPN_FIELD_DEF_PREFIX_SIZE + \ + MSG_LA_SYMB_NOPLTENTER_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ + MSG_LA_SYMB_NOPLTEXIT_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ + MSG_LA_SYMB_STRUCTCALL_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ + MSG_LA_SYMB_DLSYM_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ + MSG_LA_SYMB_ALTVALUE_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \ + CONV_INV_BUFSIZE + CONV_EXPN_FIELD_DEF_SUFFIX_SIZE + +/* + * Ensure that Conv_la_symbind_buf_t is large enough: + * + * SYMBSZ is the real minimum size of the buffer required by conv_la_symbind(). + * However, Conv_la_symbind_buf_t uses CONV_LA_SYMB_BUFSIZE to set the + * buffer size. We do things this way because the definition of SYMBSZ uses + * information that is not available in the environment of other programs + * that include the conv.h header file. + */ +#if (CONV_LA_SYMBIND_BUFSIZE != SYMBSZ) && !defined(__lint) +#define REPORT_BUFSIZE SYMBSZ +#include "report_bufsize.h" +#error "CONV_LA_SYMBIND_BUFSIZE does not match SYMBSZ" +#endif + +/* + * String conversion routine for la_symbind() flags. + */ +const char * +conv_la_symbind(uint_t symbind, Conv_la_symbind_buf_t *la_symbind_buf) +{ + static const Val_desc vda[] = { + { LA_SYMB_NOPLTENTER, MSG_LA_SYMB_NOPLTENTER }, + { LA_SYMB_NOPLTEXIT, MSG_LA_SYMB_NOPLTEXIT }, + { LA_SYMB_STRUCTCALL, MSG_LA_SYMB_STRUCTCALL }, + { LA_SYMB_DLSYM, MSG_LA_SYMB_DLSYM }, + { LA_SYMB_ALTVALUE, MSG_LA_SYMB_ALTVALUE }, + { 0, 0 } + }; + static CONV_EXPN_FIELD_ARG conv_arg = { + NULL, sizeof (la_symbind_buf->buf), NULL }; + + if (symbind == 0) + return (MSG_ORIG(MSG_GBL_NULL)); + + conv_arg.buf = la_symbind_buf->buf; + conv_arg.oflags = conv_arg.rflags = symbind; + + (void) conv_expn_field(&conv_arg, vda, 0); + + return ((const char *)la_symbind_buf->buf); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/sgs/libconv/common/audit.msg Tue Jul 20 16:29:51 2010 -0700 @@ -0,0 +1,46 @@ +# +# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Message file for cmd/sgs/libconv/common/audit.c + +@ MSG_LA_FLG_BINDTO "LA_FLG_BINDTO" +@ MSG_LA_FLG_BINDFROM "LA_FLG_BINDFROM" + +@ MSG_LA_ACT_CONSISTENT "[ LA_ACT_CONSISTENT ]" +@ MSG_LA_ACT_ADD "[ LA_ACT_ADD ]" +@ MSG_LA_ACT_DELETE "[ LA_ACT_DELETE ]" + +@ MSG_LA_SER_ORIG "LA_SER_ORIG" +@ MSG_LA_SER_LIBPATH "LA_SER_LIBPATH" +@ MSG_LA_SER_RUNPATH "LA_SER_RUNPATH" +@ MSG_LA_SER_DEFAULT "LA_SER_DEFAULT" +@ MSG_LA_SER_CONFIG "LA_SER_CONFIG" +@ MSG_LA_SER_SECURE "LA_SER_SECURE" + +@ MSG_LA_SYMB_NOPLTENTER "LA_SYMB_NOPLTENTER" +@ MSG_LA_SYMB_NOPLTEXIT "LA_SYMB_NOPLTEXIT" +@ MSG_LA_SYMB_STRUCTCALL "LA_SYMB_STRUCTCALL" +@ MSG_LA_SYMB_DLSYM "LA_SYMB_DLSYM" +@ MSG_LA_SYMB_ALTVALUE "LA_SYMB_ALTVALUE" + +@ MSG_GBL_ZERO "0" +@ MSG_GBL_NULL ""
--- a/usr/src/cmd/sgs/libconv/common/lintsup.c Tue Jul 20 16:38:52 2010 -0400 +++ b/usr/src/cmd/sgs/libconv/common/lintsup.c Tue Jul 20 16:29:51 2010 -0700 @@ -18,16 +18,15 @@ * * CDDL HEADER END */ + +/* + * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + */ /* LINTLIBRARY */ /* PROTOLIB1 */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * Supplimental definitions for lint that help us avoid + * Supplemental definitions for lint that help us avoid * options like `-x' that filter out things we want to * know about as well as things we don't. */ @@ -54,6 +53,7 @@ */ #define LINTSUP_SUPPRESS_STRINGS #include "arch_msg.h" +#include "audit_msg.h" #include "c_literal_msg.h" #include "cap_msg.h" #include "config_msg.h" @@ -89,6 +89,7 @@ #define USE(name) (void) name((Msg)&_ ## name[0]) USE(_sgs_msg_libconv_arch); + USE(_sgs_msg_libconv_audit); USE(_sgs_msg_libconv_c_literal); USE(_sgs_msg_libconv_cap); USE(_sgs_msg_libconv_config);
--- a/usr/src/cmd/sgs/libconv/common/llib-lconv Tue Jul 20 16:38:52 2010 -0400 +++ b/usr/src/cmd/sgs/libconv/common/llib-lconv Tue Jul 20 16:29:51 2010 -0700 @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. */ /* LINTLIBRARY */ /* PROTOLIB1 */ @@ -141,6 +140,10 @@ const char *conv_ent_filcmp(Word, Conv_fmt_flags_t, Conv_inv_buf_t *); const char *conv_grphdl_flags(uint_t, Conv_grphdl_flags_buf_t *); const char *conv_grpdesc_flags(uint_t, Conv_grpdesc_flags_buf_t *); +const char *conv_la_activity(uint_t, Conv_fmt_flags_t, Conv_inv_buf_t *); +const char *conv_la_bind(uint_t, Conv_la_bind_buf_t *); +const char *conv_la_search(uint_t, Conv_la_search_buf_t *); +const char *conv_la_symbind(uint_t, Conv_la_symbind_buf_t *); Isa_desc *conv_isalist(void); const char *conv_mapfile_version(Word, Conv_fmt_flags_t, Conv_inv_buf_t *);
--- a/usr/src/cmd/sgs/liblddbg/common/audit.c Tue Jul 20 16:38:52 2010 -0400 +++ b/usr/src/cmd/sgs/liblddbg/common/audit.c Tue Jul 20 16:29:51 2010 -0700 @@ -20,10 +20,8 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. */ -#pragma ident "%Z%%M% %I% %E% SMI" #include <dlfcn.h> #include <stdio.h> @@ -32,23 +30,29 @@ #include "libld.h" void -Dbg_audit_version(Lm_list *lml, const char *lib, ulong_t version) +Dbg_audit_lib(Rt_map *clmp, const char *lib, int type) { + Lm_list *clml = LIST(clmp); + const char *str; + if (DBG_NOTCLASS(DBG_C_AUDITING)) return; - Dbg_util_nl(lml, DBG_NL_STD); - dbg_print(lml, MSG_INTL(MSG_AUD_VERSION), lib, (int)version); -} + Dbg_util_nl(clml, DBG_NL_STD); + switch (type) { + case DBG_AUD_PRELOAD: + str = MSG_ORIG(MSG_AUD_PRELOAD); + break; + case DBG_AUD_GLOBAL: + str = MSG_ORIG(MSG_AUD_GLOBAL); + break; + case DBG_AUD_LOCAL: + /* FALLTHROUGH */ + default: + str = MSG_ORIG(MSG_STR_EMPTY); + } -void -Dbg_audit_lib(Lm_list *lml, const char *lib) -{ - if (DBG_NOTCLASS(DBG_C_AUDITING)) - return; - - Dbg_util_nl(lml, DBG_NL_STD); - dbg_print(lml, MSG_INTL(MSG_AUD_INIT), lib); + dbg_print(clml, MSG_INTL(MSG_AUD_LIB), lib, NAME(clmp), str); } void @@ -57,38 +61,154 @@ if (DBG_NOTCLASS(DBG_C_AUDITING)) return; - Dbg_util_nl(lml, DBG_NL_STD); dbg_print(lml, MSG_INTL(MSG_AUD_INTERFACE), lib, interface); } void -Dbg_audit_object(Lm_list *lml, const char *lib, const char *obj) +Dbg_audit_version(Lm_list *lml, const char *lib, uint_t overs, uint_t nvers) +{ + if (DBG_NOTCLASS(DBG_C_AUDITING)) + return; + + dbg_print(lml, MSG_INTL(MSG_AUD_VERSION), lib, overs, nvers); +} + +void +Dbg_audit_activity(Lm_list *lml, const char *lib, const char *obj, uint_t flags) +{ + Conv_inv_buf_t inv_buf; + + if (DBG_NOTCLASS(DBG_C_AUDITING)) + return; + + Dbg_util_nl(lml, DBG_NL_STD); + dbg_print(lml, MSG_INTL(MSG_AUD_ACTIVITY), lib, obj, + conv_la_activity(flags, CONV_FMT_ALT_DEFAULT, &inv_buf)); +} + +void +Dbg_audit_preinit(Lm_list *lml, const char *lib, const char *obj) { if (DBG_NOTCLASS(DBG_C_AUDITING)) return; Dbg_util_nl(lml, DBG_NL_STD); - dbg_print(lml, MSG_INTL(MSG_AUD_OBJECT), lib, obj); + dbg_print(lml, MSG_INTL(MSG_AUD_PREINIT), lib, obj); } void -Dbg_audit_symval(Lm_list *lml, const char *lib, const char *func, - const char *sym, Addr pval, Addr nval) +Dbg_audit_objsearch(Lm_list *lml, int call, const char *lib, + const char *oobj, uint_t flags, const char *nobj) { - char mesg[100]; + Conv_la_search_buf_t la_search_buf; + + if (DBG_NOTCLASS(DBG_C_AUDITING)) + return; + + if (call == DBG_AUD_CALL) { + Dbg_util_nl(lml, DBG_NL_STD); + dbg_print(lml, MSG_INTL(MSG_AUD_OBJSEARCH), lib, oobj, + conv_la_search(flags, &la_search_buf)); + } else { + if (nobj) + dbg_print(lml, MSG_INTL(MSG_AUD_OBJSEARCH_R), lib, + oobj, nobj); + else + dbg_print(lml, MSG_INTL(MSG_AUD_OBJSEARCH_S), lib, + oobj); + } +} + +void +Dbg_audit_objfilter(Lm_list *lml, int call, const char *lib, + const char *filter, const char *filtee, const char *ref) +{ + if (DBG_NOTCLASS(DBG_C_AUDITING)) + return; + + if (call == DBG_AUD_CALL) { + Dbg_util_nl(lml, DBG_NL_STD); + dbg_print(lml, MSG_INTL(MSG_AUD_OBJFILTER), lib, filter, + filtee, ref); + } else + dbg_print(lml, MSG_INTL(MSG_AUD_OBJFILTER_R), lib, filter); +} + +void +Dbg_audit_objopen(Lm_list *lml, int call, const char *lib, const char *obj, + uint_t flags, Boolean ignore) +{ + Conv_la_bind_buf_t la_bind_buf; if (DBG_NOTCLASS(DBG_C_AUDITING)) return; - if (DBG_NOTDETAIL()) + + if (call == DBG_AUD_CALL) { + Dbg_util_nl(lml, DBG_NL_STD); + dbg_print(lml, MSG_INTL(MSG_AUD_OBJOPEN), lib, obj); + } else { + if (ignore) + dbg_print(lml, MSG_INTL(MSG_AUD_OBJOPEN_RI), lib, obj, + conv_la_bind(flags, &la_bind_buf)); + else + dbg_print(lml, MSG_INTL(MSG_AUD_OBJOPEN_R), lib, obj, + conv_la_bind(flags, &la_bind_buf)); + } +} + +void +Dbg_audit_objclose(Lm_list *lml, const char *lib, const char *obj) +{ + if (DBG_NOTCLASS(DBG_C_AUDITING)) + return; + + Dbg_util_nl(lml, DBG_NL_STD); + dbg_print(lml, MSG_INTL(MSG_AUD_OBJCLOSE), lib, obj); +} + +void +Dbg_audit_symbind(Lm_list *lml, int call, const char *lib, const char *name, + Addr value, uint_t flags) +{ + Conv_la_symbind_buf_t la_symbind_buf; + + if (DBG_NOTCLASS(DBG_C_AUDITING)) return; - if (pval == nval) - mesg[0] = '\0'; - else - (void) sprintf(mesg, MSG_INTL(MSG_AUD_SYMNEW), EC_XWORD(nval)); + if (call == DBG_AUD_CALL) { + Dbg_util_nl(lml, DBG_NL_STD); + dbg_print(lml, MSG_INTL(MSG_AUD_SYMBIND), lib, name, + EC_XWORD(value), conv_la_symbind(flags, &la_symbind_buf)); + } else { + dbg_print(lml, MSG_INTL(MSG_AUD_SYMBIND_R), lib, name, + EC_XWORD(value), conv_la_symbind(flags, &la_symbind_buf)); + } +} + +void +Dbg_audit_pltenter(Lm_list *lml, int call, const char *lib, const char *name, + Addr value) +{ + if (DBG_NOTCLASS(DBG_C_AUDITING)) + return; - dbg_print(lml, MSG_INTL(MSG_AUD_SYM), lib, func, Dbg_demangle_name(sym), - EC_XWORD(pval), mesg); + if (call == DBG_AUD_CALL) { + Dbg_util_nl(lml, DBG_NL_STD); + dbg_print(lml, MSG_INTL(MSG_AUD_PLTENTER), lib, name, + EC_XWORD(value)); + } else { + dbg_print(lml, MSG_INTL(MSG_AUD_PLTENTER_R), lib, name, + EC_XWORD(value)); + } +} + +void +Dbg_audit_pltexit(Lm_list *lml, const char *lib, const char *name) +{ + if (DBG_NOTCLASS(DBG_C_AUDITING)) + return; + + dbg_print(lml, MSG_INTL(MSG_AUD_PLTEXIT), lib, name); } void @@ -103,7 +223,7 @@ void Dbg_audit_terminate(Lm_list *lml, const char *name) { - if (DBG_NOTCLASS(DBG_C_AUDITING | DBG_C_FILES)) + if (DBG_NOTCLASS(DBG_C_FILES)) return; dbg_print(lml, MSG_INTL(MSG_AUD_TERM), name);
--- a/usr/src/cmd/sgs/liblddbg/common/files.c Tue Jul 20 16:38:52 2010 -0400 +++ b/usr/src/cmd/sgs/liblddbg/common/files.c Tue Jul 20 16:29:51 2010 -0700 @@ -441,23 +441,17 @@ void Dbg_file_filtee(Lm_list *lml, const char *filter, const char *filtee, int audit) { - if (audit) { - if (DBG_NOTCLASS(DBG_C_AUDITING | DBG_C_FILES)) - return; + if (DBG_NOTCLASS(DBG_C_FILES)) + return; - Dbg_util_nl(lml, DBG_NL_STD); + Dbg_util_nl(lml, DBG_NL_STD); + + if (audit) dbg_print(lml, MSG_INTL(MSG_FIL_FILTEE_3), filtee); - } else { - if (DBG_NOTCLASS(DBG_C_FILES)) - return; - - Dbg_util_nl(lml, DBG_NL_STD); - if (filter) - dbg_print(lml, MSG_INTL(MSG_FIL_FILTEE_1), filtee, - filter); - else - dbg_print(lml, MSG_INTL(MSG_FIL_FILTEE_2), filtee); - } + else if (filter) + dbg_print(lml, MSG_INTL(MSG_FIL_FILTEE_1), filtee, filter); + else + dbg_print(lml, MSG_INTL(MSG_FIL_FILTEE_2), filtee); } void
--- a/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg Tue Jul 20 16:38:52 2010 -0400 +++ b/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg Tue Jul 20 16:29:51 2010 -0700 @@ -660,7 +660,7 @@ @ MSG_FIL_FILTER_1 "file=%s; filter for %s (configuration definition)" @ MSG_FIL_FILTER_2 "file=%s; filter for %s" @ MSG_FIL_FILTEE_2 "file=%s; filtee processing failed" -@ MSG_FIL_FILTEE_3 "file=%s; filtee skipped (auditing directed)" +@ MSG_FIL_FILTEE_3 "file=%s; filtee skipped (auditor directed)" @ MSG_FIL_FIXNAME "file=%s; required name=%s" @ MSG_FIL_PROMOTE "file=%s; promoting mode to %s" @ MSG_FIL_DEFERRED "file=%s; deferred dependency exchanged for file=%s" @@ -772,8 +772,8 @@ @ MSG_LIB_FIND "find object=%s; searching" @ MSG_LIB_TRYING " trying path=%s%s" -@ MSG_LIB_ALTER " trying path=%s (auditing supplied alternative)" -@ MSG_LIB_SKIP " skip path=%s (auditing directed)" +@ MSG_LIB_ALTER " trying path=%s (auditor returned alternative)" +@ MSG_LIB_SKIP " skip path=%s (auditor directed)" @ MSG_LIB_IGNORE " ignore path=%s (insecure directory name)" @ MSG_LIB_INUSE " use path=%s (implicitly secure, as directory \ has already provided dependencies)" @@ -1043,17 +1043,36 @@ # Link-Auditing Messages -@ MSG_AUD_INIT "audit library %s: processing" -@ MSG_AUD_VERSION "audit library %s: running at version: %d" -@ MSG_AUD_INTERFACE "audit library %s: provides interface: %s" -@ MSG_AUD_OBJECT "audit library %s: offered object: %s" -@ MSG_AUD_SYM "audit library %s: %s: symbol: %s: value: 0x%llx %s" -@ MSG_AUD_SYMNEW "modified to: 0x%llx" +@ MSG_AUD_LIB "auditor %s: required by: %s %s" +@ MSG_AUD_INTERFACE "auditor %s: provides interface: %s" + +@ MSG_AUD_VERSION "auditor %s: la_version(): %d: returned %d" +@ MSG_AUD_ACTIVITY "auditor %s: la_activity(): %s %s" +@ MSG_AUD_PREINIT "auditor %s: la_preinit(): %s" +@ MSG_AUD_OBJFILTER "auditor %s: la_objfilter(): %s: filtee=%s [ %s ]" +@ MSG_AUD_OBJFILTER_R "auditor %s: la_objfilter(): %s: returned 0 (filtee \ + ignored)" +@ MSG_AUD_OBJOPEN "auditor %s: la_objopen(): %s" +@ MSG_AUD_OBJOPEN_R "auditor %s: la_objopen(): %s: returned %s" +@ MSG_AUD_OBJOPEN_RI "auditor %s: la_objopen(): %s: returned %s (flags \ + ignored)" +@ MSG_AUD_OBJSEARCH "auditor %s: la_objsearch(): %s %s" +@ MSG_AUD_OBJSEARCH_R "auditor %s: la_objsearch(): %s: alternative path \ + returned: %s" +@ MSG_AUD_OBJSEARCH_S "auditor %s: la_objsearch(): %s: alternative path \ + returned: 0 (path skipped)" +@ MSG_AUD_OBJCLOSE "auditor %s: la_objclose(): %s" +@ MSG_AUD_SYMBIND "auditor %s: la_symbind(): %s: value: 0x%llx %s" +@ MSG_AUD_SYMBIND_R "auditor %s: la_symbind(): %s: returned value: \ + 0x%llx %s" +@ MSG_AUD_PLTENTER "auditor %s: la_pltenter(): %s: value: 0x%llx" +@ MSG_AUD_PLTENTER_R "auditor %s: la_pltenter(): %s: returned value: 0x%llx" +@ MSG_AUD_PLTEXIT "auditor %s: la_pltexit(): %s" @ MSG_AUD_IGNORE "file=%s; global auditing request ignored: object \ did not initiate process" @ MSG_AUD_SKIP "file=%s; skipped: using auditor from %s" -@ MSG_AUD_TERM "file=%s; auditing terminated search" +@ MSG_AUD_TERM "file=%s; auditor has indicated path should be skipped" # GOT Messages @@ -1744,3 +1763,8 @@ @ MSG_MR_PADDING "[ PADDING ]" @ MSG_MR_HDR_ELF "[ HDR_ELF ]" @ MSG_MR_HDR_AOUT "[ HDR_AOUT ]" + +# audit originator + +@ MSG_AUD_PRELOAD "[ LD_AUDIT ]" +@ MSG_AUD_GLOBAL "[ GLOBAL AUDIT ]"
--- a/usr/src/cmd/sgs/liblddbg/common/libs.c Tue Jul 20 16:38:52 2010 -0400 +++ b/usr/src/cmd/sgs/liblddbg/common/libs.c Tue Jul 20 16:29:51 2010 -0700 @@ -20,8 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved. */ #include "msg.h" #include "_debug.h" @@ -30,12 +29,13 @@ void Dbg_libs_audit(Lm_list *lml, const char *opath, const char *npath) { - if (DBG_NOTCLASS(DBG_C_LIBS | DBG_C_AUDITING)) + if (DBG_NOTCLASS(DBG_C_LIBS)) return; if (npath == opath) return; - else if (npath == 0) + + if (npath == NULL) dbg_print(lml, MSG_INTL(MSG_LIB_SKIP), opath); else dbg_print(lml, MSG_INTL(MSG_LIB_ALTER), npath);
--- a/usr/src/cmd/sgs/liblddbg/common/llib-llddbg Tue Jul 20 16:38:52 2010 -0400 +++ b/usr/src/cmd/sgs/liblddbg/common/llib-llddbg Tue Jul 20 16:29:51 2010 -0700 @@ -15,7 +15,7 @@ * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] - + * * CDDL HEADER END */ /* LINTLIBRARY */ @@ -39,15 +39,25 @@ void Dbg_args_option(Lm_list *, int, int, char *); void Dbg_args_str2chr(Lm_list *, int, const char *, int); void Dbg_args_Wldel(Lm_list *, int, const char *); +void Dbg_audit_activity(Lm_list *, const char *, const char *, uint_t); void Dbg_audit_ignore(Rt_map *); void Dbg_audit_interface(Lm_list *, const char *, const char *); -void Dbg_audit_lib(Lm_list *, const char *); -void Dbg_audit_object(Lm_list *, const char *, const char *); -void Dbg_audit_symval(Lm_list *, const char *, const char *, const char *, - Addr, Addr); +void Dbg_audit_lib(Rt_map *, const char *, int); +void Dbg_audit_objclose(Lm_list *, const char *, const char *); +void Dbg_audit_objfilter(Lm_list *, int, const char *, const char *, + const char *, const char *); +void Dbg_audit_objopen(Lm_list *, int, const char *, const char *, uint_t, + Boolean); +void Dbg_audit_objsearch(Lm_list *, int, const char *, const char *, uint_t, + const char *); +void Dbg_audit_pltenter(Lm_list *, int, const char *, const char *, Addr); +void Dbg_audit_pltexit(Lm_list *, const char *, const char *); +void Dbg_audit_preinit(Lm_list *, const char *, const char *); +void Dbg_audit_symbind(Lm_list *, int, const char *, const char *, + Addr, uint_t); void Dbg_audit_skip(Lm_list *, const char *, const char *); void Dbg_audit_terminate(Lm_list *, const char *); -void Dbg_audit_version(Lm_list *, const char *, ulong_t); +void Dbg_audit_version(Lm_list *, const char *, uint_t, uint_t); void Dbg_basic_collect(Lm_list *); void Dbg_basic_create(Lm_list *);
--- a/usr/src/cmd/sgs/liblddbg/common/mapfile-vers Tue Jul 20 16:38:52 2010 -0400 +++ b/usr/src/cmd/sgs/liblddbg/common/mapfile-vers Tue Jul 20 16:29:51 2010 -0700 @@ -42,7 +42,7 @@ $mapfile_version 2 -SYMBOL_VERSION SUNWprivate_4.81 { +SYMBOL_VERSION SUNWprivate_4.82 { global: dbg_desc { # interposed - ld.so.1(1) FLAGS = NODIRECT; @@ -55,11 +55,18 @@ Dbg_args_option; Dbg_args_str2chr; Dbg_args_Wldel; + Dbg_audit_activity; Dbg_audit_ignore; Dbg_audit_interface; Dbg_audit_lib; - Dbg_audit_object; - Dbg_audit_symval; + Dbg_audit_objclose; + Dbg_audit_objfilter; + Dbg_audit_objopen; + Dbg_audit_objsearch; + Dbg_audit_pltenter; + Dbg_audit_pltexit; + Dbg_audit_preinit; + Dbg_audit_symbind; Dbg_audit_skip; Dbg_audit_terminate; Dbg_audit_version;
--- a/usr/src/cmd/sgs/packages/common/SUNWonld-README Tue Jul 20 16:38:52 2010 -0400 +++ b/usr/src/cmd/sgs/packages/common/SUNWonld-README Tue Jul 20 16:29:51 2010 -0700 @@ -1286,9 +1286,9 @@ Solaris/SunOS 5.10_x86 patch T141445-06 -------------------------------------------------------------------------------- -------------------------------------- -Solaris 10 XXXX (9th Q-update - s10u9) -------------------------------------- +-------------------------------------- +Solaris 10 1005 (9th Q-update - s10u9) +-------------------------------------- Bugid Risk Synopsis ================================================================================ 6850124 dlopen reports "No such file or directory" in spite of ENOMEM @@ -1303,6 +1303,19 @@ Solaris/SunOS 5.10_x86 patch T143896-01 -------------------------------------------------------------------------------- +---------------------------------------- +Solaris 10 XXXX (10th Q-update - s10u10) +---------------------------------------- +Bugid Risk Synopsis +================================================================================ +6478684 isainfo/cpuid reports pause instruction not supported on amd64 + PSARC/2010/089 Removal of AV_386_PAUSE and AV_386_MON +-------------------------------------------------------------------------------- +All the above changes are incorporated in the following patches: + Solaris/SunOS 5.10_sparc patch TXXXXXX-XX + Solaris/SunOS 5.10_x86 patch TXXXXXX-XX +-------------------------------------------------------------------------------- + -------------------------------------------- Solaris Nevada (OpenSolaris 2008.05, snv_86) -------------------------------------------- @@ -1575,8 +1588,6 @@ 6918143 symbol capabilities (D) PSARC/2010/022 Linker-editors: Symbol Capabilities 6910387 .tdata and .tbss separation invalidates TLS program header information -6478684 isainfo/cpuid reports pause instruction not supported on amd64 - PSARC/2010/089 Removal of AV_386_PAUSE and AV_386_MON 6934123 elfdump -d coredumps on PA-RISC elf 6931044 ld should not allow SHT_PROGBITS .eh_frame sections on amd64 (D) 6931056 pvs -r output can include empty versions in output @@ -1603,3 +1614,5 @@ capabilities - gcc failure (link-editor components only) 6952219 ld support for archives larger than 2 GB (D, P) PSARC/2010/224 Support for archives larger than 2 GB +6956152 dlclose() from an auditor can be fatal. Preinit/activity events should + be more flexible. (D)
--- a/usr/src/cmd/sgs/rtld/common/_a.out.h Tue Jul 20 16:38:52 2010 -0400 +++ b/usr/src/cmd/sgs/rtld/common/_a.out.h Tue Jul 20 16:29:51 2010 -0700 @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _A_DOT_OUT_DOT_H #define _A_DOT_OUT_DOT_H @@ -46,7 +45,7 @@ extern int aout_get_mmap(Lm_list *, mmapobj_result_t *); extern int aout_lookup_sym(Slookup *, Sresult *, uint_t *, int *); extern Rt_map *aout_new_lmp(Lm_list *, Aliste, Fdesc *, Addr, size_t, void *, - int *); + Rt_map *, int *); extern void aout_plt_write(caddr_t, ulong_t); extern int aout_reloc(Rt_map *, uint_t, int *, APlist **); extern void aout_rtbndr(caddr_t);
--- a/usr/src/cmd/sgs/rtld/common/_audit.h Tue Jul 20 16:38:52 2010 -0400 +++ b/usr/src/cmd/sgs/rtld/common/_audit.h Tue Jul 20 16:29:51 2010 -0700 @@ -20,8 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef __AUDIT_DOT_H @@ -39,13 +38,28 @@ /* * Define all auditing structures. * - * A shared object may be a client of an audit library, in which case the - * identify of the shared object is passed to the auditor using a cookie. + * A shared object may be a client of one or more audit libraries. Calls to an + * auditor are accompanied with cookies that identify an object being audited. + * These cookies are initialized to the link-map pointers of the object being + * audited, however the auditor is free to re-allocate these cookies, and thus + * associate their own data with each object being audited. + * + * With auditing version LAV_VERSION5, local auditors can provide la_preinit() + * and la_activity() routines, each of which should be passed a cookie that + * represents the link-map of the head of the associated link-map list. These + * cookies are maintained on the associated link-map list, using the lm_cookies + * alist. These cookies are created by _audit_add_head(), and dynamically + * retrieved by the _audit_preinit() and _audit_activity() routines. + * + * Having these cookies kept on the link-map list decouples these cookies from + * the Audit_client structure of the object being locally audited. In addition, + * this model ensures that multiple objects, undergoing local auditing from the + * same auditor, receive the same head link-map cookie. */ typedef struct { Rt_map *ac_lmp; /* audit library identifier */ uintptr_t ac_cookie; /* cookie assigned to audit library */ - Word ac_flags; /* and its associated flags */ + Word ac_flags; /* and its associated flags */ } Audit_client; #define FLG_AC_BINDTO 0x00001 @@ -70,7 +84,8 @@ char *ad_name; /* originating audit names */ APlist *ad_list; /* audit objs Audit Interface list */ uint_t ad_cnt; /* no. of audit objs in this desc. */ - uint_t ad_flags; /* audit capabilities found */ + uint_t ad_flags; /* audit capabilities found. See */ + /* LML_TFLG_AUD_* flags */ }; /*
--- a/usr/src/cmd/sgs/rtld/common/_elf.h Tue Jul 20 16:38:52 2010 -0400 +++ b/usr/src/cmd/sgs/rtld/common/_elf.h Tue Jul 20 16:29:51 2010 -0700 @@ -58,10 +58,10 @@ int *); extern int elf_mach_flags_check(Rej_desc *, Ehdr *); extern Rt_map *elf_new_lmp(Lm_list *, Aliste, Fdesc *, Addr, size_t, void *, - int *); -extern Rt_map *elf_obj_file(Lm_list *, Aliste, const char *, + Rt_map *, int *); +extern Rt_map *elf_obj_file(Lm_list *, Aliste, Rt_map *, const char *, mmapobj_result_t *, mmapobj_result_t *, uint_t); -extern Rt_map *elf_obj_fini(Lm_list *, Rt_map *, int *); +extern Rt_map *elf_obj_fini(Lm_list *, Rt_map *, Rt_map *, int *); extern void elf_plt_init(void *, caddr_t); #if defined(__sparcv9) extern void elf_plt2_init(uint_t *, Rt_map *);
--- a/usr/src/cmd/sgs/rtld/common/_rtld.h Tue Jul 20 16:38:52 2010 -0400 +++ b/usr/src/cmd/sgs/rtld/common/_rtld.h Tue Jul 20 16:29:51 2010 -0700 @@ -75,7 +75,7 @@ /* Generate a link-map to describe the loaded object. */ Rt_map *(*fct_new_lmp)(Lm_list *, Aliste, Fdesc *, Addr, size_t, - void *, int *); + void *, Rt_map *, int *); /* Retrieve the entry point of the object. */ Addr (*fct_entry_pt)(void); @@ -162,6 +162,7 @@ #define AL_CNT_PLTPAD 10 /* plt padding */ #define AL_CNT_AUDITORS 2 /* auditing list */ #define AL_CNT_ENVIRON 20 /* environment list (enough for ldd) */ +#define AL_CNT_COOKIES 2 /* head link-map list cookies */ /* * Size of buffer for building error messages. @@ -276,7 +277,7 @@ #define RT_FL_NOBIND 0x00000010 /* don't carry out plt binding */ #define RT_FL_NOVERSION 0x00000020 /* disable version checking */ #define RT_FL_SECURE 0x00000040 /* setuid/segid flag */ -#define RT_FL_APPLIC 0x00000080 /* are we executing user code */ +#define RT_FL_APPLIC 0x00000080 /* executing application code */ #define RT_FL_NOENVIRON 0x00000100 /* don't process environment */ /* variables (ld.so.1 -e) */ #define RT_FL_CONFGEN 0x00000200 /* don't relocate initiating object */ @@ -519,6 +520,24 @@ #endif /* + * Error messages generated by ld.so.1 can be written to two different places. + * During initial startup, messages are flushed to the stderr. Once ld.so.1 + * has jumped to the application, messages are stored in an internal buffer for + * retrieval by dlerror(). Between these two conditions, events such as libc's + * callbacks, and calls to auditors, are effectively jumping to application + * code. These transitions from application code to ld.so.1 code are guarded by + * the following macros to ensure any error messages are directed to the + * appropriate output. The single argument, "f", is a local variable that + * can retain, and reinstate, the RT_FL_APPLIC flag of the global rtld_flags + * variable. + */ +#define APPLICATION_ENTER(f) \ + f = (rtld_flags & RT_FL_APPLIC) ? 0 : RT_FL_APPLIC; \ + rtld_flags |= f; +#define APPLICATION_RETURN(f) \ + rtld_flags &= ~f; + +/* * Data declarations. */ extern Lc_desc glcs[]; /* global external interfaces */ @@ -587,6 +606,8 @@ extern uint_t audit_argcnt; /* no. of stack args to copy */ extern Audit_desc *auditors; /* global auditors */ +extern APlist *aud_preinit; /* list of objects defining local */ +extern APlist *aud_activity; /* preinit and activity auditors */ extern char **_environ; /* environ reference for libc */ @@ -636,12 +657,13 @@ */ extern void addfree(void *, size_t); extern int append_alias(Rt_map *, const char *, int *); -extern Rt_map *analyze_lmc(Lm_list *, Aliste, Rt_map *, int *); +extern Rt_map *analyze_lmc(Lm_list *, Aliste, Rt_map *, Rt_map *, + int *); extern void atexit_fini(void); extern int bind_one(Rt_map *, Rt_map *, uint_t); extern int bufprint(Prfbuf *, const char *, ...); extern void call_array(Addr *, uint_t, Rt_map *, Word); -extern void call_fini(Lm_list *, Rt_map **); +extern void call_fini(Lm_list *, Rt_map **, Rt_map *); extern void call_init(Rt_map **, int); extern int callable(Rt_map *, Rt_map *, Grp_hdl *, uint_t); extern Rt_map *_caller(caddr_t, int); @@ -651,7 +673,8 @@ extern int cap_check_fdesc(Fdesc *, Cap *, char *, Rej_desc *); extern int cap_check_lmp(Rt_map *, Rej_desc *); extern int cap_filtees(Alist **, Aliste, const char *, Aliste, - Rt_map *, const char *, int, uint_t, int *); + Rt_map *, Rt_map *, const char *, int, uint_t, + int *); extern int cap_match(Sresult *, uint_t, Sym *, char *); extern const char *_conv_reloc_type(uint_t rel); extern Aliste create_cntl(Lm_list *, int); @@ -700,13 +723,13 @@ extern void ldso_plt_init(Rt_map *); extern void leave(Lm_list *, int); extern void lm_append(Lm_list *, Aliste, Rt_map *); -extern void lm_delete(Lm_list *, Rt_map *); +extern void lm_delete(Lm_list *, Rt_map *, Rt_map *); extern void lm_move(Lm_list *, Aliste, Aliste, Lm_cntl *, Lm_cntl *); extern Rt_map *load_cap(Lm_list *, Aliste, const char *, Rt_map *, uint_t, uint_t, Grp_hdl **, Rej_desc *, int *); extern void load_completion(Rt_map *); -extern Rt_map *load_file(Lm_list *, Aliste, Fdesc *, int *); +extern Rt_map *load_file(Lm_list *, Aliste, Rt_map *, Fdesc *, int *); extern Rt_map *load_path(Lm_list *, Aliste, Rt_map *, int, uint_t, Grp_hdl **, Fdesc *, Rej_desc *, int *); extern Rt_map *load_one(Lm_list *, Aliste, Alist *, Rt_map *, int, @@ -732,12 +755,12 @@ extern int relocate_lmc(Lm_list *, Aliste, Rt_map *, Rt_map *, int *); extern int relocate_finish(Rt_map *, APlist *, int); +extern void remove_alist(Alist **, int); extern void remove_cntl(Lm_list *, Aliste); extern int remove_hdl(Grp_hdl *, Rt_map *, int *); extern void remove_lmc(Lm_list *, Rt_map *, Aliste, const char *); extern void remove_lml(Lm_list *); -extern void remove_plist(Alist **, int); -extern void remove_so(Lm_list *, Rt_map *); +extern void remove_so(Lm_list *, Rt_map *, Rt_map *); extern int rt_cond_wait(Rt_cond *, Rt_lock *); extern int rt_critical(void); extern int rt_bind_guard(int);
--- a/usr/src/cmd/sgs/rtld/common/a.out.c Tue Jul 20 16:38:52 2010 -0400 +++ b/usr/src/cmd/sgs/rtld/common/a.out.c Tue Jul 20 16:29:51 2010 -0700 @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -282,7 +281,7 @@ nlmp = load_one(lml, lmco, palp, clmp, MODE(clmp), 0, 0, in_nfavl); - remove_plist(&palp, 1); + remove_alist(&palp, 1); if (((nlmp == 0) || (bind_one(clmp, nlmp, BND_NEEDED) == 0)) && ((lml->lm_flags & LML_FLG_TRC_ENABLE) == 0)) return (0); @@ -503,7 +502,7 @@ /* ARGSUSED6 */ Rt_map * aout_new_lmp(Lm_list *lml, Aliste lmco, Fdesc *fdp, Addr addr, size_t msize, - void *odyn, int *in_nfavl) + void *odyn, Rt_map *clmp, int *in_nfavl) { const char *name = fdp->fd_nname; Rt_map *lmp;
--- a/usr/src/cmd/sgs/rtld/common/analyze.c Tue Jul 20 16:38:52 2010 -0400 +++ b/usr/src/cmd/sgs/rtld/common/analyze.c Tue Jul 20 16:29:51 2010 -0700 @@ -102,7 +102,8 @@ * Return the initial link-map from which analysis starts for relocate_lmc(). */ Rt_map * -analyze_lmc(Lm_list *lml, Aliste nlmco, Rt_map *nlmp, int *in_nfavl) +analyze_lmc(Lm_list *lml, Aliste nlmco, Rt_map *nlmp, Rt_map *clmp, + int *in_nfavl) { Rt_map *lmp; Lm_cntl *nlmc; @@ -148,7 +149,8 @@ if (FLAGS(lmp) & FLG_RT_OBJECT) { Rt_map *olmp; - if ((olmp = elf_obj_fini(lml, lmp, in_nfavl)) == NULL) { + if ((olmp = elf_obj_fini(lml, lmp, clmp, + in_nfavl)) == NULL) { if (lml->lm_flags & LML_FLG_TRC_ENABLE) continue; nlmp = NULL; @@ -1759,7 +1761,7 @@ * process the various names by which it can be referenced. */ Rt_map * -load_file(Lm_list *lml, Aliste lmco, Fdesc *fdp, int *in_nfavl) +load_file(Lm_list *lml, Aliste lmco, Rt_map *clmp, Fdesc *fdp, int *in_nfavl) { mmapobj_result_t *fpmpp = NULL, *fmpp = NULL, *lpmpp, *lmpp; mmapobj_result_t *hmpp, *mpp, *ompp = fdp->fd_mapp; @@ -1809,7 +1811,7 @@ * processing is finished with elf_obj_fini(). */ if (ehdr && (ehdr->e_type == ET_REL)) { - if ((nlmp = elf_obj_file(lml, lmco, nname, hmpp, ompp, + if ((nlmp = elf_obj_file(lml, lmco, clmp, nname, hmpp, ompp, omapnum)) == NULL) return (nlmp); } else { @@ -1829,7 +1831,7 @@ msize = lmpp->mr_addr + lmpp->mr_msize - fmpp->mr_addr; if ((nlmp = ((fdp->fd_ftp)->fct_new_lmp)(lml, lmco, fdp, addr, - msize, NULL, in_nfavl)) == NULL) + msize, NULL, clmp, in_nfavl)) == NULL) return (NULL); /* @@ -1864,12 +1866,12 @@ if ((NAME(nlmp)[0] == '/') && (fpavl_insert(lml, nlmp, NAME(nlmp), fdp->fd_avlwhere) == 0)) { - remove_so(lml, nlmp); + remove_so(lml, nlmp, clmp); return (NULL); } if (((NAME(nlmp)[0] != '/') || (NAME(nlmp) != PATHNAME(nlmp))) && (fpavl_insert(lml, nlmp, PATHNAME(nlmp), 0) == 0)) { - remove_so(lml, nlmp); + remove_so(lml, nlmp, clmp); return (NULL); } @@ -1916,7 +1918,7 @@ olen = strlen(odir) + 1; } if ((ndir = stravl_insert(odir, 0, olen, 1)) == NULL) { - remove_so(lml, nlmp); + remove_so(lml, nlmp, clmp); return (NULL); } ORIGNAME(nlmp) = ndir; @@ -2016,8 +2018,6 @@ Word strhash = 0; int found = 0; - DBG_CALL(Dbg_libs_find(lml, oname)); - /* * Traverse the search path lists, creating full pathnames and * attempt to load each path. @@ -2098,7 +2098,7 @@ /* * Finish mapping the file and return the link-map descriptor. */ - return (load_file(lml, lmco, fdp, in_nfavl)); + return (load_file(lml, lmco, clmp, fdp, in_nfavl)); } /* @@ -2109,6 +2109,8 @@ { const char *name = pdp->pd_pname; + DBG_CALL(Dbg_libs_find(lml, name)); + /* * First generate any ldd(1) diagnostics. */ @@ -2123,11 +2125,11 @@ fdp->fd_flags |= FLG_FD_SLASH; /* - * If we're being audited tell the audit library of the file we're + * If we're being audited tell any audit libraries of the file we're * about to go search for. */ - if (((lml->lm_tflags | AFLAGS(clmp)) & LML_TFLG_AUD_ACTIVITY) && - (lml == LIST(clmp))) + if (aud_activity || + ((lml->lm_tflags | AFLAGS(clmp)) & LML_TFLG_AUD_ACTIVITY)) audit_activity(clmp, LA_ACT_ADD); if ((lml->lm_tflags | AFLAGS(clmp)) & LML_TFLG_AUD_OBJSEARCH) { @@ -2406,7 +2408,7 @@ /* * The central routine for loading shared objects. Insures ldd() diagnostics, - * handles and any other related additions are all done in one place. + * handle creation, and any other related additions are all done in one place. */ Rt_map * load_path(Lm_list *lml, Aliste lmco, Rt_map *clmp, int nmode, uint_t flags, @@ -2457,7 +2459,7 @@ _rej.rej_str = MSG_INTL(MSG_GEN_NOOPEN); DBG_CALL(Dbg_file_rejected(lml, &_rej, M_MACH)); rejection_inherit(rej, &_rej); - remove_so(lml, nlmp); + remove_so(lml, nlmp, clmp); return (NULL); } } else { @@ -2507,24 +2509,23 @@ * torn down. */ if ((FLAGS(nlmp) & FLG_RT_ANALYZED) == 0) - remove_so(lml, nlmp); + remove_so(lml, nlmp, clmp); return (NULL); } /* * If this object is new, and we're being audited, tell the audit - * library of the file we've just opened. Note, if the new link-map + * libraries of the file we've just opened. Note, if the new link-map * requires local auditing of its dependencies we also register its * opening. */ if (FLAGS(nlmp) & FLG_RT_NEWLOAD) { FLAGS(nlmp) &= ~FLG_RT_NEWLOAD; - if (((lml->lm_tflags | AFLAGS(clmp) | AFLAGS(nlmp)) & - LML_TFLG_AUD_MASK) && (((lml->lm_flags | - LIST(clmp)->lm_flags) & LML_FLG_NOAUDIT) == 0)) { + if ((lml->lm_tflags | AFLAGS(clmp) | AFLAGS(nlmp)) & + LML_TFLG_AUD_MASK) { if (audit_objopen(clmp, nlmp) == 0) { - remove_so(lml, nlmp); + remove_so(lml, nlmp, clmp); return (NULL); } }
--- a/usr/src/cmd/sgs/rtld/common/audit.c Tue Jul 20 16:38:52 2010 -0400 +++ b/usr/src/cmd/sgs/rtld/common/audit.c Tue Jul 20 16:29:51 2010 -0700 @@ -24,9 +24,9 @@ * * Audit interfaces. Auditing can be enabled in two ways: * - * o Using the LD_AUDIT environment variable + * - Using the LD_AUDIT environment variable * - * o From individual objects containing a DT_DEPAUDIT entry + * - From individual objects containing a DT_DEPAUDIT entry * (see ld(1) -P/-p options). * * The former establishes a global set of audit libraries which can inspect all @@ -39,11 +39,61 @@ * flags can occur in different data items they are defined as one to simplify * audit interface requirements. The basic test for all audit interfaces is: * - * if (((lml->lm_tflags | AFLAGS(lmp)) & LML_TFLG_AUD_MASK) && - * (lml == LIST(lmp))) + * if ((lml->lm_tflags | AFLAGS(lmp)) & LML_TFLG_AUD_MASK) + * + * Note. Auditors themselves are identified with the LML_TFLG_NOAUDIT link-map + * list flag, and no LML_TFLG_AUD_MASK flags. These flags get propagated from + * a callers link-map list to any new link-map lists created. Thus, standard + * link-maps lists have the LML_TFLG_AUD_MASK flags propagated, and should a + * new link-map list be created by an auditor, that list gets tagged as + * LML_TFLG_NOAUDIT. * * The latter link-map list equivalence test insures that auditors themselves * (invoked through DT_DEPAUDIT) are not audited. + * + * The history of version changes: + * + * LAV_VERSION1 (Solaris 2.6) + * Auditing implementation added. + * + * LAV_VERSION2 (Solaris 2.6) + * LA_SYMB_ALTVALUE support added. + * + * LAV_VERSION3 (Solaris 9 update 7) + * ld_objfilter() added. + * + * LAV_VERSION4 (Solaris 10 update 5) + * Correction of activity calls for local auditors, and introduction of + * -z globalaudit concept. + * + * LAV_VERSION5 (Solaris 11) + * Under this version, preinit and activity events are enabled from local + * auditors. The la_preinit and la_activity interfaces require a cookie + * that represents the head of the link-map list being audited. If a + * local preinit or activity interface is detected, the local auditors + * la_objopen() routine is called with a cookie that represents the object + * that heads the link-map list of the object being audited. + * + * A local auditor is loaded through adding a new dependency that requests + * auditing, and therefore an la_activity(ADD) event is already in effect. + * Regardless, the local auditors la_activity() routine is called with the + * cookie that represents the object that heads the link-map list of the + * object being audited. + * + * A local auditor can be loaded prior to the preinit event. In this case, + * the local auditors la_preinit() routine is called with the cookie that + * represents the object that heads the link-map list of the object being + * audited. After the preinit event, any la_preinit() routine within a + * local auditor will not be called. + * + * These events are intended to follow the expected sequence of events + * received by global auditors, ie: + * + * - la_objopen(main) + * - la_activity(ADD) + * - la_objopen(dependency) + * - la_activity(CONSISTENT) + * - la_preinit(main) */ #include <stdio.h> @@ -62,6 +112,63 @@ uint_t audit_flags = 0; /* Copy of specific audit flags to */ /* simplify boot_elf.s access. */ +/* + * Obtain a head link-map cookie. Local auditors can provide la_preinit() and + * la_activity() routines, and these routines require a cookie that represents + * the object that heads the link-map of the object being audited. A list of + * these cookies is maintained on the link-map list. This list allows multiple + * local objects to specify the same auditor, and to obtain the same cookie + * for the link-map that heads the link-map list. + * + * The initial cookie is created by _audit_create_head_client() which is called + * from _audit_add_head(). This cookies address is then passed to the local + * auditors ld_objopen() and la_activity() routines. Subsequent preinit and + * activity events use _audit_get_head_client() to dynamically retrieve the + * cookies address. + */ +static Audit_client * +_audit_get_head_client(Rt_map *hlmp, Rt_map *almp) +{ + Audit_client *acp; + Aliste idx; + Lm_list *hlml = LIST(hlmp); + + for (ALIST_TRAVERSE(hlml->lm_aud_cookies, idx, acp)) { + if (acp->ac_lmp == almp) + return (acp); + } + return (NULL); +} + +static Audit_client * +_audit_create_head_client(Rt_map *hlmp, Rt_map *almp) +{ + Audit_client ac, *acp; + Lm_list *hlml = LIST(hlmp); + + ac.ac_lmp = almp; + ac.ac_cookie = (uintptr_t)hlmp; + ac.ac_flags = 0; + + if ((acp = alist_append(&(hlml->lm_aud_cookies), &ac, + sizeof (Audit_client), AL_CNT_COOKIES)) == NULL) + return (NULL); + + return (acp); +} + +/* + * Determine the appropriate client. Each client structure identifies the + * link-map of the auditor it is associated with. From the client structure, + * the address of the associated cookie, that represents the object being + * audited, is retrieved so that the address can be passed to any audit call. + * + * Note, objects that are being locally audited, can provide la_preinit() and + * la_activity() routines. These routines must be passed cookies that represent + * the object that heads the link-map list of the object being audited. These + * cookies are not maintained on this objects Audit_client structure, but are + * obtained from the associated link-map lists lm_cookies alist. + */ static Audit_client * _audit_client(Audit_info *aip, Rt_map *almp) { @@ -88,26 +195,34 @@ { Audit_list *alp; Aliste idx; + Lm_list *frlml = LIST(frlmp); for (APLIST_TRAVERSE(list, idx, alp)) { Audit_client *fracp, *feacp; + Rt_map *almp = alp->al_lmp; + Lm_list *alml = LIST(almp); int ret; if (alp->al_objfilter == NULL) continue; - if ((fracp = _audit_client(AUDINFO(frlmp), - alp->al_lmp)) == NULL) + if ((fracp = _audit_client(AUDINFO(frlmp), almp)) == NULL) continue; - if ((feacp = _audit_client(AUDINFO(felmp), - alp->al_lmp)) == NULL) + if ((feacp = _audit_client(AUDINFO(felmp), almp)) == NULL) continue; - leave(LIST(alp->al_lmp), thr_flg_reenter); + DBG_CALL(Dbg_audit_objfilter(frlml, DBG_AUD_CALL, + alp->al_libname, NAME(frlmp), NAME(felmp), ref)); + + leave(alml, thr_flg_reenter); ret = (*alp->al_objfilter)(&(fracp->ac_cookie), ref, &(feacp->ac_cookie), flags); (void) enter(thr_flg_reenter); - if (ret == 0) + + if (ret == 0) { + DBG_CALL(Dbg_audit_objfilter(frlml, DBG_AUD_RET, + alp->al_libname, NAME(frlmp), NULL, NULL)); return (0); + } } return (1); } @@ -115,13 +230,13 @@ int audit_objfilter(Rt_map *frlmp, const char *ref, Rt_map *felmp, uint_t flags) { - int appl = 0, respond = 1; + uint_t rtldflags; + int respond = 1; if (rt_critical()) return (respond); - if ((rtld_flags & RT_FL_APPLIC) == 0) - appl = rtld_flags |= RT_FL_APPLIC; + APPLICATION_ENTER(rtldflags); if (auditors && (auditors->ad_flags & LML_TFLG_AUD_OBJFILTER)) respond = _audit_objfilter(auditors->ad_list, frlmp, @@ -131,8 +246,7 @@ respond = _audit_objfilter(AUDITORS(frlmp)->ad_list, frlmp, ref, felmp, flags); - if (appl) - rtld_flags &= ~RT_FL_APPLIC; + APPLICATION_RETURN(rtldflags); return (respond); } @@ -146,40 +260,57 @@ * terminates the search. */ static char * -_audit_objsearch(APlist *list, char *name, Rt_map *clmp, uint_t flags) +_audit_objsearch(APlist *list, char *oname, Rt_map *clmp, uint_t flags) { Audit_list *alp; Aliste idx; - char *nname = (char *)name; + Lm_list *clml = LIST(clmp); for (APLIST_TRAVERSE(list, idx, alp)) { Audit_client *acp; + Rt_map *almp = alp->al_lmp; + Lm_list *alml = LIST(almp); + char *nname = oname; if (alp->al_objsearch == NULL) continue; - if ((acp = _audit_client(AUDINFO(clmp), alp->al_lmp)) == NULL) + if ((acp = _audit_client(AUDINFO(clmp), almp)) == NULL) continue; - leave(LIST(alp->al_lmp), thr_flg_reenter); + DBG_CALL(Dbg_audit_objsearch(clml, DBG_AUD_CALL, + alp->al_libname, nname, flags, NULL)); + + leave(alml, thr_flg_reenter); nname = (*alp->al_objsearch)(nname, &(acp->ac_cookie), flags); (void) enter(thr_flg_reenter); - if (nname == NULL) + + /* + * Diagnose any return name that differs from the original name + * passed to the auditor. + */ + if (nname && (nname[0] == '\0')) + nname = NULL; + if ((nname != oname) || strcmp(nname, oname)) + DBG_CALL(Dbg_audit_objsearch(clml, DBG_AUD_RET, + alp->al_libname, oname, flags, nname)); + + if ((oname = nname) == NULL) break; + } - return (nname); + return (oname); } char * audit_objsearch(Rt_map *clmp, const char *name, uint_t flags) { char *nname = (char *)name; - int appl = 0; + uint_t rtldflags; if (rt_critical()) return (nname); - if ((rtld_flags & RT_FL_APPLIC) == 0) - appl = rtld_flags |= RT_FL_APPLIC; + APPLICATION_ENTER(rtldflags); if (auditors && (auditors->ad_flags & LML_TFLG_AUD_OBJSEARCH)) nname = _audit_objsearch(auditors->ad_list, nname, @@ -189,8 +320,7 @@ nname = _audit_objsearch(AUDITORS(clmp)->ad_list, nname, clmp, flags); - if (appl) - rtld_flags &= ~RT_FL_APPLIC; + APPLICATION_RETURN(rtldflags); DBG_CALL(Dbg_libs_audit(LIST(clmp), name, nname)); return (nname); @@ -201,7 +331,7 @@ * la_activity() entry points found. */ static void -_audit_activity(APlist *list, Rt_map *clmp, uint_t flags) +_audit_activity(APlist *list, Rt_map *clmp, uint_t flags, Boolean client) { Audit_list *alp; Aliste idx; @@ -211,11 +341,25 @@ Audit_client *acp; Rt_map *almp = alp->al_lmp; Lm_list *alml = LIST(almp); + uintptr_t *cookie; if (alp->al_activity == 0) continue; - if ((acp = _audit_client(AUDINFO(clmp), alp->al_lmp)) == NULL) + + /* + * Determine what cookie is required. Any auditing that + * originates from the object that heads the link-map list has + * its own cookie. Local auditors must obtain the cookie that + * represents the object that heads the link-map list. + */ + if (client) + acp = _audit_client(AUDINFO(clmp), almp); + else + acp = _audit_get_head_client(clml->lm_head, almp); + + if (acp == NULL) continue; + cookie = &(acp->ac_cookie); /* * Make sure the audit library only sees one addition/deletion @@ -226,16 +370,11 @@ * ld.so.1. */ if ((flags == LA_ACT_ADD) || (flags == LA_ACT_DELETE)) { - if (alml->lm_flags & LML_FLG_AUDITNOTIFY) continue; - if (aplist_append(&clml->lm_actaudit, clmp, - AL_CNT_ACTAUDIT) == NULL) - return; - alml->lm_flags |= LML_FLG_AUDITNOTIFY; - + clml->lm_flags |= LML_FLG_ACTAUDIT; } else { if ((alml->lm_flags & LML_FLG_AUDITNOTIFY) == 0) continue; @@ -243,8 +382,11 @@ alml->lm_flags &= ~LML_FLG_AUDITNOTIFY; } - leave(LIST(alp->al_lmp), thr_flg_reenter); - (*alp->al_activity)(&(acp->ac_cookie), flags); + DBG_CALL(Dbg_audit_activity(clml, alp->al_libname, + NAME(clml->lm_head), flags)); + + leave(alml, thr_flg_reenter); + (*alp->al_activity)(cookie, flags); (void) enter(thr_flg_reenter); } } @@ -252,41 +394,180 @@ void audit_activity(Rt_map *clmp, uint_t flags) { - int appl = 0; + Rt_map *lmp; + Aliste idx; + uint_t rtldflags; if (rt_critical()) return; - if ((rtld_flags & RT_FL_APPLIC) == 0) - appl = rtld_flags |= RT_FL_APPLIC; + APPLICATION_ENTER(rtldflags); if (auditors && (auditors->ad_flags & LML_TFLG_AUD_ACTIVITY)) - _audit_activity(auditors->ad_list, clmp, flags); + _audit_activity(auditors->ad_list, clmp, flags, TRUE); if (AUDITORS(clmp) && (AUDITORS(clmp)->ad_flags & LML_TFLG_AUD_ACTIVITY)) - _audit_activity(AUDITORS(clmp)->ad_list, clmp, flags); + _audit_activity(AUDITORS(clmp)->ad_list, clmp, flags, TRUE); + + for (APLIST_TRAVERSE(aud_activity, idx, lmp)) { + if ((clmp != lmp) && AUDITORS(lmp) && + (AUDITORS(lmp)->ad_flags & LML_TFLG_AUD_ACTIVITY)) { + _audit_activity(AUDITORS(lmp)->ad_list, lmp, flags, + FALSE); + } + } + + APPLICATION_RETURN(rtldflags); +} + +/* + * Determine whether an auditor is in use by the head link-map object. + */ +static int +_audit_used_by_head(Rt_map *hlmp, Rt_map *almp) +{ + Audit_list *alp; + Aliste idx; + + for (APLIST_TRAVERSE(AUDITORS(hlmp)->ad_list, idx, alp)) { + if (alp->al_lmp == almp) + return (1); + } + return (0); +} + +/* + * la_objopen() caller for the head link-map. Global auditors, or an auditor + * started from the object that heads a link-map list (typically the dynamic + * executable), are passed to la_objopen(). However, local auditors can + * provide activity and preinit events, and for these events, a cookie + * representing the head link-map list object is expected. This routine obtains + * these cookies from the link-map list lm_cookies element. This element + * ensures all clients of the same auditor use the same cookie. + * + * Although a local auditor will get an la_objopen() call for the object that + * heads the link-map list of the object being audited, the auditor is not + * permitted to request binding information for this head object. The head + * object has already been in existence, and bindings may have been resolved + * with it. This local auditor is coming into existence too late, and thus we + * don't allow any bindings to be caught at all. + */ +static int +_audit_add_head(Rt_map *clmp, Rt_map *hlmp, int preinit, int activity) +{ + Lm_list *clml = LIST(clmp); + Lmid_t lmid = get_linkmap_id(clml); + Audit_list *alp; + Aliste idx; + int save = 0; + + for (APLIST_TRAVERSE(AUDITORS(clmp)->ad_list, idx, alp)) { + Audit_client *acp; + Rt_map *almp = alp->al_lmp; + Lm_list *alml = LIST(almp); + uintptr_t *cookie; + uint_t rtldflags; + + /* + * Ensure this local auditor isn't already in existence as an + * auditor for the head of the link-map list. If it is, then + * this auditor will have already receive preinit and activity + * events. + */ + if (AUDITORS(hlmp) && _audit_used_by_head(hlmp, almp)) + continue; - if (appl) - rtld_flags &= ~RT_FL_APPLIC; + /* + * Create a cookie that represents the object that heads the + * link-map list. If the cookie already exists, then this + * auditor has already been established for another objects + * local auditing. In this case, do not issue a la_objopen() + * or la_activity() event, as these will have already occurred. + */ + if ((acp = _audit_get_head_client(clml->lm_head, almp)) != NULL) + continue; + if ((acp = + _audit_create_head_client(clml->lm_head, almp)) == NULL) + return (0); + + cookie = &(acp->ac_cookie); + save++; + + /* + * Call the la_objopen() if available. + */ + if (alp->al_objopen) { + uint_t flags; + + DBG_CALL(Dbg_audit_objopen(clml, DBG_AUD_CALL, + alp->al_libname, NAME(hlmp), 0, FALSE)); + + APPLICATION_ENTER(rtldflags); + leave(alml, thr_flg_reenter); + flags = (*alp->al_objopen)((Link_map *)hlmp, lmid, + cookie); + (void) enter(thr_flg_reenter); + APPLICATION_RETURN(rtldflags); + + if (flags) { + DBG_CALL(Dbg_audit_objopen(clml, DBG_AUD_RET, + alp->al_libname, NAME(hlmp), flags, TRUE)); + } + } + + /* + * Call the la_activity() if available. + */ + if (alp->al_activity) { + alml->lm_flags |= LML_FLG_AUDITNOTIFY; + clml->lm_flags |= LML_FLG_ACTAUDIT; + + DBG_CALL(Dbg_audit_activity(clml, alp->al_libname, + NAME(clml->lm_head), LA_ACT_ADD)); + + APPLICATION_ENTER(rtldflags); + leave(alml, thr_flg_reenter); + (*alp->al_activity)(cookie, LA_ACT_ADD); + (void) enter(thr_flg_reenter); + APPLICATION_RETURN(rtldflags); + } + } + + /* + * If new head link-map cookies have been generated, then maintain + * any preinit and/or activity requirements. + */ + if (save) { + if (preinit && (aplist_append(&aud_preinit, clmp, + AL_CNT_AUDITORS) == NULL)) + return (0); + if (activity && (aplist_append(&aud_activity, clmp, + AL_CNT_AUDITORS) == NULL)) + return (0); + } + return (1); } /* * la_objopen() caller. Create an audit information structure for the indicated * link-map, regardless of an la_objopen() entry point. This structure is used * to supply information to various audit interfaces (see LML_MSK_AUDINFO). - * Traverse through all audit library and call any la_objopen() entry points + * Traverse through all audit libraries and call any la_objopen() entry points * found. */ static int _audit_objopen(APlist *list, Rt_map *nlmp, Lmid_t lmid, Audit_info *aip, int *ndx) { + Lm_list *nlml = LIST(nlmp); Audit_list *alp; Aliste idx; for (APLIST_TRAVERSE(list, idx, alp)) { uint_t flags; Audit_client *acp; + Rt_map *almp = alp->al_lmp; + Lm_list *alml = LIST(almp); /* * Associate a cookie with the audit library, and assign the @@ -299,14 +580,22 @@ if (alp->al_objopen == NULL) continue; - DBG_CALL(Dbg_audit_object(LIST(alp->al_lmp), alp->al_libname, - NAME(nlmp))); + DBG_CALL(Dbg_audit_objopen(nlml, DBG_AUD_CALL, alp->al_libname, + NAME(nlmp), 0, FALSE)); - leave(LIST(alp->al_lmp), thr_flg_reenter); + leave(alml, thr_flg_reenter); flags = (*alp->al_objopen)((Link_map *)nlmp, lmid, &(acp->ac_cookie)); (void) enter(thr_flg_reenter); + /* + * Diagnose any flags returned by the auditor. + */ + if (flags) { + DBG_CALL(Dbg_audit_objopen(nlml, DBG_AUD_RET, + alp->al_libname, NAME(nlmp), flags, FALSE)); + } + if (flags & LA_FLG_BINDTO) acp->ac_flags |= FLG_AC_BINDTO; @@ -341,7 +630,8 @@ audit_objopen(Rt_map *clmp, Rt_map *nlmp) { Lmid_t lmid = get_linkmap_id(LIST(nlmp)); - int appl = 0, respond = 1, ndx = 0; + int respond = 1, ndx = 0; + uint_t rtldflags; uint_t clients = 0; Audit_info *aip; @@ -349,8 +639,9 @@ return (respond); /* - * Determine the total number of audit libraries in use. This provides - * the number of client structures required for this object. + * Determine the number of auditors that can receive information + * regarding this object. This provides the number of client + * structures required for this object. */ if (auditors) clients = auditors->ad_cnt; @@ -360,8 +651,13 @@ clients += AUDITORS(nlmp)->ad_cnt; /* - * The initial allocation of the audit information structure includes - * an array of audit clients, 1 per audit library presently available. + * Allocate an audit information structure. Each audited object + * maintains a AUDINFO() structure. As this structure can only be + * created once all auditors are loaded, a client count can now be + * computed. + * + * The allocation of the audit information structure includes an array + * of audit clients, 1 per audit library that has been loaded. * * --------------- * | ai_cnt | @@ -381,8 +677,7 @@ aip->ai_clients = (Audit_client *)((uintptr_t)aip + sizeof (Audit_info)); - if ((rtld_flags & RT_FL_APPLIC) == 0) - appl = rtld_flags |= RT_FL_APPLIC; + APPLICATION_ENTER(rtldflags); if (auditors) respond = _audit_objopen(auditors->ad_list, nlmp, @@ -394,14 +689,13 @@ respond = _audit_objopen(AUDITORS(nlmp)->ad_list, nlmp, lmid, aip, &ndx); - if (appl) - rtld_flags &= ~RT_FL_APPLIC; + APPLICATION_RETURN(rtldflags); return (respond); } /* - * la_objclose() caller. Traverse through all audit library and call any + * la_objclose() caller. Traverse through all audit libraries and call any * la_objclose() entry points found. */ void @@ -409,44 +703,94 @@ { Audit_list *alp; Aliste idx; + Lm_list *lml = LIST(lmp); for (APLIST_TRAVERSE(list, idx, alp)) { Audit_client *acp; + Rt_map *almp = alp->al_lmp; + Lm_list *alml = LIST(almp); if (alp->al_objclose == NULL) continue; - if ((acp = _audit_client(AUDINFO(lmp), alp->al_lmp)) == NULL) + if ((acp = _audit_client(AUDINFO(lmp), almp)) == NULL) continue; - leave(LIST(alp->al_lmp), thr_flg_reenter); + DBG_CALL(Dbg_audit_objclose(lml, alp->al_libname, NAME(lmp))); + + leave(alml, thr_flg_reenter); (*alp->al_objclose)(&(acp->ac_cookie)); (void) enter(thr_flg_reenter); } } +/* + * Determine any la_objclose() requirements. An object that is about to be + * deleted needs to trigger an la_objclose() event to any associated auditors. + * In the case of local auditing, a deleted object may have a number of callers, + * and each of these callers may have their own auditing requirements. To + * ensure only one la_objclose() event is sent to each auditor, collect the + * auditors from any callers and make sure there's no duplication. + */ +inline static void +add_objclose_list(Rt_map *lmp, APlist **alpp) +{ + if (AFLAGS(lmp) & LML_TFLG_AUD_OBJCLOSE) { + Audit_list *alp; + Aliste idx; + + for (APLIST_TRAVERSE(AUDITORS(lmp)->ad_list, idx, alp)) { + if (aplist_test(alpp, alp, AL_CNT_AUDITORS) == 0) + return; + } + } +} + void -audit_objclose(Rt_map *clmp, Rt_map *lmp) +audit_objclose(Rt_map *lmp, Rt_map *clmp) { - int appl = 0; + APlist *alp = NULL; + uint_t rtldflags; if (rt_critical()) return; - if ((rtld_flags & RT_FL_APPLIC) == 0) - appl = rtld_flags |= RT_FL_APPLIC; + APPLICATION_ENTER(rtldflags); if (auditors && (auditors->ad_flags & LML_TFLG_AUD_OBJCLOSE)) _audit_objclose(auditors->ad_list, lmp); - if (AUDITORS(clmp) && - (AUDITORS(clmp)->ad_flags & LML_TFLG_AUD_OBJCLOSE)) - _audit_objclose(AUDITORS(clmp)->ad_list, lmp); + + /* + * If this link-map list contains local auditors, determine if this + * object, or any of this objects CALLERS have instantiated auditors + * that need to know of la_objclose() events. + */ + if (LIST(lmp)->lm_flags & LML_FLG_LOCAUDIT) { + Bnd_desc *bdp; + Aliste idx; + + add_objclose_list(lmp, &alp); - if (appl) - rtld_flags &= ~RT_FL_APPLIC; + for (APLIST_TRAVERSE(CALLERS(lmp), idx, bdp)) + add_objclose_list(bdp->b_caller, &alp); + } + + /* + * If this close originated from dlclose(), determine whether the caller + * requires a la_objclose() event. + */ + if (clmp) + add_objclose_list(clmp, &alp); + + if (alp) { + _audit_objclose(alp, lmp); + free((void *)alp); + } + + APPLICATION_RETURN(rtldflags); } /* - * la_pltenter() caller. Traverse through all audit library and call any + * la_pltenter() caller. Traverse through all audit libraries and call any * la_pltenter() entry points found. NOTE: this routine is called via the * glue code established in elf_plt_trace_write(), the symbol descriptor is * created as part of the glue and for 32bit environments the st_name is a @@ -461,6 +805,7 @@ { Audit_list *alp; Aliste idx; + Lm_list *rlml = LIST(rlmp); #if defined(_ELF64) const char *name = (const char *)(sym->st_name + STRTAB(dlmp)); #else @@ -469,19 +814,24 @@ for (APLIST_TRAVERSE(list, idx, alp)) { Audit_client *racp, *dacp; - Addr prev = sym->st_value; + Rt_map *almp = alp->al_lmp; + Lm_list *alml = LIST(almp); + Addr ovalue = sym->st_value; if (alp->al_pltenter == 0) continue; - if ((racp = _audit_client(AUDINFO(rlmp), alp->al_lmp)) == NULL) + if ((racp = _audit_client(AUDINFO(rlmp), almp)) == NULL) continue; - if ((dacp = _audit_client(AUDINFO(dlmp), alp->al_lmp)) == NULL) + if ((dacp = _audit_client(AUDINFO(dlmp), almp)) == NULL) continue; if (((racp->ac_flags & FLG_AC_BINDFROM) == 0) || ((dacp->ac_flags & FLG_AC_BINDTO) == 0)) continue; - leave(LIST(alp->al_lmp), thr_flg_reenter); + DBG_CALL(Dbg_audit_pltenter(rlml, DBG_AUD_CALL, + alp->al_libname, name, ovalue)); + + leave(alml, thr_flg_reenter); sym->st_value = (Addr)(*alp->al_pltenter)(sym, ndx, &(racp->ac_cookie), &(dacp->ac_cookie), regs, /* BEGIN CSTYLED */ @@ -493,8 +843,10 @@ /* END CSTYLED */ (void) enter(thr_flg_reenter); - DBG_CALL(Dbg_audit_symval(LIST(alp->al_lmp), alp->al_libname, - MSG_ORIG(MSG_AUD_PLTENTER), name, prev, sym->st_name)); + if (ovalue != sym->st_value) { + DBG_CALL(Dbg_audit_pltenter(rlml, DBG_AUD_RET, + alp->al_libname, name, sym->st_value)); + } } } @@ -502,36 +854,34 @@ audit_pltenter(Rt_map *rlmp, Rt_map *dlmp, Sym *sym, uint_t ndx, void *regs, uint_t *flags) { - Sym _sym = *sym; - int _appl = 0; + Sym nsym = *sym; + uint_t rtldflags; if (rt_critical()) - return (_sym.st_value); + return (nsym.st_value); /* * We're effectively entering ld.so.1 from user (glue) code. */ (void) enter(0); - if ((rtld_flags & RT_FL_APPLIC) == 0) - _appl = rtld_flags |= RT_FL_APPLIC; + APPLICATION_ENTER(rtldflags); if (auditors && (auditors->ad_flags & LML_TFLG_AUD_PLTENTER)) - _audit_pltenter(auditors->ad_list, rlmp, dlmp, &_sym, + _audit_pltenter(auditors->ad_list, rlmp, dlmp, &nsym, ndx, regs, flags); if (AUDITORS(rlmp) && (AUDITORS(rlmp)->ad_flags & LML_TFLG_AUD_PLTENTER)) - _audit_pltenter(AUDITORS(rlmp)->ad_list, rlmp, dlmp, &_sym, + _audit_pltenter(AUDITORS(rlmp)->ad_list, rlmp, dlmp, &nsym, ndx, regs, flags); - if (_appl) - rtld_flags &= ~RT_FL_APPLIC; + APPLICATION_RETURN(rtldflags); leave(LIST(rlmp), 0); - return (_sym.st_value); + return (nsym.st_value); } /* - * la_pltexit() caller. Traverse through all audit library and call any + * la_pltexit() caller. Traverse through all audit libraries and call any * la_pltexit() entry points found. See notes above (_audit_pltenter) for * discussion on st_name. */ @@ -543,22 +893,29 @@ Aliste idx; #if defined(_ELF64) const char *name = (const char *)(sym->st_name + STRTAB(dlmp)); +#else + const char *name = (const char *)(sym->st_name); #endif + Lm_list *rlml = LIST(rlmp); for (APLIST_TRAVERSE(list, idx, alp)) { Audit_client *racp, *dacp; + Rt_map *almp = alp->al_lmp; + Lm_list *alml = LIST(almp); if (alp->al_pltexit == 0) continue; - if ((racp = _audit_client(AUDINFO(rlmp), alp->al_lmp)) == NULL) + if ((racp = _audit_client(AUDINFO(rlmp), almp)) == NULL) continue; - if ((dacp = _audit_client(AUDINFO(dlmp), alp->al_lmp)) == NULL) + if ((dacp = _audit_client(AUDINFO(dlmp), almp)) == NULL) continue; if (((racp->ac_flags & FLG_AC_BINDFROM) == 0) || ((dacp->ac_flags & FLG_AC_BINDTO) == 0)) continue; - leave(LIST(alp->al_lmp), thr_flg_reenter); + DBG_CALL(Dbg_audit_pltexit(rlml, alp->al_libname, name)); + + leave(alml, thr_flg_reenter); retval = (*alp->al_pltexit)(sym, ndx, &(racp->ac_cookie), &(dacp->ac_cookie), /* BEGIN CSTYLED */ @@ -578,7 +935,7 @@ uint_t ndx) { uintptr_t _retval = retval; - int _appl = 0; + uint_t rtldflags; if (rt_critical()) return (_retval); @@ -587,8 +944,7 @@ * We're effectively entering ld.so.1 from user (glue) code. */ (void) enter(0); - if ((rtld_flags & RT_FL_APPLIC) == 0) - _appl = rtld_flags |= RT_FL_APPLIC; + APPLICATION_ENTER(rtldflags); if (auditors && (auditors->ad_flags & LML_TFLG_AUD_PLTEXIT)) _retval = _audit_pltexit(auditors->ad_list, _retval, @@ -597,8 +953,7 @@ _retval = _audit_pltexit(AUDITORS(rlmp)->ad_list, _retval, rlmp, dlmp, sym, ndx); - if (_appl) - rtld_flags &= ~RT_FL_APPLIC; + APPLICATION_RETURN(rtldflags); leave(LIST(rlmp), 0); return (_retval); @@ -606,7 +961,7 @@ /* - * la_symbind() caller. Traverse through all audit library and call any + * la_symbind() caller. Traverse through all audit libraries and call any * la_symbind() entry points found. */ static Addr @@ -615,6 +970,7 @@ { Audit_list *alp; Aliste idx; + Lm_list *rlml = LIST(rlmp); #if defined(_ELF64) const char *name = (const char *)(sym->st_name + STRTAB(dlmp)); #else @@ -623,14 +979,16 @@ for (APLIST_TRAVERSE(list, idx, alp)) { Audit_client *racp, *dacp; - Addr prev = sym->st_value; - uint_t lflags; + Rt_map *almp = alp->al_lmp; + Lm_list *alml = LIST(almp); + Addr ovalue = sym->st_value; + uint_t lflags, oflags = *flags; if (alp->al_symbind == 0) continue; - if ((racp = _audit_client(AUDINFO(rlmp), alp->al_lmp)) == NULL) + if ((racp = _audit_client(AUDINFO(rlmp), almp)) == NULL) continue; - if ((dacp = _audit_client(AUDINFO(dlmp), alp->al_lmp)) == NULL) + if ((dacp = _audit_client(AUDINFO(dlmp), almp)) == NULL) continue; if (((racp->ac_flags & FLG_AC_BINDFROM) == 0) || ((dacp->ac_flags & FLG_AC_BINDTO) == 0)) @@ -642,10 +1000,13 @@ * object has been identified as BINDTO. Use a local version of * the flags, so that any user update can be collected. */ - called++; - lflags = (*flags & ~(LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)); + (*called)++; + lflags = (oflags & ~(LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)); - leave(LIST(alp->al_lmp), thr_flg_reenter); + DBG_CALL(Dbg_audit_symbind(rlml, DBG_AUD_CALL, + alp->al_libname, name, ovalue, oflags)); + + leave(alml, thr_flg_reenter); sym->st_value = (*alp->al_symbind)(sym, ndx, &(racp->ac_cookie), &(dacp->ac_cookie), /* BEGIN CSTYLED */ @@ -664,11 +1025,14 @@ * has been supplied. */ *flags |= (lflags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)); - if ((prev != sym->st_value) && (alp->al_vernum >= LAV_VERSION2)) + if ((ovalue != sym->st_value) && + (alp->al_vernum >= LAV_VERSION2)) *flags |= LA_SYMB_ALTVALUE; - DBG_CALL(Dbg_audit_symval(LIST(alp->al_lmp), alp->al_libname, - MSG_ORIG(MSG_AUD_SYMBIND), name, prev, sym->st_value)); + if ((ovalue != sym->st_value) || (oflags != *flags)) { + DBG_CALL(Dbg_audit_symbind(rlml, DBG_AUD_RET, + alp->al_libname, name, sym->st_value, *flags)); + } } return (sym->st_value); } @@ -677,8 +1041,9 @@ audit_symbind(Rt_map *rlmp, Rt_map *dlmp, Sym *sym, uint_t ndx, Addr value, uint_t *flags) { - Sym _sym; - int _appl = 0, called = 0; + Sym nsym; + int called = 0; + uint_t rtldflags; /* * Construct a new symbol from that supplied but with the real address. @@ -686,37 +1051,35 @@ * big enough to hold a character pointer. We pass this pointer as a * separate parameter for 64-bit audit libraries. */ - _sym = *sym; - _sym.st_value = value; + nsym = *sym; + nsym.st_value = value; if (rt_critical()) - return (_sym.st_value); + return (nsym.st_value); #if !defined(_ELF64) - _sym.st_name += (Word)STRTAB(dlmp); + nsym.st_name += (Word)STRTAB(dlmp); #endif - if ((rtld_flags & RT_FL_APPLIC) == 0) - _appl = rtld_flags |= RT_FL_APPLIC; + APPLICATION_ENTER(rtldflags); if (auditors && (auditors->ad_flags & LML_TFLG_AUD_SYMBIND)) - _sym.st_value = _audit_symbind(auditors->ad_list, - rlmp, dlmp, &_sym, ndx, flags, &called); + nsym.st_value = _audit_symbind(auditors->ad_list, + rlmp, dlmp, &nsym, ndx, flags, &called); if (AUDITORS(rlmp) && (AUDITORS(rlmp)->ad_flags & LML_TFLG_AUD_SYMBIND)) - _sym.st_value = _audit_symbind(AUDITORS(rlmp)->ad_list, - rlmp, dlmp, &_sym, ndx, flags, &called); + nsym.st_value = _audit_symbind(AUDITORS(rlmp)->ad_list, + rlmp, dlmp, &nsym, ndx, flags, &called); /* * If no la_symbind() was called for this interface, fabricate that no * la_pltenter, or la_pltexit is required. This helps reduce the glue * code created for further auditing. */ - if (caller == 0) + if (called == 0) *flags |= (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT); - if (_appl) - rtld_flags &= ~RT_FL_APPLIC; + APPLICATION_RETURN(rtldflags); - return (_sym.st_value); + return (nsym.st_value); } /* @@ -724,43 +1087,70 @@ * la_preinit() entry points found. */ static void -_audit_preinit(APlist *list, Rt_map *clmp) +_audit_preinit(APlist *list, Rt_map *clmp, Boolean client) { Audit_list *alp; Aliste idx; + Lm_list *clml = LIST(clmp); for (APLIST_TRAVERSE(list, idx, alp)) { Audit_client *acp; + Rt_map *almp = alp->al_lmp; + Lm_list *alml = LIST(almp); + uintptr_t *cookie; if (alp->al_preinit == 0) continue; - if ((acp = _audit_client(AUDINFO(clmp), alp->al_lmp)) == NULL) - continue; - leave(LIST(alp->al_lmp), thr_flg_reenter); - (*alp->al_preinit)(&(acp->ac_cookie)); + /* + * Determine what cookie is required. Any auditing that + * originates from the object that heads the link-map list has + * its own cookie. Local auditors must obtain the cookie that + * represents the object that heads the link-map list. + */ + if (client) + acp = _audit_client(AUDINFO(clmp), almp); + else + acp = _audit_get_head_client(clml->lm_head, almp); + + if (acp == NULL) + continue; + cookie = &(acp->ac_cookie); + + DBG_CALL(Dbg_audit_preinit(clml, alp->al_libname, + NAME(clml->lm_head))); + + leave(alml, thr_flg_reenter); + (*alp->al_preinit)(cookie); (void) enter(thr_flg_reenter); } } void -audit_preinit(Rt_map *clmp) +audit_preinit(Rt_map *mlmp) { - int appl = 0; + Rt_map *clmp; + Aliste idx; + uint_t rtldflags; if (rt_critical()) return; - if ((rtld_flags & RT_FL_APPLIC) == 0) - appl = rtld_flags |= RT_FL_APPLIC; + APPLICATION_ENTER(rtldflags); if (auditors && (auditors->ad_flags & LML_TFLG_AUD_PREINIT)) - _audit_preinit(auditors->ad_list, clmp); - if (AUDITORS(clmp) && (AUDITORS(clmp)->ad_flags & LML_TFLG_AUD_PREINIT)) - _audit_preinit(AUDITORS(clmp)->ad_list, clmp); + _audit_preinit(auditors->ad_list, mlmp, TRUE); + + if (AUDITORS(mlmp) && (AUDITORS(mlmp)->ad_flags & LML_TFLG_AUD_PREINIT)) + _audit_preinit(AUDITORS(mlmp)->ad_list, mlmp, TRUE); - if (appl) - rtld_flags &= ~RT_FL_APPLIC; + for (APLIST_TRAVERSE(aud_preinit, idx, clmp)) { + if (AUDITORS(clmp) && + (AUDITORS(clmp)->ad_flags & LML_TFLG_AUD_PREINIT)) + _audit_preinit(AUDITORS(clmp)->ad_list, clmp, FALSE); + } + + APPLICATION_RETURN(rtldflags); } /* @@ -768,7 +1158,7 @@ * and then close each one down. This is done rather than using the handles * directly from the auditors, as the audit list can be torn down as a result * of the dlclose. In other words, what you're pointing at can be removed - * while your still pointing at it. + * while you're still pointing at it. */ void audit_desc_cleanup(Rt_map *clmp) @@ -790,7 +1180,12 @@ adp->ad_list = NULL; free(adp); + + /* + * Indicate that the caller is no longer being audited. + */ AUDITORS(clmp) = NULL; + AFLAGS(clmp) &= ~LML_TFLG_AUD_MASK; if (ghalp) { Grp_hdl *ghp; @@ -804,6 +1199,24 @@ } /* + * Objects that establish local auditors may have been added to preinit or + * activity lists. Remove the object from this list if it is present. + */ +static void +remove_auditor(APlist *alp, Rt_map *clmp) +{ + Rt_map *lmp; + Aliste idx; + + for (APLIST_TRAVERSE(alp, idx, lmp)) { + if (lmp == clmp) { + aplist_delete(alp, &idx); + return; + } + } +} + +/* * Clean up (free) an audit information structure. */ void @@ -816,6 +1229,12 @@ if (aip->ai_dynplts) free(aip->ai_dynplts); + + if (aud_preinit) + remove_auditor(aud_preinit, clmp); + if (aud_activity) + remove_auditor(aud_activity, clmp); + free(aip); } @@ -830,7 +1249,7 @@ } Aud_info; static const Aud_info aud_info[] = { - { MSG_SYM_LAVERSION, 0 }, /* MSG_ORIG(MSG_SYM_LAVERSION) */ + { MSG_SYM_LAVERSION, 0, 0 }, /* MSG_ORIG(MSG_SYM_LAVERSION) */ { MSG_SYM_LAPREINIT, /* MSG_ORIG(MSG_SYM_LAPREINIT) */ LML_TFLG_AUD_PREINIT, 0 }, { MSG_SYM_LAOBJSEARCH, /* MSG_ORIG(MSG_SYM_LAOBJSEARCH) */ @@ -912,6 +1331,12 @@ if (auflag) audit_flags |= auflag; + /* + * Note, unlike most other diagnostics, where we wish to + * identify the lmid of the caller, here we use the lmid of + * the auditor itself to show the association of the auditor + * and the interfaces it provides. + */ DBG_CALL(Dbg_audit_interface(LIST(alp->al_lmp), alp->al_libname, sr.sr_name)); return (addr); @@ -941,11 +1366,27 @@ int audit_setup(Rt_map *clmp, Audit_desc *adp, uint_t orig, int *in_nfavl) { - char *ptr, *next; - Lm_list *clml = LIST(clmp); - int error = 1; + char *ptr, *next; + Lm_list *clml = LIST(clmp); + Rt_map *hlmp; + int error = 1, activity = 0, preinit = 0; + uint_t rtldflags; - DBG_CALL(Dbg_audit_lib(clml, adp->ad_name)); + /* + * Determine the type of auditing for diagnostics. + */ + if (DBG_ENABLED) { + int type; + + if (orig & PD_FLG_EXTLOAD) + type = DBG_AUD_PRELOAD; + else if (FLAGS1(clmp) & FL1_RT_GLOBAUD) + type = DBG_AUD_GLOBAL; + else + type = DBG_AUD_LOCAL; + + DBG_CALL(Dbg_audit_lib(clmp, adp->ad_name, type)); + } /* * Mark that we have at least one auditing link map @@ -960,9 +1401,12 @@ ptr; ptr = strtok_r(NULL, MSG_ORIG(MSG_STR_DELIMIT), &next)) { Grp_hdl *ghp; Rt_map *lmp; + Lm_list *lml; Rt_map **tobj; Audit_list *alp; + DBG_CALL(Dbg_util_nl(clml, DBG_NL_STD)); + /* * Open the audit library on its own link-map. */ @@ -973,19 +1417,31 @@ continue; } lmp = ghp->gh_ownlmp; + lml = LIST(lmp); /* * If this auditor has already been loaded, reuse it. */ - if ((alp = LIST(lmp)->lm_alp) != NULL) { + if ((alp = lml->lm_alp) != NULL) { if (aplist_append(&(adp->ad_list), alp, AL_CNT_AUDITORS) == NULL) return (audit_disable(ptr, clmp, ghp, alp)); adp->ad_cnt++; - DBG_CALL(Dbg_audit_version(clml, alp->al_libname, - alp->al_vernum)); adp->ad_flags |= alp->al_flags; + + /* + * If this existing auditor provides preinit or + * activity routines, track their existence. The + * instantiation of a local auditor requires a cookie + * be created that represents the object that heads + * the link-map list of the object being audited. + */ + if (alp->al_preinit) + preinit++; + if (alp->al_activity) + activity++; + continue; } @@ -998,7 +1454,7 @@ * Refer to external.c:get_lcinterface(). */ if ((rtld_flags2 & RT_FL2_UNIFPROC) == 0) - LIST(lmp)->lm_flags |= LML_FLG_HOLDLOCK; + lml->lm_flags |= LML_FLG_HOLDLOCK; /* * Allocate an audit list descriptor for this object and @@ -1018,26 +1474,31 @@ */ if ((alp->al_version = (uint_t(*)())audit_symget(alp, AI_LAVERSION, in_nfavl)) == 0) { - eprintf(LIST(lmp), ERR_FATAL, MSG_INTL(MSG_GEN_NOSYM), + eprintf(lml, ERR_FATAL, MSG_INTL(MSG_GEN_NOSYM), MSG_ORIG(MSG_SYM_LAVERSION)); error = audit_disable(ptr, clmp, ghp, alp); continue; } - if ((tobj = tsort(lmp, LIST(lmp)->lm_init, RT_SORT_REV)) == + if ((tobj = tsort(lmp, lml->lm_init, RT_SORT_REV)) == (Rt_map **)S_ERROR) return (audit_disable(ptr, clmp, ghp, alp)); - rtld_flags |= RT_FL_APPLIC; - if (tobj != (Rt_map **)NULL) + if (tobj) call_init(tobj, DBG_INIT_SORT); - alp->al_vernum = alp->al_version(LAV_CURRENT); - rtld_flags &= ~RT_FL_APPLIC; + APPLICATION_ENTER(rtldflags); + leave(lml, thr_flg_reenter); + alp->al_vernum = (*alp->al_version)(LAV_CURRENT); + (void) enter(thr_flg_reenter); + APPLICATION_RETURN(rtldflags); + + DBG_CALL(Dbg_audit_version(clml, alp->al_libname, + LAV_CURRENT, alp->al_vernum)); if ((alp->al_vernum < LAV_VERSION1) || (alp->al_vernum > LAV_CURRENT)) { - eprintf(LIST(lmp), ERR_FATAL, MSG_INTL(MSG_AUD_BADVERS), + eprintf(lml, ERR_FATAL, MSG_INTL(MSG_AUD_BADVERS), LAV_CURRENT, alp->al_vernum); error = audit_disable(ptr, clmp, ghp, alp); continue; @@ -1048,14 +1509,10 @@ return (audit_disable(ptr, clmp, ghp, alp)); adp->ad_cnt++; - DBG_CALL(Dbg_audit_version(clml, alp->al_libname, - alp->al_vernum)); /* * Collect any remaining entry points. */ - alp->al_preinit = (void(*)())audit_symget(alp, - AI_LAPREINIT, in_nfavl); alp->al_objsearch = (char *(*)())audit_symget(alp, AI_LAOBJSEARCH, in_nfavl); alp->al_objopen = (uint_t(*)())audit_symget(alp, @@ -1064,8 +1521,6 @@ AI_LAOBJFILTER, in_nfavl); alp->al_objclose = (uint_t(*)())audit_symget(alp, AI_LAOBJCLOSE, in_nfavl); - alp->al_activity = (void (*)())audit_symget(alp, - AI_LAACTIVITY, in_nfavl); alp->al_symbind = (uintptr_t(*)())audit_symget(alp, AI_LASYMBIND, in_nfavl); alp->al_pltenter = (uintptr_t(*)())audit_symget(alp, @@ -1073,15 +1528,37 @@ alp->al_pltexit = (uintptr_t(*)())audit_symget(alp, AI_LAPLTEXIT, in_nfavl); + if ((alp->al_preinit = (void(*)())audit_symget(alp, + AI_LAPREINIT, in_nfavl)) != NULL) + preinit++; + if ((alp->al_activity = (void(*)())audit_symget(alp, + AI_LAACTIVITY, in_nfavl)) != NULL) + activity++; + /* * Collect the individual object flags, and assign this audit * list descriptor to its associated link-map list. */ adp->ad_flags |= alp->al_flags; - LIST(lmp)->lm_alp = alp; + lml->lm_alp = alp; } /* + * If the caller isn't the head of its own link-map list, then any + * preinit or activity entry points need to be tracked separately. + * These "events" are not associated with a particular link-map, and + * thus a traversal of any existing preinit and activity clients is + * required. + * + * If either of these events are required, establish a cookie for the + * object at the head of the link-map list, and make an initial ADD + * activity for these local auditors. + */ + if ((preinit || activity) && ((hlmp = clml->lm_head) != clmp) && + (_audit_add_head(clmp, hlmp, preinit, activity) == 0)) + return (0); + + /* * Free the original audit string, as this descriptor may be used again * to add additional auditing. */
--- a/usr/src/cmd/sgs/rtld/common/cap.c Tue Jul 20 16:38:52 2010 -0400 +++ b/usr/src/cmd/sgs/rtld/common/cap.c Tue Jul 20 16:29:51 2010 -0700 @@ -652,7 +652,8 @@ int cap_filtees(Alist **alpp, Aliste oidx, const char *dir, Aliste nlmco, - Rt_map *flmp, const char *ref, int mode, uint_t flags, int *in_nfavl) + Rt_map *flmp, Rt_map *clmp, const char *ref, int mode, uint_t flags, + int *in_nfavl) { Alist *fdalp = NULL; Aliste idx; @@ -729,7 +730,7 @@ * Finish processing the objects associated with this request. */ if (nlmp && ghp && (((nlmp = analyze_lmc(lml, nlmco, nlmp, - in_nfavl)) == NULL) || + clmp, in_nfavl)) == NULL) || (relocate_lmc(lml, nlmco, flmp, nlmp, in_nfavl) == 0))) nlmp = NULL;
--- a/usr/src/cmd/sgs/rtld/common/dlfcns.c Tue Jul 20 16:38:52 2010 -0400 +++ b/usr/src/cmd/sgs/rtld/common/dlfcns.c Tue Jul 20 16:29:51 2010 -0700 @@ -456,6 +456,7 @@ dlclose_core(Grp_hdl *ghp, Rt_map *clmp, Lm_list *lml) { int error; + Rt_map *lmp; /* * If we're already at atexit() there's no point processing further, @@ -489,6 +490,21 @@ return (0); /* + * If this handle is associated with an object that is not on the base + * link-map control list, or it has not yet been relocated, then this + * handle must have originated from an auditors interaction. User code + * can only execute and bind to relocated objects on the base link-map + * control list. A non-relocated object, or an object on a non-base + * link-map control list, is in the process of being loaded, and + * therefore we do not attempt to remove the handle, as we might + * mistakenly delete the object thinking that its loading has failed. + */ + if (((lmp = ghp->gh_ownlmp) != NULL) && + ((CNTL(lmp) != ALIST_OFF_DATA) || + ((FLAGS(lmp) & FLG_RT_RELOCED) == 0))) + return (0); + + /* * This handle is no longer being referenced, remove it. If this handle * is part of an alternative link-map list, determine if the whole list * can be removed also. @@ -730,7 +746,7 @@ return (NULL); if ((palp->al_arritems > 1) && ((mode & RTLD_FIRST) == 0)) { - remove_plist(&palp, 1); + remove_alist(&palp, 1); eprintf(lml, ERR_FATAL, MSG_INTL(MSG_ARG_ILLMODE_5)); return (NULL); } @@ -740,7 +756,7 @@ * associated object. */ if ((nlmco = create_cntl(lml, 1)) == NULL) { - remove_plist(&palp, 1); + remove_alist(&palp, 1); return (NULL); } olmco = nlmco; @@ -752,7 +768,7 @@ * Remove any expanded pathname infrastructure, and if the dependency * couldn't be loaded, cleanup. */ - remove_plist(&palp, 1); + remove_alist(&palp, 1); if (nlmp == NULL) { remove_cntl(lml, olmco); return (NULL); @@ -776,7 +792,7 @@ /* * Finish processing the objects associated with this request. */ - if (((nlmp = analyze_lmc(lml, nlmco, nlmp, in_nfavl)) == NULL) || + if (((nlmp = analyze_lmc(lml, nlmco, nlmp, clmp, in_nfavl)) == NULL) || (relocate_lmc(lml, nlmco, clmp, nlmp, in_nfavl) == 0)) { ghp = NULL; nlmp = NULL; @@ -864,9 +880,8 @@ * audited. Insure all audit dependencies are loaded. */ lml->lm_tflags &= ~LML_TFLG_AUD_MASK; - lml->lm_tflags |= - (LML_TFLG_NOLAZYLD | LML_TFLG_LOADFLTR); - lml->lm_flags |= LML_FLG_NOAUDIT; + lml->lm_tflags |= (LML_TFLG_NOLAZYLD | + LML_TFLG_LOADFLTR | LML_TFLG_NOAUDIT); } if (aplist_append(&dynlm_list, lml, AL_CNT_DYNLIST) == NULL) {
--- a/usr/src/cmd/sgs/rtld/common/elf.c Tue Jul 20 16:38:52 2010 -0400 +++ b/usr/src/cmd/sgs/rtld/common/elf.c Tue Jul 20 16:29:51 2010 -0700 @@ -420,7 +420,7 @@ * Establish a link-map control list for this request. */ if ((lmco = create_cntl(lml, 0)) == NULL) { - remove_plist(&palp, 1); + remove_alist(&palp, 1); return (NULL); } @@ -435,7 +435,7 @@ * dependency count of the caller, together with the link-map lists * count of objects that still have lazy dependencies pending. */ - remove_plist(&palp, 1); + remove_alist(&palp, 1); if (--LAZY(clmp) == 0) LIST(clmp)->lm_lazy--; @@ -444,7 +444,7 @@ * create an association between the caller and this dependency. */ if (nlmp && ((bind_one(clmp, nlmp, BND_NEEDED) == 0) || - ((nlmp = analyze_lmc(lml, lmco, nlmp, in_nfavl)) == NULL) || + ((nlmp = analyze_lmc(lml, lmco, nlmp, clmp, in_nfavl)) == NULL) || (relocate_lmc(lml, lmco, clmp, nlmp, in_nfavl) == 0))) dip->di_info = nlmp = NULL; @@ -729,7 +729,7 @@ * error suppression state, if it had been previously set in * this routine. */ - remove_plist(&palp, 0); + remove_alist(&palp, 0); if (silent) rtld_flags &= ~RT_FL_SILENCERR; @@ -743,7 +743,7 @@ (LML_FLG_LOADAVAIL | LML_FLG_TRC_ENABLE))) continue; else { - remove_plist(&palp, 1); + remove_alist(&palp, 1); return (0); } } @@ -752,7 +752,7 @@ if (LAZY(clmp)) lml->lm_lazy++; - remove_plist(&palp, 1); + remove_alist(&palp, 1); return (1); } @@ -930,7 +930,7 @@ */ DBG_CALL(Dbg_cap_filter(lml, dir, ilmp)); if (cap_filtees((Alist **)&dip->di_info, idx, dir, - lmco, ilmp, filtees, mode, + lmco, ilmp, clmp, filtees, mode, (FLG_RT_PUBHDL | FLG_RT_CAP), in_nfavl) == 0) { if ((lml->lm_flags & LML_FLG_TRC_ENABLE) && (dip->di_flags & FLG_DI_AUXFLTR) && @@ -1114,7 +1114,7 @@ * this filtee if necessary. */ if (nlmp && ghp && (((nlmp = analyze_lmc(lml, - lmco, nlmp, in_nfavl)) == NULL) || + lmco, nlmp, clmp, in_nfavl)) == NULL) || (relocate_lmc(lml, lmco, ilmp, nlmp, in_nfavl) == 0))) nlmp = NULL; @@ -1244,7 +1244,7 @@ * use the null symbol routine. */ if (any == 0) { - remove_plist((Alist **)&(dip->di_info), 1); + remove_alist((Alist **)&(dip->di_info), 1); elf_disable_filtee(ilmp, dip); } @@ -1644,7 +1644,7 @@ */ Rt_map * elf_new_lmp(Lm_list *lml, Aliste lmco, Fdesc *fdp, Addr addr, size_t msize, - void *odyn, int *in_nfavl) + void *odyn, Rt_map *clmp, int *in_nfavl) { const char *name = fdp->fd_nname; Rt_map *lmp; @@ -2115,7 +2115,7 @@ if ((rti = alist_append(&lml->lm_rti, NULL, sizeof (Rti_desc), AL_CNT_RTLDINFO)) == NULL) { - remove_so(0, lmp); + remove_so(0, lmp, clmp); return (NULL); } rti->rti_lmp = lmp; @@ -2262,13 +2262,13 @@ if (((AUDITORS(lmp) = calloc(1, sizeof (Audit_desc))) == NULL) || ((AUDITORS(lmp)->ad_name = strdup(cp)) == NULL)) { - remove_so(0, lmp); + remove_so(0, lmp, clmp); return (NULL); } if (lml_main.lm_head) { if (audit_setup(lmp, AUDITORS(lmp), 0, in_nfavl) == 0) { - remove_so(0, lmp); + remove_so(0, lmp, clmp); return (NULL); } AFLAGS(lmp) |= AUDITORS(lmp)->ad_flags; @@ -2278,7 +2278,7 @@ } if (tphdr && (tls_assign(lml, lmp, tphdr) == 0)) { - remove_so(0, lmp); + remove_so(0, lmp, clmp); return (NULL); }
--- a/usr/src/cmd/sgs/rtld/common/external.c Tue Jul 20 16:38:52 2010 -0400 +++ b/usr/src/cmd/sgs/rtld/common/external.c Tue Jul 20 16:29:51 2010 -0700 @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -478,7 +477,8 @@ if ((fptr = (void (*)())lml->lm_lcs[CI_THRINIT].lc_un.lc_func) != NULL) { lml->lm_lcs[CI_THRINIT].lc_un.lc_func = NULL; - leave(NULL, thr_flg_reenter); + + leave(lml, thr_flg_reenter); (*fptr)(); (void) enter(thr_flg_reenter); @@ -578,11 +578,7 @@ size_t thr_min_stack() { -#ifdef _LP64 - return (8 * 1024); -#else - return (4 * 1024); -#endif + return (sizeof (uintptr_t) * 1024); } /* @@ -592,7 +588,6 @@ * the dynamic linker, so we redefine these to call the primitive, * non-cancellation interfaces. */ - int close(int fildes) {
--- a/usr/src/cmd/sgs/rtld/common/globals.c Tue Jul 20 16:38:52 2010 -0400 +++ b/usr/src/cmd/sgs/rtld/common/globals.c Tue Jul 20 16:29:51 2010 -0700 @@ -112,7 +112,7 @@ const char *rtldname = MSG_ORIG(MSG_FIL_RTLD); char *lasterr = NULL; /* string describing last error */ - /* cleared by each dlerror() */ + /* cleared by each dlerror() */ Interp *interp = NULL; /* ELF interpreter info */ APlist *hdl_alp[HDLIST_SZ+2]; /* dlopen() handle list */ size_t syspagsz = 0; /* system page size */ @@ -121,25 +121,27 @@ Isa_desc *isa = NULL; /* isalist descriptor */ uint_t audit_argcnt = 64; /* no. of stack args to copy (default */ - /* is all) */ + /* is all) */ Audit_desc *auditors = NULL; /* global auditors (LD_AUDIT) */ +APlist *aud_preinit = NULL; /* list of objects defining local */ +APlist *aud_activity = NULL; /* preinit and activity auditors */ const char *rpl_audit = NULL; /* replaceable LD_AUDIT string */ const char *rpl_debug = NULL; /* replaceable LD_DEBUG string */ const char *rpl_ldflags = NULL; /* replaceable LD_FLAGS string */ const char *rpl_libpath = NULL; /* replaceable LD_LIBRARY_PATH string */ -Alist *rpl_libdirs = NULL; /* and associated Pdesc list */ +Alist *rpl_libdirs = NULL; /* and associated Pdesc list */ const char *rpl_preload = NULL; /* replaceable LD_PRELOAD string */ const char *prm_audit = NULL; /* permanent LD_AUDIT string */ const char *prm_debug = NULL; /* permanent LD_DEBUG string */ const char *prm_ldflags = NULL; /* permanent LD_FLAGS string */ const char *prm_libpath = NULL; /* permanent LD_LIBRARY_PATH string */ -Alist *prm_libdirs = NULL; /* and associated Pdesc list */ +Alist *prm_libdirs = NULL; /* and associated Pdesc list */ const char *prm_preload = NULL; /* permanent LD_PRELOAD string */ uint_t env_info = 0; /* information regarding environment */ - /* variables */ + /* variables */ int killsig = SIGKILL; /* signal sent on fatal exit */ APlist *free_alp = NULL; /* defragmentation list */
--- a/usr/src/cmd/sgs/rtld/common/object.c Tue Jul 20 16:38:52 2010 -0400 +++ b/usr/src/cmd/sgs/rtld/common/object.c Tue Jul 20 16:29:51 2010 -0700 @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -156,7 +155,7 @@ * sections). */ Rt_map * -elf_obj_file(Lm_list *lml, Aliste lmco, const char *name, +elf_obj_file(Lm_list *lml, Aliste lmco, Rt_map *clmp, const char *name, mmapobj_result_t *hmpp, mmapobj_result_t *mpp, uint_t mnum) { Rej_desc rej; @@ -179,7 +178,7 @@ md.md_mnum = mnum; if (alist_append(&mpalp, &md, sizeof (Mmap_desc), AL_CNT_MPOBJS) == NULL) { - remove_so(lml, olmp); + remove_so(lml, olmp, clmp); return (NULL); } @@ -189,7 +188,7 @@ */ if (ld_process_mem(name, name, hmpp->mr_addr, hmpp->mr_msize, (Ofl_desc *)ELFPRV(olmp), &rej) == (Ifl_desc *)S_ERROR) { - remove_so(lml, olmp); + remove_so(lml, olmp, clmp); return (NULL); } @@ -231,7 +230,7 @@ * the appropriate link-edit functionality (refer to sgs/ld/common/main.c). */ Rt_map * -elf_obj_fini(Lm_list *lml, Rt_map *lmp, int *in_nfavl) +elf_obj_fini(Lm_list *lml, Rt_map *lmp, Rt_map *clmp, int *in_nfavl) { Ofl_desc *ofl = (Ofl_desc *)ELFPRV(lmp); Rt_map *nlmp, *tlmp; @@ -331,7 +330,7 @@ */ fd.fd_nname = ofl->ofl_name; if ((nlmp = elf_new_lmp(lml, CNTL(olmp), &fd, (Addr)hmpp->mr_addr, - ofl->ofl_size, 0, in_nfavl)) == NULL) + ofl->ofl_size, NULL, clmp, in_nfavl)) == NULL) return (NULL); MMAPS(nlmp) = hmpp; @@ -426,7 +425,7 @@ * opened. */ if ((lml->lm_tflags | AFLAGS(nlmp)) & LML_TFLG_AUD_MASK) { - if (audit_objopen(lmp, lmp) == 0) + if (audit_objopen(nlmp, nlmp) == 0) return (NULL); } return (nlmp);
--- a/usr/src/cmd/sgs/rtld/common/paths.c Tue Jul 20 16:38:52 2010 -0400 +++ b/usr/src/cmd/sgs/rtld/common/paths.c Tue Jul 20 16:29:51 2010 -0700 @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -163,7 +162,7 @@ } if (rpl_libdirs && (rtld_flags & RT_FL_SECURE) && (search || DBG_ENABLED)) - remove_plist(&rpl_libdirs, 1); + remove_alist(&rpl_libdirs, 1); if (rpl_libdirs == NULL) { /* @@ -204,7 +203,7 @@ prm_libpath, config->c_name); if (prm_libdirs && (rtld_flags & RT_FL_SECURE) && (search || DBG_ENABLED)) - remove_plist(&prm_libdirs, 1); + remove_alist(&prm_libdirs, 1); if (prm_libdirs == NULL) { /* @@ -241,7 +240,7 @@ RPATH(lmp), NAME(lmp)); if (RLIST(lmp) && (rtld_flags & RT_FL_SECURE) && (search || DBG_ENABLED)) - remove_plist(&RLIST(lmp), 1); + remove_alist(&RLIST(lmp), 1); if (RLIST(lmp) == NULL) { /*
--- a/usr/src/cmd/sgs/rtld/common/remove.c Tue Jul 20 16:38:52 2010 -0400 +++ b/usr/src/cmd/sgs/rtld/common/remove.c Tue Jul 20 16:29:51 2010 -0700 @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -140,10 +139,11 @@ /* * Break down an Alist containing pathname descriptors. In most instances, the - * Alist is cleaned of all entries, but retained for later use. + * Alist is removed completely. However, in some instances the alist is cleaned + * of all entries, but retained for later use. */ void -remove_plist(Alist **alpp, int complete) +remove_alist(Alist **alpp, int complete) { Alist *alp = *alpp; @@ -152,8 +152,7 @@ free((void *)alp); *alpp = NULL; } else { - alp->al_nitems = 0; - alp->al_next = ALIST_OFF_DATA; + alist_reset(alp); } } } @@ -170,23 +169,14 @@ remove_lml(Lm_list *lml) { if (lml && (lml->lm_head == NULL)) { - /* - * As a whole link-map list is being removed, the debuggers - * would have been alerted of this deletion (or an addition - * in the case we're here to clean up from a failure). Set - * the main link-map list so that a consistent registration - * can be signaled to the debuggers when we leave ld.so.1. - */ - lml_main.lm_flags |= LML_FLG_DBNOTIF; - if (lml->lm_lmidstr) free(lml->lm_lmidstr); if (lml->lm_alp) free(lml->lm_alp); if (lml->lm_lists) free(lml->lm_lists); - if (lml->lm_actaudit) - free(lml->lm_actaudit); + if (lml->lm_aud_cookies) + free(lml->lm_aud_cookies); /* * Cleanup any pending RTLDINFO in the case where it was @@ -219,7 +209,7 @@ * link-map creation failure. */ void -remove_so(Lm_list *lml, Rt_map *lmp) +remove_so(Lm_list *lml, Rt_map *lmp, Rt_map *clmp) { Dyninfo *dip; @@ -230,7 +220,7 @@ * Unlink the link map from the link-map list. */ if (lml && lmp) - lm_delete(lml, lmp); + lm_delete(lml, lmp, clmp); /* * If this object contributed any local external vectors for the current @@ -257,6 +247,33 @@ DBG_CALL(Dbg_file_delete(lmp)); /* + * If this object is an auditor, determine whether any link-map lists + * are maintaining cookies to represent this auditor. These cookies + * are established for local auditing preinit and activity events. + */ + if (FLAGS(lmp) & FLG_RT_AUDIT) { + Lm_list *nlml; + Aliste idx1; + + for (APLIST_TRAVERSE(dynlm_list, idx1, nlml)) { + Rt_map *hlmp = nlml->lm_head; + Audit_client *acp; + Aliste idx2; + + if ((hlmp == NULL) || (FLAGS(hlmp) & FLG_RT_AUDIT)) + continue; + + for (ALIST_TRAVERSE(nlml->lm_aud_cookies, idx2, acp)) { + if (acp->ac_lmp != lmp) { + alist_delete(nlml->lm_aud_cookies, + &idx2); + break; + } + } + } + } + + /* * If this is a temporary link-map, put in place to facilitate the * link-edit or a relocatable object, then the link-map contains no * information that needs to be cleaned up. @@ -288,7 +305,7 @@ ((dip->di_flags & MSK_DI_FILTER) == 0)) continue; - remove_plist((Alist **)&(dip->di_info), 1); + remove_alist((Alist **)&(dip->di_info), 1); } } @@ -296,7 +313,7 @@ * Deallocate any remaining cruft and free the link-map. */ if (RLIST(lmp)) - remove_plist(&RLIST(lmp), 1); + remove_alist(&RLIST(lmp), 1); if (AUDITORS(lmp)) audit_desc_cleanup(lmp); @@ -488,7 +505,7 @@ * that are apart of this link-map control list. */ static void -remove_incomplete(Lm_list *lml, Aliste lmco) +remove_incomplete(Lm_list *lml, Aliste lmco, Rt_map *clmp) { Rt_map *lmp; Lm_cntl *lmc; @@ -497,7 +514,20 @@ lmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, lmco); /* - * First, remove any lists that may point between objects. + * If auditing is in effect, the loading of these objects might have + * resulted in la_objopen() events being posted. Normally, an + * la_objclose() event is posted after an object's .fini is executed, + * just before the objects are unloaded. These failed objects do not + * have their .fini's executed, but an la_objclose() event should still + * be posted to any auditors. + */ + if ((lml->lm_tflags | AFLAGS(clmp)) & LML_TFLG_AUD_OBJCLOSE) { + for (lmp = lmc->lc_head; lmp; lmp = NEXT_RT_MAP(lmp)) + audit_objclose(lmp, clmp); + } + + /* + * Remove any lists that may point between objects. */ for (lmp = lmc->lc_head; lmp; lmp = NEXT_RT_MAP(lmp)) remove_lists(lmp, 1); @@ -508,7 +538,7 @@ * next link-map. */ while ((lmp = lmc->lc_head) != NULL) - remove_so(lml, lmp); + remove_so(lml, lmp, clmp); lmc->lc_head = lmc->lc_tail = NULL; } @@ -541,7 +571,7 @@ * this parent will have callers that are not apart of this dlclose() * family, and thus would be caught by the CALLERS test below. However, * if the caller had itself been dlopen'ed, it may not have any explicit - * callers registered for itself. Thus, but looking for objects with + * callers registered for itself. Thus, by looking for objects with * handles we can ferret out these outsiders. */ for (APLIST_TRAVERSE(HANDLES(lmp), idx, ghp)) { @@ -869,7 +899,7 @@ * list, and any handle that may have been created. */ if ((lmc->lc_flags & LMC_FLG_RELOCATING) == 0) { - remove_incomplete(lml, lmco); + remove_incomplete(lml, lmco, clmp); if (ghp) { ghp->gh_refcnt = 1; @@ -981,7 +1011,7 @@ * - Remove the handle descriptors for each deleted object, and hopefully * the whole handle. * - * An handle that can't be deleted is added to an orphans list. This list is + * A handle that can't be deleted is added to an orphans list. This list is * revisited any time another dlclose() request results in handle descriptors * being deleted. These deleted descriptors can be sufficient to allow the * final deletion of the orphaned handles. @@ -1294,14 +1324,6 @@ Rt_map **tobj; /* - * If we're being audited tell the audit library that we're - * about to go deleting dependencies. - */ - if (clmp && ((LIST(clmp)->lm_tflags | AFLAGS(clmp)) & - LML_TFLG_AUD_ACTIVITY)) - audit_activity(clmp, LA_ACT_DELETE); - - /* * Sort and fire all fini's of the objects selected for * deletion. Note that we have to start our search from the * link-map head - there's no telling whether this object has @@ -1317,23 +1339,7 @@ (RT_SORT_DELETE | RT_SORT_FWD))) != NULL) && (tobj != (Rt_map **)S_ERROR)) { error = purge_exit_handlers(lml, tobj); - call_fini(lml, tobj); - } - - /* - * Audit the closure of the dlopen'ed object to any local - * auditors. Any global auditors would have been caught by - * call_fini(), but as the link-maps CALLERS was removed - * already we do the local auditors explicitly. - */ - for (APLIST_TRAVERSE(ghalp, idx1, ghp2)) { - Grp_hdl *ghp = ghp2; - Rt_map *dlmp = ghp->gh_ownlmp; - - if (clmp && dlmp && - ((LIST(dlmp)->lm_flags & LML_FLG_NOAUDIT) == 0) && - (AFLAGS(clmp) & LML_TFLG_AUD_OBJCLOSE)) - _audit_objclose(AUDITORS(clmp)->ad_list, dlmp); + call_fini(lml, tobj, clmp); } } @@ -1466,7 +1472,7 @@ if ((FLAGS(lmp) & FLG_RT_DELETE) && ((flags & GPD_PARENT) == 0)) { tls_modaddrem(lmp, TM_FLG_MODREM); - remove_so(LIST(lmp), lmp); + remove_so(LIST(lmp), lmp, clmp); } }
--- a/usr/src/cmd/sgs/rtld/common/rtld.msg Tue Jul 20 16:38:52 2010 -0400 +++ b/usr/src/cmd/sgs/rtld/common/rtld.msg Tue Jul 20 16:29:51 2010 -0700 @@ -422,6 +422,3 @@ @ MSG_LMID_FMT "%s%d" @ MSG_LMID_MAXED "ALTMAXEDOUT" - -@ MSG_AUD_PLTENTER "la_pltenter" -@ MSG_AUD_SYMBIND "la_symbind"
--- a/usr/src/cmd/sgs/rtld/common/setup.c Tue Jul 20 16:38:52 2010 -0400 +++ b/usr/src/cmd/sgs/rtld/common/setup.c Tue Jul 20 16:29:51 2010 -0700 @@ -133,7 +133,7 @@ PD_FLG_EXTLOAD, 0) != 0) nlmp = load_one(&lml_main, ALIST_OFF_DATA, palp, *clmp, MODE(mlmp), flags, 0, NULL); - remove_plist(&palp, 0); + remove_alist(&palp, 0); if (rtld_flags & RT_FL_SECURE) rtld_flags2 &= ~RT_FL2_FTL2WARN; if (nlmp && (bind_one(*clmp, nlmp, BND_NEEDED) == 0)) @@ -333,8 +333,8 @@ if (alist_append(&lml_rtld.lm_lists, NULL, sizeof (Lm_cntl), AL_CNT_LMLISTS) == NULL) return (0); - lml_rtld.lm_flags |= (LML_FLG_RTLDLM | LML_FLG_NOAUDIT | - LML_FLG_HOLDLOCK); + lml_rtld.lm_flags |= (LML_FLG_RTLDLM | LML_FLG_HOLDLOCK); + lml_rtld.lm_tflags |= LML_TFLG_NOAUDIT; lml_rtld.lm_lmid = LM_ID_LDSO; lml_rtld.lm_lmidstr = (char *)MSG_ORIG(MSG_LMID_LDSO); @@ -427,7 +427,7 @@ return (0); if ((rlmp = elf_new_lmp(&lml_rtld, ALIST_OFF_DATA, &fdr, (Addr)mpp->mr_addr, (size_t)((uintptr_t)eaddr - (uintptr_t)ld_base), - NULL, NULL)) == NULL) + NULL, NULL, NULL)) == NULL) return (0); MMAPS(rlmp) = mpp; @@ -481,7 +481,7 @@ fdm.fd_dev = status.st_dev; fdm.fd_ino = status.st_ino; - if ((mlmp = load_file(&lml_main, ALIST_OFF_DATA, &fdm, + if ((mlmp = load_file(&lml_main, ALIST_OFF_DATA, NULL, &fdm, NULL)) == NULL) return (0); @@ -545,7 +545,7 @@ stravl_insert(execname, 0, 0, 0)) == NULL) return (0); if ((mlmp = aout_new_lmp(&lml_main, ALIST_OFF_DATA, - &fdm, 0, 0, aoutdyn, NULL)) == NULL) + &fdm, 0, 0, aoutdyn, NULL, NULL)) == NULL) return (0); /* @@ -678,8 +678,9 @@ if ((fdm.fd_nname = stravl_insert(execname, 0, 0, 0)) == NULL) return (0); - if ((mlmp = elf_new_lmp(&lml_main, ALIST_OFF_DATA, &fdm, - (Addr)hmpp->mr_addr, msize, NULL, NULL)) == NULL) + if ((mlmp = elf_new_lmp(&lml_main, ALIST_OFF_DATA, + &fdm, (Addr)hmpp->mr_addr, msize, + NULL, NULL, NULL)) == NULL) return (0); MMAPS(mlmp) = fmpp; @@ -1033,7 +1034,7 @@ /* * Load all dependent (needed) objects. */ - if (analyze_lmc(&lml_main, ALIST_OFF_DATA, mlmp, NULL) == NULL) + if (analyze_lmc(&lml_main, ALIST_OFF_DATA, mlmp, mlmp, NULL) == NULL) return (0); /* @@ -1102,9 +1103,11 @@ */ rd_event(&lml_main, RD_PREINIT, 0); - if ((lml_main.lm_tflags | AFLAGS(mlmp)) & LML_TFLG_AUD_ACTIVITY) + if (aud_activity || + ((lml_main.lm_tflags | AFLAGS(mlmp)) & LML_TFLG_AUD_ACTIVITY)) audit_activity(mlmp, LA_ACT_CONSISTENT); - if ((lml_main.lm_tflags | AFLAGS(mlmp)) & LML_TFLG_AUD_PREINIT) + if (aud_preinit || + ((lml_main.lm_tflags | AFLAGS(mlmp)) & LML_TFLG_AUD_PREINIT)) audit_preinit(mlmp); /* @@ -1194,8 +1197,6 @@ rt_thr_init(&lml_main); } - rtld_flags |= RT_FL_APPLIC; - /* * Fire all dependencies .init sections. Identify any unused * dependencies, and leave the runtime linker - effectively calling @@ -1213,7 +1214,8 @@ DBG_CALL(Dbg_util_call_main(mlmp)); - rtld_flags |= RT_FL_OPERATION; + rtld_flags |= (RT_FL_OPERATION | RT_FL_APPLIC); + leave(LIST(mlmp), 0); return (mlmp);
--- a/usr/src/cmd/sgs/rtld/common/tsort.c Tue Jul 20 16:38:52 2010 -0400 +++ b/usr/src/cmd/sgs/rtld/common/tsort.c Tue Jul 20 16:29:51 2010 -0700 @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -155,9 +154,9 @@ * each object a group identifier so that cyclic dependent callers can * be better traced (see trace_sort()), or analyzed for non-use. */ - if (((init = (lmflags & LML_FLG_TRC_INIT)) == 0) && - ((unref = (lmflags & LML_FLG_TRC_UNREF)) == 0) && - (DBG_ENABLED == 0)) + init = lmflags & LML_FLG_TRC_INIT; + unref = lmflags & LML_FLG_TRC_UNREF; + if ((init == 0) && (unref == 0) && (DBG_ENABLED == 0)) return (1); if (init) {
--- a/usr/src/cmd/sgs/rtld/common/util.c Tue Jul 20 16:38:52 2010 -0400 +++ b/usr/src/cmd/sgs/rtld/common/util.c Tue Jul 20 16:29:51 2010 -0700 @@ -98,26 +98,18 @@ * We also don't want to trigger multiple RD_ADD/RD_DELETE events any time we * enter ld.so.1. * - * With auditors, we may be in the process of relocating a collection of - * objects, and will leave() ld.so.1 to call the auditor. At this point we - * must indicate an RD_CONSISTENT event, but librtld_db will not report an - * object to the debuggers until relocation processing has been completed on it. - * To allow for the collection of these objects that are pending relocation, an - * RD_ADD event is set after completing a series of relocations on the primary - * link-map control list. + * Set an RD_ADD/RD_DELETE event and indicate that an RD_CONSISTENT event is + * required later (RT_FL_DBNOTIF): * - * Set an RD_ADD/RD_DELETE event and indicate that an RD_CONSISTENT event is - * required later (LML_FLG_DBNOTIF): - * - * i the first time we add or delete an object to the primary link-map + * i. the first time we add or delete an object to the primary link-map * control list. - * ii the first time we move a secondary link-map control list to the primary + * ii. the first time we move a secondary link-map control list to the primary * link-map control list (effectively, this is like adding a group of * objects to the primary link-map control list). * - * Set an RD_CONSISTENT event when it is required (LML_FLG_DBNOTIF is set) and + * Set an RD_CONSISTENT event when it is required (RT_FL_DBNOTIF is set): * - * i each time we leave the runtime linker. + * i. each time we leave the runtime linker. */ void rd_event(Lm_list *lml, rd_event_e event, r_state_e state) @@ -134,8 +126,6 @@ case RD_DLACTIVITY: switch (state) { case RT_CONSISTENT: - lml->lm_flags &= ~LML_FLG_DBNOTIF; - /* * Do we need to send a notification? */ @@ -145,8 +135,6 @@ break; case RT_ADD: case RT_DELETE: - lml->lm_flags |= LML_FLG_DBNOTIF; - /* * If we are already in an inconsistent state, no * notification is required. @@ -628,8 +616,8 @@ * If the caller is an auditor, and the destination isn't, then don't * run any .inits (see comments in load_completion()). */ - if ((LIST(clmp)->lm_flags & LML_FLG_NOAUDIT) && - (LIST(clmp) != LIST(dlmp))) + if ((LIST(clmp)->lm_tflags & LML_TFLG_NOAUDIT) && + ((LIST(dlmp)->lm_tflags & LML_TFLG_NOAUDIT) == 0)) return; if ((dlmp == clmp) || (rtld_flags & RT_FL_INITFIRST)) @@ -680,13 +668,16 @@ * Call the .*array[] entries */ for (ndx = start; ndx != stop; ndx += incr) { - void (*fptr)(void) = (void(*)())array[ndx]; + uint_t rtldflags; + void (*fptr)(void) = (void(*)())array[ndx]; DBG_CALL(Dbg_util_call_array(lmp, (void *)fptr, ndx, shtype)); + APPLICATION_ENTER(rtldflags); leave(LIST(lmp), 0); (*fptr)(); (void) enter(0); + APPLICATION_RETURN(rtldflags); } } @@ -717,7 +708,6 @@ for (_tobj = _nobj = tobj, _nobj++; *_tobj != NULL; _tobj++, _nobj++) { Rt_map *lmp = *_tobj; void (*iptr)() = INIT(lmp); - uint_t rtldflags; if (FLAGS(lmp) & FLG_RT_INITCALL) continue; @@ -725,17 +715,6 @@ FLAGS(lmp) |= FLG_RT_INITCALL; /* - * It is possible, that during the initial handshake with libc, - * an interposition object has resolved a symbol binding, and - * that this objects .init must be fired. As we're about to - * run user code, make sure any dynamic linking errors remain - * internal (ie., only obtainable from dlerror()), and are not - * flushed to stderr. - */ - rtldflags = (rtld_flags & RT_FL_APPLIC) ? 0 : RT_FL_APPLIC; - rtld_flags |= rtldflags; - - /* * Establish an initfirst state if necessary - no other inits * will be fired (because of additional relocation bindings) * when in this state. @@ -747,9 +726,13 @@ DBG_CALL(Dbg_util_call_init(lmp, flag)); if (iptr) { + uint_t rtldflags; + + APPLICATION_ENTER(rtldflags); leave(LIST(lmp), 0); (*iptr)(); (void) enter(0); + APPLICATION_RETURN(rtldflags); } call_array(INITARRAY(lmp), INITARRAYSZ(lmp), lmp, @@ -759,11 +742,6 @@ DBG_CALL(Dbg_util_call_init(lmp, DBG_INIT_DONE)); /* - * Return to a non-application setting if necessary. - */ - rtld_flags &= ~rtldflags; - - /* * Set the initdone flag regardless of whether this object * actually contains an .init section. This flag prevents us * from processing this section again for an .init and also @@ -796,20 +774,18 @@ } /* - * Function called by atexit(3C). Calls all .fini sections related with the - * mains dependent shared libraries in the order in which the shared libraries - * have been loaded. Skip any .fini defined in the main executable, as this - * will be called by crt0 (main was never marked as initdone). + * Call .fini sections for the topologically sorted list of objects. This + * routine is called from remove_hdl() for any objects being torn down as part + * of a dlclose() operation, and from atexit() processing for all the remaining + * objects within the process. */ void -call_fini(Lm_list * lml, Rt_map ** tobj) +call_fini(Lm_list *lml, Rt_map **tobj, Rt_map *clmp) { Rt_map **_tobj; for (_tobj = tobj; *_tobj != NULL; _tobj++) { - Rt_map *clmp, * lmp = *_tobj; - Aliste idx; - Bnd_desc *bdp; + Rt_map *lmp = *_tobj; /* * Only fire a .fini if the objects corresponding .init has @@ -827,9 +803,13 @@ SHT_FINI_ARRAY); if (fptr) { - leave(LIST(lmp), 0); + uint_t rtldflags; + + APPLICATION_ENTER(rtldflags); + leave(lml, 0); (*fptr)(); (void) enter(0); + APPLICATION_RETURN(rtldflags); } } @@ -840,40 +820,25 @@ continue; /* - * Audit `close' operations at this point. The library has - * exercised its last instructions (regardless of whether it - * will be unmapped or not). - * - * First call any global auditing. - */ - if (lml->lm_tflags & LML_TFLG_AUD_OBJCLOSE) - _audit_objclose(auditors->ad_list, lmp); - - /* - * Finally determine whether this object has local auditing - * requirements by inspecting itself and then its dependencies. + * This object has exercised its last instructions (regardless + * of whether it will be unmapped or not). Audit this closure. */ - if ((lml->lm_flags & LML_FLG_LOCAUDIT) == 0) - continue; - - if (AFLAGS(lmp) & LML_TFLG_AUD_OBJCLOSE) - _audit_objclose(AUDITORS(lmp)->ad_list, lmp); - - for (APLIST_TRAVERSE(CALLERS(lmp), idx, bdp)) { - clmp = bdp->b_caller; - - if (AFLAGS(clmp) & LML_TFLG_AUD_OBJCLOSE) { - _audit_objclose(AUDITORS(clmp)->ad_list, lmp); - break; - } - } + if ((lml->lm_tflags & LML_TFLG_NOAUDIT) == 0) + audit_objclose(lmp, clmp); } + DBG_CALL(Dbg_bind_plt_summary(lml, M_MACH, pltcnt21d, pltcnt24d, pltcntu32, pltcntu44, pltcntfull, pltcntfar)); free(tobj); } +/* + * Function called by atexit(3C). Calls all .fini sections within the objects + * that make up the process. As .fini processing is the last opportunity for + * any new bindings to be established, this is also a convenient location to + * check for unused objects. + */ void atexit_fini() { @@ -895,19 +860,7 @@ */ if (((tobj = tsort(lmp, lml->lm_obj, RT_SORT_FWD)) != NULL) && (tobj != (Rt_map **)S_ERROR)) - call_fini(lml, tobj); - - /* - * Add an explicit close to main and ld.so.1. Although main's .fini is - * collected in call_fini() to provide for FINITARRAY processing, its - * audit_objclose is explicitly skipped. This provides for it to be - * called last, here. This is the reverse of the explicit calls to - * audit_objopen() made in setup(). - */ - if ((lml->lm_tflags | AFLAGS(lmp)) & LML_TFLG_AUD_MASK) { - audit_objclose(lmp, (Rt_map *)lml_rtld.lm_head); - audit_objclose(lmp, lmp); - } + call_fini(lml, tobj, NULL); /* * Now that all .fini code has been run, see what unreferenced objects @@ -916,18 +869,17 @@ unused(lml); /* - * Traverse any alternative link-map lists. + * Traverse any alternative link-map lists, looking for non-auditors. */ for (APLIST_TRAVERSE(dynlm_list, idx, lml)) { /* * Ignore the base-link-map list, which has already been - * processed, and the runtime linkers link-map list, which is - * typically processed last. + * processed, the runtime linkers link-map list, which is + * processed last, and any auditors. */ - if (lml->lm_flags & (LML_FLG_BASELM | LML_FLG_RTLDLM)) - continue; - - if ((lmp = (Rt_map *)lml->lm_head) == NULL) + if ((lml->lm_flags & (LML_FLG_BASELM | LML_FLG_RTLDLM)) || + (lml->lm_tflags & LML_TFLG_AUD_MASK) || + ((lmp = (Rt_map *)lml->lm_head) == NULL)) continue; lml->lm_flags |= LML_FLG_ATEXIT; @@ -938,7 +890,49 @@ */ if (((tobj = tsort(lmp, lml->lm_obj, RT_SORT_FWD)) != NULL) && (tobj != (Rt_map **)S_ERROR)) - call_fini(lml, tobj); + call_fini(lml, tobj, NULL); + + unused(lml); + } + + /* + * Add an explicit close to main and ld.so.1. Although main's .fini is + * collected in call_fini() to provide for FINITARRAY processing, its + * audit_objclose is explicitly skipped. This provides for it to be + * called last, here. This is the reverse of the explicit calls to + * audit_objopen() made in setup(). + */ + lml = &lml_main; + lmp = (Rt_map *)lml->lm_head; + + if ((lml->lm_tflags | AFLAGS(lmp)) & LML_TFLG_AUD_MASK) { + audit_objclose((Rt_map *)lml_rtld.lm_head, lmp); + audit_objclose(lmp, lmp); + } + + /* + * Traverse any alternative link-map lists, looking for non-auditors. + */ + for (APLIST_TRAVERSE(dynlm_list, idx, lml)) { + /* + * Ignore the base-link-map list, which has already been + * processed, the runtime linkers link-map list, which is + * processed last, and any non-auditors. + */ + if ((lml->lm_flags & (LML_FLG_BASELM | LML_FLG_RTLDLM)) || + ((lml->lm_tflags & LML_TFLG_AUD_MASK) == 0) || + ((lmp = (Rt_map *)lml->lm_head) == NULL)) + continue; + + lml->lm_flags |= LML_FLG_ATEXIT; + lml->lm_flags &= ~LML_FLG_INTRPOSETSORT; + + /* + * Reverse topologically sort the link-map for .fini execution. + */ + if (((tobj = tsort(lmp, lml->lm_obj, RT_SORT_FWD)) != NULL) && + (tobj != (Rt_map **)S_ERROR)) + call_fini(lml, tobj, NULL); unused(lml); } @@ -954,7 +948,7 @@ if (((tobj = tsort(lmp, lml->lm_obj, RT_SORT_FWD)) != NULL) && (tobj != (Rt_map **)S_ERROR)) - call_fini(lml, tobj); + call_fini(lml, tobj, NULL); leave(&lml_main, 0); } @@ -1046,15 +1040,15 @@ (lml->lm_obj)++; /* - * If we're about to add a new object to the main link-map control list, - * alert the debuggers that we are about to mess with this list. - * Additions of individual objects to the main link-map control list - * occur during initial setup as the applications immediate dependencies - * are loaded. Individual objects are also loaded on the main link-map - * control list of new alternative link-map control lists. + * If we're about to add a new object to the main link-map control + * list, alert the debuggers. Additions of individual objects to the + * main link-map control list occur during initial setup as the + * applications immediate dependencies are loaded. Additional objects + * are loaded on the main link-map control list after they have been + * fully initialized on an alternative link-map control list. See + * lm_move(). */ - if ((lmco == ALIST_OFF_DATA) && - ((lml->lm_flags & LML_FLG_DBNOTIF) == 0)) + if (lmco == ALIST_OFF_DATA) rd_event(lml, RD_DLACTIVITY, RT_ADD); /* LINTED */ @@ -1162,7 +1156,7 @@ * Delete an item from the specified link map control list. */ void -lm_delete(Lm_list *lml, Rt_map *lmp) +lm_delete(Lm_list *lml, Rt_map *lmp, Rt_map *clmp) { Lm_cntl *lmc; @@ -1175,12 +1169,19 @@ /* * If we're about to delete an object from the main link-map control - * list, alert the debuggers that we are about to mess with this list. + * list, alert the debuggers. */ - if ((CNTL(lmp) == ALIST_OFF_DATA) && - ((lml->lm_flags & LML_FLG_DBNOTIF) == 0)) + if (CNTL(lmp) == ALIST_OFF_DATA) rd_event(lml, RD_DLACTIVITY, RT_DELETE); + /* + * If we're being audited tell the audit library that we're + * about to go deleting dependencies. + */ + if (clmp && (aud_activity || + ((LIST(clmp)->lm_tflags | AFLAGS(clmp)) & LML_TFLG_AUD_ACTIVITY))) + audit_activity(clmp, LA_ACT_DELETE); + /* LINTED */ lmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, CNTL(lmp)); @@ -1222,12 +1223,11 @@ /* * If we're about to add a new family of objects to the main link-map - * control list, alert the debuggers that we are about to mess with this - * list. Additions of object families to the main link-map control - * list occur during lazy loading, filtering and dlopen(). + * control list, alert the debuggers. Additions of object families to + * the main link-map control list occur during lazy loading, filtering + * and dlopen(). */ - if ((plmco == ALIST_OFF_DATA) && - ((lml->lm_flags & LML_FLG_DBNOTIF) == 0)) + if (plmco == ALIST_OFF_DATA) rd_event(lml, RD_DLACTIVITY, RT_ADD); DBG_CALL(Dbg_file_cntl(lml, nlmco, plmco)); @@ -1526,8 +1526,10 @@ } else if ((len == MSG_LD_CONFGEN_SIZE) && (strncmp(s1, MSG_ORIG(MSG_LD_CONFGEN), MSG_LD_CONFGEN_SIZE) == 0)) { /* - * Set by crle(1) to indicate it's building a - * configuration file, not documented for general use. + * This variable is not documented for general use. + * Although originaly designed for internal use with + * crle(1), this variable is in use by the Studio + * auditing tools. Hence, it can't be removed. */ select |= SEL_ACT_SPEC_2; variable = ENV_FLG_CONFGEN; @@ -1625,8 +1627,10 @@ } else if ((len == MSG_LD_LOADAVAIL_SIZE) && (strncmp(s1, MSG_ORIG(MSG_LD_LOADAVAIL), MSG_LD_LOADAVAIL_SIZE) == 0)) { /* - * Internal use by crle(1), not documented for general - * use. + * This variable is not documented for general use. + * Although originaly designed for internal use with + * crle(1), this variable is in use by the Studio + * auditing tools. Hence, it can't be removed. */ select |= SEL_ACT_LML; val = LML_FLG_LOADAVAIL; @@ -2892,7 +2896,7 @@ prf.pr_buf = prf.pr_cur = nextptr; prf.pr_len = ERRSIZE - (nextptr - errbuf); - if (!(rtld_flags & RT_FL_APPLIC)) + if ((rtld_flags & RT_FL_APPLIC) == 0) prf.pr_fd = 2; else prf.pr_fd = -1; @@ -3348,33 +3352,23 @@ /* * Generic cleanup routine called prior to returning control to the user. - * Insures that any ld.so.1 specific file descriptors or temporary mapping are + * Ensures that any ld.so.1 specific file descriptors or temporary mapping are * released, and any locks dropped. */ void leave(Lm_list *lml, int flags) { - Lm_list *elml = lml; - Rt_map *clmp; - Aliste idx; - /* - * Alert the debuggers that the link-maps are consistent. Note, in the - * case of tearing down a whole link-map list, lml will be null. In - * this case use the main link-map list to test for a notification. + * Alert the debuggers that the link-maps are consistent. */ - if (elml == NULL) - elml = &lml_main; - if (elml->lm_flags & LML_FLG_DBNOTIF) - rd_event(elml, RD_DLACTIVITY, RT_CONSISTENT); + rd_event(lml, RD_DLACTIVITY, RT_CONSISTENT); /* * Alert any auditors that the link-maps are consistent. */ - for (APLIST_TRAVERSE(elml->lm_actaudit, idx, clmp)) { - audit_activity(clmp, LA_ACT_CONSISTENT); - - aplist_delete(elml->lm_actaudit, &idx); + if (lml->lm_flags & LML_FLG_ACTAUDIT) { + audit_activity(lml->lm_head, LA_ACT_CONSISTENT); + lml->lm_flags &= ~LML_FLG_ACTAUDIT; } if (nu_fd != FD_UNAVAIL) { @@ -3402,7 +3396,7 @@ * - The ld.so.1's link-map list. * - The auditor's link-map if the environment is pre-UPM. */ - if (lml && (lml->lm_flags & LML_FLG_HOLDLOCK)) + if (lml->lm_flags & LML_FLG_HOLDLOCK) return; if (rt_bind_clear(0) & THR_FLG_RTLD) {
--- a/usr/src/cmd/sgs/rtld/mdbmod/common/rtld.c Tue Jul 20 16:38:52 2010 -0400 +++ b/usr/src/cmd/sgs/rtld/mdbmod/common/rtld.c Tue Jul 20 16:29:51 2010 -0700 @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <msg.h> @@ -708,7 +707,6 @@ static const mdb_bitmask_t lml_flags_bit[] = { { MSG_ORIG(MSG_LFL_BASELM), LML_FLG_BASELM, LML_FLG_BASELM }, { MSG_ORIG(MSG_LFL_RTLDLM), LML_FLG_RTLDLM, LML_FLG_RTLDLM }, - { MSG_ORIG(MSG_LFL_NOAUDIT), LML_FLG_NOAUDIT, LML_FLG_NOAUDIT }, { MSG_ORIG(MSG_LFL_PLTREL), LML_FLG_PLTREL, LML_FLG_PLTREL }, { MSG_ORIG(MSG_LFL_HOLDLOCK), LML_FLG_HOLDLOCK, LML_FLG_HOLDLOCK }, { MSG_ORIG(MSG_LFL_ENVIRON), LML_FLG_ENVIRON, LML_FLG_ENVIRON }, @@ -716,7 +714,6 @@ { MSG_ORIG(MSG_LFL_LOCAUDIT), LML_FLG_LOCAUDIT, LML_FLG_LOCAUDIT }, { MSG_ORIG(MSG_LFL_LOADAVAIL), LML_FLG_LOADAVAIL, LML_FLG_LOADAVAIL }, { MSG_ORIG(MSG_LFL_IGNRELERR), LML_FLG_IGNRELERR, LML_FLG_IGNRELERR }, - { MSG_ORIG(MSG_LFL_DBNOTIF), LML_FLG_DBNOTIF, LML_FLG_DBNOTIF }, { MSG_ORIG(MSG_LFL_STARTREL), LML_FLG_STARTREL, LML_FLG_STARTREL }, { MSG_ORIG(MSG_LFL_ATEXIT), LML_FLG_ATEXIT, LML_FLG_ATEXIT }, { MSG_ORIG(MSG_LFL_OBJADDED), LML_FLG_OBJADDED, LML_FLG_OBJADDED }, @@ -753,6 +750,7 @@ static const mdb_bitmask_t lml_tflags_bit[] = { { MSG_ORIG(MSG_LTFL_NOLAZYLD), LML_TFLG_NOLAZYLD, LML_TFLG_NOLAZYLD }, { MSG_ORIG(MSG_LTFL_NODIRECT), LML_TFLG_NODIRECT, LML_TFLG_NODIRECT }, + { MSG_ORIG(MSG_LTFL_NOAUDIT), LML_TFLG_NOAUDIT, LML_TFLG_NOAUDIT }, { MSG_ORIG(MSG_LTFL_LOADFLTR), LML_TFLG_LOADFLTR, LML_TFLG_LOADFLTR }, { MSG_ORIG(MSG_LTFL_AUD_PREINIT), LML_TFLG_AUD_PREINIT,
--- a/usr/src/cmd/sgs/rtld/mdbmod/common/rtld.msg Tue Jul 20 16:38:52 2010 -0400 +++ b/usr/src/cmd/sgs/rtld/mdbmod/common/rtld.msg Tue Jul 20 16:29:51 2010 -0700 @@ -20,8 +20,7 @@ # # -# Copyright 2010 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. # @ _START_ @@ -145,7 +144,6 @@ @ MSG_LFL_BASELM "BASELM" @ MSG_LFL_RTLDLM "RTLDLM" -@ MSG_LFL_NOAUDIT "NO-AUDIT" @ MSG_LFL_PLTREL "DEFERRED-PLT-RELOCATION" @ MSG_LFL_HOLDLOCK "HOLD-LOCK" @ MSG_LFL_ENVIRON "ENVIRON" @@ -153,7 +151,6 @@ @ MSG_LFL_LOCAUDIT "LOCAL-AUDIT" @ MSG_LFL_LOADAVAIL "LOAD-AVAILABLE" @ MSG_LFL_IGNRELERR "IGNORE-RELOCATION-ERROR" -@ MSG_LFL_DBNOTIF "DBG-NOTIFY" @ MSG_LFL_STARTREL "START-RELOCATION" @ MSG_LFL_ATEXIT "ATEXIT" @ MSG_LFL_OBJADDED "OBJECT-ADDED" @@ -176,6 +173,7 @@ @ MSG_LTFL_NOLAZYLD "NO-LAZY-LOADING" @ MSG_LTFL_NODIRECT "NO-DIRECT" +@ MSG_LTFL_NOAUDIT "NO-AUDIT" @ MSG_LTFL_LOADFLTR "LOAD-FILTER" @ MSG_LTFL_AUD_PREINIT "AUD_PREINIT"
--- a/usr/src/head/link.h Tue Jul 20 16:38:52 2010 -0400 +++ b/usr/src/head/link.h Tue Jul 20 16:29:51 2010 -0700 @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _LINK_H @@ -126,8 +125,9 @@ #define LAV_VERSION2 2 #define LAV_VERSION3 3 #define LAV_VERSION4 4 -#define LAV_CURRENT LAV_VERSION4 -#define LAV_NUM 5 +#define LAV_VERSION5 5 +#define LAV_CURRENT LAV_VERSION5 +#define LAV_NUM 6 /* * Flags that can be or'd into the la_objopen() return code @@ -165,6 +165,7 @@ #define LA_ACT_CONSISTENT 0x00 /* add/deletion of objects complete */ #define LA_ACT_ADD 0x01 /* objects being added */ #define LA_ACT_DELETE 0x02 /* objects being deleted */ +#define LA_ACT_MAX 3 #ifndef _KERNEL