예제 #1
0
파일: audit.c 프로젝트: andreiw/polaris
/*
 * la_filter() caller.  Traverses through all audit libraries and call any
 * la_filter() entry points found.  A zero return from an auditor indicates
 * that the filtee should be ignored.
 */
static int
_audit_objfilter(List *list, Rt_map *frlmp, const char *ref, Rt_map *felmp,
    uint_t flags)
{
	Audit_list	*alp;
	Listnode	*lnp;

	for (LIST_TRAVERSE(list, lnp, alp)) {
		Audit_client	*fracp, *feacp;

		if (alp->al_objfilter == 0)
			continue;
		if ((fracp = _audit_client(AUDINFO(frlmp), alp->al_lmp)) == 0)
			continue;
		if ((feacp = _audit_client(AUDINFO(felmp), alp->al_lmp)) == 0)
			continue;

		leave(LIST(alp->al_lmp));
		if ((*alp->al_objfilter)(&(fracp->ac_cookie), ref,
		    &(feacp->ac_cookie), flags) == 0)
			return (0);
		(void) enter();
	}
	return (1);
}
예제 #2
0
파일: audit.c 프로젝트: andreiw/polaris
/*
 * la_pltexit() caller.  Traverses through all audit library and calls any
 * la_pltexit() entry points found.  See notes above (_audit_pltenter) for
 * discussion on st_name.
 */
static Addr
_audit_pltexit(List *list, uintptr_t retval, Rt_map *rlmp, Rt_map *dlmp,
    Sym *sym, uint_t ndx)
{
	Audit_list	*alp;
	Listnode	*lnp;
#if	defined(_ELF64)
	const char	*name = (const char *)(sym->st_name + STRTAB(dlmp));
#endif

	for (LIST_TRAVERSE(list, lnp, alp)) {
		Audit_client	*racp, *dacp;

		if (alp->al_pltexit == 0)
			continue;
		if ((racp = _audit_client(AUDINFO(rlmp), alp->al_lmp)) == 0)
			continue;
		if ((dacp = _audit_client(AUDINFO(dlmp), alp->al_lmp)) == 0)
			continue;
		if (((racp->ac_flags & FLG_AC_BINDFROM) == 0) ||
		    ((dacp->ac_flags & FLG_AC_BINDTO) == 0))
			continue;

		leave(LIST(alp->al_lmp));
		retval = (*alp->al_pltexit)(sym, ndx,
		    &(racp->ac_cookie), &(dacp->ac_cookie),
#if	defined(_ELF64)
		    retval, name);
#else
		    retval);
#endif
		(void) enter();
	}
	return (retval);
}
예제 #3
0
/*
 * la_activity() caller.  Traverse through all audit libraries and call any
 * la_activity() entry points found.
 */
static void
_audit_activity(APlist *list, Rt_map *clmp, uint_t flags, 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_activity == 0)
			continue;

		/*
		 * 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
		 * at a time.  This ensures the library doesn't see numerous
		 * events from lazy loading a series of libraries.  Keep track
		 * of this caller having called an auditor, so that the
		 * appropriate "consistent" event can be supplied on leaving
		 * ld.so.1.
		 */
		if ((flags == LA_ACT_ADD) || (flags == LA_ACT_DELETE)) {
			if (alml->lm_flags & LML_FLG_AUDITNOTIFY)
				continue;

			alml->lm_flags |= LML_FLG_AUDITNOTIFY;
			clml->lm_flags |= LML_FLG_ACTAUDIT;
		} else {
			if ((alml->lm_flags & LML_FLG_AUDITNOTIFY) == 0)
				continue;

			alml->lm_flags &= ~LML_FLG_AUDITNOTIFY;
		}

		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);
	}
}
예제 #4
0
파일: audit.c 프로젝트: andreiw/polaris
/*
 * la_pltenter() caller.  Traverses through all audit library and calls 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
 * pointer to the real symbol name (ie. it's already been adjusted with the
 * objects base offset).  For 64bit environments the st_name remains the
 * original symbol offset and in this case it is used to compute the real name
 * pointer and pass as a separate argument to the auditor.
 */
