1*edb34883SAdam H. Leventhal /* 2*edb34883SAdam H. Leventhal * CDDL HEADER START 3*edb34883SAdam H. Leventhal * 4*edb34883SAdam H. Leventhal * This file and its contents are supplied under the terms of the 5*edb34883SAdam H. Leventhal * Common Development and Distribution License ("CDDL"), version 1.0. 6*edb34883SAdam H. Leventhal * You may only use this file in accordance with the terms of version 7*edb34883SAdam H. Leventhal * 1.0 of the CDDL. 8*edb34883SAdam H. Leventhal * 9*edb34883SAdam H. Leventhal * A full copy of the text of the CDDL should have accompanied this 10*edb34883SAdam H. Leventhal * source. A copy of the CDDL is also available via the Internet at 11*edb34883SAdam H. Leventhal * http://www.illumos.org/license/CDDL. 12*edb34883SAdam H. Leventhal * 13*edb34883SAdam H. Leventhal * CDDL HEADER END 14*edb34883SAdam H. Leventhal */ 15*edb34883SAdam H. Leventhal 16*edb34883SAdam H. Leventhal /* 17*edb34883SAdam H. Leventhal * Copyright (c) 2012 by Delphix. All rights reserved. 18*edb34883SAdam H. Leventhal */ 19*edb34883SAdam H. Leventhal 20*edb34883SAdam H. Leventhal /* 21*edb34883SAdam H. Leventhal * This file implements an audit library that can be used to force the loading 22*edb34883SAdam H. Leventhal * of helper providers. The default disposition for a helper provider -- USDT 23*edb34883SAdam H. Leventhal * and ustack helpers -- is to load itself from it's containing object's .init 24*edb34883SAdam H. Leventhal * section. In cases where startup time is deemed critical, USDT authors can 25*edb34883SAdam H. Leventhal * use the -xlazyload option to dtrace(1M) to disable automatic loading (it's 26*edb34883SAdam H. Leventhal * difficult to make the case for the utility of this feature for anything 27*edb34883SAdam H. Leventhal * other than libc which, indeed, was the sole motivation). If a binary has 28*edb34883SAdam H. Leventhal * been compiled with automatic loading disabled, this audit library may be 29*edb34883SAdam H. Leventhal * used to force automatic loading: 30*edb34883SAdam H. Leventhal * 31*edb34883SAdam H. Leventhal * LD_AUDIT_32=/usr/lib/dtrace/libdaudit.so 32*edb34883SAdam H. Leventhal * LD_AUDIT_64=/usr/lib/dtrace/64/libdaudit.so 33*edb34883SAdam H. Leventhal */ 34*edb34883SAdam H. Leventhal 35*edb34883SAdam H. Leventhal #include <link.h> 36*edb34883SAdam H. Leventhal #include <stdio.h> 37*edb34883SAdam H. Leventhal #include <libproc.h> 38*edb34883SAdam H. Leventhal #include <strings.h> 39*edb34883SAdam H. Leventhal 40*edb34883SAdam H. Leventhal #include <dlink.h> 41*edb34883SAdam H. Leventhal 42*edb34883SAdam H. Leventhal typedef struct obj_list { 43*edb34883SAdam H. Leventhal struct obj_list *ol_next; 44*edb34883SAdam H. Leventhal char *ol_name; 45*edb34883SAdam H. Leventhal uintptr_t ol_addr; 46*edb34883SAdam H. Leventhal Lmid_t ol_lmid; 47*edb34883SAdam H. Leventhal } obj_list_t; 48*edb34883SAdam H. Leventhal 49*edb34883SAdam H. Leventhal static obj_list_t *list; 50*edb34883SAdam H. Leventhal 51*edb34883SAdam H. Leventhal #pragma init(dtrace_daudit_init) 52*edb34883SAdam H. Leventhal static void 53*edb34883SAdam H. Leventhal dtrace_daudit_init(void) 54*edb34883SAdam H. Leventhal { 55*edb34883SAdam H. Leventhal dtrace_link_init(); 56*edb34883SAdam H. Leventhal } 57*edb34883SAdam H. Leventhal 58*edb34883SAdam H. Leventhal /*ARGSUSED*/ 59*edb34883SAdam H. Leventhal uint_t 60*edb34883SAdam H. Leventhal la_version(uint_t version) 61*edb34883SAdam H. Leventhal { 62*edb34883SAdam H. Leventhal return (LAV_CURRENT); 63*edb34883SAdam H. Leventhal } 64*edb34883SAdam H. Leventhal 65*edb34883SAdam H. Leventhal /* 66*edb34883SAdam H. Leventhal * Record objects into our linked list as they're loaded. 67*edb34883SAdam H. Leventhal */ 68*edb34883SAdam H. Leventhal /*ARGSUSED*/ 69*edb34883SAdam H. Leventhal uint_t 70*edb34883SAdam H. Leventhal la_objopen(Link_map *lmp, Lmid_t lmid, uintptr_t *cookie) 71*edb34883SAdam H. Leventhal { 72*edb34883SAdam H. Leventhal obj_list_t *node; 73*edb34883SAdam H. Leventhal 74*edb34883SAdam H. Leventhal /* 75*edb34883SAdam H. Leventhal * If we can't allocate the next node in our list, we'll try to emit a 76*edb34883SAdam H. Leventhal * message, but it's possible that might fail as well. 77*edb34883SAdam H. Leventhal */ 78*edb34883SAdam H. Leventhal if ((node = malloc(sizeof (obj_list_t))) == NULL) { 79*edb34883SAdam H. Leventhal dprintf(0, "libdaudit: failed to allocate"); 80*edb34883SAdam H. Leventhal return (0); 81*edb34883SAdam H. Leventhal } 82*edb34883SAdam H. Leventhal node->ol_next = list; 83*edb34883SAdam H. Leventhal node->ol_name = strdup(lmp->l_name); 84*edb34883SAdam H. Leventhal node->ol_addr = lmp->l_addr; 85*edb34883SAdam H. Leventhal node->ol_lmid = lmid; 86*edb34883SAdam H. Leventhal list = node; 87*edb34883SAdam H. Leventhal 88*edb34883SAdam H. Leventhal return (0); 89*edb34883SAdam H. Leventhal } 90*edb34883SAdam H. Leventhal 91*edb34883SAdam H. Leventhal /* 92*edb34883SAdam H. Leventhal * Once the link maps have reached a consistent state, process the list of 93*edb34883SAdam H. Leventhal * objects that were loaded. We need to use libproc to search for the 94*edb34883SAdam H. Leventhal * ___SUNW_dof symbol rather than dlsym(3C) since the symbol is not in the 95*edb34883SAdam H. Leventhal * dynamic (run-time) symbol table (though it is, of course, in the symtab). 96*edb34883SAdam H. Leventhal * Once we find it, we ioctl(2) it to the kernel just as we would have from 97*edb34883SAdam H. Leventhal * the .init section if automatic loading were enabled. 98*edb34883SAdam H. Leventhal */ 99*edb34883SAdam H. Leventhal /*ARGSUSED*/ 100*edb34883SAdam H. Leventhal void 101*edb34883SAdam H. Leventhal la_activity(uintptr_t *cookie, uint_t flags) 102*edb34883SAdam H. Leventhal { 103*edb34883SAdam H. Leventhal struct ps_prochandle *P; 104*edb34883SAdam H. Leventhal int err, ret; 105*edb34883SAdam H. Leventhal GElf_Sym sym; 106*edb34883SAdam H. Leventhal 107*edb34883SAdam H. Leventhal if (flags != LA_ACT_CONSISTENT) 108*edb34883SAdam H. Leventhal return; 109*edb34883SAdam H. Leventhal 110*edb34883SAdam H. Leventhal while (list != NULL) { 111*edb34883SAdam H. Leventhal obj_list_t *node = list; 112*edb34883SAdam H. Leventhal char *name = node->ol_name; 113*edb34883SAdam H. Leventhal 114*edb34883SAdam H. Leventhal list = node->ol_next; 115*edb34883SAdam H. Leventhal 116*edb34883SAdam H. Leventhal P = Pgrab(getpid(), PGRAB_RDONLY, &err); 117*edb34883SAdam H. Leventhal ret = Plookup_by_name(P, name, "___SUNW_dof", &sym); 118*edb34883SAdam H. Leventhal Prelease(P, 0); 119*edb34883SAdam H. Leventhal 120*edb34883SAdam H. Leventhal if (ret == 0) { 121*edb34883SAdam H. Leventhal dtrace_link_dof((void *)(uintptr_t)sym.st_value, 122*edb34883SAdam H. Leventhal node->ol_lmid, node->ol_name, node->ol_addr); 123*edb34883SAdam H. Leventhal } 124*edb34883SAdam H. Leventhal 125*edb34883SAdam H. Leventhal free(node->ol_name); 126*edb34883SAdam H. Leventhal free(node); 127*edb34883SAdam H. Leventhal } 128*edb34883SAdam H. Leventhal } 129