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/11/sys/kern/kern_linker.c 359652 2020-04-06 07:16:31Z 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 57301751Scem#ifdef DDB 58301751Scem#include <ddb/ddb.h> 59301751Scem#endif 60301751Scem 61196019Srwatson#include <net/vnet.h> 62196019Srwatson 63163606Srwatson#include <security/mac/mac_framework.h> 64163606Srwatson 6559603Sdfr#include "linker_if.h" 6659603Sdfr 67157144Sjkoshy#ifdef HWPMC_HOOKS 68157144Sjkoshy#include <sys/pmckern.h> 69157144Sjkoshy#endif 70157144Sjkoshy 7140961Speter#ifdef KLD_DEBUG 7240961Speterint kld_debug = 0; 73267992ShselaskySYSCTL_INT(_debug, OID_AUTO, kld_debug, CTLFLAG_RWTUN, 74232999Sae &kld_debug, 0, "Set various levels of KLD debug"); 7540961Speter#endif 7640961Speter 77290728Sjhb/* These variables are used by kernel debuggers to enumerate loaded files. */ 78290728Sjhbconst int kld_off_address = offsetof(struct linker_file, address); 79290728Sjhbconst int kld_off_filename = offsetof(struct linker_file, filename); 80290728Sjhbconst int kld_off_pathname = offsetof(struct linker_file, pathname); 81290728Sjhbconst int kld_off_next = offsetof(struct linker_file, link.tqe_next); 82290728Sjhb 8391040Sarr/* 8491040Sarr * static char *linker_search_path(const char *name, struct mod_depend 8591040Sarr * *verinfo); 8691040Sarr */ 8791040Sarrstatic const char *linker_basename(const char *path); 8859751Speter 89159800Sjhb/* 90159800Sjhb * Find a currently loaded file given its filename. 91159800Sjhb */ 92159800Sjhbstatic linker_file_t linker_find_file_by_name(const char* _filename); 93159800Sjhb 94159800Sjhb/* 95159800Sjhb * Find a currently loaded file given its file id. 96159800Sjhb */ 97159800Sjhbstatic linker_file_t linker_find_file_by_id(int _fileid); 98159800Sjhb 9978161Speter/* Metadata from the static kernel */ 10078161SpeterSET_DECLARE(modmetadata_set, struct mod_metadata); 10178161Speter 10259751SpeterMALLOC_DEFINE(M_LINKER, "linker", "kernel linker"); 10359751Speter 10440906Speterlinker_file_t linker_kernel_file; 10531324Sbde 106159845Sjhbstatic struct sx kld_sx; /* kernel linker lock */ 10798452Sarr 108172862Sjb/* 109172862Sjb * Load counter used by clients to determine if a linker file has been 110172862Sjb * re-loaded. This counter is incremented for each file load. 111172862Sjb */ 112172862Sjbstatic int loadcnt; 113172862Sjb 11425537Sdfrstatic linker_class_list_t classes; 11550068Sgrogstatic linker_file_list_t linker_files; 11625537Sdfrstatic int next_file_id = 1; 11798452Sarrstatic int linker_no_more_classes = 0; 11825537Sdfr 11986553Sarr#define LINKER_GET_NEXT_FILE_ID(a) do { \ 12091040Sarr linker_file_t lftmp; \ 12186553Sarr \ 122254810Smarkj if (!cold) \ 123254810Smarkj sx_assert(&kld_sx, SA_XLOCKED); \ 12486553Sarrretry: \ 12591040Sarr TAILQ_FOREACH(lftmp, &linker_files, link) { \ 12691040Sarr if (next_file_id == lftmp->id) { \ 12791040Sarr next_file_id++; \ 12891040Sarr goto retry; \ 12991040Sarr } \ 13091040Sarr } \ 13191040Sarr (a) = next_file_id; \ 13286553Sarr} while(0) 13386553Sarr 13486553Sarr 13559751Speter/* XXX wrong name; we're looking at version provision tags here, not modules */ 13660938Sjaketypedef TAILQ_HEAD(, modlist) modlisthead_t; 13759751Speterstruct modlist { 13891040Sarr TAILQ_ENTRY(modlist) link; /* chain together all modules */ 13991040Sarr linker_file_t container; 14091040Sarr const char *name; 14191040Sarr int version; 14259751Speter}; 14391040Sarrtypedef struct modlist *modlist_t; 14491040Sarrstatic modlisthead_t found_modules; 14559751Speter 146159796Sjhbstatic int linker_file_add_dependency(linker_file_t file, 147159796Sjhb linker_file_t dep); 148159845Sjhbstatic caddr_t linker_file_lookup_symbol_internal(linker_file_t file, 149159845Sjhb const char* name, int deps); 150159796Sjhbstatic int linker_load_module(const char *kldname, 151159796Sjhb const char *modname, struct linker_file *parent, 152275469Simp const struct mod_depend *verinfo, struct linker_file **lfpp); 153275469Simpstatic modlist_t modlist_lookup2(const char *name, const struct mod_depend *verinfo); 15494321Sbrian 15525537Sdfrstatic void 15691040Sarrlinker_init(void *arg) 15725537Sdfr{ 15891040Sarr 159159845Sjhb sx_init(&kld_sx, "kernel linker"); 16091040Sarr TAILQ_INIT(&classes); 16191040Sarr TAILQ_INIT(&linker_files); 16225537Sdfr} 16325537Sdfr 164359652ShselaskySYSINIT(linker, SI_SUB_KLD, SI_ORDER_FIRST, linker_init, NULL); 16525537Sdfr 16698452Sarrstatic void 16798452Sarrlinker_stop_class_add(void *arg) 16898452Sarr{ 16998452Sarr 17098452Sarr linker_no_more_classes = 1; 17198452Sarr} 17298452Sarr 173177253SrwatsonSYSINIT(linker_class, SI_SUB_KLD, SI_ORDER_ANY, linker_stop_class_add, NULL); 17498452Sarr 17525537Sdfrint 17659603Sdfrlinker_add_class(linker_class_t lc) 17725537Sdfr{ 17891040Sarr 17998452Sarr /* 180144443Sjhb * We disallow any class registration past SI_ORDER_ANY 181144443Sjhb * of SI_SUB_KLD. We bump the reference count to keep the 182144443Sjhb * ops from being freed. 18398452Sarr */ 18498452Sarr if (linker_no_more_classes == 1) 18598452Sarr return (EPERM); 18691040Sarr kobj_class_compile((kobj_class_t) lc); 187144443Sjhb ((kobj_class_t)lc)->refs++; /* XXX: kobj_mtx */ 18891040Sarr TAILQ_INSERT_TAIL(&classes, lc, link); 18991040Sarr return (0); 19025537Sdfr} 19125537Sdfr 19225537Sdfrstatic void 19325537Sdfrlinker_file_sysinit(linker_file_t lf) 19425537Sdfr{ 19591040Sarr struct sysinit **start, **stop, **sipp, **xipp, *save; 19625537Sdfr 19791040Sarr KLD_DPF(FILE, ("linker_file_sysinit: calling SYSINITs for %s\n", 19891040Sarr lf->filename)); 19925537Sdfr 200254811Smarkj sx_assert(&kld_sx, SA_XLOCKED); 201254811Smarkj 202284160Sjhb if (linker_file_lookup_set(lf, "sysinit_set", &start, &stop, NULL) != 0) 20391040Sarr return; 20491040Sarr /* 20591040Sarr * Perform a bubble sort of the system initialization objects by 20691040Sarr * their subsystem (primary key) and order (secondary key). 207159840Sjhb * 20891040Sarr * Since some things care about execution order, this is the operation 20991040Sarr * which ensures continued function. 21091040Sarr */ 21191040Sarr for (sipp = start; sipp < stop; sipp++) { 21291040Sarr for (xipp = sipp + 1; xipp < stop; xipp++) { 21391040Sarr if ((*sipp)->subsystem < (*xipp)->subsystem || 21491040Sarr ((*sipp)->subsystem == (*xipp)->subsystem && 21591040Sarr (*sipp)->order <= (*xipp)->order)) 21691040Sarr continue; /* skip */ 21791040Sarr save = *sipp; 21891040Sarr *sipp = *xipp; 21991040Sarr *xipp = save; 22091040Sarr } 22125537Sdfr } 22225537Sdfr 22391040Sarr /* 22491040Sarr * Traverse the (now) ordered list of system initialization tasks. 22591040Sarr * Perform each task, and continue on to the next task. 22691040Sarr */ 227254811Smarkj sx_xunlock(&kld_sx); 228160142Sjhb mtx_lock(&Giant); 22991040Sarr for (sipp = start; sipp < stop; sipp++) { 23091040Sarr if ((*sipp)->subsystem == SI_SUB_DUMMY) 23191040Sarr continue; /* skip dummy task(s) */ 23225537Sdfr 23391040Sarr /* Call function */ 23491040Sarr (*((*sipp)->func)) ((*sipp)->udata); 23591040Sarr } 236160142Sjhb mtx_unlock(&Giant); 237254811Smarkj sx_xlock(&kld_sx); 23825537Sdfr} 23925537Sdfr 24041055Speterstatic void 24141055Speterlinker_file_sysuninit(linker_file_t lf) 24241055Speter{ 24391040Sarr struct sysinit **start, **stop, **sipp, **xipp, *save; 24441055Speter 24591040Sarr KLD_DPF(FILE, ("linker_file_sysuninit: calling SYSUNINITs for %s\n", 24691040Sarr lf->filename)); 24741055Speter 248254811Smarkj sx_assert(&kld_sx, SA_XLOCKED); 249254811Smarkj 250284160Sjhb if (linker_file_lookup_set(lf, "sysuninit_set", &start, &stop, 25191040Sarr NULL) != 0) 25291040Sarr return; 25341055Speter 25491040Sarr /* 25591040Sarr * Perform a reverse bubble sort of the system initialization objects 25691040Sarr * by their subsystem (primary key) and order (secondary key). 257159840Sjhb * 25891040Sarr * Since some things care about execution order, this is the operation 25991040Sarr * which ensures continued function. 26091040Sarr */ 26191040Sarr for (sipp = start; sipp < stop; sipp++) { 26291040Sarr for (xipp = sipp + 1; xipp < stop; xipp++) { 26391040Sarr if ((*sipp)->subsystem > (*xipp)->subsystem || 26491040Sarr ((*sipp)->subsystem == (*xipp)->subsystem && 26591040Sarr (*sipp)->order >= (*xipp)->order)) 26691040Sarr continue; /* skip */ 26791040Sarr save = *sipp; 26891040Sarr *sipp = *xipp; 26991040Sarr *xipp = save; 27091040Sarr } 27141055Speter } 27241055Speter 27391040Sarr /* 27491040Sarr * Traverse the (now) ordered list of system initialization tasks. 27591040Sarr * Perform each task, and continue on to the next task. 27691040Sarr */ 277254811Smarkj sx_xunlock(&kld_sx); 278160142Sjhb mtx_lock(&Giant); 27991040Sarr for (sipp = start; sipp < stop; sipp++) { 28091040Sarr if ((*sipp)->subsystem == SI_SUB_DUMMY) 28191040Sarr continue; /* skip dummy task(s) */ 28241055Speter 28391040Sarr /* Call function */ 28491040Sarr (*((*sipp)->func)) ((*sipp)->udata); 28591040Sarr } 286160142Sjhb mtx_unlock(&Giant); 287254811Smarkj sx_xlock(&kld_sx); 28841055Speter} 28941055Speter 29044078Sdfrstatic void 291324748Savglinker_file_register_sysctls(linker_file_t lf, bool enable) 29244078Sdfr{ 29391040Sarr struct sysctl_oid **start, **stop, **oidp; 29444078Sdfr 29591040Sarr KLD_DPF(FILE, 29691040Sarr ("linker_file_register_sysctls: registering SYSCTLs for %s\n", 29791040Sarr lf->filename)); 29844078Sdfr 299254811Smarkj sx_assert(&kld_sx, SA_XLOCKED); 300254811Smarkj 301284160Sjhb if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0) 30291040Sarr return; 30344078Sdfr 304254811Smarkj sx_xunlock(&kld_sx); 305287835Smjg sysctl_wlock(); 306324748Savg for (oidp = start; oidp < stop; oidp++) { 307324748Savg if (enable) 308324748Savg sysctl_register_oid(*oidp); 309324748Savg else 310324748Savg sysctl_register_disabled_oid(*oidp); 311324748Savg } 312324748Savg sysctl_wunlock(); 313324748Savg sx_xlock(&kld_sx); 314324748Savg} 315324748Savg 316324748Savgstatic void 317324748Savglinker_file_enable_sysctls(linker_file_t lf) 318324748Savg{ 319324748Savg struct sysctl_oid **start, **stop, **oidp; 320324748Savg 321324748Savg KLD_DPF(FILE, 322324748Savg ("linker_file_enable_sysctls: enable SYSCTLs for %s\n", 323324748Savg lf->filename)); 324324748Savg 325324748Savg sx_assert(&kld_sx, SA_XLOCKED); 326324748Savg 327324748Savg if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0) 328324748Savg return; 329324748Savg 330324748Savg sx_xunlock(&kld_sx); 331324748Savg sysctl_wlock(); 33291040Sarr for (oidp = start; oidp < stop; oidp++) 333324748Savg sysctl_enable_oid(*oidp); 334287835Smjg sysctl_wunlock(); 335254811Smarkj sx_xlock(&kld_sx); 33644078Sdfr} 33744078Sdfr 33844078Sdfrstatic void 33944078Sdfrlinker_file_unregister_sysctls(linker_file_t lf) 34044078Sdfr{ 34191040Sarr struct sysctl_oid **start, **stop, **oidp; 34244078Sdfr 343233295Sae KLD_DPF(FILE, ("linker_file_unregister_sysctls: unregistering SYSCTLs" 34491040Sarr " for %s\n", lf->filename)); 34544078Sdfr 346254811Smarkj sx_assert(&kld_sx, SA_XLOCKED); 347254811Smarkj 348284160Sjhb if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0) 34991040Sarr return; 35044078Sdfr 351254811Smarkj sx_xunlock(&kld_sx); 352287835Smjg sysctl_wlock(); 35391040Sarr for (oidp = start; oidp < stop; oidp++) 35491040Sarr sysctl_unregister_oid(*oidp); 355287835Smjg sysctl_wunlock(); 356254811Smarkj sx_xlock(&kld_sx); 35744078Sdfr} 35844078Sdfr 35959751Speterstatic int 36059751Speterlinker_file_register_modules(linker_file_t lf) 36159751Speter{ 36291040Sarr struct mod_metadata **start, **stop, **mdp; 36391040Sarr const moduledata_t *moddata; 364146733Spjd int first_error, error; 36559751Speter 36691040Sarr KLD_DPF(FILE, ("linker_file_register_modules: registering modules" 36791040Sarr " in %s\n", lf->filename)); 36859751Speter 369254811Smarkj sx_assert(&kld_sx, SA_XLOCKED); 370254811Smarkj 371284160Sjhb if (linker_file_lookup_set(lf, "modmetadata_set", &start, 372159841Sjhb &stop, NULL) != 0) { 37391040Sarr /* 37491040Sarr * This fallback should be unnecessary, but if we get booted 37591040Sarr * from boot2 instead of loader and we are missing our 37691040Sarr * metadata then we have to try the best we can. 37791040Sarr */ 37891040Sarr if (lf == linker_kernel_file) { 37991040Sarr start = SET_BEGIN(modmetadata_set); 38091040Sarr stop = SET_LIMIT(modmetadata_set); 38191040Sarr } else 38291040Sarr return (0); 38378161Speter } 384146733Spjd first_error = 0; 38591040Sarr for (mdp = start; mdp < stop; mdp++) { 38691040Sarr if ((*mdp)->md_type != MDT_MODULE) 38791040Sarr continue; 38891040Sarr moddata = (*mdp)->md_data; 38991040Sarr KLD_DPF(FILE, ("Registering module %s in %s\n", 39091040Sarr moddata->name, lf->filename)); 39191040Sarr error = module_register(moddata, lf); 392146730Spjd if (error) { 39391068Sarr printf("Module %s failed to register: %d\n", 39491040Sarr moddata->name, error); 395146733Spjd if (first_error == 0) 396146733Spjd first_error = error; 397146730Spjd } 39859751Speter } 399146733Spjd return (first_error); 40059751Speter} 40159751Speter 40259751Speterstatic void 40359751Speterlinker_init_kernel_modules(void) 40459751Speter{ 40591040Sarr 406254810Smarkj sx_xlock(&kld_sx); 40791040Sarr linker_file_register_modules(linker_kernel_file); 408254810Smarkj sx_xunlock(&kld_sx); 40959751Speter} 41059751Speter 411177253SrwatsonSYSINIT(linker_kernel, SI_SUB_KLD, SI_ORDER_ANY, linker_init_kernel_modules, 412359652Shselasky NULL); 41359751Speter 414101241Smuxstatic int 41591040Sarrlinker_load_file(const char *filename, linker_file_t *result) 41625537Sdfr{ 41791040Sarr linker_class_t lc; 41891040Sarr linker_file_t lf; 419234186Sjhb int foundfile, error, modules; 42025537Sdfr 42191040Sarr /* Refuse to load modules if securelevel raised */ 422192895Sjamie if (prison0.pr_securelevel > 0) 42391040Sarr return (EPERM); 42462261Sarchie 425254810Smarkj sx_assert(&kld_sx, SA_XLOCKED); 42691040Sarr lf = linker_find_file_by_name(filename); 42791040Sarr if (lf) { 42891040Sarr KLD_DPF(FILE, ("linker_load_file: file %s is already loaded," 42991040Sarr " incrementing refs\n", filename)); 43091040Sarr *result = lf; 43191040Sarr lf->refs++; 432159585Sjhb return (0); 43391040Sarr } 43491040Sarr foundfile = 0; 435159585Sjhb error = 0; 43698452Sarr 43798452Sarr /* 43898452Sarr * We do not need to protect (lock) classes here because there is 43998452Sarr * no class registration past startup (SI_SUB_KLD, SI_ORDER_ANY) 44098452Sarr * and there is no class deregistration mechanism at this time. 44198452Sarr */ 44291040Sarr TAILQ_FOREACH(lc, &classes, link) { 44391040Sarr KLD_DPF(FILE, ("linker_load_file: trying to load %s\n", 44491040Sarr filename)); 44591040Sarr error = LINKER_LOAD_FILE(lc, filename, &lf); 44691040Sarr /* 44791040Sarr * If we got something other than ENOENT, then it exists but 44891040Sarr * we cannot load it for some other reason. 44991040Sarr */ 45091040Sarr if (error != ENOENT) 45191040Sarr foundfile = 1; 45291040Sarr if (lf) { 453146730Spjd error = linker_file_register_modules(lf); 454146730Spjd if (error == EEXIST) { 455146730Spjd linker_file_unload(lf, LINKER_UNLOAD_FORCE); 456159585Sjhb return (error); 457146730Spjd } 458234186Sjhb modules = !TAILQ_EMPTY(&lf->modules); 459324748Savg linker_file_register_sysctls(lf, false); 46091040Sarr linker_file_sysinit(lf); 46191040Sarr lf->flags |= LINKER_FILE_LINKED; 462234186Sjhb 463234186Sjhb /* 464234186Sjhb * If all of the modules in this file failed 465234186Sjhb * to load, unload the file and return an 466234186Sjhb * error of ENOEXEC. 467234186Sjhb */ 468234186Sjhb if (modules && TAILQ_EMPTY(&lf->modules)) { 469234186Sjhb linker_file_unload(lf, LINKER_UNLOAD_FORCE); 470234186Sjhb return (ENOEXEC); 471234186Sjhb } 472324748Savg linker_file_enable_sysctls(lf); 473259587Smarkj EVENTHANDLER_INVOKE(kld_load, lf); 47491040Sarr *result = lf; 475159585Sjhb return (0); 47691040Sarr } 47791040Sarr } 47842755Speter /* 47991040Sarr * Less than ideal, but tells the user whether it failed to load or 48091040Sarr * the module was not found. 48142755Speter */ 482105337Ssam if (foundfile) { 483188440Sattilio 484105337Ssam /* 485188440Sattilio * If the file type has not been recognized by the last try 486188440Sattilio * printout a message before to fail. 487188440Sattilio */ 488188440Sattilio if (error == ENOSYS) 489188440Sattilio printf("linker_load_file: Unsupported file type\n"); 490188440Sattilio 491188440Sattilio /* 492105337Ssam * Format not recognized or otherwise unloadable. 493105337Ssam * When loading a module that is statically built into 494105337Ssam * the kernel EEXIST percolates back up as the return 495105337Ssam * value. Preserve this so that apps like sysinstall 496105337Ssam * can recognize this special case and not post bogus 497105337Ssam * dialog boxes. 498105337Ssam */ 499105337Ssam if (error != EEXIST) 500105337Ssam error = ENOEXEC; 501105337Ssam } else 50291068Sarr error = ENOENT; /* Nothing found */ 50391040Sarr return (error); 50425537Sdfr} 50525537Sdfr 50678413Sbrianint 50794321Sbrianlinker_reference_module(const char *modname, struct mod_depend *verinfo, 50894321Sbrian linker_file_t *result) 50978413Sbrian{ 51094321Sbrian modlist_t mod; 511159804Sjhb int error; 51294321Sbrian 513254810Smarkj sx_xlock(&kld_sx); 51494321Sbrian if ((mod = modlist_lookup2(modname, verinfo)) != NULL) { 51594321Sbrian *result = mod->container; 51694321Sbrian (*result)->refs++; 517254810Smarkj sx_xunlock(&kld_sx); 51894321Sbrian return (0); 51994321Sbrian } 52094321Sbrian 521159804Sjhb error = linker_load_module(NULL, modname, NULL, verinfo, result); 522254810Smarkj sx_xunlock(&kld_sx); 523159804Sjhb return (error); 52478413Sbrian} 52578413Sbrian 526159804Sjhbint 527159804Sjhblinker_release_module(const char *modname, struct mod_depend *verinfo, 528159804Sjhb linker_file_t lf) 529159804Sjhb{ 530159804Sjhb modlist_t mod; 531159804Sjhb int error; 532159804Sjhb 533254810Smarkj sx_xlock(&kld_sx); 534159804Sjhb if (lf == NULL) { 535159804Sjhb KASSERT(modname != NULL, 536159804Sjhb ("linker_release_module: no file or name")); 537159804Sjhb mod = modlist_lookup2(modname, verinfo); 538159804Sjhb if (mod == NULL) { 539254810Smarkj sx_xunlock(&kld_sx); 540159804Sjhb return (ESRCH); 541159804Sjhb } 542159804Sjhb lf = mod->container; 543159804Sjhb } else 544159804Sjhb KASSERT(modname == NULL && verinfo == NULL, 545159804Sjhb ("linker_release_module: both file and name")); 546159804Sjhb error = linker_file_unload(lf, LINKER_UNLOAD_NORMAL); 547254810Smarkj sx_xunlock(&kld_sx); 548159804Sjhb return (error); 549159804Sjhb} 550159804Sjhb 551159800Sjhbstatic linker_file_t 55291040Sarrlinker_find_file_by_name(const char *filename) 55325537Sdfr{ 554159585Sjhb linker_file_t lf; 55591040Sarr char *koname; 55625537Sdfr 557111119Simp koname = malloc(strlen(filename) + 4, M_LINKER, M_WAITOK); 55891040Sarr sprintf(koname, "%s.ko", filename); 55940861Speter 560254810Smarkj sx_assert(&kld_sx, SA_XLOCKED); 56191040Sarr TAILQ_FOREACH(lf, &linker_files, link) { 56292032Sdwmalone if (strcmp(lf->filename, koname) == 0) 56391040Sarr break; 56492032Sdwmalone if (strcmp(lf->filename, filename) == 0) 56591040Sarr break; 56691040Sarr } 567159585Sjhb free(koname, M_LINKER); 56891040Sarr return (lf); 56925537Sdfr} 57025537Sdfr 571159800Sjhbstatic linker_file_t 57225537Sdfrlinker_find_file_by_id(int fileid) 57325537Sdfr{ 574159585Sjhb linker_file_t lf; 575159845Sjhb 576254810Smarkj sx_assert(&kld_sx, SA_XLOCKED); 57791040Sarr TAILQ_FOREACH(lf, &linker_files, link) 578166921Sjhb if (lf->id == fileid && lf->flags & LINKER_FILE_LINKED) 57991040Sarr break; 58091040Sarr return (lf); 58125537Sdfr} 58225537Sdfr 583159797Sjhbint 584159797Sjhblinker_file_foreach(linker_predicate_t *predicate, void *context) 585159797Sjhb{ 586159797Sjhb linker_file_t lf; 587159797Sjhb int retval = 0; 588159797Sjhb 589254810Smarkj sx_xlock(&kld_sx); 590159797Sjhb TAILQ_FOREACH(lf, &linker_files, link) { 591159797Sjhb retval = predicate(lf, context); 592159797Sjhb if (retval != 0) 593159797Sjhb break; 594159797Sjhb } 595254810Smarkj sx_xunlock(&kld_sx); 596159797Sjhb return (retval); 597159797Sjhb} 598159797Sjhb 59925537Sdfrlinker_file_t 60091040Sarrlinker_make_file(const char *pathname, linker_class_t lc) 60125537Sdfr{ 60291040Sarr linker_file_t lf; 60391040Sarr const char *filename; 60425537Sdfr 605254810Smarkj if (!cold) 606254810Smarkj sx_assert(&kld_sx, SA_XLOCKED); 60791040Sarr filename = linker_basename(pathname); 60840159Speter 609172862Sjb KLD_DPF(FILE, ("linker_make_file: new file, filename='%s' for pathname='%s'\n", filename, pathname)); 610111119Simp lf = (linker_file_t)kobj_create((kobj_class_t)lc, M_LINKER, M_WAITOK); 61191040Sarr if (lf == NULL) 612159585Sjhb return (NULL); 613273334Smarcel lf->ctors_addr = 0; 614273334Smarcel lf->ctors_size = 0; 61591040Sarr lf->refs = 1; 61691040Sarr lf->userrefs = 0; 61791040Sarr lf->flags = 0; 618254396Smarkj lf->filename = strdup(filename, M_LINKER); 619254396Smarkj lf->pathname = strdup(pathname, M_LINKER); 62091040Sarr LINKER_GET_NEXT_FILE_ID(lf->id); 62191040Sarr lf->ndeps = 0; 62291040Sarr lf->deps = NULL; 623172862Sjb lf->loadcnt = ++loadcnt; 62491040Sarr STAILQ_INIT(&lf->common); 62591040Sarr TAILQ_INIT(&lf->modules); 62691040Sarr TAILQ_INSERT_TAIL(&linker_files, lf, link); 62791040Sarr return (lf); 62825537Sdfr} 62925537Sdfr 63025537Sdfrint 631132117Sphklinker_file_unload(linker_file_t file, int flags) 63225537Sdfr{ 63391040Sarr module_t mod, next; 63491040Sarr modlist_t ml, nextml; 63591040Sarr struct common_symbol *cp; 63691040Sarr int error, i; 63725537Sdfr 63891040Sarr /* Refuse to unload modules if securelevel raised. */ 639192895Sjamie if (prison0.pr_securelevel > 0) 64091040Sarr return (EPERM); 64125537Sdfr 642254810Smarkj sx_assert(&kld_sx, SA_XLOCKED); 64391040Sarr KLD_DPF(FILE, ("linker_file_unload: lf->refs=%d\n", file->refs)); 64491040Sarr 645159584Sjhb /* Easy case of just dropping a reference. */ 646159584Sjhb if (file->refs > 1) { 647159584Sjhb file->refs--; 648159584Sjhb return (0); 649159584Sjhb } 650159584Sjhb 651259587Smarkj /* Give eventhandlers a chance to prevent the unload. */ 652259587Smarkj error = 0; 653259587Smarkj EVENTHANDLER_INVOKE(kld_unload_try, file, &error); 654259587Smarkj if (error != 0) 655259587Smarkj return (EBUSY); 656259587Smarkj 657159584Sjhb KLD_DPF(FILE, ("linker_file_unload: file is unloading," 658159584Sjhb " informing modules\n")); 659159584Sjhb 660159584Sjhb /* 661185635Sjhb * Quiesce all the modules to give them a chance to veto the unload. 662159584Sjhb */ 663185635Sjhb MOD_SLOCK; 664185635Sjhb for (mod = TAILQ_FIRST(&file->modules); mod; 665185635Sjhb mod = module_getfnext(mod)) { 666185635Sjhb 667185635Sjhb error = module_quiesce(mod); 668185635Sjhb if (error != 0 && flags != LINKER_UNLOAD_FORCE) { 669185635Sjhb KLD_DPF(FILE, ("linker_file_unload: module %s" 670185635Sjhb " vetoed unload\n", module_getname(mod))); 671185635Sjhb /* 672185635Sjhb * XXX: Do we need to tell all the quiesced modules 673185635Sjhb * that they can resume work now via a new module 674185635Sjhb * event? 675185635Sjhb */ 676185635Sjhb MOD_SUNLOCK; 677185635Sjhb return (error); 678185635Sjhb } 679185635Sjhb } 680185635Sjhb MOD_SUNLOCK; 681185635Sjhb 682185635Sjhb /* 683185635Sjhb * Inform any modules associated with this file that they are 684234186Sjhb * being unloaded. 685185635Sjhb */ 686159584Sjhb MOD_XLOCK; 687159584Sjhb for (mod = TAILQ_FIRST(&file->modules); mod; mod = next) { 688159584Sjhb next = module_getfnext(mod); 689159584Sjhb MOD_XUNLOCK; 690159584Sjhb 69191040Sarr /* 692159584Sjhb * Give the module a chance to veto the unload. 69391040Sarr */ 694185635Sjhb if ((error = module_unload(mod)) != 0) { 695233276Sae#ifdef KLD_DEBUG 696233276Sae MOD_SLOCK; 697185635Sjhb KLD_DPF(FILE, ("linker_file_unload: module %s" 698199457Sgonzo " failed unload\n", module_getname(mod))); 699233276Sae MOD_SUNLOCK; 700233276Sae#endif 701159584Sjhb return (error); 702159584Sjhb } 70392547Sarr MOD_XLOCK; 704159584Sjhb module_release(mod); 705159584Sjhb } 706159584Sjhb MOD_XUNLOCK; 70791040Sarr 708159586Sjhb TAILQ_FOREACH_SAFE(ml, &found_modules, link, nextml) { 709128057Speadar if (ml->container == file) { 71091040Sarr TAILQ_REMOVE(&found_modules, ml, link); 711128057Speadar free(ml, M_LINKER); 712128057Speadar } 71391040Sarr } 71425537Sdfr 715159840Sjhb /* 716159840Sjhb * Don't try to run SYSUNINITs if we are unloaded due to a 71791040Sarr * link error. 71891040Sarr */ 71991040Sarr if (file->flags & LINKER_FILE_LINKED) { 720188209Sjhb file->flags &= ~LINKER_FILE_LINKED; 721324748Savg linker_file_unregister_sysctls(file); 72291040Sarr linker_file_sysuninit(file); 72325537Sdfr } 72491040Sarr TAILQ_REMOVE(&linker_files, file, link); 72525537Sdfr 72691040Sarr if (file->deps) { 72791040Sarr for (i = 0; i < file->ndeps; i++) 728132117Sphk linker_file_unload(file->deps[i], flags); 72991040Sarr free(file->deps, M_LINKER); 73091040Sarr file->deps = NULL; 73159751Speter } 732160245Sjhb while ((cp = STAILQ_FIRST(&file->common)) != NULL) { 733160245Sjhb STAILQ_REMOVE_HEAD(&file->common, link); 73491040Sarr free(cp, M_LINKER); 73591040Sarr } 73659751Speter 73791040Sarr LINKER_UNLOAD(file); 738259587Smarkj 739259587Smarkj EVENTHANDLER_INVOKE(kld_unload, file->filename, file->address, 740259587Smarkj file->size); 741259587Smarkj 74291040Sarr if (file->filename) { 74391040Sarr free(file->filename, M_LINKER); 74491040Sarr file->filename = NULL; 74591040Sarr } 746172862Sjb if (file->pathname) { 747172862Sjb free(file->pathname, M_LINKER); 748172862Sjb file->pathname = NULL; 749172862Sjb } 75091040Sarr kobj_delete((kobj_t) file, M_LINKER); 751159584Sjhb return (0); 75225537Sdfr} 75325537Sdfr 754179238Sjbint 755179238Sjblinker_ctf_get(linker_file_t file, linker_ctf_t *lc) 756179238Sjb{ 757179238Sjb return (LINKER_CTF_GET(file, lc)); 758179238Sjb} 759179238Sjb 760159796Sjhbstatic int 76186469Siedowselinker_file_add_dependency(linker_file_t file, linker_file_t dep) 76225537Sdfr{ 76391040Sarr linker_file_t *newdeps; 76425537Sdfr 765254810Smarkj sx_assert(&kld_sx, SA_XLOCKED); 766264173Skib file->deps = realloc(file->deps, (file->ndeps + 1) * sizeof(*newdeps), 767264173Skib M_LINKER, M_WAITOK | M_ZERO); 76891040Sarr file->deps[file->ndeps] = dep; 76991040Sarr file->ndeps++; 770199457Sgonzo KLD_DPF(FILE, ("linker_file_add_dependency:" 771199457Sgonzo " adding %s as dependency for %s\n", 772199457Sgonzo dep->filename, file->filename)); 77391040Sarr return (0); 77425537Sdfr} 77525537Sdfr 77678161Speter/* 77791040Sarr * Locate a linker set and its contents. This is a helper function to avoid 778159841Sjhb * linker_if.h exposure elsewhere. Note: firstp and lastp are really void **. 779159841Sjhb * This function is used in this file so we can avoid having lots of (void **) 780159841Sjhb * casts. 78178161Speter */ 782284160Sjhbint 783284160Sjhblinker_file_lookup_set(linker_file_t file, const char *name, 78491040Sarr void *firstp, void *lastp, int *countp) 78578161Speter{ 78678161Speter 787254811Smarkj sx_assert(&kld_sx, SA_LOCKED); 788254811Smarkj return (LINKER_LOOKUP_SET(file, name, firstp, lastp, countp)); 78978161Speter} 79078161Speter 791173714Sjb/* 792173714Sjb * List all functions in a file. 793173714Sjb */ 794173714Sjbint 795173714Sjblinker_file_function_listall(linker_file_t lf, 796179238Sjb linker_function_nameval_callback_t callback_func, void *arg) 797173714Sjb{ 798173714Sjb return (LINKER_EACH_FUNCTION_NAMEVAL(lf, callback_func, arg)); 799173714Sjb} 800173714Sjb 80125537Sdfrcaddr_t 80291040Sarrlinker_file_lookup_symbol(linker_file_t file, const char *name, int deps) 80325537Sdfr{ 804159845Sjhb caddr_t sym; 805159845Sjhb int locked; 806159845Sjhb 807254810Smarkj locked = sx_xlocked(&kld_sx); 808159845Sjhb if (!locked) 809254810Smarkj sx_xlock(&kld_sx); 810159845Sjhb sym = linker_file_lookup_symbol_internal(file, name, deps); 811159845Sjhb if (!locked) 812254810Smarkj sx_xunlock(&kld_sx); 813159845Sjhb return (sym); 814159845Sjhb} 815159845Sjhb 816159845Sjhbstatic caddr_t 817159845Sjhblinker_file_lookup_symbol_internal(linker_file_t file, const char *name, 818159845Sjhb int deps) 819159845Sjhb{ 82091040Sarr c_linker_sym_t sym; 82191040Sarr linker_symval_t symval; 82291040Sarr caddr_t address; 82391040Sarr size_t common_size = 0; 82492032Sdwmalone int i; 82525537Sdfr 826254810Smarkj sx_assert(&kld_sx, SA_XLOCKED); 827109605Sjake KLD_DPF(SYM, ("linker_file_lookup_symbol: file=%p, name=%s, deps=%d\n", 82891040Sarr file, name, deps)); 82925537Sdfr 83091040Sarr if (LINKER_LOOKUP_SYMBOL(file, name, &sym) == 0) { 83191040Sarr LINKER_SYMBOL_VALUES(file, sym, &symval); 83291040Sarr if (symval.value == 0) 83391040Sarr /* 83491040Sarr * For commons, first look them up in the 83591040Sarr * dependencies and only allocate space if not found 83691040Sarr * there. 83791040Sarr */ 83891040Sarr common_size = symval.size; 83991040Sarr else { 84091040Sarr KLD_DPF(SYM, ("linker_file_lookup_symbol: symbol" 841109605Sjake ".value=%p\n", symval.value)); 84291040Sarr return (symval.value); 84391040Sarr } 84440159Speter } 84591040Sarr if (deps) { 84691040Sarr for (i = 0; i < file->ndeps; i++) { 847159845Sjhb address = linker_file_lookup_symbol_internal( 848159845Sjhb file->deps[i], name, 0); 84991040Sarr if (address) { 85091040Sarr KLD_DPF(SYM, ("linker_file_lookup_symbol:" 851109605Sjake " deps value=%p\n", address)); 85291040Sarr return (address); 85391040Sarr } 85491040Sarr } 85525537Sdfr } 85691040Sarr if (common_size > 0) { 85791040Sarr /* 85891040Sarr * This is a common symbol which was not found in the 85991040Sarr * dependencies. We maintain a simple common symbol table in 86091040Sarr * the file object. 86191040Sarr */ 86291040Sarr struct common_symbol *cp; 86342849Speter 86491040Sarr STAILQ_FOREACH(cp, &file->common, link) { 86592032Sdwmalone if (strcmp(cp->name, name) == 0) { 86691040Sarr KLD_DPF(SYM, ("linker_file_lookup_symbol:" 867109605Sjake " old common value=%p\n", cp->address)); 86891040Sarr return (cp->address); 86991040Sarr } 87091040Sarr } 87191040Sarr /* 87291040Sarr * Round the symbol size up to align. 87391040Sarr */ 87491040Sarr common_size = (common_size + sizeof(int) - 1) & -sizeof(int); 87591040Sarr cp = malloc(sizeof(struct common_symbol) 87691040Sarr + common_size + strlen(name) + 1, M_LINKER, 877111119Simp M_WAITOK | M_ZERO); 87891040Sarr cp->address = (caddr_t)(cp + 1); 87991040Sarr cp->name = cp->address + common_size; 88091040Sarr strcpy(cp->name, name); 88191040Sarr bzero(cp->address, common_size); 88291040Sarr STAILQ_INSERT_TAIL(&file->common, cp, link); 88325537Sdfr 88491040Sarr KLD_DPF(SYM, ("linker_file_lookup_symbol: new common" 885109605Sjake " value=%p\n", cp->address)); 88691040Sarr return (cp->address); 88740159Speter } 88891040Sarr KLD_DPF(SYM, ("linker_file_lookup_symbol: fail\n")); 88991040Sarr return (0); 89025537Sdfr} 89125537Sdfr 89225537Sdfr/* 893174132Srwatson * Both DDB and stack(9) rely on the kernel linker to provide forward and 894174132Srwatson * backward lookup of symbols. However, DDB and sometimes stack(9) need to 895174132Srwatson * do this in a lockfree manner. We provide a set of internal helper 896174132Srwatson * routines to perform these operations without locks, and then wrappers that 897174132Srwatson * optionally lock. 898159840Sjhb * 899174132Srwatson * linker_debug_lookup() is ifdef DDB as currently it's only used by DDB. 90040159Speter */ 901174132Srwatson#ifdef DDB 902174132Srwatsonstatic int 903174132Srwatsonlinker_debug_lookup(const char *symstr, c_linker_sym_t *sym) 90440159Speter{ 90591040Sarr linker_file_t lf; 90640159Speter 90791040Sarr TAILQ_FOREACH(lf, &linker_files, link) { 90891040Sarr if (LINKER_LOOKUP_SYMBOL(lf, symstr, sym) == 0) 90991040Sarr return (0); 91091040Sarr } 91191040Sarr return (ENOENT); 91240159Speter} 913174132Srwatson#endif 91440159Speter 915174132Srwatsonstatic int 916174132Srwatsonlinker_debug_search_symbol(caddr_t value, c_linker_sym_t *sym, long *diffp) 91740159Speter{ 91891040Sarr linker_file_t lf; 91991040Sarr c_linker_sym_t best, es; 92091040Sarr u_long diff, bestdiff, off; 92140159Speter 92291040Sarr best = 0; 92391040Sarr off = (uintptr_t)value; 92491040Sarr bestdiff = off; 92591040Sarr TAILQ_FOREACH(lf, &linker_files, link) { 92691040Sarr if (LINKER_SEARCH_SYMBOL(lf, value, &es, &diff) != 0) 92791040Sarr continue; 92891040Sarr if (es != 0 && diff < bestdiff) { 92991040Sarr best = es; 93091040Sarr bestdiff = diff; 93191040Sarr } 93291040Sarr if (bestdiff == 0) 93391040Sarr break; 93440159Speter } 93591040Sarr if (best) { 93691040Sarr *sym = best; 93791040Sarr *diffp = bestdiff; 93891040Sarr return (0); 93991040Sarr } else { 94091040Sarr *sym = 0; 94191040Sarr *diffp = off; 94291040Sarr return (ENOENT); 94391040Sarr } 94440159Speter} 94540159Speter 946174132Srwatsonstatic int 947174132Srwatsonlinker_debug_symbol_values(c_linker_sym_t sym, linker_symval_t *symval) 94840159Speter{ 94991040Sarr linker_file_t lf; 95040159Speter 95191040Sarr TAILQ_FOREACH(lf, &linker_files, link) { 95291040Sarr if (LINKER_SYMBOL_VALUES(lf, sym, symval) == 0) 95391040Sarr return (0); 95491040Sarr } 95591040Sarr return (ENOENT); 95640159Speter} 957174132Srwatson 958174132Srwatsonstatic int 959174132Srwatsonlinker_debug_search_symbol_name(caddr_t value, char *buf, u_int buflen, 960174132Srwatson long *offset) 961174132Srwatson{ 962174132Srwatson linker_symval_t symval; 963174132Srwatson c_linker_sym_t sym; 964174132Srwatson int error; 965174132Srwatson 966174132Srwatson *offset = 0; 967174132Srwatson error = linker_debug_search_symbol(value, &sym, offset); 968174132Srwatson if (error) 969174132Srwatson return (error); 970174132Srwatson error = linker_debug_symbol_values(sym, &symval); 971174132Srwatson if (error) 972174132Srwatson return (error); 973174132Srwatson strlcpy(buf, symval.name, buflen); 974174132Srwatson return (0); 975174132Srwatson} 976174132Srwatson 977174132Srwatson/* 978174132Srwatson * DDB Helpers. DDB has to look across multiple files with their own symbol 979174132Srwatson * tables and string tables. 980174132Srwatson * 981174132Srwatson * Note that we do not obey list locking protocols here. We really don't need 982174132Srwatson * DDB to hang because somebody's got the lock held. We'll take the chance 983298819Spfg * that the files list is inconsistent instead. 984174132Srwatson */ 985212994Savg#ifdef DDB 986174132Srwatsonint 987174132Srwatsonlinker_ddb_lookup(const char *symstr, c_linker_sym_t *sym) 988174132Srwatson{ 989174132Srwatson 990174132Srwatson return (linker_debug_lookup(symstr, sym)); 991174132Srwatson} 992212994Savg#endif 993174132Srwatson 994174132Srwatsonint 995174132Srwatsonlinker_ddb_search_symbol(caddr_t value, c_linker_sym_t *sym, long *diffp) 996174132Srwatson{ 997174132Srwatson 998174132Srwatson return (linker_debug_search_symbol(value, sym, diffp)); 999174132Srwatson} 1000174132Srwatson 1001174132Srwatsonint 1002174132Srwatsonlinker_ddb_symbol_values(c_linker_sym_t sym, linker_symval_t *symval) 1003174132Srwatson{ 1004174132Srwatson 1005174132Srwatson return (linker_debug_symbol_values(sym, symval)); 1006174132Srwatson} 1007174132Srwatson 1008174132Srwatsonint 1009174132Srwatsonlinker_ddb_search_symbol_name(caddr_t value, char *buf, u_int buflen, 1010174132Srwatson long *offset) 1011174132Srwatson{ 1012174132Srwatson 1013174132Srwatson return (linker_debug_search_symbol_name(value, buf, buflen, offset)); 1014174132Srwatson} 101540159Speter 101640159Speter/* 1017174132Srwatson * stack(9) helper for non-debugging environemnts. Unlike DDB helpers, we do 1018174132Srwatson * obey locking protocols, and offer a significantly less complex interface. 1019174132Srwatson */ 1020174132Srwatsonint 1021174132Srwatsonlinker_search_symbol_name(caddr_t value, char *buf, u_int buflen, 1022174132Srwatson long *offset) 1023174132Srwatson{ 1024178380Spjd int error; 1025174132Srwatson 1026273431Smjg sx_slock(&kld_sx); 1027174132Srwatson error = linker_debug_search_symbol_name(value, buf, buflen, offset); 1028273431Smjg sx_sunlock(&kld_sx); 1029174132Srwatson return (error); 1030174132Srwatson} 1031174132Srwatson 1032174132Srwatson/* 103325537Sdfr * Syscalls. 103425537Sdfr */ 103525537Sdfrint 1036159588Sjhbkern_kldload(struct thread *td, const char *file, int *fileid) 103725537Sdfr{ 1038159588Sjhb const char *kldname, *modname; 103991040Sarr linker_file_t lf; 1040159588Sjhb int error; 104125537Sdfr 104293159Sarr if ((error = securelevel_gt(td->td_ucred, 0)) != 0) 1043159588Sjhb return (error); 104493159Sarr 1045164033Srwatson if ((error = priv_check(td, PRIV_KLD_LOAD)) != 0) 1046159588Sjhb return (error); 104725537Sdfr 104891040Sarr /* 1049191917Szec * It is possible that kldloaded module will attach a new ifnet, 1050191816Szec * so vnet context must be set when this ocurs. 1051191816Szec */ 1052191816Szec CURVNET_SET(TD_TO_VNET(td)); 1053191816Szec 1054191816Szec /* 1055159841Sjhb * If file does not contain a qualified name or any dot in it 1056159841Sjhb * (kldname.ko, or kldname.ver.ko) treat it as an interface 105791040Sarr * name. 105891040Sarr */ 1059229272Sed if (strchr(file, '/') || strchr(file, '.')) { 1060159588Sjhb kldname = file; 106191040Sarr modname = NULL; 106291040Sarr } else { 106391040Sarr kldname = NULL; 1064159588Sjhb modname = file; 106591040Sarr } 1066159588Sjhb 1067254810Smarkj sx_xlock(&kld_sx); 106891040Sarr error = linker_load_module(kldname, modname, NULL, NULL, &lf); 1069224156Srstone if (error) { 1070254810Smarkj sx_xunlock(&kld_sx); 1071224156Srstone goto done; 1072224156Srstone } 1073224156Srstone lf->userrefs++; 1074224156Srstone if (fileid != NULL) 1075224156Srstone *fileid = lf->id; 1076259587Smarkj sx_xunlock(&kld_sx); 1077254266Smarkj 1078224156Srstonedone: 1079191816Szec CURVNET_RESTORE(); 108091040Sarr return (error); 108125537Sdfr} 108225537Sdfr 1083159588Sjhbint 1084225617Skmacysys_kldload(struct thread *td, struct kldload_args *uap) 1085159588Sjhb{ 1086159588Sjhb char *pathname = NULL; 1087159596Smarcel int error, fileid; 1088159588Sjhb 1089159588Sjhb td->td_retval[0] = -1; 1090159588Sjhb 1091159588Sjhb pathname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); 1092159588Sjhb error = copyinstr(uap->file, pathname, MAXPATHLEN, NULL); 1093159596Smarcel if (error == 0) { 1094159596Smarcel error = kern_kldload(td, pathname, &fileid); 1095159596Smarcel if (error == 0) 1096159596Smarcel td->td_retval[0] = fileid; 1097159596Smarcel } 1098159588Sjhb free(pathname, M_TEMP); 1099159588Sjhb return (error); 1100159588Sjhb} 1101159588Sjhb 1102159588Sjhbint 1103132117Sphkkern_kldunload(struct thread *td, int fileid, int flags) 110425537Sdfr{ 110591040Sarr linker_file_t lf; 110691040Sarr int error = 0; 110725537Sdfr 110893159Sarr if ((error = securelevel_gt(td->td_ucred, 0)) != 0) 1109159588Sjhb return (error); 111093159Sarr 1111164033Srwatson if ((error = priv_check(td, PRIV_KLD_UNLOAD)) != 0) 1112159588Sjhb return (error); 111325537Sdfr 1114191816Szec CURVNET_SET(TD_TO_VNET(td)); 1115254810Smarkj sx_xlock(&kld_sx); 1116132117Sphk lf = linker_find_file_by_id(fileid); 111791040Sarr if (lf) { 111891040Sarr KLD_DPF(FILE, ("kldunload: lf->userrefs=%d\n", lf->userrefs)); 1119172862Sjb 1120259587Smarkj if (lf->userrefs == 0) { 1121132117Sphk /* 1122132117Sphk * XXX: maybe LINKER_UNLOAD_FORCE should override ? 1123132117Sphk */ 112491040Sarr printf("kldunload: attempt to unload file that was" 112591040Sarr " loaded by the kernel\n"); 1126159840Sjhb error = EBUSY; 1127159588Sjhb } else { 1128159588Sjhb lf->userrefs--; 1129159588Sjhb error = linker_file_unload(lf, flags); 1130159588Sjhb if (error) 1131159588Sjhb lf->userrefs++; 1132159588Sjhb } 113391040Sarr } else 113491040Sarr error = ENOENT; 1135259587Smarkj sx_xunlock(&kld_sx); 1136157144Sjkoshy 1137191816Szec CURVNET_RESTORE(); 113891068Sarr return (error); 113925537Sdfr} 114025537Sdfr 114125537Sdfrint 1142225617Skmacysys_kldunload(struct thread *td, struct kldunload_args *uap) 1143132117Sphk{ 1144132117Sphk 1145132117Sphk return (kern_kldunload(td, uap->fileid, LINKER_UNLOAD_NORMAL)); 1146132117Sphk} 1147132117Sphk 1148132117Sphkint 1149225617Skmacysys_kldunloadf(struct thread *td, struct kldunloadf_args *uap) 1150132117Sphk{ 1151132117Sphk 1152132117Sphk if (uap->flags != LINKER_UNLOAD_NORMAL && 1153132117Sphk uap->flags != LINKER_UNLOAD_FORCE) 1154132117Sphk return (EINVAL); 1155132117Sphk return (kern_kldunload(td, uap->fileid, uap->flags)); 1156132117Sphk} 1157132117Sphk 1158132117Sphkint 1159225617Skmacysys_kldfind(struct thread *td, struct kldfind_args *uap) 116025537Sdfr{ 116191040Sarr char *pathname; 116291040Sarr const char *filename; 116391040Sarr linker_file_t lf; 1164159791Sjhb int error; 116525537Sdfr 1166107089Srwatson#ifdef MAC 1167172930Srwatson error = mac_kld_check_stat(td->td_ucred); 1168107089Srwatson if (error) 1169107089Srwatson return (error); 1170107089Srwatson#endif 1171107089Srwatson 117291040Sarr td->td_retval[0] = -1; 117382749Sdillon 1174111119Simp pathname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); 1175107855Salfred if ((error = copyinstr(uap->file, pathname, MAXPATHLEN, NULL)) != 0) 117691040Sarr goto out; 117725537Sdfr 117891040Sarr filename = linker_basename(pathname); 1179254810Smarkj sx_xlock(&kld_sx); 118091040Sarr lf = linker_find_file_by_name(filename); 118191040Sarr if (lf) 118291040Sarr td->td_retval[0] = lf->id; 118391040Sarr else 118491040Sarr error = ENOENT; 1185254810Smarkj sx_xunlock(&kld_sx); 118625537Sdfrout: 1187159791Sjhb free(pathname, M_TEMP); 118891040Sarr return (error); 118925537Sdfr} 119025537Sdfr 119125537Sdfrint 1192225617Skmacysys_kldnext(struct thread *td, struct kldnext_args *uap) 119325537Sdfr{ 119491040Sarr linker_file_t lf; 119591040Sarr int error = 0; 119625537Sdfr 1197107089Srwatson#ifdef MAC 1198172930Srwatson error = mac_kld_check_stat(td->td_ucred); 1199107089Srwatson if (error) 1200107089Srwatson return (error); 1201107089Srwatson#endif 1202107089Srwatson 1203254810Smarkj sx_xlock(&kld_sx); 1204166921Sjhb if (uap->fileid == 0) 1205166921Sjhb lf = TAILQ_FIRST(&linker_files); 1206166921Sjhb else { 1207166921Sjhb lf = linker_find_file_by_id(uap->fileid); 1208166921Sjhb if (lf == NULL) { 1209166921Sjhb error = ENOENT; 1210166921Sjhb goto out; 1211166921Sjhb } 1212166921Sjhb lf = TAILQ_NEXT(lf, link); 121391040Sarr } 1214166921Sjhb 1215166921Sjhb /* Skip partially loaded files. */ 1216166921Sjhb while (lf != NULL && !(lf->flags & LINKER_FILE_LINKED)) 1217166921Sjhb lf = TAILQ_NEXT(lf, link); 1218166921Sjhb 1219166921Sjhb if (lf) 1220166921Sjhb td->td_retval[0] = lf->id; 1221166921Sjhb else 1222166921Sjhb td->td_retval[0] = 0; 122382749Sdillonout: 1224254810Smarkj sx_xunlock(&kld_sx); 122591040Sarr return (error); 122625537Sdfr} 122725537Sdfr 122825537Sdfrint 1229225617Skmacysys_kldstat(struct thread *td, struct kldstat_args *uap) 123025537Sdfr{ 1231325866Sgordon struct kld_file_stat *stat; 1232220158Skib int error, version; 123325537Sdfr 1234159587Sjhb /* 1235159587Sjhb * Check the version of the user's structure. 1236159587Sjhb */ 1237220158Skib if ((error = copyin(&uap->stat->version, &version, sizeof(version))) 1238220158Skib != 0) 1239159587Sjhb return (error); 1240220158Skib if (version != sizeof(struct kld_file_stat_1) && 1241220158Skib version != sizeof(struct kld_file_stat)) 1242159587Sjhb return (EINVAL); 1243159587Sjhb 1244325866Sgordon stat = malloc(sizeof(*stat), M_TEMP, M_WAITOK | M_ZERO); 1245325866Sgordon error = kern_kldstat(td, uap->fileid, stat); 1246325866Sgordon if (error == 0) 1247325866Sgordon error = copyout(stat, uap->stat, version); 1248325866Sgordon free(stat, M_TEMP); 1249325866Sgordon return (error); 1250220158Skib} 1251220158Skib 1252220158Skibint 1253220158Skibkern_kldstat(struct thread *td, int fileid, struct kld_file_stat *stat) 1254220158Skib{ 1255220158Skib linker_file_t lf; 1256220158Skib int namelen; 1257107089Srwatson#ifdef MAC 1258220158Skib int error; 1259220158Skib 1260172930Srwatson error = mac_kld_check_stat(td->td_ucred); 1261107089Srwatson if (error) 1262107089Srwatson return (error); 1263107089Srwatson#endif 1264107089Srwatson 1265254810Smarkj sx_xlock(&kld_sx); 1266220158Skib lf = linker_find_file_by_id(fileid); 126791040Sarr if (lf == NULL) { 1268254810Smarkj sx_xunlock(&kld_sx); 1269159587Sjhb return (ENOENT); 127091040Sarr } 127125537Sdfr 1272172862Sjb /* Version 1 fields: */ 127391040Sarr namelen = strlen(lf->filename) + 1; 127491040Sarr if (namelen > MAXPATHLEN) 127591040Sarr namelen = MAXPATHLEN; 1276220158Skib bcopy(lf->filename, &stat->name[0], namelen); 1277220158Skib stat->refs = lf->refs; 1278220158Skib stat->id = lf->id; 1279220158Skib stat->address = lf->address; 1280220158Skib stat->size = lf->size; 1281220158Skib /* Version 2 fields: */ 1282220158Skib namelen = strlen(lf->pathname) + 1; 1283220158Skib if (namelen > MAXPATHLEN) 1284220158Skib namelen = MAXPATHLEN; 1285220158Skib bcopy(lf->pathname, &stat->pathname[0], namelen); 1286254810Smarkj sx_xunlock(&kld_sx); 128725537Sdfr 128891040Sarr td->td_retval[0] = 0; 1289220158Skib return (0); 129025537Sdfr} 129125537Sdfr 1292301751Scem#ifdef DDB 1293301751ScemDB_COMMAND(kldstat, db_kldstat) 1294301751Scem{ 1295301751Scem linker_file_t lf; 1296301751Scem 1297301751Scem#define POINTER_WIDTH ((int)(sizeof(void *) * 2 + 2)) 1298301751Scem db_printf("Id Refs Address%*c Size Name\n", POINTER_WIDTH - 7, ' '); 1299301751Scem#undef POINTER_WIDTH 1300301751Scem TAILQ_FOREACH(lf, &linker_files, link) { 1301301751Scem if (db_pager_quit) 1302301751Scem return; 1303301751Scem db_printf("%2d %4d %p %-8zx %s\n", lf->id, lf->refs, 1304301751Scem lf->address, lf->size, lf->filename); 1305301751Scem } 1306301751Scem} 1307301751Scem#endif /* DDB */ 1308301751Scem 130925537Sdfrint 1310225617Skmacysys_kldfirstmod(struct thread *td, struct kldfirstmod_args *uap) 131125537Sdfr{ 131291040Sarr linker_file_t lf; 131391040Sarr module_t mp; 131491040Sarr int error = 0; 131525537Sdfr 1316107089Srwatson#ifdef MAC 1317172930Srwatson error = mac_kld_check_stat(td->td_ucred); 1318107089Srwatson if (error) 1319107089Srwatson return (error); 1320107089Srwatson#endif 1321107089Srwatson 1322254810Smarkj sx_xlock(&kld_sx); 1323107849Salfred lf = linker_find_file_by_id(uap->fileid); 132491040Sarr if (lf) { 132592547Sarr MOD_SLOCK; 132691040Sarr mp = TAILQ_FIRST(&lf->modules); 132791040Sarr if (mp != NULL) 132891040Sarr td->td_retval[0] = module_getid(mp); 132991040Sarr else 133091040Sarr td->td_retval[0] = 0; 133192547Sarr MOD_SUNLOCK; 133291040Sarr } else 133391040Sarr error = ENOENT; 1334254810Smarkj sx_xunlock(&kld_sx); 133591040Sarr return (error); 133625537Sdfr} 133740159Speter 133841090Speterint 1339225617Skmacysys_kldsym(struct thread *td, struct kldsym_args *uap) 134041090Speter{ 134191040Sarr char *symstr = NULL; 134291040Sarr c_linker_sym_t sym; 134391040Sarr linker_symval_t symval; 134491040Sarr linker_file_t lf; 134591040Sarr struct kld_sym_lookup lookup; 134691040Sarr int error = 0; 134741090Speter 1348107089Srwatson#ifdef MAC 1349172930Srwatson error = mac_kld_check_stat(td->td_ucred); 1350107089Srwatson if (error) 1351107089Srwatson return (error); 1352107089Srwatson#endif 1353107089Srwatson 1354107849Salfred if ((error = copyin(uap->data, &lookup, sizeof(lookup))) != 0) 1355159843Sjhb return (error); 135691068Sarr if (lookup.version != sizeof(lookup) || 1357159843Sjhb uap->cmd != KLDSYM_LOOKUP) 1358159843Sjhb return (EINVAL); 1359111119Simp symstr = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); 136091040Sarr if ((error = copyinstr(lookup.symname, symstr, MAXPATHLEN, NULL)) != 0) 136191040Sarr goto out; 1362254810Smarkj sx_xlock(&kld_sx); 1363107849Salfred if (uap->fileid != 0) { 1364107849Salfred lf = linker_find_file_by_id(uap->fileid); 1365159843Sjhb if (lf == NULL) 136691040Sarr error = ENOENT; 1367159843Sjhb else if (LINKER_LOOKUP_SYMBOL(lf, symstr, &sym) == 0 && 136891040Sarr LINKER_SYMBOL_VALUES(lf, sym, &symval) == 0) { 136991040Sarr lookup.symvalue = (uintptr_t) symval.value; 137091040Sarr lookup.symsize = symval.size; 1371107855Salfred error = copyout(&lookup, uap->data, sizeof(lookup)); 137291040Sarr } else 137391040Sarr error = ENOENT; 137491040Sarr } else { 137591040Sarr TAILQ_FOREACH(lf, &linker_files, link) { 137691040Sarr if (LINKER_LOOKUP_SYMBOL(lf, symstr, &sym) == 0 && 137791040Sarr LINKER_SYMBOL_VALUES(lf, sym, &symval) == 0) { 137891040Sarr lookup.symvalue = (uintptr_t)symval.value; 137991040Sarr lookup.symsize = symval.size; 1380107849Salfred error = copyout(&lookup, uap->data, 138191040Sarr sizeof(lookup)); 138291068Sarr break; 138391040Sarr } 138491040Sarr } 138591040Sarr if (lf == NULL) 138691040Sarr error = ENOENT; 138741090Speter } 1388254810Smarkj sx_xunlock(&kld_sx); 138941090Speterout: 1390159843Sjhb free(symstr, M_TEMP); 139191040Sarr return (error); 139241090Speter} 139341090Speter 139440159Speter/* 139540159Speter * Preloaded module support 139640159Speter */ 139740159Speter 139859751Speterstatic modlist_t 139974642Sbpmodlist_lookup(const char *name, int ver) 140059751Speter{ 140191040Sarr modlist_t mod; 140259751Speter 140391040Sarr TAILQ_FOREACH(mod, &found_modules, link) { 140492032Sdwmalone if (strcmp(mod->name, name) == 0 && 140592032Sdwmalone (ver == 0 || mod->version == ver)) 140691040Sarr return (mod); 140791040Sarr } 140891040Sarr return (NULL); 140959751Speter} 141059751Speter 141174642Sbpstatic modlist_t 1412275469Simpmodlist_lookup2(const char *name, const struct mod_depend *verinfo) 141383321Speter{ 141491040Sarr modlist_t mod, bestmod; 141592032Sdwmalone int ver; 141683321Speter 141791040Sarr if (verinfo == NULL) 141891040Sarr return (modlist_lookup(name, 0)); 141991040Sarr bestmod = NULL; 1420159586Sjhb TAILQ_FOREACH(mod, &found_modules, link) { 142192032Sdwmalone if (strcmp(mod->name, name) != 0) 142291040Sarr continue; 142391040Sarr ver = mod->version; 142491040Sarr if (ver == verinfo->md_ver_preferred) 142591040Sarr return (mod); 142691040Sarr if (ver >= verinfo->md_ver_minimum && 142791068Sarr ver <= verinfo->md_ver_maximum && 1428120382Sfjoe (bestmod == NULL || ver > bestmod->version)) 142991040Sarr bestmod = mod; 143091040Sarr } 143191040Sarr return (bestmod); 143283321Speter} 143383321Speter 143483321Speterstatic modlist_t 143578501Sdesmodlist_newmodule(const char *modname, int version, linker_file_t container) 143674642Sbp{ 143791040Sarr modlist_t mod; 143874642Sbp 143992705Sarr mod = malloc(sizeof(struct modlist), M_LINKER, M_NOWAIT | M_ZERO); 144091040Sarr if (mod == NULL) 144191040Sarr panic("no memory for module list"); 144291040Sarr mod->container = container; 144391040Sarr mod->name = modname; 144491040Sarr mod->version = version; 144591040Sarr TAILQ_INSERT_TAIL(&found_modules, mod, link); 144691040Sarr return (mod); 144774642Sbp} 144874642Sbp 144940159Speterstatic void 145078161Speterlinker_addmodules(linker_file_t lf, struct mod_metadata **start, 145191040Sarr struct mod_metadata **stop, int preload) 145274642Sbp{ 145391040Sarr struct mod_metadata *mp, **mdp; 145491040Sarr const char *modname; 145591040Sarr int ver; 145674642Sbp 145791040Sarr for (mdp = start; mdp < stop; mdp++) { 1458109605Sjake mp = *mdp; 145991040Sarr if (mp->md_type != MDT_VERSION) 146091040Sarr continue; 1461109605Sjake modname = mp->md_cval; 1462292077Simp ver = ((const struct mod_version *)mp->md_data)->mv_version; 146391040Sarr if (modlist_lookup(modname, ver) != NULL) { 146491040Sarr printf("module %s already present!\n", modname); 146591040Sarr /* XXX what can we do? this is a build error. :-( */ 146691040Sarr continue; 146791040Sarr } 146891040Sarr modlist_newmodule(modname, ver, lf); 146974642Sbp } 147074642Sbp} 147174642Sbp 147274642Sbpstatic void 147391040Sarrlinker_preload(void *arg) 147440159Speter{ 147591040Sarr caddr_t modptr; 147691040Sarr const char *modname, *nmodname; 147791040Sarr char *modtype; 1478160244Sjhb linker_file_t lf, nlf; 147991040Sarr linker_class_t lc; 148092032Sdwmalone int error; 148191040Sarr linker_file_list_t loaded_files; 148291040Sarr linker_file_list_t depended_files; 148391040Sarr struct mod_metadata *mp, *nmp; 148491040Sarr struct mod_metadata **start, **stop, **mdp, **nmdp; 1485275469Simp const struct mod_depend *verinfo; 148691040Sarr int nver; 148791040Sarr int resolves; 148891040Sarr modlist_t mod; 148991040Sarr struct sysinit **si_start, **si_stop; 149040159Speter 149191040Sarr TAILQ_INIT(&loaded_files); 149291040Sarr TAILQ_INIT(&depended_files); 149391040Sarr TAILQ_INIT(&found_modules); 149491040Sarr error = 0; 149559751Speter 149691040Sarr modptr = NULL; 1497254810Smarkj sx_xlock(&kld_sx); 149891040Sarr while ((modptr = preload_search_next_name(modptr)) != NULL) { 149991040Sarr modname = (char *)preload_search_info(modptr, MODINFO_NAME); 150091040Sarr modtype = (char *)preload_search_info(modptr, MODINFO_TYPE); 150191040Sarr if (modname == NULL) { 150291040Sarr printf("Preloaded module at %p does not have a" 150391040Sarr " name!\n", modptr); 150491040Sarr continue; 150591040Sarr } 150691040Sarr if (modtype == NULL) { 150791040Sarr printf("Preloaded module at %p does not have a type!\n", 150891040Sarr modptr); 150991040Sarr continue; 151091040Sarr } 1511131398Sjhb if (bootverbose) 1512131398Sjhb printf("Preloaded %s \"%s\" at %p.\n", modtype, modname, 1513131398Sjhb modptr); 151440159Speter lf = NULL; 151591040Sarr TAILQ_FOREACH(lc, &classes, link) { 151691040Sarr error = LINKER_LINK_PRELOAD(lc, modname, &lf); 1517134364Siedowse if (!error) 151891040Sarr break; 1519134364Siedowse lf = NULL; 152091040Sarr } 152191040Sarr if (lf) 152291040Sarr TAILQ_INSERT_TAIL(&loaded_files, lf, loaded); 152340159Speter } 152440159Speter 152591040Sarr /* 152691040Sarr * First get a list of stuff in the kernel. 152791040Sarr */ 1528284160Sjhb if (linker_file_lookup_set(linker_kernel_file, MDT_SETNAME, &start, 1529284160Sjhb &stop, NULL) == 0) 153091040Sarr linker_addmodules(linker_kernel_file, start, stop, 1); 153159751Speter 153259751Speter /* 1533167019Sjhb * This is a once-off kinky bubble sort to resolve relocation 1534167019Sjhb * dependency requirements. 153559751Speter */ 153691040Sarrrestart: 153791040Sarr TAILQ_FOREACH(lf, &loaded_files, loaded) { 1538284160Sjhb error = linker_file_lookup_set(lf, MDT_SETNAME, &start, 153991040Sarr &stop, NULL); 154091040Sarr /* 154191040Sarr * First, look to see if we would successfully link with this 154291040Sarr * stuff. 154391040Sarr */ 154491040Sarr resolves = 1; /* unless we know otherwise */ 154591040Sarr if (!error) { 154691040Sarr for (mdp = start; mdp < stop; mdp++) { 1547109605Sjake mp = *mdp; 154891040Sarr if (mp->md_type != MDT_DEPEND) 154991040Sarr continue; 1550109605Sjake modname = mp->md_cval; 1551109605Sjake verinfo = mp->md_data; 155291040Sarr for (nmdp = start; nmdp < stop; nmdp++) { 1553109605Sjake nmp = *nmdp; 155491040Sarr if (nmp->md_type != MDT_VERSION) 155591040Sarr continue; 1556109605Sjake nmodname = nmp->md_cval; 155792032Sdwmalone if (strcmp(modname, nmodname) == 0) 155891040Sarr break; 155991040Sarr } 156091040Sarr if (nmdp < stop) /* it's a self reference */ 156191040Sarr continue; 1562159840Sjhb 156391040Sarr /* 156491040Sarr * ok, the module isn't here yet, we 156591040Sarr * are not finished 156691040Sarr */ 156791068Sarr if (modlist_lookup2(modname, verinfo) == NULL) 156891040Sarr resolves = 0; 156991040Sarr } 157064143Speter } 157191040Sarr /* 157291040Sarr * OK, if we found our modules, we can link. So, "provide" 157391040Sarr * the modules inside and add it to the end of the link order 157491040Sarr * list. 157591040Sarr */ 157691040Sarr if (resolves) { 157791040Sarr if (!error) { 157891040Sarr for (mdp = start; mdp < stop; mdp++) { 1579109605Sjake mp = *mdp; 158091040Sarr if (mp->md_type != MDT_VERSION) 158191040Sarr continue; 1582109605Sjake modname = mp->md_cval; 1583292077Simp nver = ((const struct mod_version *) 1584109605Sjake mp->md_data)->mv_version; 158591040Sarr if (modlist_lookup(modname, 158691040Sarr nver) != NULL) { 158791040Sarr printf("module %s already" 158891040Sarr " present!\n", modname); 1589160244Sjhb TAILQ_REMOVE(&loaded_files, 1590160244Sjhb lf, loaded); 1591132117Sphk linker_file_unload(lf, 1592132117Sphk LINKER_UNLOAD_FORCE); 159391040Sarr /* we changed tailq next ptr */ 159491068Sarr goto restart; 159591040Sarr } 159691040Sarr modlist_newmodule(modname, nver, lf); 159791040Sarr } 159891040Sarr } 159991040Sarr TAILQ_REMOVE(&loaded_files, lf, loaded); 160091040Sarr TAILQ_INSERT_TAIL(&depended_files, lf, loaded); 160191040Sarr /* 160291040Sarr * Since we provided modules, we need to restart the 160391040Sarr * sort so that the previous files that depend on us 160491040Sarr * have a chance. Also, we've busted the tailq next 160591040Sarr * pointer with the REMOVE. 160691040Sarr */ 160791040Sarr goto restart; 160859751Speter } 160959751Speter } 161091040Sarr 161159751Speter /* 161291040Sarr * At this point, we check to see what could not be resolved.. 161359751Speter */ 1614160242Sjhb while ((lf = TAILQ_FIRST(&loaded_files)) != NULL) { 1615160242Sjhb TAILQ_REMOVE(&loaded_files, lf, loaded); 161691040Sarr printf("KLD file %s is missing dependencies\n", lf->filename); 1617132117Sphk linker_file_unload(lf, LINKER_UNLOAD_FORCE); 161840159Speter } 161959751Speter 162078161Speter /* 162191040Sarr * We made it. Finish off the linking in the order we determined. 162278161Speter */ 1623160244Sjhb TAILQ_FOREACH_SAFE(lf, &depended_files, loaded, nlf) { 162491040Sarr if (linker_kernel_file) { 162591040Sarr linker_kernel_file->refs++; 162691040Sarr error = linker_file_add_dependency(lf, 162791040Sarr linker_kernel_file); 162891040Sarr if (error) 162991040Sarr panic("cannot add dependency"); 163091040Sarr } 163191040Sarr lf->userrefs++; /* so we can (try to) kldunload it */ 1632284160Sjhb error = linker_file_lookup_set(lf, MDT_SETNAME, &start, 163391040Sarr &stop, NULL); 163491040Sarr if (!error) { 163591040Sarr for (mdp = start; mdp < stop; mdp++) { 1636109605Sjake mp = *mdp; 163791040Sarr if (mp->md_type != MDT_DEPEND) 163891040Sarr continue; 1639109605Sjake modname = mp->md_cval; 1640109605Sjake verinfo = mp->md_data; 164191040Sarr mod = modlist_lookup2(modname, verinfo); 1642216988Strasz if (mod == NULL) { 1643216988Strasz printf("KLD file %s - cannot find " 1644216988Strasz "dependency \"%s\"\n", 1645216988Strasz lf->filename, modname); 1646216988Strasz goto fail; 1647216988Strasz } 1648151484Sjdp /* Don't count self-dependencies */ 1649151484Sjdp if (lf == mod->container) 1650151484Sjdp continue; 165191040Sarr mod->container->refs++; 165291040Sarr error = linker_file_add_dependency(lf, 165391040Sarr mod->container); 165491040Sarr if (error) 165591040Sarr panic("cannot add dependency"); 165691040Sarr } 165791040Sarr } 165891040Sarr /* 165991040Sarr * Now do relocation etc using the symbol search paths 166091040Sarr * established by the dependencies 166191040Sarr */ 166291040Sarr error = LINKER_LINK_PRELOAD_FINISH(lf); 166391040Sarr if (error) { 166491040Sarr printf("KLD file %s - could not finalize loading\n", 166591040Sarr lf->filename); 1666216988Strasz goto fail; 166791040Sarr } 166891040Sarr linker_file_register_modules(lf); 1669284160Sjhb if (linker_file_lookup_set(lf, "sysinit_set", &si_start, 167091040Sarr &si_stop, NULL) == 0) 167191040Sarr sysinit_add(si_start, si_stop); 1672324748Savg linker_file_register_sysctls(lf, true); 167391040Sarr lf->flags |= LINKER_FILE_LINKED; 1674216988Strasz continue; 1675216988Straszfail: 1676216988Strasz TAILQ_REMOVE(&depended_files, lf, loaded); 1677216988Strasz linker_file_unload(lf, LINKER_UNLOAD_FORCE); 167859751Speter } 1679254810Smarkj sx_xunlock(&kld_sx); 168091040Sarr /* woohoo! we made it! */ 168140159Speter} 168240159Speter 1683359652ShselaskySYSINIT(preload, SI_SUB_KLD, SI_ORDER_MIDDLE, linker_preload, NULL); 168440159Speter 168540159Speter/* 168640159Speter * Search for a not-loaded module by name. 1687159840Sjhb * 168840159Speter * Modules may be found in the following locations: 1689159840Sjhb * 169091040Sarr * - preloaded (result is just the module name) - on disk (result is full path 169191040Sarr * to module) 1692159840Sjhb * 169391040Sarr * If the module name is qualified in any way (contains path, etc.) the we 169491040Sarr * simply return a copy of it. 1695159840Sjhb * 169640159Speter * The search path can be manipulated via sysctl. Note that we use the ';' 169740159Speter * character as a separator to be consistent with the bootloader. 169840159Speter */ 169940159Speter 170083321Speterstatic char linker_hintfile[] = "linker.hints"; 1701111852Srustatic char linker_path[MAXPATHLEN] = "/boot/kernel;/boot/modules"; 170240159Speter 1703267992ShselaskySYSCTL_STRING(_kern, OID_AUTO, module_path, CTLFLAG_RWTUN, linker_path, 170491040Sarr sizeof(linker_path), "module load search path"); 170540159Speter 170677843SpeterTUNABLE_STR("module_path", linker_path, sizeof(linker_path)); 170770417Speter 170859751Speterstatic char *linker_ext_list[] = { 170983321Speter "", 171059751Speter ".ko", 171159751Speter NULL 171259751Speter}; 171359751Speter 171483321Speter/* 171591040Sarr * Check if file actually exists either with or without extension listed in 171691040Sarr * the linker_ext_list. (probably should be generic for the rest of the 171791040Sarr * kernel) 171883321Speter */ 171959751Speterstatic char * 172091040Sarrlinker_lookup_file(const char *path, int pathlen, const char *name, 172191040Sarr int namelen, struct vattr *vap) 172240159Speter{ 172391040Sarr struct nameidata nd; 172491040Sarr struct thread *td = curthread; /* XXX */ 172591040Sarr char *result, **cpp, *sep; 1726241896Skib int error, len, extlen, reclen, flags; 172791040Sarr enum vtype type; 172840159Speter 172991040Sarr extlen = 0; 173091040Sarr for (cpp = linker_ext_list; *cpp; cpp++) { 173191040Sarr len = strlen(*cpp); 173291040Sarr if (len > extlen) 173391040Sarr extlen = len; 173491040Sarr } 173591040Sarr extlen++; /* trailing '\0' */ 173691040Sarr sep = (path[pathlen - 1] != '/') ? "/" : ""; 173783321Speter 173891040Sarr reclen = pathlen + strlen(sep) + namelen + extlen + 1; 1739111119Simp result = malloc(reclen, M_LINKER, M_WAITOK); 174091040Sarr for (cpp = linker_ext_list; *cpp; cpp++) { 174191040Sarr snprintf(result, reclen, "%.*s%s%.*s%s", pathlen, path, sep, 174291040Sarr namelen, name, *cpp); 174391040Sarr /* 174491040Sarr * Attempt to open the file, and return the path if 174591040Sarr * we succeed and it's a regular file. 174691040Sarr */ 1747241896Skib NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, result, td); 174891040Sarr flags = FREAD; 1749170152Skib error = vn_open(&nd, &flags, 0, NULL); 175091040Sarr if (error == 0) { 175191040Sarr NDFREE(&nd, NDF_ONLY_PNBUF); 175291040Sarr type = nd.ni_vp->v_type; 175391040Sarr if (vap) 1754182371Sattilio VOP_GETATTR(nd.ni_vp, vap, td->td_ucred); 1755175294Sattilio VOP_UNLOCK(nd.ni_vp, 0); 175691406Sjhb vn_close(nd.ni_vp, FREAD, td->td_ucred, td); 175791040Sarr if (type == VREG) 175891040Sarr return (result); 175991040Sarr } 176083321Speter } 176191040Sarr free(result, M_LINKER); 176291040Sarr return (NULL); 176383321Speter} 176483321Speter 176591040Sarr#define INT_ALIGN(base, ptr) ptr = \ 1766298433Spfg (base) + roundup2((ptr) - (base), sizeof(int)) 176783321Speter 176883321Speter/* 176991040Sarr * Lookup KLD which contains requested module in the "linker.hints" file. If 177091040Sarr * version specification is available, then try to find the best KLD. 177183321Speter * Otherwise just find the latest one. 177283321Speter */ 177383321Speterstatic char * 177491040Sarrlinker_hints_lookup(const char *path, int pathlen, const char *modname, 1775275469Simp int modnamelen, const struct mod_depend *verinfo) 177683321Speter{ 177791040Sarr struct thread *td = curthread; /* XXX */ 177891406Sjhb struct ucred *cred = td ? td->td_ucred : NULL; 177991040Sarr struct nameidata nd; 178091040Sarr struct vattr vattr, mattr; 178191040Sarr u_char *hints = NULL; 178291040Sarr u_char *cp, *recptr, *bufend, *result, *best, *pathbuf, *sep; 1783231949Skib int error, ival, bestver, *intp, found, flags, clen, blen; 1784231949Skib ssize_t reclen; 178583321Speter 178691040Sarr result = NULL; 178791040Sarr bestver = found = 0; 178883321Speter 178991040Sarr sep = (path[pathlen - 1] != '/') ? "/" : ""; 179091040Sarr reclen = imax(modnamelen, strlen(linker_hintfile)) + pathlen + 179191040Sarr strlen(sep) + 1; 1792111119Simp pathbuf = malloc(reclen, M_LINKER, M_WAITOK); 179391040Sarr snprintf(pathbuf, reclen, "%.*s%s%s", pathlen, path, sep, 179491040Sarr linker_hintfile); 179583321Speter 1796241896Skib NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, pathbuf, td); 179791040Sarr flags = FREAD; 1798170152Skib error = vn_open(&nd, &flags, 0, NULL); 179991040Sarr if (error) 180091040Sarr goto bad; 180191040Sarr NDFREE(&nd, NDF_ONLY_PNBUF); 180291040Sarr if (nd.ni_vp->v_type != VREG) 180391040Sarr goto bad; 180491040Sarr best = cp = NULL; 1805182371Sattilio error = VOP_GETATTR(nd.ni_vp, &vattr, cred); 180691040Sarr if (error) 180791040Sarr goto bad; 180891040Sarr /* 180991040Sarr * XXX: we need to limit this number to some reasonable value 181091040Sarr */ 1811275261Simp if (vattr.va_size > LINKER_HINTS_MAX) { 181291040Sarr printf("hints file too large %ld\n", (long)vattr.va_size); 181391040Sarr goto bad; 181491040Sarr } 1815111119Simp hints = malloc(vattr.va_size, M_TEMP, M_WAITOK); 181691068Sarr error = vn_rdwr(UIO_READ, nd.ni_vp, (caddr_t)hints, vattr.va_size, 0, 1817101941Srwatson UIO_SYSSPACE, IO_NODELOCKED, cred, NOCRED, &reclen, td); 181891040Sarr if (error) 181991040Sarr goto bad; 1820175294Sattilio VOP_UNLOCK(nd.ni_vp, 0); 182191040Sarr vn_close(nd.ni_vp, FREAD, cred, td); 182291040Sarr nd.ni_vp = NULL; 182391040Sarr if (reclen != 0) { 1824231949Skib printf("can't read %zd\n", reclen); 182591040Sarr goto bad; 182691040Sarr } 182791040Sarr intp = (int *)hints; 182883321Speter ival = *intp++; 182991040Sarr if (ival != LINKER_HINTS_VERSION) { 183091040Sarr printf("hints file version mismatch %d\n", ival); 183191040Sarr goto bad; 183283321Speter } 183391040Sarr bufend = hints + vattr.va_size; 183491040Sarr recptr = (u_char *)intp; 183591040Sarr clen = blen = 0; 183691040Sarr while (recptr < bufend && !found) { 183791040Sarr intp = (int *)recptr; 183891040Sarr reclen = *intp++; 183991040Sarr ival = *intp++; 184091040Sarr cp = (char *)intp; 184191040Sarr switch (ival) { 184291040Sarr case MDT_VERSION: 184391040Sarr clen = *cp++; 184491040Sarr if (clen != modnamelen || bcmp(cp, modname, clen) != 0) 184591040Sarr break; 184691040Sarr cp += clen; 184791040Sarr INT_ALIGN(hints, cp); 184891040Sarr ival = *(int *)cp; 184991040Sarr cp += sizeof(int); 185091040Sarr clen = *cp++; 185191040Sarr if (verinfo == NULL || 185291040Sarr ival == verinfo->md_ver_preferred) { 185391040Sarr found = 1; 185491040Sarr break; 185591040Sarr } 185691040Sarr if (ival >= verinfo->md_ver_minimum && 185791040Sarr ival <= verinfo->md_ver_maximum && 185891040Sarr ival > bestver) { 185991040Sarr bestver = ival; 186091040Sarr best = cp; 186191040Sarr blen = clen; 186291040Sarr } 186391040Sarr break; 186491040Sarr default: 186591040Sarr break; 186691040Sarr } 186791040Sarr recptr += reclen + sizeof(int); 186891040Sarr } 186983321Speter /* 187091040Sarr * Finally check if KLD is in the place 187183321Speter */ 187291040Sarr if (found) 187391040Sarr result = linker_lookup_file(path, pathlen, cp, clen, &mattr); 187491040Sarr else if (best) 187591040Sarr result = linker_lookup_file(path, pathlen, best, blen, &mattr); 187691040Sarr 187791040Sarr /* 187891040Sarr * KLD is newer than hints file. What we should do now? 187991040Sarr */ 188091040Sarr if (result && timespeccmp(&mattr.va_mtime, &vattr.va_mtime, >)) 188191040Sarr printf("warning: KLD '%s' is newer than the linker.hints" 188291040Sarr " file\n", result); 188383321Speterbad: 1884105167Sphk free(pathbuf, M_LINKER); 188591040Sarr if (hints) 188691040Sarr free(hints, M_TEMP); 188799553Sjeff if (nd.ni_vp != NULL) { 1888175294Sattilio VOP_UNLOCK(nd.ni_vp, 0); 188991040Sarr vn_close(nd.ni_vp, FREAD, cred, td); 189099553Sjeff } 189191040Sarr /* 189291040Sarr * If nothing found or hints is absent - fallback to the old 189391040Sarr * way by using "kldname[.ko]" as module name. 189491040Sarr */ 189591040Sarr if (!found && !bestver && result == NULL) 189691040Sarr result = linker_lookup_file(path, pathlen, modname, 189791040Sarr modnamelen, NULL); 189891040Sarr return (result); 189983321Speter} 190083321Speter 190183321Speter/* 190283321Speter * Lookup KLD which contains requested module in the all directories. 190383321Speter */ 190483321Speterstatic char * 190583321Speterlinker_search_module(const char *modname, int modnamelen, 1906275469Simp const struct mod_depend *verinfo) 190783321Speter{ 190891040Sarr char *cp, *ep, *result; 190983321Speter 191091040Sarr /* 191191040Sarr * traverse the linker path 191291040Sarr */ 191391040Sarr for (cp = linker_path; *cp; cp = ep + 1) { 191491040Sarr /* find the end of this component */ 191591040Sarr for (ep = cp; (*ep != 0) && (*ep != ';'); ep++); 191691068Sarr result = linker_hints_lookup(cp, ep - cp, modname, 191791068Sarr modnamelen, verinfo); 191891040Sarr if (result != NULL) 191991040Sarr return (result); 192091040Sarr if (*ep == 0) 192191040Sarr break; 192291040Sarr } 192391040Sarr return (NULL); 192483321Speter} 192583321Speter 192683321Speter/* 192783321Speter * Search for module in all directories listed in the linker_path. 192883321Speter */ 192983321Speterstatic char * 193083321Speterlinker_search_kld(const char *name) 193183321Speter{ 1932158972Sdelphij char *cp, *ep, *result; 1933158972Sdelphij int len; 193483321Speter 193591040Sarr /* qualified at all? */ 1936229272Sed if (strchr(name, '/')) 1937254396Smarkj return (strdup(name, M_LINKER)); 193840159Speter 193991040Sarr /* traverse the linker path */ 194091040Sarr len = strlen(name); 194191040Sarr for (ep = linker_path; *ep; ep++) { 194291040Sarr cp = ep; 194391040Sarr /* find the end of this component */ 194491040Sarr for (; *ep != 0 && *ep != ';'; ep++); 194591040Sarr result = linker_lookup_file(cp, ep - cp, name, len, NULL); 194691040Sarr if (result != NULL) 194791040Sarr return (result); 194891040Sarr } 194991040Sarr return (NULL); 195040159Speter} 195159751Speter 195259751Speterstatic const char * 195391040Sarrlinker_basename(const char *path) 195459751Speter{ 195591040Sarr const char *filename; 195659751Speter 1957229272Sed filename = strrchr(path, '/'); 195891040Sarr if (filename == NULL) 195991040Sarr return path; 196091040Sarr if (filename[1]) 196191040Sarr filename++; 196291040Sarr return (filename); 196359751Speter} 196459751Speter 1965157144Sjkoshy#ifdef HWPMC_HOOKS 196659751Speter/* 1967157144Sjkoshy * Inform hwpmc about the set of kernel modules currently loaded. 1968157144Sjkoshy */ 1969157144Sjkoshyvoid * 1970157144Sjkoshylinker_hwpmc_list_objects(void) 1971157144Sjkoshy{ 1972195159Sattilio linker_file_t lf; 1973195159Sattilio struct pmckern_map_in *kobase; 1974195159Sattilio int i, nmappings; 1975157144Sjkoshy 1976195159Sattilio nmappings = 0; 1977254810Smarkj sx_slock(&kld_sx); 1978195159Sattilio TAILQ_FOREACH(lf, &linker_files, link) 1979195159Sattilio nmappings++; 1980157144Sjkoshy 1981195159Sattilio /* Allocate nmappings + 1 entries. */ 1982195159Sattilio kobase = malloc((nmappings + 1) * sizeof(struct pmckern_map_in), 1983184214Sdes M_LINKER, M_WAITOK | M_ZERO); 1984195159Sattilio i = 0; 1985195159Sattilio TAILQ_FOREACH(lf, &linker_files, link) { 1986157144Sjkoshy 1987195159Sattilio /* Save the info for this linker file. */ 1988195159Sattilio kobase[i].pm_file = lf->filename; 1989195159Sattilio kobase[i].pm_address = (uintptr_t)lf->address; 1990195159Sattilio i++; 1991157144Sjkoshy } 1992254810Smarkj sx_sunlock(&kld_sx); 1993157144Sjkoshy 1994195159Sattilio KASSERT(i > 0, ("linker_hpwmc_list_objects: no kernel objects?")); 1995157144Sjkoshy 1996157144Sjkoshy /* The last entry of the malloced area comprises of all zeros. */ 1997195159Sattilio KASSERT(kobase[i].pm_file == NULL, 1998157144Sjkoshy ("linker_hwpmc_list_objects: last object not NULL")); 1999157144Sjkoshy 2000195159Sattilio return ((void *)kobase); 2001157144Sjkoshy} 2002157144Sjkoshy#endif 2003157144Sjkoshy 2004157144Sjkoshy/* 200591040Sarr * Find a file which contains given module and load it, if "parent" is not 200691040Sarr * NULL, register a reference to it. 200759751Speter */ 2008159796Sjhbstatic int 200983321Speterlinker_load_module(const char *kldname, const char *modname, 2010275469Simp struct linker_file *parent, const struct mod_depend *verinfo, 201191040Sarr struct linker_file **lfpp) 201259751Speter{ 201391040Sarr linker_file_t lfdep; 201491040Sarr const char *filename; 201591040Sarr char *pathname; 201691040Sarr int error; 201759751Speter 2018254810Smarkj sx_assert(&kld_sx, SA_XLOCKED); 201991040Sarr if (modname == NULL) { 202091040Sarr /* 202191040Sarr * We have to load KLD 202291040Sarr */ 202391068Sarr KASSERT(verinfo == NULL, ("linker_load_module: verinfo" 202491068Sarr " is not NULL")); 2025355418Shselasky /* check if root file system is not mounted */ 2026355418Shselasky if (rootvnode == NULL || curproc->p_fd->fd_rdir == NULL) 2027355418Shselasky return (ENXIO); 202891040Sarr pathname = linker_search_kld(kldname); 202991040Sarr } else { 203091040Sarr if (modlist_lookup2(modname, verinfo) != NULL) 203191040Sarr return (EEXIST); 2032355418Shselasky /* check if root file system is not mounted */ 2033355418Shselasky if (rootvnode == NULL || curproc->p_fd->fd_rdir == NULL) 2034355418Shselasky return (ENXIO); 203594322Sbrian if (kldname != NULL) 2036254396Smarkj pathname = strdup(kldname, M_LINKER); 203794322Sbrian else 203891040Sarr /* 203991040Sarr * Need to find a KLD with required module 204091040Sarr */ 204191040Sarr pathname = linker_search_module(modname, 204291040Sarr strlen(modname), verinfo); 204391040Sarr } 204491040Sarr if (pathname == NULL) 204591040Sarr return (ENOENT); 204691040Sarr 204783321Speter /* 204891040Sarr * Can't load more than one file with the same basename XXX: 204991040Sarr * Actually it should be possible to have multiple KLDs with 205091040Sarr * the same basename but different path because they can 205191040Sarr * provide different versions of the same modules. 205283321Speter */ 205391040Sarr filename = linker_basename(pathname); 2054159792Sjhb if (linker_find_file_by_name(filename)) 205591040Sarr error = EEXIST; 2056159792Sjhb else do { 205791040Sarr error = linker_load_file(pathname, &lfdep); 205891040Sarr if (error) 205991040Sarr break; 206091040Sarr if (modname && verinfo && 206191040Sarr modlist_lookup2(modname, verinfo) == NULL) { 2062132117Sphk linker_file_unload(lfdep, LINKER_UNLOAD_FORCE); 206391040Sarr error = ENOENT; 206491040Sarr break; 206591040Sarr } 206691040Sarr if (parent) { 206791040Sarr error = linker_file_add_dependency(parent, lfdep); 206891040Sarr if (error) 206991040Sarr break; 207091040Sarr } 207191040Sarr if (lfpp) 207291040Sarr *lfpp = lfdep; 207391040Sarr } while (0); 2074159791Sjhb free(pathname, M_LINKER); 207591040Sarr return (error); 207659751Speter} 207759751Speter 207859751Speter/* 207991040Sarr * This routine is responsible for finding dependencies of userland initiated 208091040Sarr * kldload(2)'s of files. 208159751Speter */ 208259751Speterint 208386469Siedowselinker_load_dependencies(linker_file_t lf) 208459751Speter{ 208591040Sarr linker_file_t lfdep; 208691040Sarr struct mod_metadata **start, **stop, **mdp, **nmdp; 208791040Sarr struct mod_metadata *mp, *nmp; 2088275469Simp const struct mod_depend *verinfo; 208991040Sarr modlist_t mod; 209091040Sarr const char *modname, *nmodname; 2091340052Sbz int ver, error = 0; 209259751Speter 209391040Sarr /* 2094298819Spfg * All files are dependent on /kernel. 209591040Sarr */ 2096254810Smarkj sx_assert(&kld_sx, SA_XLOCKED); 209791040Sarr if (linker_kernel_file) { 209891040Sarr linker_kernel_file->refs++; 209991040Sarr error = linker_file_add_dependency(lf, linker_kernel_file); 210091040Sarr if (error) 210191040Sarr return (error); 210259751Speter } 2103284160Sjhb if (linker_file_lookup_set(lf, MDT_SETNAME, &start, &stop, 2104340052Sbz NULL) != 0) 210591040Sarr return (0); 210691040Sarr for (mdp = start; mdp < stop; mdp++) { 2107109605Sjake mp = *mdp; 210891040Sarr if (mp->md_type != MDT_VERSION) 210991040Sarr continue; 2110109605Sjake modname = mp->md_cval; 2111292077Simp ver = ((const struct mod_version *)mp->md_data)->mv_version; 211291040Sarr mod = modlist_lookup(modname, ver); 211391040Sarr if (mod != NULL) { 211491040Sarr printf("interface %s.%d already present in the KLD" 211591040Sarr " '%s'!\n", modname, ver, 211691040Sarr mod->container->filename); 211791040Sarr return (EEXIST); 211891040Sarr } 211991040Sarr } 212074642Sbp 212191040Sarr for (mdp = start; mdp < stop; mdp++) { 2122109605Sjake mp = *mdp; 212391040Sarr if (mp->md_type != MDT_DEPEND) 212491040Sarr continue; 2125109605Sjake modname = mp->md_cval; 2126109605Sjake verinfo = mp->md_data; 212791040Sarr nmodname = NULL; 212891040Sarr for (nmdp = start; nmdp < stop; nmdp++) { 2129109605Sjake nmp = *nmdp; 213091040Sarr if (nmp->md_type != MDT_VERSION) 213191040Sarr continue; 2132109605Sjake nmodname = nmp->md_cval; 213392032Sdwmalone if (strcmp(modname, nmodname) == 0) 213491040Sarr break; 213591040Sarr } 213691040Sarr if (nmdp < stop)/* early exit, it's a self reference */ 213791040Sarr continue; 213891040Sarr mod = modlist_lookup2(modname, verinfo); 213991040Sarr if (mod) { /* woohoo, it's loaded already */ 214091040Sarr lfdep = mod->container; 214191040Sarr lfdep->refs++; 214291040Sarr error = linker_file_add_dependency(lf, lfdep); 214391040Sarr if (error) 214491040Sarr break; 214591040Sarr continue; 214691040Sarr } 214791040Sarr error = linker_load_module(NULL, modname, lf, verinfo, NULL); 214891040Sarr if (error) { 2149231931Sdelphij printf("KLD %s: depends on %s - not available or" 2150195803Srpaulo " version mismatch\n", lf->filename, modname); 215191040Sarr break; 215291040Sarr } 215359751Speter } 215459751Speter 215591040Sarr if (error) 215691040Sarr return (error); 215791040Sarr linker_addmodules(lf, start, stop, 0); 215891040Sarr return (error); 215959751Speter} 216085736Sgreen 216185736Sgreenstatic int 216285736Sgreensysctl_kern_function_list_iterate(const char *name, void *opaque) 216385736Sgreen{ 216485736Sgreen struct sysctl_req *req; 216585736Sgreen 216685736Sgreen req = opaque; 216785736Sgreen return (SYSCTL_OUT(req, name, strlen(name) + 1)); 216885736Sgreen} 216985736Sgreen 217085736Sgreen/* 217185736Sgreen * Export a nul-separated, double-nul-terminated list of all function names 217285736Sgreen * in the kernel. 217385736Sgreen */ 217485736Sgreenstatic int 217585736Sgreensysctl_kern_function_list(SYSCTL_HANDLER_ARGS) 217685736Sgreen{ 217785736Sgreen linker_file_t lf; 217885736Sgreen int error; 217985736Sgreen 2180107089Srwatson#ifdef MAC 2181172930Srwatson error = mac_kld_check_stat(req->td->td_ucred); 2182107089Srwatson if (error) 2183107089Srwatson return (error); 2184107089Srwatson#endif 2185126253Struckman error = sysctl_wire_old_buffer(req, 0); 2186126253Struckman if (error != 0) 2187126253Struckman return (error); 2188254810Smarkj sx_xlock(&kld_sx); 218985736Sgreen TAILQ_FOREACH(lf, &linker_files, link) { 219085736Sgreen error = LINKER_EACH_FUNCTION_NAME(lf, 219185736Sgreen sysctl_kern_function_list_iterate, req); 219298452Sarr if (error) { 2193254810Smarkj sx_xunlock(&kld_sx); 219485736Sgreen return (error); 219598452Sarr } 219685736Sgreen } 2197254810Smarkj sx_xunlock(&kld_sx); 219885736Sgreen return (SYSCTL_OUT(req, "", 1)); 219985736Sgreen} 220085736Sgreen 2201217555SmdfSYSCTL_PROC(_kern, OID_AUTO, function_list, CTLTYPE_OPAQUE | CTLFLAG_RD, 220291040Sarr NULL, 0, sysctl_kern_function_list, "", "kernel function list"); 2203