static void
_audit_pltenter(List *list, Rt_map *rlmp, Rt_map *dlmp, Sym *sym,
    uint_t ndx, void *regs, uint_t *flags)
{
	Audit_list	*alp;
	Listnode	*lnp;
#if	defined(_ELF64)
	const char	*name = (const char *)(sym->st_name + STRTAB(dlmp));
#else
	const char	*name = (const char *)(sym->st_name);
#endif

	for (LIST_TRAVERSE(list, lnp, alp)) {
		Audit_client	*racp, *dacp;
		Addr		prev = sym->st_value;

		if (alp->al_pltenter == 0)
			continue;
		if ((racp = _audit_client(AUDINFO(rlmp), alp->al_lmp)) == 0)
			continue;
		if ((dacp = _audit_client(AUDINFO(dlmp), alp->al_lmp)) == 0)
			continue;
		if (((racp->ac_flags & FLG_AC_BINDFROM) == 0) ||
		    ((dacp->ac_flags & FLG_AC_BINDTO) == 0))
			continue;

		leave(LIST(alp->al_lmp));
		sym->st_value = (Addr)(*alp->al_pltenter)(sym, ndx,
		    &(racp->ac_cookie), &(dacp->ac_cookie), regs,
#if	defined(_ELF64)
		    flags, name);
#else
		    flags);
#endif
		(void) enter();

		DBG_CALL(Dbg_audit_symval(LIST(alp->al_lmp), alp->al_libname,
		    MSG_ORIG(MSG_AUD_PLTENTER), name, prev, sym->st_name));
	}
}
예제 #5
0
/*
 * la_filter() caller.  Traverse through all audit libraries and call any
 * la_filter() entry points found.  A zero return from an auditor indicates
 * that the filtee should be ignored.
 */
static int
_audit_objfilter(APlist *list, Rt_map *frlmp, const char *ref, Rt_map *felmp,
    uint_t flags)
{
	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), almp)) == NULL)
			continue;
		if ((feacp = _audit_client(AUDINFO(felmp), almp)) == NULL)
			continue;

		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) {
			DBG_CALL(Dbg_audit_objfilter(frlml, DBG_AUD_RET,
			    alp->al_libname, NAME(frlmp), NULL, NULL));
			return (0);
		}
	}
	return (1);
}
예제 #6
0
파일: audit.c 프로젝트: andreiw/polaris
/*
 * la_preinit() caller.  Traverses through all audit libraries and calls any
 * la_preinit() entry points found.
 */
static void
_audit_preinit(List *list, Rt_map *clmp)
{
	Audit_list	*alp;
	Listnode	*lnp;

	for (LIST_TRAVERSE(list, lnp, alp)) {
		Audit_client	*acp;

		if (alp->al_preinit == 0)
			continue;
		if ((acp = _audit_client(AUDINFO(clmp), alp->al_lmp)) == 0)
			continue;

		leave(LIST(alp->al_lmp));
		(*alp->al_preinit)(&(acp->ac_cookie));
		(void) enter();
	}
}
예제 #7
0
파일: audit.c 프로젝트: andreiw/polaris
/*
 * la_objclose() caller.  Traverses through all audit library and calls any
 * la_objclose() entry points found.
 */
void
_audit_objclose(List * list, Rt_map * lmp)
{
	Audit_list *	alp;
	Listnode *	lnp;

	for (LIST_TRAVERSE(list, lnp, alp)) {
		Audit_client *	acp;

		if (alp->al_objclose == 0)
			continue;
		if ((acp = _audit_client(AUDINFO(lmp), alp->al_lmp)) == 0)
			continue;

		leave(LIST(alp->al_lmp));
		(*alp->al_objclose)(&(acp->ac_cookie));
		(void) enter();
	}
}
예제 #8
0
파일: audit.c 프로젝트: andreiw/polaris
/*
 * la_activity() caller.  Traverses through all audit library and calls any
 * la_activity() entry points found.
 */
