125537Sdfr/*- 259603Sdfr * Copyright (c) 1997-2000 Doug Rabson 325537Sdfr * All rights reserved. 425537Sdfr * 525537Sdfr * Redistribution and use in source and binary forms, with or without 625537Sdfr * modification, are permitted provided that the following conditions 725537Sdfr * are met: 825537Sdfr * 1. Redistributions of source code must retain the above copyright 925537Sdfr * notice, this list of conditions and the following disclaimer. 1025537Sdfr * 2. Redistributions in binary form must reproduce the above copyright 1125537Sdfr * notice, this list of conditions and the following disclaimer in the 1225537Sdfr * documentation and/or other materials provided with the distribution. 1325537Sdfr * 1425537Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1525537Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1625537Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1725537Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1825537Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1925537Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2025537Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2125537Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2225537Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2325537Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2425537Sdfr * SUCH DAMAGE. 2525537Sdfr */ 2625537Sdfr 27116182Sobrien#include <sys/cdefs.h> 28116182Sobrien__FBSDID("$FreeBSD: stable/10/sys/kern/kern_linker.c 355419 2019-12-05 14:53:46Z hselasky $"); 29116182Sobrien 3040159Speter#include "opt_ddb.h" 31227151Sfjoe#include "opt_kld.h" 32157144Sjkoshy#include "opt_hwpmc_hooks.h" 3340159Speter 3425537Sdfr#include <sys/param.h> 3525537Sdfr#include <sys/kernel.h> 3625537Sdfr#include <sys/systm.h> 3725537Sdfr#include <sys/malloc.h> 3825537Sdfr#include <sys/sysproto.h> 3925537Sdfr#include <sys/sysent.h> 40164033Srwatson#include <sys/priv.h> 4125537Sdfr#include <sys/proc.h> 4225537Sdfr#include <sys/lock.h> 4382749Sdillon#include <sys/mutex.h> 4492547Sarr#include <sys/sx.h> 4525537Sdfr#include <sys/module.h> 46159808Sjhb#include <sys/mount.h> 4725537Sdfr#include <sys/linker.h> 48254266Smarkj#include <sys/eventhandler.h> 4940159Speter#include <sys/fcntl.h> 50192895Sjamie#include <sys/jail.h> 5140159Speter#include <sys/libkern.h> 5240159Speter#include <sys/namei.h> 5340159Speter#include <sys/vnode.h> 54159588Sjhb#include <sys/syscallsubr.h> 5540159Speter#include <sys/sysctl.h> 5625537Sdfr 57196019Srwatson#include <net/vnet.h> 58196019Srwatson 59163606Srwatson#include <security/mac/mac_framework.h> 60163606Srwatson 6159603Sdfr#include "linker_if.h" 6259603Sdfr 63157144Sjkoshy#ifdef HWPMC_HOOKS 64157144Sjkoshy#include <sys/pmckern.h> 65157144Sjkoshy#endif 66157144Sjkoshy 6740961Speter#ifdef KLD_DEBUG 6840961Speterint kld_debug = 0; 69232999SaeSYSCTL_INT(_debug, OID_AUTO, kld_debug, CTLFLAG_RW | CTLFLAG_TUN, 70232999Sae &kld_debug, 0, "Set various levels of KLD debug"); 71232997SaeTUNABLE_INT("debug.kld_debug", &kld_debug); 7240961Speter#endif 7340961Speter 74294283Sjhb/* These variables are used by kernel debuggers to enumerate loaded files. */ 75294283Sjhbconst int kld_off_address = offsetof(struct linker_file, address); 76294283Sjhbconst int kld_off_filename = offsetof(struct linker_file, filename); 77294283Sjhbconst int kld_off_pathname = offsetof(struct linker_file, pathname); 78294283Sjhbconst int kld_off_next = offsetof(struct linker_file, link.tqe_next); 79294283Sjhb 8091040Sarr/* 8191040Sarr * static char *linker_search_path(const char *name, struct mod_depend 8291040Sarr * *verinfo); 8391040Sarr */ 8491040Sarrstatic const char *linker_basename(const char *path); 8559751Speter 86159800Sjhb/* 87159800Sjhb * Find a currently loaded file given its filename. 88159800Sjhb */ 89159800Sjhbstatic linker_file_t linker_find_file_by_name(const char* _filename); 90159800Sjhb 91159800Sjhb/* 92159800Sjhb * Find a currently loaded file given its file id. 93159800Sjhb */ 94159800Sjhbstatic linker_file_t linker_find_file_by_id(int _fileid); 95159800Sjhb 9678161Speter/* Metadata from the static kernel */ 9778161SpeterSET_DECLARE(modmetadata_set, struct mod_metadata); 9878161Speter 9959751SpeterMALLOC_DEFINE(M_LINKER, "linker", "kernel linker"); 10059751Speter 10140906Speterlinker_file_t linker_kernel_file; 10231324Sbde 103159845Sjhbstatic struct sx kld_sx; /* kernel linker lock */ 10498452Sarr 105172862Sjb/* 106172862Sjb * Load counter used by clients to determine if a linker file has been 107172862Sjb * re-loaded. This counter is incremented for each file load. 108172862Sjb */ 109172862Sjbstatic int loadcnt; 110172862Sjb 11125537Sdfrstatic linker_class_list_t classes; 11250068Sgrogstatic linker_file_list_t linker_files; 11325537Sdfrstatic int next_file_id = 1; 11498452Sarrstatic int linker_no_more_classes = 0; 11525537Sdfr 11686553Sarr#define LINKER_GET_NEXT_FILE_ID(a) do { \ 11791040Sarr linker_file_t lftmp; \ 11886553Sarr \ 119254810Smarkj if (!cold) \ 120254810Smarkj sx_assert(&kld_sx, SA_XLOCKED); \ 12186553Sarrretry: \ 12291040Sarr TAILQ_FOREACH(lftmp, &linker_files, link) { \ 12391040Sarr if (next_file_id == lftmp->id) { \ 12491040Sarr next_file_id++; \ 12591040Sarr goto retry; \ 12691040Sarr } \ 12791040Sarr } \ 12891040Sarr (a) = next_file_id; \ 12986553Sarr} while(0) 13086553Sarr 13186553Sarr 13259751Speter/* XXX wrong name; we're looking at version provision tags here, not modules */ 13360938Sjaketypedef TAILQ_HEAD(, modlist) modlisthead_t; 13459751Speterstruct modlist { 13591040Sarr TAILQ_ENTRY(modlist) link; /* chain together all modules */ 13691040Sarr linker_file_t container; 13791040Sarr const char *name; 13891040Sarr int version; 13959751Speter}; 14091040Sarrtypedef struct modlist *modlist_t; 14191040Sarrstatic modlisthead_t found_modules; 14259751Speter 143159796Sjhbstatic int linker_file_add_dependency(linker_file_t file, 144159796Sjhb linker_file_t dep); 145159845Sjhbstatic caddr_t linker_file_lookup_symbol_internal(linker_file_t file, 146159845Sjhb const char* name, int deps); 147159796Sjhbstatic int linker_load_module(const char *kldname, 148159796Sjhb const char *modname, struct linker_file *parent, 149159796Sjhb struct mod_depend *verinfo, struct linker_file **lfpp); 150159796Sjhbstatic modlist_t modlist_lookup2(const char *name, struct mod_depend *verinfo); 15194321Sbrian 15225537Sdfrstatic void 15391040Sarrlinker_init(void *arg) 15425537Sdfr{ 15591040Sarr 156159845Sjhb sx_init(&kld_sx, "kernel linker"); 15791040Sarr TAILQ_INIT(&classes); 15891040Sarr TAILQ_INIT(&linker_files); 15925537Sdfr} 16025537Sdfr 161177253SrwatsonSYSINIT(linker, SI_SUB_KLD, SI_ORDER_FIRST, linker_init, 0); 16225537Sdfr 16398452Sarrstatic void 16498452Sarrlinker_stop_class_add(void *arg) 16598452Sarr{ 16698452Sarr 16798452Sarr linker_no_more_classes = 1; 16898452Sarr} 16998452Sarr 170177253SrwatsonSYSINIT(linker_class, SI_SUB_KLD, SI_ORDER_ANY, linker_stop_class_add, NULL); 17198452Sarr 17225537Sdfrint 17359603Sdfrlinker_add_class(linker_class_t lc) 17425537Sdfr{ 17591040Sarr 17698452Sarr /* 177144443Sjhb * We disallow any class registration past SI_ORDER_ANY 178144443Sjhb * of SI_SUB_KLD. We bump the reference count to keep the 179144443Sjhb * ops from being freed. 18098452Sarr */ 18198452Sarr if (linker_no_more_classes == 1) 18298452Sarr return (EPERM); 18391040Sarr kobj_class_compile((kobj_class_t) lc); 184144443Sjhb ((kobj_class_t)lc)->refs++; /* XXX: kobj_mtx */ 18591040Sarr TAILQ_INSERT_TAIL(&classes, lc, link); 18691040Sarr return (0); 18725537Sdfr} 18825537Sdfr 18925537Sdfrstatic void 19025537Sdfrlinker_file_sysinit(linker_file_t lf) 19125537Sdfr{ 19291040Sarr struct sysinit **start, **stop, **sipp, **xipp, *save; 19325537Sdfr 19491040Sarr KLD_DPF(FILE, ("linker_file_sysinit: calling SYSINITs for %s\n", 19591040Sarr lf->filename)); 19625537Sdfr 197254811Smarkj sx_assert(&kld_sx, SA_XLOCKED); 198254811Smarkj 19991040Sarr if (linker_file_lookup_set(lf, "sysinit_set", &start, &stop, NULL) != 0) 20091040Sarr return; 20191040Sarr /* 20291040Sarr * Perform a bubble sort of the system initialization objects by 20391040Sarr * their subsystem (primary key) and order (secondary key). 204159840Sjhb * 20591040Sarr * Since some things care about execution order, this is the operation 20691040Sarr * which ensures continued function. 20791040Sarr */ 20891040Sarr for (sipp = start; sipp < stop; sipp++) { 20991040Sarr for (xipp = sipp + 1; xipp < stop; xipp++) { 21091040Sarr if ((*sipp)->subsystem < (*xipp)->subsystem || 21191040Sarr ((*sipp)->subsystem == (*xipp)->subsystem && 21291040Sarr (*sipp)->order <= (*xipp)->order)) 21391040Sarr continue; /* skip */ 21491040Sarr save = *sipp; 21591040Sarr *sipp = *xipp; 21691040Sarr *xipp = save; 21791040Sarr } 21825537Sdfr } 21925537Sdfr 22091040Sarr /* 22191040Sarr * Traverse the (now) ordered list of system initialization tasks. 22291040Sarr * Perform each task, and continue on to the next task. 22391040Sarr */ 224254811Smarkj sx_xunlock(&kld_sx); 225160142Sjhb mtx_lock(&Giant); 22691040Sarr for (sipp = start; sipp < stop; sipp++) { 22791040Sarr if ((*sipp)->subsystem == SI_SUB_DUMMY) 22891040Sarr continue; /* skip dummy task(s) */ 22925537Sdfr 23091040Sarr /* Call function */ 23191040Sarr (*((*sipp)->func)) ((*sipp)->udata); 23291040Sarr } 233160142Sjhb mtx_unlock(&Giant); 234254811Smarkj sx_xlock(&kld_sx); 23525537Sdfr} 23625537Sdfr 23741055Speterstatic void 23841055Speterlinker_file_sysuninit(linker_file_t lf) 23941055Speter{ 24091040Sarr struct sysinit **start, **stop, **sipp, **xipp, *save; 24141055Speter 24291040Sarr KLD_DPF(FILE, ("linker_file_sysuninit: calling SYSUNINITs for %s\n", 24391040Sarr lf->filename)); 24441055Speter 245254811Smarkj sx_assert(&kld_sx, SA_XLOCKED); 246254811Smarkj 24791068Sarr if (linker_file_lookup_set(lf, "sysuninit_set", &start, &stop, 24891040Sarr NULL) != 0) 24991040Sarr return; 25041055Speter 25191040Sarr /* 25291040Sarr * Perform a reverse bubble sort of the system initialization objects 25391040Sarr * by their subsystem (primary key) and order (secondary key). 254159840Sjhb * 25591040Sarr * Since some things care about execution order, this is the operation 25691040Sarr * which ensures continued function. 25791040Sarr */ 25891040Sarr for (sipp = start; sipp < stop; sipp++) { 25991040Sarr for (xipp = sipp + 1; xipp < stop; xipp++) { 26091040Sarr if ((*sipp)->subsystem > (*xipp)->subsystem || 26191040Sarr ((*sipp)->subsystem == (*xipp)->subsystem && 26291040Sarr (*sipp)->order >= (*xipp)->order)) 26391040Sarr continue; /* skip */ 26491040Sarr save = *sipp; 26591040Sarr *sipp = *xipp; 26691040Sarr *xipp = save; 26791040Sarr } 26841055Speter } 26941055Speter 27091040Sarr /* 27191040Sarr * Traverse the (now) ordered list of system initialization tasks. 27291040Sarr * Perform each task, and continue on to the next task. 27391040Sarr */ 274254811Smarkj sx_xunlock(&kld_sx); 275160142Sjhb mtx_lock(&Giant); 27691040Sarr for (sipp = start; sipp < stop; sipp++) { 27791040Sarr if ((*sipp)->subsystem == SI_SUB_DUMMY) 27891040Sarr continue; /* skip dummy task(s) */ 27941055Speter 28091040Sarr /* Call function */ 28191040Sarr (*((*sipp)->func)) ((*sipp)->udata); 28291040Sarr } 283160142Sjhb mtx_unlock(&Giant); 284254811Smarkj sx_xlock(&kld_sx); 28541055Speter} 28641055Speter 28744078Sdfrstatic void 288324749Savglinker_file_register_sysctls(linker_file_t lf, bool enable) 28944078Sdfr{ 29091040Sarr struct sysctl_oid **start, **stop, **oidp; 29144078Sdfr 29291040Sarr KLD_DPF(FILE, 29391040Sarr ("linker_file_register_sysctls: registering SYSCTLs for %s\n", 29491040Sarr lf->filename)); 29544078Sdfr 296254811Smarkj sx_assert(&kld_sx, SA_XLOCKED); 297254811Smarkj 29891040Sarr if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0) 29991040Sarr return; 30044078Sdfr 301254811Smarkj sx_xunlock(&kld_sx); 302188232Sjhb sysctl_lock(); 303324749Savg for (oidp = start; oidp < stop; oidp++) { 304324749Savg if (enable) 305324749Savg sysctl_register_oid(*oidp); 306324749Savg else 307324749Savg sysctl_register_disabled_oid(*oidp); 308324749Savg } 309324749Savg sysctl_unlock(); 310324749Savg sx_xlock(&kld_sx); 311324749Savg} 312324749Savg 313324749Savgstatic void 314324749Savglinker_file_enable_sysctls(linker_file_t lf) 315324749Savg{ 316324749Savg struct sysctl_oid **start, **stop, **oidp; 317324749Savg 318324749Savg KLD_DPF(FILE, 319324749Savg ("linker_file_enable_sysctls: enable SYSCTLs for %s\n", 320324749Savg lf->filename)); 321324749Savg 322324749Savg sx_assert(&kld_sx, SA_XLOCKED); 323324749Savg 324324749Savg if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0) 325324749Savg return; 326324749Savg 327324749Savg sx_xunlock(&kld_sx); 328324749Savg sysctl_lock(); 32991040Sarr for (oidp = start; oidp < stop; oidp++) 330324749Savg sysctl_enable_oid(*oidp); 331188232Sjhb sysctl_unlock(); 332254811Smarkj sx_xlock(&kld_sx); 33344078Sdfr} 33444078Sdfr 33544078Sdfrstatic void 33644078Sdfrlinker_file_unregister_sysctls(linker_file_t lf) 33744078Sdfr{ 33891040Sarr struct sysctl_oid **start, **stop, **oidp; 33944078Sdfr 340233295Sae KLD_DPF(FILE, ("linker_file_unregister_sysctls: unregistering SYSCTLs" 34191040Sarr " for %s\n", lf->filename)); 34244078Sdfr 343254811Smarkj sx_assert(&kld_sx, SA_XLOCKED); 344254811Smarkj 34591040Sarr if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0) 34691040Sarr return; 34744078Sdfr 348254811Smarkj sx_xunlock(&kld_sx); 349188232Sjhb sysctl_lock(); 35091040Sarr for (oidp = start; oidp < stop; oidp++) 35191040Sarr sysctl_unregister_oid(*oidp); 352188232Sjhb sysctl_unlock(); 353254811Smarkj sx_xlock(&kld_sx); 35444078Sdfr} 35544078Sdfr 35659751Speterstatic int 35759751Speterlinker_file_register_modules(linker_file_t lf) 35859751Speter{ 35991040Sarr struct mod_metadata **start, **stop, **mdp; 36091040Sarr const moduledata_t *moddata; 361146733Spjd int first_error, error; 36259751Speter 36391040Sarr KLD_DPF(FILE, ("linker_file_register_modules: registering modules" 36491040Sarr " in %s\n", lf->filename)); 36559751Speter 366254811Smarkj sx_assert(&kld_sx, SA_XLOCKED); 367254811Smarkj 36891068Sarr if (linker_file_lookup_set(lf, "modmetadata_set", &start, 369159841Sjhb &stop, NULL) != 0) { 37091040Sarr /* 37191040Sarr * This fallback should be unnecessary, but if we get booted 37291040Sarr * from boot2 instead of loader and we are missing our 37391040Sarr * metadata then we have to try the best we can. 37491040Sarr */ 37591040Sarr if (lf == linker_kernel_file) { 37691040Sarr start = SET_BEGIN(modmetadata_set); 37791040Sarr stop = SET_LIMIT(modmetadata_set); 37891040Sarr } else 37991040Sarr return (0); 38078161Speter } 381146733Spjd first_error = 0; 38291040Sarr for (mdp = start; mdp < stop; mdp++) { 38391040Sarr if ((*mdp)->md_type != MDT_MODULE) 38491040Sarr continue; 38591040Sarr moddata = (*mdp)->md_data; 38691040Sarr KLD_DPF(FILE, ("Registering module %s in %s\n", 38791040Sarr moddata->name, lf->filename)); 38891040Sarr error = module_register(moddata, lf); 389146730Spjd if (error) { 39091068Sarr printf("Module %s failed to register: %d\n", 39191040Sarr moddata->name, error); 392146733Spjd if (first_error == 0) 393146733Spjd first_error = error; 394146730Spjd } 39559751Speter } 396146733Spjd return (first_error); 39759751Speter} 39859751Speter 39959751Speterstatic void 40059751Speterlinker_init_kernel_modules(void) 40159751Speter{ 40291040Sarr 403254810Smarkj sx_xlock(&kld_sx); 40491040Sarr linker_file_register_modules(linker_kernel_file); 405254810Smarkj sx_xunlock(&kld_sx); 40659751Speter} 40759751Speter 408177253SrwatsonSYSINIT(linker_kernel, SI_SUB_KLD, SI_ORDER_ANY, linker_init_kernel_modules, 409177253Srwatson 0); 41059751Speter 411101241Smuxstatic int 41291040Sarrlinker_load_file(const char *filename, linker_file_t *result) 41325537Sdfr{ 41491040Sarr linker_class_t lc; 41591040Sarr linker_file_t lf; 416234186Sjhb int foundfile, error, modules; 41725537Sdfr 41891040Sarr /* Refuse to load modules if securelevel raised */ 419192895Sjamie if (prison0.pr_securelevel > 0) 42091040Sarr return (EPERM); 42162261Sarchie 422254810Smarkj sx_assert(&kld_sx, SA_XLOCKED); 42391040Sarr lf = linker_find_file_by_name(filename); 42491040Sarr if (lf) { 42591040Sarr KLD_DPF(FILE, ("linker_load_file: file %s is already loaded," 42691040Sarr " incrementing refs\n", filename)); 42791040Sarr *result = lf; 42891040Sarr lf->refs++; 429159585Sjhb return (0); 43091040Sarr } 43191040Sarr foundfile = 0; 432159585Sjhb error = 0; 43398452Sarr 43498452Sarr /* 43598452Sarr * We do not need to protect (lock) classes here because there is 43698452Sarr * no class registration past startup (SI_SUB_KLD, SI_ORDER_ANY) 43798452Sarr * and there is no class deregistration mechanism at this time. 43898452Sarr */ 43991040Sarr TAILQ_FOREACH(lc, &classes, link) { 44091040Sarr KLD_DPF(FILE, ("linker_load_file: trying to load %s\n", 44191040Sarr filename)); 44291040Sarr error = LINKER_LOAD_FILE(lc, filename, &lf); 44391040Sarr /* 44491040Sarr * If we got something other than ENOENT, then it exists but 44591040Sarr * we cannot load it for some other reason. 44691040Sarr */ 44791040Sarr if (error != ENOENT) 44891040Sarr foundfile = 1; 44991040Sarr if (lf) { 450146730Spjd error = linker_file_register_modules(lf); 451146730Spjd if (error == EEXIST) { 452146730Spjd linker_file_unload(lf, LINKER_UNLOAD_FORCE); 453159585Sjhb return (error); 454146730Spjd } 455234186Sjhb modules = !TAILQ_EMPTY(&lf->modules); 456324749Savg linker_file_register_sysctls(lf, false); 45791040Sarr linker_file_sysinit(lf); 45891040Sarr lf->flags |= LINKER_FILE_LINKED; 459234186Sjhb 460234186Sjhb /* 461234186Sjhb * If all of the modules in this file failed 462234186Sjhb * to load, unload the file and return an 463234186Sjhb * error of ENOEXEC. 464234186Sjhb */ 465234186Sjhb if (modules && TAILQ_EMPTY(&lf->modules)) { 466234186Sjhb linker_file_unload(lf, LINKER_UNLOAD_FORCE); 467234186Sjhb return (ENOEXEC); 468234186Sjhb } 469324749Savg linker_file_enable_sysctls(lf); 470262039Savg EVENTHANDLER_INVOKE(kld_load, lf); 47191040Sarr *result = lf; 472159585Sjhb return (0); 47391040Sarr } 47491040Sarr } 47542755Speter /* 47691040Sarr * Less than ideal, but tells the user whether it failed to load or 47791040Sarr * the module was not found. 47842755Speter */ 479105337Ssam if (foundfile) { 480188440Sattilio 481105337Ssam /* 482188440Sattilio * If the file type has not been recognized by the last try 483188440Sattilio * printout a message before to fail. 484188440Sattilio */ 485188440Sattilio if (error == ENOSYS) 486188440Sattilio printf("linker_load_file: Unsupported file type\n"); 487188440Sattilio 488188440Sattilio /* 489105337Ssam * Format not recognized or otherwise unloadable. 490105337Ssam * When loading a module that is statically built into 491105337Ssam * the kernel EEXIST percolates back up as the return 492105337Ssam * value. Preserve this so that apps like sysinstall 493105337Ssam * can recognize this special case and not post bogus 494105337Ssam * dialog boxes. 495105337Ssam */ 496105337Ssam if (error != EEXIST) 497105337Ssam error = ENOEXEC; 498105337Ssam } else 49991068Sarr error = ENOENT; /* Nothing found */ 50091040Sarr return (error); 50125537Sdfr} 50225537Sdfr 50378413Sbrianint 50494321Sbrianlinker_reference_module(const char *modname, struct mod_depend *verinfo, 50594321Sbrian linker_file_t *result) 50678413Sbrian{ 50794321Sbrian modlist_t mod; 508159804Sjhb int error; 50994321Sbrian 510254810Smarkj sx_xlock(&kld_sx); 51194321Sbrian if ((mod = modlist_lookup2(modname, verinfo)) != NULL) { 51294321Sbrian *result = mod->container; 51394321Sbrian (*result)->refs++; 514254810Smarkj sx_xunlock(&kld_sx); 51594321Sbrian return (0); 51694321Sbrian } 51794321Sbrian 518159804Sjhb error = linker_load_module(NULL, modname, NULL, verinfo, result); 519254810Smarkj sx_xunlock(&kld_sx); 520159804Sjhb return (error); 52178413Sbrian} 52278413Sbrian 523159804Sjhbint 524159804Sjhblinker_release_module(const char *modname, struct mod_depend *verinfo, 525159804Sjhb linker_file_t lf) 526159804Sjhb{ 527159804Sjhb modlist_t mod; 528159804Sjhb int error; 529159804Sjhb 530254810Smarkj sx_xlock(&kld_sx); 531159804Sjhb if (lf == NULL) { 532159804Sjhb KASSERT(modname != NULL, 533159804Sjhb ("linker_release_module: no file or name")); 534159804Sjhb mod = modlist_lookup2(modname, verinfo); 535159804Sjhb if (mod == NULL) { 536254810Smarkj sx_xunlock(&kld_sx); 537159804Sjhb return (ESRCH); 538159804Sjhb } 539159804Sjhb lf = mod->container; 540159804Sjhb } else 541159804Sjhb KASSERT(modname == NULL && verinfo == NULL, 542159804Sjhb ("linker_release_module: both file and name")); 543159804Sjhb error = linker_file_unload(lf, LINKER_UNLOAD_NORMAL); 544254810Smarkj sx_xunlock(&kld_sx); 545159804Sjhb return (error); 546159804Sjhb} 547159804Sjhb 548159800Sjhbstatic linker_file_t 54991040Sarrlinker_find_file_by_name(const char *filename) 55025537Sdfr{ 551159585Sjhb linker_file_t lf; 55291040Sarr char *koname; 55325537Sdfr 554111119Simp koname = malloc(strlen(filename) + 4, M_LINKER, M_WAITOK); 55591040Sarr sprintf(koname, "%s.ko", filename); 55640861Speter 557254810Smarkj sx_assert(&kld_sx, SA_XLOCKED); 55891040Sarr TAILQ_FOREACH(lf, &linker_files, link) { 55992032Sdwmalone if (strcmp(lf->filename, koname) == 0) 56091040Sarr break; 56192032Sdwmalone if (strcmp(lf->filename, filename) == 0) 56291040Sarr break; 56391040Sarr } 564159585Sjhb free(koname, M_LINKER); 56591040Sarr return (lf); 56625537Sdfr} 56725537Sdfr 568159800Sjhbstatic linker_file_t 56925537Sdfrlinker_find_file_by_id(int fileid) 57025537Sdfr{ 571159585Sjhb linker_file_t lf; 572159845Sjhb 573254810Smarkj sx_assert(&kld_sx, SA_XLOCKED); 57491040Sarr TAILQ_FOREACH(lf, &linker_files, link) 575166921Sjhb if (lf->id == fileid && lf->flags & LINKER_FILE_LINKED) 57691040Sarr break; 57791040Sarr return (lf); 57825537Sdfr} 57925537Sdfr 580159797Sjhbint 581159797Sjhblinker_file_foreach(linker_predicate_t *predicate, void *context) 582159797Sjhb{ 583159797Sjhb linker_file_t lf; 584159797Sjhb int retval = 0; 585159797Sjhb 586254810Smarkj sx_xlock(&kld_sx); 587159797Sjhb TAILQ_FOREACH(lf, &linker_files, link) { 588159797Sjhb retval = predicate(lf, context); 589159797Sjhb if (retval != 0) 590159797Sjhb break; 591159797Sjhb } 592254810Smarkj sx_xunlock(&kld_sx); 593159797Sjhb return (retval); 594159797Sjhb} 595159797Sjhb 59625537Sdfrlinker_file_t 59791040Sarrlinker_make_file(const char *pathname, linker_class_t lc) 59825537Sdfr{ 59991040Sarr linker_file_t lf; 60091040Sarr const char *filename; 60125537Sdfr 602254810Smarkj if (!cold) 603254810Smarkj sx_assert(&kld_sx, SA_XLOCKED); 60491040Sarr filename = linker_basename(pathname); 60540159Speter 606172862Sjb KLD_DPF(FILE, ("linker_make_file: new file, filename='%s' for pathname='%s'\n", filename, pathname)); 607111119Simp lf = (linker_file_t)kobj_create((kobj_class_t)lc, M_LINKER, M_WAITOK); 60891040Sarr if (lf == NULL) 609159585Sjhb return (NULL); 61091040Sarr lf->refs = 1; 61191040Sarr lf->userrefs = 0; 61291040Sarr lf->flags = 0; 613254396Smarkj lf->filename = strdup(filename, M_LINKER); 614254396Smarkj lf->pathname = strdup(pathname, M_LINKER); 61591040Sarr LINKER_GET_NEXT_FILE_ID(lf->id); 61691040Sarr lf->ndeps = 0; 61791040Sarr lf->deps = NULL; 618172862Sjb lf->loadcnt = ++loadcnt; 61991040Sarr STAILQ_INIT(&lf->common); 62091040Sarr TAILQ_INIT(&lf->modules); 62191040Sarr TAILQ_INSERT_TAIL(&linker_files, lf, link); 62291040Sarr return (lf); 62325537Sdfr} 62425537Sdfr 62525537Sdfrint 626132117Sphklinker_file_unload(linker_file_t file, int flags) 62725537Sdfr{ 62891040Sarr module_t mod, next; 62991040Sarr modlist_t ml, nextml; 63091040Sarr struct common_symbol *cp; 63191040Sarr int error, i; 63225537Sdfr 63391040Sarr /* Refuse to unload modules if securelevel raised. */ 634192895Sjamie if (prison0.pr_securelevel > 0) 63591040Sarr return (EPERM); 63625537Sdfr 637254810Smarkj sx_assert(&kld_sx, SA_XLOCKED); 63891040Sarr KLD_DPF(FILE, ("linker_file_unload: lf->refs=%d\n", file->refs)); 63991040Sarr 640159584Sjhb /* Easy case of just dropping a reference. */ 641159584Sjhb if (file->refs > 1) { 642159584Sjhb file->refs--; 643159584Sjhb return (0); 644159584Sjhb } 645159584Sjhb 646262039Savg /* Give eventhandlers a chance to prevent the unload. */ 647262039Savg error = 0; 648262039Savg EVENTHANDLER_INVOKE(kld_unload_try, file, &error); 649262039Savg if (error != 0) 650262039Savg return (EBUSY); 651262039Savg 652159584Sjhb KLD_DPF(FILE, ("linker_file_unload: file is unloading," 653159584Sjhb " informing modules\n")); 654159584Sjhb 655159584Sjhb /* 656185635Sjhb * Quiesce all the modules to give them a chance to veto the unload. 657159584Sjhb */ 658185635Sjhb MOD_SLOCK; 659185635Sjhb for (mod = TAILQ_FIRST(&file->modules); mod; 660185635Sjhb mod = module_getfnext(mod)) { 661185635Sjhb 662185635Sjhb error = module_quiesce(mod); 663185635Sjhb if (error != 0 && flags != LINKER_UNLOAD_FORCE) { 664185635Sjhb KLD_DPF(FILE, ("linker_file_unload: module %s" 665185635Sjhb " vetoed unload\n", module_getname(mod))); 666185635Sjhb /* 667185635Sjhb * XXX: Do we need to tell all the quiesced modules 668185635Sjhb * that they can resume work now via a new module 669185635Sjhb * event? 670185635Sjhb */ 671185635Sjhb MOD_SUNLOCK; 672185635Sjhb return (error); 673185635Sjhb } 674185635Sjhb } 675185635Sjhb MOD_SUNLOCK; 676185635Sjhb 677185635Sjhb /* 678185635Sjhb * Inform any modules associated with this file that they are 679234186Sjhb * being unloaded. 680185635Sjhb */ 681159584Sjhb MOD_XLOCK; 682159584Sjhb for (mod = TAILQ_FIRST(&file->modules); mod; mod = next) { 683159584Sjhb next = module_getfnext(mod); 684159584Sjhb MOD_XUNLOCK; 685159584Sjhb 68691040Sarr /* 687159584Sjhb * Give the module a chance to veto the unload. 68891040Sarr */ 689185635Sjhb if ((error = module_unload(mod)) != 0) { 690233276Sae#ifdef KLD_DEBUG 691233276Sae MOD_SLOCK; 692185635Sjhb KLD_DPF(FILE, ("linker_file_unload: module %s" 693199457Sgonzo " failed unload\n", module_getname(mod))); 694233276Sae MOD_SUNLOCK; 695233276Sae#endif 696159584Sjhb return (error); 697159584Sjhb } 69892547Sarr MOD_XLOCK; 699159584Sjhb module_release(mod); 700159584Sjhb } 701159584Sjhb MOD_XUNLOCK; 70291040Sarr 703159586Sjhb TAILQ_FOREACH_SAFE(ml, &found_modules, link, nextml) { 704128057Speadar if (ml->container == file) { 70591040Sarr TAILQ_REMOVE(&found_modules, ml, link); 706128057Speadar free(ml, M_LINKER); 707128057Speadar } 70891040Sarr } 70925537Sdfr 710159840Sjhb /* 711159840Sjhb * Don't try to run SYSUNINITs if we are unloaded due to a 71291040Sarr * link error. 71391040Sarr */ 71491040Sarr if (file->flags & LINKER_FILE_LINKED) { 715188209Sjhb file->flags &= ~LINKER_FILE_LINKED; 716324749Savg linker_file_unregister_sysctls(file); 71791040Sarr linker_file_sysuninit(file); 71825537Sdfr } 71991040Sarr TAILQ_REMOVE(&linker_files, file, link); 72025537Sdfr 72191040Sarr if (file->deps) { 72291040Sarr for (i = 0; i < file->ndeps; i++) 723132117Sphk linker_file_unload(file->deps[i], flags); 72491040Sarr free(file->deps, M_LINKER); 72591040Sarr file->deps = NULL; 72659751Speter } 727160245Sjhb while ((cp = STAILQ_FIRST(&file->common)) != NULL) { 728160245Sjhb STAILQ_REMOVE_HEAD(&file->common, link); 72991040Sarr free(cp, M_LINKER); 73091040Sarr } 73159751Speter 73291040Sarr LINKER_UNLOAD(file); 733262039Savg 734262039Savg EVENTHANDLER_INVOKE(kld_unload, file->filename, file->address, 735262039Savg file->size); 736262039Savg 73791040Sarr if (file->filename) { 73891040Sarr free(file->filename, M_LINKER); 73991040Sarr file->filename = NULL; 74091040Sarr } 741172862Sjb if (file->pathname) { 742172862Sjb free(file->pathname, M_LINKER); 743172862Sjb file->pathname = NULL; 744172862Sjb } 74591040Sarr kobj_delete((kobj_t) file, M_LINKER); 746159584Sjhb return (0); 74725537Sdfr} 74825537Sdfr 749179238Sjbint 750179238Sjblinker_ctf_get(linker_file_t file, linker_ctf_t *lc) 751179238Sjb{ 752179238Sjb return (LINKER_CTF_GET(file, lc)); 753179238Sjb} 754179238Sjb 755159796Sjhbstatic int 75686469Siedowselinker_file_add_dependency(linker_file_t file, linker_file_t dep) 75725537Sdfr{ 75891040Sarr linker_file_t *newdeps; 75925537Sdfr 760254810Smarkj sx_assert(&kld_sx, SA_XLOCKED); 761264370Skib file->deps = realloc(file->deps, (file->ndeps + 1) * sizeof(*newdeps), 762264370Skib M_LINKER, M_WAITOK | M_ZERO); 76391040Sarr file->deps[file->ndeps] = dep; 76491040Sarr file->ndeps++; 765199457Sgonzo KLD_DPF(FILE, ("linker_file_add_dependency:" 766199457Sgonzo " adding %s as dependency for %s\n", 767199457Sgonzo dep->filename, file->filename)); 76891040Sarr return (0); 76925537Sdfr} 77025537Sdfr 77178161Speter/* 77291040Sarr * Locate a linker set and its contents. This is a helper function to avoid 773159841Sjhb * linker_if.h exposure elsewhere. Note: firstp and lastp are really void **. 774159841Sjhb * This function is used in this file so we can avoid having lots of (void **) 775159841Sjhb * casts. 77678161Speter */ 77778161Speterint 77878161Speterlinker_file_lookup_set(linker_file_t file, const char *name, 77991040Sarr void *firstp, void *lastp, int *countp) 78078161Speter{ 78178161Speter 782254811Smarkj sx_assert(&kld_sx, SA_LOCKED); 783254811Smarkj return (LINKER_LOOKUP_SET(file, name, firstp, lastp, countp)); 78478161Speter} 78578161Speter 786173714Sjb/* 787173714Sjb * List all functions in a file. 788173714Sjb */ 789173714Sjbint 790173714Sjblinker_file_function_listall(linker_file_t lf, 791179238Sjb linker_function_nameval_callback_t callback_func, void *arg) 792173714Sjb{ 793173714Sjb return (LINKER_EACH_FUNCTION_NAMEVAL(lf, callback_func, arg)); 794173714Sjb} 795173714Sjb 79625537Sdfrcaddr_t 79791040Sarrlinker_file_lookup_symbol(linker_file_t file, const char *name, int deps) 79825537Sdfr{ 799159845Sjhb caddr_t sym; 800159845Sjhb int locked; 801159845Sjhb 802254810Smarkj locked = sx_xlocked(&kld_sx); 803159845Sjhb if (!locked) 804254810Smarkj sx_xlock(&kld_sx); 805159845Sjhb sym = linker_file_lookup_symbol_internal(file, name, deps); 806159845Sjhb if (!locked) 807254810Smarkj sx_xunlock(&kld_sx); 808159845Sjhb return (sym); 809159845Sjhb} 810159845Sjhb 811159845Sjhbstatic caddr_t 812159845Sjhblinker_file_lookup_symbol_internal(linker_file_t file, const char *name, 813159845Sjhb int deps) 814159845Sjhb{ 81591040Sarr c_linker_sym_t sym; 81691040Sarr linker_symval_t symval; 81791040Sarr caddr_t address; 81891040Sarr size_t common_size = 0; 81992032Sdwmalone int i; 82025537Sdfr 821254810Smarkj sx_assert(&kld_sx, SA_XLOCKED); 822109605Sjake KLD_DPF(SYM, ("linker_file_lookup_symbol: file=%p, name=%s, deps=%d\n", 82391040Sarr file, name, deps)); 82425537Sdfr 82591040Sarr if (LINKER_LOOKUP_SYMBOL(file, name, &sym) == 0) { 82691040Sarr LINKER_SYMBOL_VALUES(file, sym, &symval); 82791040Sarr if (symval.value == 0) 82891040Sarr /* 82991040Sarr * For commons, first look them up in the 83091040Sarr * dependencies and only allocate space if not found 83191040Sarr * there. 83291040Sarr */ 83391040Sarr common_size = symval.size; 83491040Sarr else { 83591040Sarr KLD_DPF(SYM, ("linker_file_lookup_symbol: symbol" 836109605Sjake ".value=%p\n", symval.value)); 83791040Sarr return (symval.value); 83891040Sarr } 83940159Speter } 84091040Sarr if (deps) { 84191040Sarr for (i = 0; i < file->ndeps; i++) { 842159845Sjhb address = linker_file_lookup_symbol_internal( 843159845Sjhb file->deps[i], name, 0); 84491040Sarr if (address) { 84591040Sarr KLD_DPF(SYM, ("linker_file_lookup_symbol:" 846109605Sjake " deps value=%p\n", address)); 84791040Sarr return (address); 84891040Sarr } 84991040Sarr } 85025537Sdfr } 85191040Sarr if (common_size > 0) { 85291040Sarr /* 85391040Sarr * This is a common symbol which was not found in the 85491040Sarr * dependencies. We maintain a simple common symbol table in 85591040Sarr * the file object. 85691040Sarr */ 85791040Sarr struct common_symbol *cp; 85842849Speter 85991040Sarr STAILQ_FOREACH(cp, &file->common, link) { 86092032Sdwmalone if (strcmp(cp->name, name) == 0) { 86191040Sarr KLD_DPF(SYM, ("linker_file_lookup_symbol:" 862109605Sjake " old common value=%p\n", cp->address)); 86391040Sarr return (cp->address); 86491040Sarr } 86591040Sarr } 86691040Sarr /* 86791040Sarr * Round the symbol size up to align. 86891040Sarr */ 86991040Sarr common_size = (common_size + sizeof(int) - 1) & -sizeof(int); 87091040Sarr cp = malloc(sizeof(struct common_symbol) 87191040Sarr + common_size + strlen(name) + 1, M_LINKER, 872111119Simp M_WAITOK | M_ZERO); 87391040Sarr cp->address = (caddr_t)(cp + 1); 87491040Sarr cp->name = cp->address + common_size; 87591040Sarr strcpy(cp->name, name); 87691040Sarr bzero(cp->address, common_size); 87791040Sarr STAILQ_INSERT_TAIL(&file->common, cp, link); 87825537Sdfr 87991040Sarr KLD_DPF(SYM, ("linker_file_lookup_symbol: new common" 880109605Sjake " value=%p\n", cp->address)); 88191040Sarr return (cp->address); 88240159Speter } 88391040Sarr KLD_DPF(SYM, ("linker_file_lookup_symbol: fail\n")); 88491040Sarr return (0); 88525537Sdfr} 88625537Sdfr 88725537Sdfr/* 888174132Srwatson * Both DDB and stack(9) rely on the kernel linker to provide forward and 889174132Srwatson * backward lookup of symbols. However, DDB and sometimes stack(9) need to 890174132Srwatson * do this in a lockfree manner. We provide a set of internal helper 891174132Srwatson * routines to perform these operations without locks, and then wrappers that 892174132Srwatson * optionally lock. 893159840Sjhb * 894174132Srwatson * linker_debug_lookup() is ifdef DDB as currently it's only used by DDB. 89540159Speter */ 896174132Srwatson#ifdef DDB 897174132Srwatsonstatic int 898174132Srwatsonlinker_debug_lookup(const char *symstr, c_linker_sym_t *sym) 89940159Speter{ 90091040Sarr linker_file_t lf; 90140159Speter 90291040Sarr TAILQ_FOREACH(lf, &linker_files, link) { 90391040Sarr if (LINKER_LOOKUP_SYMBOL(lf, symstr, sym) == 0) 90491040Sarr return (0); 90591040Sarr } 90691040Sarr return (ENOENT); 90740159Speter} 908174132Srwatson#endif 90940159Speter 910174132Srwatsonstatic int 911174132Srwatsonlinker_debug_search_symbol(caddr_t value, c_linker_sym_t *sym, long *diffp) 91240159Speter{ 91391040Sarr linker_file_t lf; 91491040Sarr c_linker_sym_t best, es; 91591040Sarr u_long diff, bestdiff, off; 91640159Speter 91791040Sarr best = 0; 91891040Sarr off = (uintptr_t)value; 91991040Sarr bestdiff = off; 92091040Sarr TAILQ_FOREACH(lf, &linker_files, link) { 92191040Sarr if (LINKER_SEARCH_SYMBOL(lf, value, &es, &diff) != 0) 92291040Sarr continue; 92391040Sarr if (es != 0 && diff < bestdiff) { 92491040Sarr best = es; 92591040Sarr bestdiff = diff; 92691040Sarr } 92791040Sarr if (bestdiff == 0) 92891040Sarr break; 92940159Speter } 93091040Sarr if (best) { 93191040Sarr *sym = best; 93291040Sarr *diffp = bestdiff; 93391040Sarr return (0); 93491040Sarr } else { 93591040Sarr *sym = 0; 93691040Sarr *diffp = off; 93791040Sarr return (ENOENT); 93891040Sarr } 93940159Speter} 94040159Speter 941174132Srwatsonstatic int 942174132Srwatsonlinker_debug_symbol_values(c_linker_sym_t sym, linker_symval_t *symval) 94340159Speter{ 94491040Sarr linker_file_t lf; 94540159Speter 94691040Sarr TAILQ_FOREACH(lf, &linker_files, link) { 94791040Sarr if (LINKER_SYMBOL_VALUES(lf, sym, symval) == 0) 94891040Sarr return (0); 94991040Sarr } 95091040Sarr return (ENOENT); 95140159Speter} 952174132Srwatson 953174132Srwatsonstatic int 954174132Srwatsonlinker_debug_search_symbol_name(caddr_t value, char *buf, u_int buflen, 955174132Srwatson long *offset) 956174132Srwatson{ 957174132Srwatson linker_symval_t symval; 958174132Srwatson c_linker_sym_t sym; 959174132Srwatson int error; 960174132Srwatson 961174132Srwatson *offset = 0; 962174132Srwatson error = linker_debug_search_symbol(value, &sym, offset); 963174132Srwatson if (error) 964174132Srwatson return (error); 965174132Srwatson error = linker_debug_symbol_values(sym, &symval); 966174132Srwatson if (error) 967174132Srwatson return (error); 968174132Srwatson strlcpy(buf, symval.name, buflen); 969174132Srwatson return (0); 970174132Srwatson} 971174132Srwatson 972174132Srwatson/* 973174132Srwatson * DDB Helpers. DDB has to look across multiple files with their own symbol 974174132Srwatson * tables and string tables. 975174132Srwatson * 976174132Srwatson * Note that we do not obey list locking protocols here. We really don't need 977174132Srwatson * DDB to hang because somebody's got the lock held. We'll take the chance 978302234Sbdrewery * that the files list is inconsistent instead. 979174132Srwatson */ 980212994Savg#ifdef DDB 981174132Srwatsonint 982174132Srwatsonlinker_ddb_lookup(const char *symstr, c_linker_sym_t *sym) 983174132Srwatson{ 984174132Srwatson 985174132Srwatson return (linker_debug_lookup(symstr, sym)); 986174132Srwatson} 987212994Savg#endif 988174132Srwatson 989174132Srwatsonint 990174132Srwatsonlinker_ddb_search_symbol(caddr_t value, c_linker_sym_t *sym, long *diffp) 991174132Srwatson{ 992174132Srwatson 993174132Srwatson return (linker_debug_search_symbol(value, sym, diffp)); 994174132Srwatson} 995174132Srwatson 996174132Srwatsonint 997174132Srwatsonlinker_ddb_symbol_values(c_linker_sym_t sym, linker_symval_t *symval) 998174132Srwatson{ 999174132Srwatson 1000174132Srwatson return (linker_debug_symbol_values(sym, symval)); 1001174132Srwatson} 1002174132Srwatson 1003174132Srwatsonint 1004174132Srwatsonlinker_ddb_search_symbol_name(caddr_t value, char *buf, u_int buflen, 1005174132Srwatson long *offset) 1006174132Srwatson{ 1007174132Srwatson 1008174132Srwatson return (linker_debug_search_symbol_name(value, buf, buflen, offset)); 1009174132Srwatson} 101040159Speter 101140159Speter/* 1012174132Srwatson * stack(9) helper for non-debugging environemnts. Unlike DDB helpers, we do 1013174132Srwatson * obey locking protocols, and offer a significantly less complex interface. 1014174132Srwatson */ 1015174132Srwatsonint 1016174132Srwatsonlinker_search_symbol_name(caddr_t value, char *buf, u_int buflen, 1017174132Srwatson long *offset) 1018174132Srwatson{ 1019178380Spjd int error; 1020174132Srwatson 1021254810Smarkj sx_xlock(&kld_sx); 1022174132Srwatson error = linker_debug_search_symbol_name(value, buf, buflen, offset); 1023254810Smarkj sx_xunlock(&kld_sx); 1024174132Srwatson return (error); 1025174132Srwatson} 1026174132Srwatson 1027174132Srwatson/* 102825537Sdfr * Syscalls. 102925537Sdfr */ 103025537Sdfrint 1031159588Sjhbkern_kldload(struct thread *td, const char *file, int *fileid) 103225537Sdfr{ 1033159588Sjhb const char *kldname, *modname; 103491040Sarr linker_file_t lf; 1035159588Sjhb int error; 103625537Sdfr 103793159Sarr if ((error = securelevel_gt(td->td_ucred, 0)) != 0) 1038159588Sjhb return (error); 103993159Sarr 1040164033Srwatson if ((error = priv_check(td, PRIV_KLD_LOAD)) != 0) 1041159588Sjhb return (error); 104225537Sdfr 104391040Sarr /* 1044191917Szec * It is possible that kldloaded module will attach a new ifnet, 1045191816Szec * so vnet context must be set when this ocurs. 1046191816Szec */ 1047191816Szec CURVNET_SET(TD_TO_VNET(td)); 1048191816Szec 1049191816Szec /* 1050159841Sjhb * If file does not contain a qualified name or any dot in it 1051159841Sjhb * (kldname.ko, or kldname.ver.ko) treat it as an interface 105291040Sarr * name. 105391040Sarr */ 1054229272Sed if (strchr(file, '/') || strchr(file, '.')) { 1055159588Sjhb kldname = file; 105691040Sarr modname = NULL; 105791040Sarr } else { 105891040Sarr kldname = NULL; 1059159588Sjhb modname = file; 106091040Sarr } 1061159588Sjhb 1062254810Smarkj sx_xlock(&kld_sx); 106391040Sarr error = linker_load_module(kldname, modname, NULL, NULL, &lf); 1064224156Srstone if (error) { 1065254810Smarkj sx_xunlock(&kld_sx); 1066224156Srstone goto done; 1067224156Srstone } 1068224156Srstone lf->userrefs++; 1069224156Srstone if (fileid != NULL) 1070224156Srstone *fileid = lf->id; 1071262039Savg sx_xunlock(&kld_sx); 1072254266Smarkj 1073224156Srstonedone: 1074191816Szec CURVNET_RESTORE(); 107591040Sarr return (error); 107625537Sdfr} 107725537Sdfr 1078159588Sjhbint 1079225617Skmacysys_kldload(struct thread *td, struct kldload_args *uap) 1080159588Sjhb{ 1081159588Sjhb char *pathname = NULL; 1082159596Smarcel int error, fileid; 1083159588Sjhb 1084159588Sjhb td->td_retval[0] = -1; 1085159588Sjhb 1086159588Sjhb pathname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); 1087159588Sjhb error = copyinstr(uap->file, pathname, MAXPATHLEN, NULL); 1088159596Smarcel if (error == 0) { 1089159596Smarcel error = kern_kldload(td, pathname, &fileid); 1090159596Smarcel if (error == 0) 1091159596Smarcel td->td_retval[0] = fileid; 1092159596Smarcel } 1093159588Sjhb free(pathname, M_TEMP); 1094159588Sjhb return (error); 1095159588Sjhb} 1096159588Sjhb 1097159588Sjhbint 1098132117Sphkkern_kldunload(struct thread *td, int fileid, int flags) 109925537Sdfr{ 110091040Sarr linker_file_t lf; 110191040Sarr int error = 0; 110225537Sdfr 110393159Sarr if ((error = securelevel_gt(td->td_ucred, 0)) != 0) 1104159588Sjhb return (error); 110593159Sarr 1106164033Srwatson if ((error = priv_check(td, PRIV_KLD_UNLOAD)) != 0) 1107159588Sjhb return (error); 110825537Sdfr 1109191816Szec CURVNET_SET(TD_TO_VNET(td)); 1110254810Smarkj sx_xlock(&kld_sx); 1111132117Sphk lf = linker_find_file_by_id(fileid); 111291040Sarr if (lf) { 111391040Sarr KLD_DPF(FILE, ("kldunload: lf->userrefs=%d\n", lf->userrefs)); 1114172862Sjb 1115262039Savg if (lf->userrefs == 0) { 1116132117Sphk /* 1117132117Sphk * XXX: maybe LINKER_UNLOAD_FORCE should override ? 1118132117Sphk */ 111991040Sarr printf("kldunload: attempt to unload file that was" 112091040Sarr " loaded by the kernel\n"); 1121159840Sjhb error = EBUSY; 1122159588Sjhb } else { 1123159588Sjhb lf->userrefs--; 1124159588Sjhb error = linker_file_unload(lf, flags); 1125159588Sjhb if (error) 1126159588Sjhb lf->userrefs++; 1127159588Sjhb } 112891040Sarr } else 112991040Sarr error = ENOENT; 1130262039Savg sx_xunlock(&kld_sx); 1131157144Sjkoshy 1132191816Szec CURVNET_RESTORE(); 113391068Sarr return (error); 113425537Sdfr} 113525537Sdfr 113625537Sdfrint 1137225617Skmacysys_kldunload(struct thread *td, struct kldunload_args *uap) 1138132117Sphk{ 1139132117Sphk 1140132117Sphk return (kern_kldunload(td, uap->fileid, LINKER_UNLOAD_NORMAL)); 1141132117Sphk} 1142132117Sphk 1143132117Sphkint 1144225617Skmacysys_kldunloadf(struct thread *td, struct kldunloadf_args *uap) 1145132117Sphk{ 1146132117Sphk 1147132117Sphk if (uap->flags != LINKER_UNLOAD_NORMAL && 1148132117Sphk uap->flags != LINKER_UNLOAD_FORCE) 1149132117Sphk return (EINVAL); 1150132117Sphk return (kern_kldunload(td, uap->fileid, uap->flags)); 1151132117Sphk} 1152132117Sphk 1153132117Sphkint 1154225617Skmacysys_kldfind(struct thread *td, struct kldfind_args *uap) 115525537Sdfr{ 115691040Sarr char *pathname; 115791040Sarr const char *filename; 115891040Sarr linker_file_t lf; 1159159791Sjhb int error; 116025537Sdfr 1161107089Srwatson#ifdef MAC 1162172930Srwatson error = mac_kld_check_stat(td->td_ucred); 1163107089Srwatson if (error) 1164107089Srwatson return (error); 1165107089Srwatson#endif 1166107089Srwatson 116791040Sarr td->td_retval[0] = -1; 116882749Sdillon 1169111119Simp pathname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); 1170107855Salfred if ((error = copyinstr(uap->file, pathname, MAXPATHLEN, NULL)) != 0) 117191040Sarr goto out; 117225537Sdfr 117391040Sarr filename = linker_basename(pathname); 1174254810Smarkj sx_xlock(&kld_sx); 117591040Sarr lf = linker_find_file_by_name(filename); 117691040Sarr if (lf) 117791040Sarr td->td_retval[0] = lf->id; 117891040Sarr else 117991040Sarr error = ENOENT; 1180254810Smarkj sx_xunlock(&kld_sx); 118125537Sdfrout: 1182159791Sjhb free(pathname, M_TEMP); 118391040Sarr return (error); 118425537Sdfr} 118525537Sdfr 118625537Sdfrint 1187225617Skmacysys_kldnext(struct thread *td, struct kldnext_args *uap) 118825537Sdfr{ 118991040Sarr linker_file_t lf; 119091040Sarr int error = 0; 119125537Sdfr 1192107089Srwatson#ifdef MAC 1193172930Srwatson error = mac_kld_check_stat(td->td_ucred); 1194107089Srwatson if (error) 1195107089Srwatson return (error); 1196107089Srwatson#endif 1197107089Srwatson 1198254810Smarkj sx_xlock(&kld_sx); 1199166921Sjhb if (uap->fileid == 0) 1200166921Sjhb lf = TAILQ_FIRST(&linker_files); 1201166921Sjhb else { 1202166921Sjhb lf = linker_find_file_by_id(uap->fileid); 1203166921Sjhb if (lf == NULL) { 1204166921Sjhb error = ENOENT; 1205166921Sjhb goto out; 1206166921Sjhb } 1207166921Sjhb lf = TAILQ_NEXT(lf, link); 120891040Sarr } 1209166921Sjhb 1210166921Sjhb /* Skip partially loaded files. */ 1211166921Sjhb while (lf != NULL && !(lf->flags & LINKER_FILE_LINKED)) 1212166921Sjhb lf = TAILQ_NEXT(lf, link); 1213166921Sjhb 1214166921Sjhb if (lf) 1215166921Sjhb td->td_retval[0] = lf->id; 1216166921Sjhb else 1217166921Sjhb td->td_retval[0] = 0; 121882749Sdillonout: 1219254810Smarkj sx_xunlock(&kld_sx); 122091040Sarr return (error); 122125537Sdfr} 122225537Sdfr 122325537Sdfrint 1224225617Skmacysys_kldstat(struct thread *td, struct kldstat_args *uap) 122525537Sdfr{ 1226325867Sgordon struct kld_file_stat *stat; 1227220158Skib int error, version; 122825537Sdfr 1229159587Sjhb /* 1230159587Sjhb * Check the version of the user's structure. 1231159587Sjhb */ 1232220158Skib if ((error = copyin(&uap->stat->version, &version, sizeof(version))) 1233220158Skib != 0) 1234159587Sjhb return (error); 1235220158Skib if (version != sizeof(struct kld_file_stat_1) && 1236220158Skib version != sizeof(struct kld_file_stat)) 1237159587Sjhb return (EINVAL); 1238159587Sjhb 1239325867Sgordon stat = malloc(sizeof(*stat), M_TEMP, M_WAITOK | M_ZERO); 1240325867Sgordon error = kern_kldstat(td, uap->fileid, stat); 1241325867Sgordon if (error == 0) 1242325867Sgordon error = copyout(stat, uap->stat, version); 1243325867Sgordon free(stat, M_TEMP); 1244325867Sgordon return (error); 1245220158Skib} 1246220158Skib 1247220158Skibint 1248220158Skibkern_kldstat(struct thread *td, int fileid, struct kld_file_stat *stat) 1249220158Skib{ 1250220158Skib linker_file_t lf; 1251220158Skib int namelen; 1252107089Srwatson#ifdef MAC 1253220158Skib int error; 1254220158Skib 1255172930Srwatson error = mac_kld_check_stat(td->td_ucred); 1256107089Srwatson if (error) 1257107089Srwatson return (error); 1258107089Srwatson#endif 1259107089Srwatson 1260254810Smarkj sx_xlock(&kld_sx); 1261220158Skib lf = linker_find_file_by_id(fileid); 126291040Sarr if (lf == NULL) { 1263254810Smarkj sx_xunlock(&kld_sx); 1264159587Sjhb return (ENOENT); 126591040Sarr } 126625537Sdfr 1267172862Sjb /* Version 1 fields: */ 126891040Sarr namelen = strlen(lf->filename) + 1; 126991040Sarr if (namelen > MAXPATHLEN) 127091040Sarr namelen = MAXPATHLEN; 1271220158Skib bcopy(lf->filename, &stat->name[0], namelen); 1272220158Skib stat->refs = lf->refs; 1273220158Skib stat->id = lf->id; 1274220158Skib stat->address = lf->address; 1275220158Skib stat->size = lf->size; 1276220158Skib /* Version 2 fields: */ 1277220158Skib namelen = strlen(lf->pathname) + 1; 1278220158Skib if (namelen > MAXPATHLEN) 1279220158Skib namelen = MAXPATHLEN; 1280220158Skib bcopy(lf->pathname, &stat->pathname[0], namelen); 1281254810Smarkj sx_xunlock(&kld_sx); 128225537Sdfr 128391040Sarr td->td_retval[0] = 0; 1284220158Skib return (0); 128525537Sdfr} 128625537Sdfr 128725537Sdfrint 1288225617Skmacysys_kldfirstmod(struct thread *td, struct kldfirstmod_args *uap) 128925537Sdfr{ 129091040Sarr linker_file_t lf; 129191040Sarr module_t mp; 129291040Sarr int error = 0; 129325537Sdfr 1294107089Srwatson#ifdef MAC 1295172930Srwatson error = mac_kld_check_stat(td->td_ucred); 1296107089Srwatson if (error) 1297107089Srwatson return (error); 1298107089Srwatson#endif 1299107089Srwatson 1300254810Smarkj sx_xlock(&kld_sx); 1301107849Salfred lf = linker_find_file_by_id(uap->fileid); 130291040Sarr if (lf) { 130392547Sarr MOD_SLOCK; 130491040Sarr mp = TAILQ_FIRST(&lf->modules); 130591040Sarr if (mp != NULL) 130691040Sarr td->td_retval[0] = module_getid(mp); 130791040Sarr else 130891040Sarr td->td_retval[0] = 0; 130992547Sarr MOD_SUNLOCK; 131091040Sarr } else 131191040Sarr error = ENOENT; 1312254810Smarkj sx_xunlock(&kld_sx); 131391040Sarr return (error); 131425537Sdfr} 131540159Speter 131641090Speterint 1317225617Skmacysys_kldsym(struct thread *td, struct kldsym_args *uap) 131841090Speter{ 131991040Sarr char *symstr = NULL; 132091040Sarr c_linker_sym_t sym; 132191040Sarr linker_symval_t symval; 132291040Sarr linker_file_t lf; 132391040Sarr struct kld_sym_lookup lookup; 132491040Sarr int error = 0; 132541090Speter 1326107089Srwatson#ifdef MAC 1327172930Srwatson error = mac_kld_check_stat(td->td_ucred); 1328107089Srwatson if (error) 1329107089Srwatson return (error); 1330107089Srwatson#endif 1331107089Srwatson 1332107849Salfred if ((error = copyin(uap->data, &lookup, sizeof(lookup))) != 0) 1333159843Sjhb return (error); 133491068Sarr if (lookup.version != sizeof(lookup) || 1335159843Sjhb uap->cmd != KLDSYM_LOOKUP) 1336159843Sjhb return (EINVAL); 1337111119Simp symstr = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); 133891040Sarr if ((error = copyinstr(lookup.symname, symstr, MAXPATHLEN, NULL)) != 0) 133991040Sarr goto out; 1340254810Smarkj sx_xlock(&kld_sx); 1341107849Salfred if (uap->fileid != 0) { 1342107849Salfred lf = linker_find_file_by_id(uap->fileid); 1343159843Sjhb if (lf == NULL) 134491040Sarr error = ENOENT; 1345159843Sjhb else if (LINKER_LOOKUP_SYMBOL(lf, symstr, &sym) == 0 && 134691040Sarr LINKER_SYMBOL_VALUES(lf, sym, &symval) == 0) { 134791040Sarr lookup.symvalue = (uintptr_t) symval.value; 134891040Sarr lookup.symsize = symval.size; 1349107855Salfred error = copyout(&lookup, uap->data, sizeof(lookup)); 135091040Sarr } else 135191040Sarr error = ENOENT; 135291040Sarr } else { 135391040Sarr TAILQ_FOREACH(lf, &linker_files, link) { 135491040Sarr if (LINKER_LOOKUP_SYMBOL(lf, symstr, &sym) == 0 && 135591040Sarr LINKER_SYMBOL_VALUES(lf, sym, &symval) == 0) { 135691040Sarr lookup.symvalue = (uintptr_t)symval.value; 135791040Sarr lookup.symsize = symval.size; 1358107849Salfred error = copyout(&lookup, uap->data, 135991040Sarr sizeof(lookup)); 136091068Sarr break; 136191040Sarr } 136291040Sarr } 136391040Sarr if (lf == NULL) 136491040Sarr error = ENOENT; 136541090Speter } 1366254810Smarkj sx_xunlock(&kld_sx); 136741090Speterout: 1368159843Sjhb free(symstr, M_TEMP); 136991040Sarr return (error); 137041090Speter} 137141090Speter 137240159Speter/* 137340159Speter * Preloaded module support 137440159Speter */ 137540159Speter 137659751Speterstatic modlist_t 137774642Sbpmodlist_lookup(const char *name, int ver) 137859751Speter{ 137991040Sarr modlist_t mod; 138059751Speter 138191040Sarr TAILQ_FOREACH(mod, &found_modules, link) { 138292032Sdwmalone if (strcmp(mod->name, name) == 0 && 138392032Sdwmalone (ver == 0 || mod->version == ver)) 138491040Sarr return (mod); 138591040Sarr } 138691040Sarr return (NULL); 138759751Speter} 138859751Speter 138974642Sbpstatic modlist_t 139083321Spetermodlist_lookup2(const char *name, struct mod_depend *verinfo) 139183321Speter{ 139291040Sarr modlist_t mod, bestmod; 139392032Sdwmalone int ver; 139483321Speter 139591040Sarr if (verinfo == NULL) 139691040Sarr return (modlist_lookup(name, 0)); 139791040Sarr bestmod = NULL; 1398159586Sjhb TAILQ_FOREACH(mod, &found_modules, link) { 139992032Sdwmalone if (strcmp(mod->name, name) != 0) 140091040Sarr continue; 140191040Sarr ver = mod->version; 140291040Sarr if (ver == verinfo->md_ver_preferred) 140391040Sarr return (mod); 140491040Sarr if (ver >= verinfo->md_ver_minimum && 140591068Sarr ver <= verinfo->md_ver_maximum && 1406120382Sfjoe (bestmod == NULL || ver > bestmod->version)) 140791040Sarr bestmod = mod; 140891040Sarr } 140991040Sarr return (bestmod); 141083321Speter} 141183321Speter 141283321Speterstatic modlist_t 141378501Sdesmodlist_newmodule(const char *modname, int version, linker_file_t container) 141474642Sbp{ 141591040Sarr modlist_t mod; 141674642Sbp 141792705Sarr mod = malloc(sizeof(struct modlist), M_LINKER, M_NOWAIT | M_ZERO); 141891040Sarr if (mod == NULL) 141991040Sarr panic("no memory for module list"); 142091040Sarr mod->container = container; 142191040Sarr mod->name = modname; 142291040Sarr mod->version = version; 142391040Sarr TAILQ_INSERT_TAIL(&found_modules, mod, link); 142491040Sarr return (mod); 142574642Sbp} 142674642Sbp 142740159Speterstatic void 142878161Speterlinker_addmodules(linker_file_t lf, struct mod_metadata **start, 142991040Sarr struct mod_metadata **stop, int preload) 143074642Sbp{ 143191040Sarr struct mod_metadata *mp, **mdp; 143291040Sarr const char *modname; 143391040Sarr int ver; 143474642Sbp 143591040Sarr for (mdp = start; mdp < stop; mdp++) { 1436109605Sjake mp = *mdp; 143791040Sarr if (mp->md_type != MDT_VERSION) 143891040Sarr continue; 1439109605Sjake modname = mp->md_cval; 1440109605Sjake ver = ((struct mod_version *)mp->md_data)->mv_version; 144191040Sarr if (modlist_lookup(modname, ver) != NULL) { 144291040Sarr printf("module %s already present!\n", modname); 144391040Sarr /* XXX what can we do? this is a build error. :-( */ 144491040Sarr continue; 144591040Sarr } 144691040Sarr modlist_newmodule(modname, ver, lf); 144774642Sbp } 144874642Sbp} 144974642Sbp 145074642Sbpstatic void 145191040Sarrlinker_preload(void *arg) 145240159Speter{ 145391040Sarr caddr_t modptr; 145491040Sarr const char *modname, *nmodname; 145591040Sarr char *modtype; 1456160244Sjhb linker_file_t lf, nlf; 145791040Sarr linker_class_t lc; 145892032Sdwmalone int error; 145991040Sarr linker_file_list_t loaded_files; 146091040Sarr linker_file_list_t depended_files; 146191040Sarr struct mod_metadata *mp, *nmp; 146291040Sarr struct mod_metadata **start, **stop, **mdp, **nmdp; 146391040Sarr struct mod_depend *verinfo; 146491040Sarr int nver; 146591040Sarr int resolves; 146691040Sarr modlist_t mod; 146791040Sarr struct sysinit **si_start, **si_stop; 146840159Speter 146991040Sarr TAILQ_INIT(&loaded_files); 147091040Sarr TAILQ_INIT(&depended_files); 147191040Sarr TAILQ_INIT(&found_modules); 147291040Sarr error = 0; 147359751Speter 147491040Sarr modptr = NULL; 1475254810Smarkj sx_xlock(&kld_sx); 147691040Sarr while ((modptr = preload_search_next_name(modptr)) != NULL) { 147791040Sarr modname = (char *)preload_search_info(modptr, MODINFO_NAME); 147891040Sarr modtype = (char *)preload_search_info(modptr, MODINFO_TYPE); 147991040Sarr if (modname == NULL) { 148091040Sarr printf("Preloaded module at %p does not have a" 148191040Sarr " name!\n", modptr); 148291040Sarr continue; 148391040Sarr } 148491040Sarr if (modtype == NULL) { 148591040Sarr printf("Preloaded module at %p does not have a type!\n", 148691040Sarr modptr); 148791040Sarr continue; 148891040Sarr } 1489131398Sjhb if (bootverbose) 1490131398Sjhb printf("Preloaded %s \"%s\" at %p.\n", modtype, modname, 1491131398Sjhb modptr); 149240159Speter lf = NULL; 149391040Sarr TAILQ_FOREACH(lc, &classes, link) { 149491040Sarr error = LINKER_LINK_PRELOAD(lc, modname, &lf); 1495134364Siedowse if (!error) 149691040Sarr break; 1497134364Siedowse lf = NULL; 149891040Sarr } 149991040Sarr if (lf) 150091040Sarr TAILQ_INSERT_TAIL(&loaded_files, lf, loaded); 150140159Speter } 150240159Speter 150391040Sarr /* 150491040Sarr * First get a list of stuff in the kernel. 150591040Sarr */ 150691040Sarr if (linker_file_lookup_set(linker_kernel_file, MDT_SETNAME, &start, 150791040Sarr &stop, NULL) == 0) 150891040Sarr linker_addmodules(linker_kernel_file, start, stop, 1); 150959751Speter 151059751Speter /* 1511167019Sjhb * This is a once-off kinky bubble sort to resolve relocation 1512167019Sjhb * dependency requirements. 151359751Speter */ 151491040Sarrrestart: 151591040Sarr TAILQ_FOREACH(lf, &loaded_files, loaded) { 151691040Sarr error = linker_file_lookup_set(lf, MDT_SETNAME, &start, 151791040Sarr &stop, NULL); 151891040Sarr /* 151991040Sarr * First, look to see if we would successfully link with this 152091040Sarr * stuff. 152191040Sarr */ 152291040Sarr resolves = 1; /* unless we know otherwise */ 152391040Sarr if (!error) { 152491040Sarr for (mdp = start; mdp < stop; mdp++) { 1525109605Sjake mp = *mdp; 152691040Sarr if (mp->md_type != MDT_DEPEND) 152791040Sarr continue; 1528109605Sjake modname = mp->md_cval; 1529109605Sjake verinfo = mp->md_data; 153091040Sarr for (nmdp = start; nmdp < stop; nmdp++) { 1531109605Sjake nmp = *nmdp; 153291040Sarr if (nmp->md_type != MDT_VERSION) 153391040Sarr continue; 1534109605Sjake nmodname = nmp->md_cval; 153592032Sdwmalone if (strcmp(modname, nmodname) == 0) 153691040Sarr break; 153791040Sarr } 153891040Sarr if (nmdp < stop) /* it's a self reference */ 153991040Sarr continue; 1540159840Sjhb 154191040Sarr /* 154291040Sarr * ok, the module isn't here yet, we 154391040Sarr * are not finished 154491040Sarr */ 154591068Sarr if (modlist_lookup2(modname, verinfo) == NULL) 154691040Sarr resolves = 0; 154791040Sarr } 154864143Speter } 154991040Sarr /* 155091040Sarr * OK, if we found our modules, we can link. So, "provide" 155191040Sarr * the modules inside and add it to the end of the link order 155291040Sarr * list. 155391040Sarr */ 155491040Sarr if (resolves) { 155591040Sarr if (!error) { 155691040Sarr for (mdp = start; mdp < stop; mdp++) { 1557109605Sjake mp = *mdp; 155891040Sarr if (mp->md_type != MDT_VERSION) 155991040Sarr continue; 1560109605Sjake modname = mp->md_cval; 1561109605Sjake nver = ((struct mod_version *) 1562109605Sjake mp->md_data)->mv_version; 156391040Sarr if (modlist_lookup(modname, 156491040Sarr nver) != NULL) { 156591040Sarr printf("module %s already" 156691040Sarr " present!\n", modname); 1567160244Sjhb TAILQ_REMOVE(&loaded_files, 1568160244Sjhb lf, loaded); 1569132117Sphk linker_file_unload(lf, 1570132117Sphk LINKER_UNLOAD_FORCE); 157191040Sarr /* we changed tailq next ptr */ 157291068Sarr goto restart; 157391040Sarr } 157491040Sarr modlist_newmodule(modname, nver, lf); 157591040Sarr } 157691040Sarr } 157791040Sarr TAILQ_REMOVE(&loaded_files, lf, loaded); 157891040Sarr TAILQ_INSERT_TAIL(&depended_files, lf, loaded); 157991040Sarr /* 158091040Sarr * Since we provided modules, we need to restart the 158191040Sarr * sort so that the previous files that depend on us 158291040Sarr * have a chance. Also, we've busted the tailq next 158391040Sarr * pointer with the REMOVE. 158491040Sarr */ 158591040Sarr goto restart; 158659751Speter } 158759751Speter } 158891040Sarr 158959751Speter /* 159091040Sarr * At this point, we check to see what could not be resolved.. 159159751Speter */ 1592160242Sjhb while ((lf = TAILQ_FIRST(&loaded_files)) != NULL) { 1593160242Sjhb TAILQ_REMOVE(&loaded_files, lf, loaded); 159491040Sarr printf("KLD file %s is missing dependencies\n", lf->filename); 1595132117Sphk linker_file_unload(lf, LINKER_UNLOAD_FORCE); 159640159Speter } 159759751Speter 159878161Speter /* 159991040Sarr * We made it. Finish off the linking in the order we determined. 160078161Speter */ 1601160244Sjhb TAILQ_FOREACH_SAFE(lf, &depended_files, loaded, nlf) { 160291040Sarr if (linker_kernel_file) { 160391040Sarr linker_kernel_file->refs++; 160491040Sarr error = linker_file_add_dependency(lf, 160591040Sarr linker_kernel_file); 160691040Sarr if (error) 160791040Sarr panic("cannot add dependency"); 160891040Sarr } 160991040Sarr lf->userrefs++; /* so we can (try to) kldunload it */ 161091040Sarr error = linker_file_lookup_set(lf, MDT_SETNAME, &start, 161191040Sarr &stop, NULL); 161291040Sarr if (!error) { 161391040Sarr for (mdp = start; mdp < stop; mdp++) { 1614109605Sjake mp = *mdp; 161591040Sarr if (mp->md_type != MDT_DEPEND) 161691040Sarr continue; 1617109605Sjake modname = mp->md_cval; 1618109605Sjake verinfo = mp->md_data; 161991040Sarr mod = modlist_lookup2(modname, verinfo); 1620216988Strasz if (mod == NULL) { 1621216988Strasz printf("KLD file %s - cannot find " 1622216988Strasz "dependency \"%s\"\n", 1623216988Strasz lf->filename, modname); 1624216988Strasz goto fail; 1625216988Strasz } 1626151484Sjdp /* Don't count self-dependencies */ 1627151484Sjdp if (lf == mod->container) 1628151484Sjdp continue; 162991040Sarr mod->container->refs++; 163091040Sarr error = linker_file_add_dependency(lf, 163191040Sarr mod->container); 163291040Sarr if (error) 163391040Sarr panic("cannot add dependency"); 163491040Sarr } 163591040Sarr } 163691040Sarr /* 163791040Sarr * Now do relocation etc using the symbol search paths 163891040Sarr * established by the dependencies 163991040Sarr */ 164091040Sarr error = LINKER_LINK_PRELOAD_FINISH(lf); 164191040Sarr if (error) { 164291040Sarr printf("KLD file %s - could not finalize loading\n", 164391040Sarr lf->filename); 1644216988Strasz goto fail; 164591040Sarr } 164691040Sarr linker_file_register_modules(lf); 164791040Sarr if (linker_file_lookup_set(lf, "sysinit_set", &si_start, 164891040Sarr &si_stop, NULL) == 0) 164991040Sarr sysinit_add(si_start, si_stop); 1650324749Savg linker_file_register_sysctls(lf, true); 165191040Sarr lf->flags |= LINKER_FILE_LINKED; 1652216988Strasz continue; 1653216988Straszfail: 1654216988Strasz TAILQ_REMOVE(&depended_files, lf, loaded); 1655216988Strasz linker_file_unload(lf, LINKER_UNLOAD_FORCE); 165659751Speter } 1657254810Smarkj sx_xunlock(&kld_sx); 165891040Sarr /* woohoo! we made it! */ 165940159Speter} 166040159Speter 1661177253SrwatsonSYSINIT(preload, SI_SUB_KLD, SI_ORDER_MIDDLE, linker_preload, 0); 166240159Speter 166340159Speter/* 166440159Speter * Search for a not-loaded module by name. 1665159840Sjhb * 166640159Speter * Modules may be found in the following locations: 1667159840Sjhb * 166891040Sarr * - preloaded (result is just the module name) - on disk (result is full path 166991040Sarr * to module) 1670159840Sjhb * 167191040Sarr * If the module name is qualified in any way (contains path, etc.) the we 167291040Sarr * simply return a copy of it. 1673159840Sjhb * 167440159Speter * The search path can be manipulated via sysctl. Note that we use the ';' 167540159Speter * character as a separator to be consistent with the bootloader. 167640159Speter */ 167740159Speter 167883321Speterstatic char linker_hintfile[] = "linker.hints"; 1679111852Srustatic char linker_path[MAXPATHLEN] = "/boot/kernel;/boot/modules"; 168040159Speter 168140159SpeterSYSCTL_STRING(_kern, OID_AUTO, module_path, CTLFLAG_RW, linker_path, 168291040Sarr sizeof(linker_path), "module load search path"); 168340159Speter 168477843SpeterTUNABLE_STR("module_path", linker_path, sizeof(linker_path)); 168570417Speter 168659751Speterstatic char *linker_ext_list[] = { 168783321Speter "", 168859751Speter ".ko", 168959751Speter NULL 169059751Speter}; 169159751Speter 169283321Speter/* 169391040Sarr * Check if file actually exists either with or without extension listed in 169491040Sarr * the linker_ext_list. (probably should be generic for the rest of the 169591040Sarr * kernel) 169683321Speter */ 169759751Speterstatic char * 169891040Sarrlinker_lookup_file(const char *path, int pathlen, const char *name, 169991040Sarr int namelen, struct vattr *vap) 170040159Speter{ 170191040Sarr struct nameidata nd; 170291040Sarr struct thread *td = curthread; /* XXX */ 170391040Sarr char *result, **cpp, *sep; 1704241896Skib int error, len, extlen, reclen, flags; 170591040Sarr enum vtype type; 170640159Speter 170791040Sarr extlen = 0; 170891040Sarr for (cpp = linker_ext_list; *cpp; cpp++) { 170991040Sarr len = strlen(*cpp); 171091040Sarr if (len > extlen) 171191040Sarr extlen = len; 171291040Sarr } 171391040Sarr extlen++; /* trailing '\0' */ 171491040Sarr sep = (path[pathlen - 1] != '/') ? "/" : ""; 171583321Speter 171691040Sarr reclen = pathlen + strlen(sep) + namelen + extlen + 1; 1717111119Simp result = malloc(reclen, M_LINKER, M_WAITOK); 171891040Sarr for (cpp = linker_ext_list; *cpp; cpp++) { 171991040Sarr snprintf(result, reclen, "%.*s%s%.*s%s", pathlen, path, sep, 172091040Sarr namelen, name, *cpp); 172191040Sarr /* 172291040Sarr * Attempt to open the file, and return the path if 172391040Sarr * we succeed and it's a regular file. 172491040Sarr */ 1725241896Skib NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, result, td); 172691040Sarr flags = FREAD; 1727170152Skib error = vn_open(&nd, &flags, 0, NULL); 172891040Sarr if (error == 0) { 172991040Sarr NDFREE(&nd, NDF_ONLY_PNBUF); 173091040Sarr type = nd.ni_vp->v_type; 173191040Sarr if (vap) 1732182371Sattilio VOP_GETATTR(nd.ni_vp, vap, td->td_ucred); 1733175294Sattilio VOP_UNLOCK(nd.ni_vp, 0); 173491406Sjhb vn_close(nd.ni_vp, FREAD, td->td_ucred, td); 173591040Sarr if (type == VREG) 173691040Sarr return (result); 173791040Sarr } 173883321Speter } 173991040Sarr free(result, M_LINKER); 174091040Sarr return (NULL); 174183321Speter} 174283321Speter 174391040Sarr#define INT_ALIGN(base, ptr) ptr = \ 174483321Speter (base) + (((ptr) - (base) + sizeof(int) - 1) & ~(sizeof(int) - 1)) 174583321Speter 174683321Speter/* 174791040Sarr * Lookup KLD which contains requested module in the "linker.hints" file. If 174891040Sarr * version specification is available, then try to find the best KLD. 174983321Speter * Otherwise just find the latest one. 175083321Speter */ 175183321Speterstatic char * 175291040Sarrlinker_hints_lookup(const char *path, int pathlen, const char *modname, 175391040Sarr int modnamelen, struct mod_depend *verinfo) 175483321Speter{ 175591040Sarr struct thread *td = curthread; /* XXX */ 175691406Sjhb struct ucred *cred = td ? td->td_ucred : NULL; 175791040Sarr struct nameidata nd; 175891040Sarr struct vattr vattr, mattr; 175991040Sarr u_char *hints = NULL; 176091040Sarr u_char *cp, *recptr, *bufend, *result, *best, *pathbuf, *sep; 1761231949Skib int error, ival, bestver, *intp, found, flags, clen, blen; 1762231949Skib ssize_t reclen; 176383321Speter 176491040Sarr result = NULL; 176591040Sarr bestver = found = 0; 176683321Speter 176791040Sarr sep = (path[pathlen - 1] != '/') ? "/" : ""; 176891040Sarr reclen = imax(modnamelen, strlen(linker_hintfile)) + pathlen + 176991040Sarr strlen(sep) + 1; 1770111119Simp pathbuf = malloc(reclen, M_LINKER, M_WAITOK); 177191040Sarr snprintf(pathbuf, reclen, "%.*s%s%s", pathlen, path, sep, 177291040Sarr linker_hintfile); 177383321Speter 1774241896Skib NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, pathbuf, td); 177591040Sarr flags = FREAD; 1776170152Skib error = vn_open(&nd, &flags, 0, NULL); 177791040Sarr if (error) 177891040Sarr goto bad; 177991040Sarr NDFREE(&nd, NDF_ONLY_PNBUF); 178091040Sarr if (nd.ni_vp->v_type != VREG) 178191040Sarr goto bad; 178291040Sarr best = cp = NULL; 1783182371Sattilio error = VOP_GETATTR(nd.ni_vp, &vattr, cred); 178491040Sarr if (error) 178591040Sarr goto bad; 178691040Sarr /* 178791040Sarr * XXX: we need to limit this number to some reasonable value 178891040Sarr */ 178991040Sarr if (vattr.va_size > 100 * 1024) { 179091040Sarr printf("hints file too large %ld\n", (long)vattr.va_size); 179191040Sarr goto bad; 179291040Sarr } 1793111119Simp hints = malloc(vattr.va_size, M_TEMP, M_WAITOK); 179491068Sarr error = vn_rdwr(UIO_READ, nd.ni_vp, (caddr_t)hints, vattr.va_size, 0, 1795101941Srwatson UIO_SYSSPACE, IO_NODELOCKED, cred, NOCRED, &reclen, td); 179691040Sarr if (error) 179791040Sarr goto bad; 1798175294Sattilio VOP_UNLOCK(nd.ni_vp, 0); 179991040Sarr vn_close(nd.ni_vp, FREAD, cred, td); 180091040Sarr nd.ni_vp = NULL; 180191040Sarr if (reclen != 0) { 1802231949Skib printf("can't read %zd\n", reclen); 180391040Sarr goto bad; 180491040Sarr } 180591040Sarr intp = (int *)hints; 180683321Speter ival = *intp++; 180791040Sarr if (ival != LINKER_HINTS_VERSION) { 180891040Sarr printf("hints file version mismatch %d\n", ival); 180991040Sarr goto bad; 181083321Speter } 181191040Sarr bufend = hints + vattr.va_size; 181291040Sarr recptr = (u_char *)intp; 181391040Sarr clen = blen = 0; 181491040Sarr while (recptr < bufend && !found) { 181591040Sarr intp = (int *)recptr; 181691040Sarr reclen = *intp++; 181791040Sarr ival = *intp++; 181891040Sarr cp = (char *)intp; 181991040Sarr switch (ival) { 182091040Sarr case MDT_VERSION: 182191040Sarr clen = *cp++; 182291040Sarr if (clen != modnamelen || bcmp(cp, modname, clen) != 0) 182391040Sarr break; 182491040Sarr cp += clen; 182591040Sarr INT_ALIGN(hints, cp); 182691040Sarr ival = *(int *)cp; 182791040Sarr cp += sizeof(int); 182891040Sarr clen = *cp++; 182991040Sarr if (verinfo == NULL || 183091040Sarr ival == verinfo->md_ver_preferred) { 183191040Sarr found = 1; 183291040Sarr break; 183391040Sarr } 183491040Sarr if (ival >= verinfo->md_ver_minimum && 183591040Sarr ival <= verinfo->md_ver_maximum && 183691040Sarr ival > bestver) { 183791040Sarr bestver = ival; 183891040Sarr best = cp; 183991040Sarr blen = clen; 184091040Sarr } 184191040Sarr break; 184291040Sarr default: 184391040Sarr break; 184491040Sarr } 184591040Sarr recptr += reclen + sizeof(int); 184691040Sarr } 184783321Speter /* 184891040Sarr * Finally check if KLD is in the place 184983321Speter */ 185091040Sarr if (found) 185191040Sarr result = linker_lookup_file(path, pathlen, cp, clen, &mattr); 185291040Sarr else if (best) 185391040Sarr result = linker_lookup_file(path, pathlen, best, blen, &mattr); 185491040Sarr 185591040Sarr /* 185691040Sarr * KLD is newer than hints file. What we should do now? 185791040Sarr */ 185891040Sarr if (result && timespeccmp(&mattr.va_mtime, &vattr.va_mtime, >)) 185991040Sarr printf("warning: KLD '%s' is newer than the linker.hints" 186091040Sarr " file\n", result); 186183321Speterbad: 1862105167Sphk free(pathbuf, M_LINKER); 186391040Sarr if (hints) 186491040Sarr free(hints, M_TEMP); 186599553Sjeff if (nd.ni_vp != NULL) { 1866175294Sattilio VOP_UNLOCK(nd.ni_vp, 0); 186791040Sarr vn_close(nd.ni_vp, FREAD, cred, td); 186899553Sjeff } 186991040Sarr /* 187091040Sarr * If nothing found or hints is absent - fallback to the old 187191040Sarr * way by using "kldname[.ko]" as module name. 187291040Sarr */ 187391040Sarr if (!found && !bestver && result == NULL) 187491040Sarr result = linker_lookup_file(path, pathlen, modname, 187591040Sarr modnamelen, NULL); 187691040Sarr return (result); 187783321Speter} 187883321Speter 187983321Speter/* 188083321Speter * Lookup KLD which contains requested module in the all directories. 188183321Speter */ 188283321Speterstatic char * 188383321Speterlinker_search_module(const char *modname, int modnamelen, 188491040Sarr struct mod_depend *verinfo) 188583321Speter{ 188691040Sarr char *cp, *ep, *result; 188783321Speter 188891040Sarr /* 188991040Sarr * traverse the linker path 189091040Sarr */ 189191040Sarr for (cp = linker_path; *cp; cp = ep + 1) { 189291040Sarr /* find the end of this component */ 189391040Sarr for (ep = cp; (*ep != 0) && (*ep != ';'); ep++); 189491068Sarr result = linker_hints_lookup(cp, ep - cp, modname, 189591068Sarr modnamelen, verinfo); 189691040Sarr if (result != NULL) 189791040Sarr return (result); 189891040Sarr if (*ep == 0) 189991040Sarr break; 190091040Sarr } 190191040Sarr return (NULL); 190283321Speter} 190383321Speter 190483321Speter/* 190583321Speter * Search for module in all directories listed in the linker_path. 190683321Speter */ 190783321Speterstatic char * 190883321Speterlinker_search_kld(const char *name) 190983321Speter{ 1910158972Sdelphij char *cp, *ep, *result; 1911158972Sdelphij int len; 191283321Speter 191391040Sarr /* qualified at all? */ 1914229272Sed if (strchr(name, '/')) 1915254396Smarkj return (strdup(name, M_LINKER)); 191640159Speter 191791040Sarr /* traverse the linker path */ 191891040Sarr len = strlen(name); 191991040Sarr for (ep = linker_path; *ep; ep++) { 192091040Sarr cp = ep; 192191040Sarr /* find the end of this component */ 192291040Sarr for (; *ep != 0 && *ep != ';'; ep++); 192391040Sarr result = linker_lookup_file(cp, ep - cp, name, len, NULL); 192491040Sarr if (result != NULL) 192591040Sarr return (result); 192691040Sarr } 192791040Sarr return (NULL); 192840159Speter} 192959751Speter 193059751Speterstatic const char * 193191040Sarrlinker_basename(const char *path) 193259751Speter{ 193391040Sarr const char *filename; 193459751Speter 1935229272Sed filename = strrchr(path, '/'); 193691040Sarr if (filename == NULL) 193791040Sarr return path; 193891040Sarr if (filename[1]) 193991040Sarr filename++; 194091040Sarr return (filename); 194159751Speter} 194259751Speter 1943157144Sjkoshy#ifdef HWPMC_HOOKS 194459751Speter/* 1945157144Sjkoshy * Inform hwpmc about the set of kernel modules currently loaded. 1946157144Sjkoshy */ 1947157144Sjkoshyvoid * 1948157144Sjkoshylinker_hwpmc_list_objects(void) 1949157144Sjkoshy{ 1950195159Sattilio linker_file_t lf; 1951195159Sattilio struct pmckern_map_in *kobase; 1952195159Sattilio int i, nmappings; 1953157144Sjkoshy 1954195159Sattilio nmappings = 0; 1955254810Smarkj sx_slock(&kld_sx); 1956195159Sattilio TAILQ_FOREACH(lf, &linker_files, link) 1957195159Sattilio nmappings++; 1958157144Sjkoshy 1959195159Sattilio /* Allocate nmappings + 1 entries. */ 1960195159Sattilio kobase = malloc((nmappings + 1) * sizeof(struct pmckern_map_in), 1961184214Sdes M_LINKER, M_WAITOK | M_ZERO); 1962195159Sattilio i = 0; 1963195159Sattilio TAILQ_FOREACH(lf, &linker_files, link) { 1964157144Sjkoshy 1965195159Sattilio /* Save the info for this linker file. */ 1966195159Sattilio kobase[i].pm_file = lf->filename; 1967195159Sattilio kobase[i].pm_address = (uintptr_t)lf->address; 1968195159Sattilio i++; 1969157144Sjkoshy } 1970254810Smarkj sx_sunlock(&kld_sx); 1971157144Sjkoshy 1972195159Sattilio KASSERT(i > 0, ("linker_hpwmc_list_objects: no kernel objects?")); 1973157144Sjkoshy 1974157144Sjkoshy /* The last entry of the malloced area comprises of all zeros. */ 1975195159Sattilio KASSERT(kobase[i].pm_file == NULL, 1976157144Sjkoshy ("linker_hwpmc_list_objects: last object not NULL")); 1977157144Sjkoshy 1978195159Sattilio return ((void *)kobase); 1979157144Sjkoshy} 1980157144Sjkoshy#endif 1981157144Sjkoshy 1982157144Sjkoshy/* 198391040Sarr * Find a file which contains given module and load it, if "parent" is not 198491040Sarr * NULL, register a reference to it. 198559751Speter */ 1986159796Sjhbstatic int 198783321Speterlinker_load_module(const char *kldname, const char *modname, 198891040Sarr struct linker_file *parent, struct mod_depend *verinfo, 198991040Sarr struct linker_file **lfpp) 199059751Speter{ 199191040Sarr linker_file_t lfdep; 199291040Sarr const char *filename; 199391040Sarr char *pathname; 199491040Sarr int error; 199559751Speter 1996254810Smarkj sx_assert(&kld_sx, SA_XLOCKED); 199791040Sarr if (modname == NULL) { 199891040Sarr /* 199991040Sarr * We have to load KLD 200091040Sarr */ 200191068Sarr KASSERT(verinfo == NULL, ("linker_load_module: verinfo" 200291068Sarr " is not NULL")); 2003355419Shselasky /* check if root file system is not mounted */ 2004355419Shselasky if (rootvnode == NULL || curproc->p_fd->fd_rdir == NULL) 2005355419Shselasky return (ENXIO); 200691040Sarr pathname = linker_search_kld(kldname); 200791040Sarr } else { 200891040Sarr if (modlist_lookup2(modname, verinfo) != NULL) 200991040Sarr return (EEXIST); 2010355419Shselasky /* check if root file system is not mounted */ 2011355419Shselasky if (rootvnode == NULL || curproc->p_fd->fd_rdir == NULL) 2012355419Shselasky return (ENXIO); 201394322Sbrian if (kldname != NULL) 2014254396Smarkj pathname = strdup(kldname, M_LINKER); 201594322Sbrian else 201691040Sarr /* 201791040Sarr * Need to find a KLD with required module 201891040Sarr */ 201991040Sarr pathname = linker_search_module(modname, 202091040Sarr strlen(modname), verinfo); 202191040Sarr } 202291040Sarr if (pathname == NULL) 202391040Sarr return (ENOENT); 202491040Sarr 202583321Speter /* 202691040Sarr * Can't load more than one file with the same basename XXX: 202791040Sarr * Actually it should be possible to have multiple KLDs with 202891040Sarr * the same basename but different path because they can 202991040Sarr * provide different versions of the same modules. 203083321Speter */ 203191040Sarr filename = linker_basename(pathname); 2032159792Sjhb if (linker_find_file_by_name(filename)) 203391040Sarr error = EEXIST; 2034159792Sjhb else do { 203591040Sarr error = linker_load_file(pathname, &lfdep); 203691040Sarr if (error) 203791040Sarr break; 203891040Sarr if (modname && verinfo && 203991040Sarr modlist_lookup2(modname, verinfo) == NULL) { 2040132117Sphk linker_file_unload(lfdep, LINKER_UNLOAD_FORCE); 204191040Sarr error = ENOENT; 204291040Sarr break; 204391040Sarr } 204491040Sarr if (parent) { 204591040Sarr error = linker_file_add_dependency(parent, lfdep); 204691040Sarr if (error) 204791040Sarr break; 204891040Sarr } 204991040Sarr if (lfpp) 205091040Sarr *lfpp = lfdep; 205191040Sarr } while (0); 2052159791Sjhb free(pathname, M_LINKER); 205391040Sarr return (error); 205459751Speter} 205559751Speter 205659751Speter/* 205791040Sarr * This routine is responsible for finding dependencies of userland initiated 205891040Sarr * kldload(2)'s of files. 205959751Speter */ 206059751Speterint 206186469Siedowselinker_load_dependencies(linker_file_t lf) 206259751Speter{ 206391040Sarr linker_file_t lfdep; 206491040Sarr struct mod_metadata **start, **stop, **mdp, **nmdp; 206591040Sarr struct mod_metadata *mp, *nmp; 206691040Sarr struct mod_depend *verinfo; 206791040Sarr modlist_t mod; 206891040Sarr const char *modname, *nmodname; 206992032Sdwmalone int ver, error = 0, count; 207059751Speter 207191040Sarr /* 2072302234Sbdrewery * All files are dependent on /kernel. 207391040Sarr */ 2074254810Smarkj sx_assert(&kld_sx, SA_XLOCKED); 207591040Sarr if (linker_kernel_file) { 207691040Sarr linker_kernel_file->refs++; 207791040Sarr error = linker_file_add_dependency(lf, linker_kernel_file); 207891040Sarr if (error) 207991040Sarr return (error); 208059751Speter } 208191040Sarr if (linker_file_lookup_set(lf, MDT_SETNAME, &start, &stop, 208291040Sarr &count) != 0) 208391040Sarr return (0); 208491040Sarr for (mdp = start; mdp < stop; mdp++) { 2085109605Sjake mp = *mdp; 208691040Sarr if (mp->md_type != MDT_VERSION) 208791040Sarr continue; 2088109605Sjake modname = mp->md_cval; 2089109605Sjake ver = ((struct mod_version *)mp->md_data)->mv_version; 209091040Sarr mod = modlist_lookup(modname, ver); 209191040Sarr if (mod != NULL) { 209291040Sarr printf("interface %s.%d already present in the KLD" 209391040Sarr " '%s'!\n", modname, ver, 209491040Sarr mod->container->filename); 209591040Sarr return (EEXIST); 209691040Sarr } 209791040Sarr } 209874642Sbp 209991040Sarr for (mdp = start; mdp < stop; mdp++) { 2100109605Sjake mp = *mdp; 210191040Sarr if (mp->md_type != MDT_DEPEND) 210291040Sarr continue; 2103109605Sjake modname = mp->md_cval; 2104109605Sjake verinfo = mp->md_data; 210591040Sarr nmodname = NULL; 210691040Sarr for (nmdp = start; nmdp < stop; nmdp++) { 2107109605Sjake nmp = *nmdp; 210891040Sarr if (nmp->md_type != MDT_VERSION) 210991040Sarr continue; 2110109605Sjake nmodname = nmp->md_cval; 211192032Sdwmalone if (strcmp(modname, nmodname) == 0) 211291040Sarr break; 211391040Sarr } 211491040Sarr if (nmdp < stop)/* early exit, it's a self reference */ 211591040Sarr continue; 211691040Sarr mod = modlist_lookup2(modname, verinfo); 211791040Sarr if (mod) { /* woohoo, it's loaded already */ 211891040Sarr lfdep = mod->container; 211991040Sarr lfdep->refs++; 212091040Sarr error = linker_file_add_dependency(lf, lfdep); 212191040Sarr if (error) 212291040Sarr break; 212391040Sarr continue; 212491040Sarr } 212591040Sarr error = linker_load_module(NULL, modname, lf, verinfo, NULL); 212691040Sarr if (error) { 2127231931Sdelphij printf("KLD %s: depends on %s - not available or" 2128195803Srpaulo " version mismatch\n", lf->filename, modname); 212991040Sarr break; 213091040Sarr } 213159751Speter } 213259751Speter 213391040Sarr if (error) 213491040Sarr return (error); 213591040Sarr linker_addmodules(lf, start, stop, 0); 213691040Sarr return (error); 213759751Speter} 213885736Sgreen 213985736Sgreenstatic int 214085736Sgreensysctl_kern_function_list_iterate(const char *name, void *opaque) 214185736Sgreen{ 214285736Sgreen struct sysctl_req *req; 214385736Sgreen 214485736Sgreen req = opaque; 214585736Sgreen return (SYSCTL_OUT(req, name, strlen(name) + 1)); 214685736Sgreen} 214785736Sgreen 214885736Sgreen/* 214985736Sgreen * Export a nul-separated, double-nul-terminated list of all function names 215085736Sgreen * in the kernel. 215185736Sgreen */ 215285736Sgreenstatic int 215385736Sgreensysctl_kern_function_list(SYSCTL_HANDLER_ARGS) 215485736Sgreen{ 215585736Sgreen linker_file_t lf; 215685736Sgreen int error; 215785736Sgreen 2158107089Srwatson#ifdef MAC 2159172930Srwatson error = mac_kld_check_stat(req->td->td_ucred); 2160107089Srwatson if (error) 2161107089Srwatson return (error); 2162107089Srwatson#endif 2163126253Struckman error = sysctl_wire_old_buffer(req, 0); 2164126253Struckman if (error != 0) 2165126253Struckman return (error); 2166254810Smarkj sx_xlock(&kld_sx); 216785736Sgreen TAILQ_FOREACH(lf, &linker_files, link) { 216885736Sgreen error = LINKER_EACH_FUNCTION_NAME(lf, 216985736Sgreen sysctl_kern_function_list_iterate, req); 217098452Sarr if (error) { 2171254810Smarkj sx_xunlock(&kld_sx); 217285736Sgreen return (error); 217398452Sarr } 217485736Sgreen } 2175254810Smarkj sx_xunlock(&kld_sx); 217685736Sgreen return (SYSCTL_OUT(req, "", 1)); 217785736Sgreen} 217885736Sgreen 2179217555SmdfSYSCTL_PROC(_kern, OID_AUTO, function_list, CTLTYPE_OPAQUE | CTLFLAG_RD, 218091040Sarr NULL, 0, sysctl_kern_function_list, "", "kernel function list"); 2181