static void
_audit_activity(List * list, Rt_map * clmp, uint_t flags)
{
	Audit_list *	alp;
	Listnode *	lnp;

	for (LIST_TRAVERSE(list, lnp, alp)) {
		Audit_client *	acp;

		if (alp->al_activity == 0)
			continue;
		if ((acp = _audit_client(AUDINFO(clmp), alp->al_lmp)) == 0)
			continue;

		leave(LIST(alp->al_lmp));
		(*alp->al_activity)(&(acp->ac_cookie), flags);
		(void) enter();
	}
}
예제 #9
0
/*
 * la_objsearch() caller.  Traverse through all audit libraries and call any
 * la_objsearch() entry points found.
 *
 * Effectively any audit library can change the name we're working with, so we
 * continue to propagate the new name to each audit library.  Any 0 return
 * terminates the search.
 */
static char *
_audit_objsearch(APlist *list, char *oname, Rt_map *clmp, uint_t flags)
{
	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);
		char		*nname = oname;

		if (alp->al_objsearch == NULL)
			continue;
		if ((acp = _audit_client(AUDINFO(clmp), almp)) == NULL)
			continue;

		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);

		/*
		 * 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 (oname);
}
예제 #10
0
파일: audit.c 프로젝트: andreiw/polaris
/*
 * la_objsearch() caller.  Traverses through all audit libraries and call any
 * la_objsearch() entry points found.
 *
 * Effectively any audit library can change the name we're working with, so we
 * continue to propagate the new name to each audit library.  Any 0 return
 * terminates the search.
 */
static char *
_audit_objsearch(List *list, char *name, Rt_map *clmp, uint_t flags)
{
	Audit_list	*alp;
	Listnode	*lnp;
	char		*nname = (char *)name;

	for (LIST_TRAVERSE(list, lnp, alp)) {
		Audit_client	*acp;

		if (alp->al_objsearch == 0)
			continue;
		if ((acp = _audit_client(AUDINFO(clmp), alp->al_lmp)) == 0)
			continue;

		leave(LIST(alp->al_lmp));
		nname = (*alp->al_objsearch)(nname, &(acp->ac_cookie), flags);
		(void) enter();
		if (nname == 0)
			break;
	}
	return (nname);
}
예제 #11
0
/*
 * la_objclose() caller.  Traverse through all audit libraries and call any
 * la_objclose() entry points found.
 */
void
_audit_objclose(APlist *list, Rt_map *lmp)
{
	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), almp)) == NULL)
			continue;

		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);
	}
}
예제 #12
0
파일: audit.c 프로젝트: andreiw/polaris
/*
 * la_symbind() caller.  Traverses through all audit library and calls any
 * la_symbind() entry points found.
 */
static Addr
_audit_symbind(List *list, Rt_map *rlmp, Rt_map *dlmp, Sym *sym, uint_t ndx,
    uint_t *flags, int *called)
{
	Audit_list	*alp;
	Listnode	*lnp;
#if	defined(_ELF64)
	const char	*name = (const char *)(sym->st_name + STRTAB(dlmp));
#else
	const char	*name = (const char *)(sym->st_name);
#endif

	for (LIST_TRAVERSE(list, lnp, alp)) {
		Audit_client	*racp, *dacp;
		Addr		prev = sym->st_value;
		uint_t		lflags;

		if (alp->al_symbind == 0)
			continue;
		if ((racp = _audit_client(AUDINFO(rlmp), alp->al_lmp)) == 0)
			continue;
		if ((dacp = _audit_client(AUDINFO(dlmp), alp->al_lmp)) == 0)
			continue;
		if (((racp->ac_flags & FLG_AC_BINDFROM) == 0) ||
		    ((dacp->ac_flags & FLG_AC_BINDTO) == 0))
			continue;

		/*
		 * The la_symbind interface is only called when the calling
		 * object has been identified as BINDFROM, and the destination
		 * 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));

		leave(LIST(alp->al_lmp));
		sym->st_value = (*alp->al_symbind)(sym, ndx,
		    &(racp->ac_cookie), &(dacp->ac_cookie),
#if	defined(_ELF64)
		    &lflags, name);
#else
		    &lflags);
#endif
		(void) enter();

		/*
		 * If the auditor indicated that they did not want to process
		 * pltenter, or pltexit audits for this symbol, retain this
		 * information.  Also retain whether an alternative symbol value
		 * has been supplied.
		 */
		*flags |= (lflags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT));
		if ((prev != 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));
	}
	return (sym->st_value);
}