34#include "opt_hwpmc_hooks.h"
38#include <sys/boottrace.h>
39#include <sys/eventhandler.h>
42#include <sys/kernel.h>
43#include <sys/libkern.h>
44#include <sys/linker.h>
46#include <sys/malloc.h>
47#include <sys/module.h>
54#include <sys/syscallsubr.h>
55#include <sys/sysctl.h>
56#include <sys/sysent.h>
57#include <sys/sysproto.h>
66#include <security/mac/mac_framework.h>
71#include <sys/pmckern.h>
76SYSCTL_INT(_debug, OID_AUTO, kld_debug, CTLFLAG_RWTUN,
77 &kld_debug, 0,
"Set various levels of KLD debug");
84const int kld_off_next = offsetof(
struct linker_file, link.tqe_next);
124#define LINKER_GET_NEXT_FILE_ID(a) do { \
125 linker_file_t lftmp; \
128 sx_assert(&kld_sx, SA_XLOCKED); \
130 TAILQ_FOREACH(lftmp, &linker_files, link) { \
131 if (next_file_id == lftmp->id) { \
136 (a) = next_file_id; \
142 TAILQ_ENTRY(modlist) link;
143 linker_file_t container;
153 const char*
name,
int deps);
155 const char *modname,
struct linker_file *
parent,
156 const struct mod_depend *verinfo,
struct linker_file **lfpp);
163 sx_init(&
kld_sx,
"kernel linker");
191 ((kobj_class_t)
lc)->refs++;
202 KLD_DPF(FILE, (
"linker_file_sysinit: calling SYSINITs for %s\n",
205 sx_assert(&
kld_sx, SA_XLOCKED);
216 for (sipp =
start; sipp <
stop; sipp++) {
217 for (xipp = sipp + 1; xipp <
stop; xipp++) {
218 if ((*sipp)->subsystem < (*xipp)->subsystem ||
219 ((*sipp)->subsystem == (*xipp)->subsystem &&
220 (*sipp)->order <= (*xipp)->order))
235 for (sipp =
start; sipp <
stop; sipp++) {
236 if ((*sipp)->subsystem == SI_SUB_DUMMY)
239 if ((*sipp)->subsystem > last)
240 BOOTTRACE(
"%s: sysinit 0x%7x", lf->filename,
244 (*((*sipp)->func)) ((*sipp)->udata);
245 last = (*sipp)->subsystem;
257 KLD_DPF(FILE, (
"linker_file_sysuninit: calling SYSUNINITs for %s\n",
260 sx_assert(&
kld_sx, SA_XLOCKED);
273 for (sipp =
start; sipp <
stop; sipp++) {
274 for (xipp = sipp + 1; xipp <
stop; xipp++) {
275 if ((*sipp)->subsystem > (*xipp)->subsystem ||
276 ((*sipp)->subsystem == (*xipp)->subsystem &&
277 (*sipp)->order >= (*xipp)->order))
292 for (sipp =
start; sipp <
stop; sipp++) {
293 if ((*sipp)->subsystem == SI_SUB_DUMMY)
296 if ((*sipp)->subsystem > last)
297 BOOTTRACE(
"%s: sysuninit 0x%7x", lf->filename,
301 (*((*sipp)->func)) ((*sipp)->udata);
302 last = (*sipp)->subsystem;
311 struct sysctl_oid **
start, **
stop, **oidp;
314 (
"linker_file_register_sysctls: registering SYSCTLs for %s\n",
317 sx_assert(&
kld_sx, SA_XLOCKED);
324 for (oidp =
start; oidp <
stop; oidp++) {
337 struct sysctl_oid **
start, **
stop, **oidp;
340 (
"linker_file_enable_sysctls: enable SYSCTLs for %s\n",
343 sx_assert(&
kld_sx, SA_XLOCKED);
359 struct sysctl_oid **
start, **
stop, **oidp;
361 KLD_DPF(FILE, (
"linker_file_unregister_sysctls: unregistering SYSCTLs"
362 " for %s\n", lf->filename));
364 sx_assert(&
kld_sx, SA_XLOCKED);
380 struct mod_metadata **
start, **
stop, **mdp;
381 const moduledata_t *moddata;
382 int first_error, error;
384 KLD_DPF(FILE, (
"linker_file_register_modules: registering modules"
385 " in %s\n", lf->filename));
387 sx_assert(&
kld_sx, SA_XLOCKED);
396 start = SET_BEGIN(modmetadata_set);
397 stop = SET_LIMIT(modmetadata_set);
403 if ((*mdp)->md_type != MDT_MODULE)
405 moddata = (*mdp)->md_data;
406 KLD_DPF(FILE, (
"Registering module %s in %s\n",
407 moddata->name, lf->filename));
410 printf(
"Module %s failed to register: %d\n",
411 moddata->name, error);
412 if (first_error == 0)
416 return (first_error);
436 int foundfile, error, modules;
439 if (
prison0.pr_securelevel > 0)
442 sx_assert(&
kld_sx, SA_XLOCKED);
445 KLD_DPF(FILE, (
"linker_load_file: file %s is already loaded,"
460 KLD_DPF(FILE, (
"linker_load_file: trying to load %s\n",
471 if (error == EEXIST) {
475 modules = !TAILQ_EMPTY(&lf->modules);
478 lf->flags |= LINKER_FILE_LINKED;
485 if (modules && TAILQ_EMPTY(&lf->modules)) {
490 EVENTHANDLER_INVOKE(kld_load, lf);
505 printf(
"%s: %s - unsupported file type\n",
552 KASSERT(modname != NULL,
553 (
"linker_release_module: no file or name"));
561 KASSERT(modname == NULL && verinfo == NULL,
562 (
"linker_release_module: both file and name"));
577 sx_assert(&
kld_sx, SA_XLOCKED);
579 if (strcmp(lf->filename, koname) == 0)
581 if (strcmp(lf->filename,
filename) == 0)
584 free(koname, M_LINKER);
593 sx_assert(&
kld_sx, SA_XLOCKED);
595 if (lf->id == fileid && lf->flags & LINKER_FILE_LINKED)
608 retval = predicate(lf, context);
623 sx_assert(&
kld_sx, SA_XLOCKED);
626 KLD_DPF(FILE, (
"linker_make_file: new file, filename='%s' for pathname='%s'\n",
filename, pathname));
627 lf = (linker_file_t)
kobj_create((kobj_class_t)
lc, M_LINKER, M_WAITOK);
637 lf->filename = strdup(
filename, M_LINKER);
638 lf->pathname = strdup(pathname, M_LINKER);
647 STAILQ_INIT(&lf->common);
648 TAILQ_INIT(&lf->modules);
658 struct common_symbol *cp;
662 if (
prison0.pr_securelevel > 0)
665 sx_assert(&
kld_sx, SA_XLOCKED);
666 KLD_DPF(FILE, (
"linker_file_unload: lf->refs=%d\n", file->refs));
669 if (file->refs > 1) {
676 EVENTHANDLER_INVOKE(kld_unload_try, file, &error);
680 KLD_DPF(FILE, (
"linker_file_unload: file is unloading,"
681 " informing modules\n"));
687 for (mod = TAILQ_FIRST(&file->modules); mod;
690 if (error != 0 &&
flags != LINKER_UNLOAD_FORCE) {
691 KLD_DPF(FILE, (
"linker_file_unload: module %s"
709 for (mod = TAILQ_FIRST(&file->modules); mod; mod = next) {
719 KLD_DPF(FILE, (
"linker_file_unload: module %s"
731 if (ml->container == file) {
741 if (file->flags & LINKER_FILE_LINKED) {
742 file->flags &= ~LINKER_FILE_LINKED;
749 for (i = 0; i < file->ndeps; i++)
751 free(file->deps, M_LINKER);
754 while ((cp = STAILQ_FIRST(&file->common)) != NULL) {
755 STAILQ_REMOVE_HEAD(&file->common, link);
761 EVENTHANDLER_INVOKE(kld_unload, file->filename, file->address,
764 if (file->filename) {
765 free(file->filename, M_LINKER);
766 file->filename = NULL;
768 if (file->pathname) {
769 free(file->pathname, M_LINKER);
770 file->pathname = NULL;
779 return (LINKER_CTF_GET(file,
lc));
785 linker_file_t *newdeps;
787 sx_assert(&
kld_sx, SA_XLOCKED);
788 file->deps =
realloc(file->deps, (file->ndeps + 1) *
sizeof(*newdeps),
789 M_LINKER, M_WAITOK | M_ZERO);
790 file->deps[file->ndeps] = dep;
792 KLD_DPF(FILE, (
"linker_file_add_dependency:"
793 " adding %s as dependency for %s\n",
794 dep->filename, file->filename));
806 void *firstp,
void *lastp,
int *countp)
809 sx_assert(&
kld_sx, SA_LOCKED);
810 return (LINKER_LOOKUP_SET(file,
name, firstp, lastp, countp));
818 linker_function_nameval_callback_t callback_func,
void *arg)
820 return (LINKER_EACH_FUNCTION_NAMEVAL(lf, callback_func, arg));
829 locked = sx_xlocked(&
kld_sx);
843 linker_symval_t symval;
845 size_t common_size = 0;
848 sx_assert(&
kld_sx, SA_XLOCKED);
849 KLD_DPF(SYM, (
"linker_file_lookup_symbol: file=%p, name=%s, deps=%d\n",
852 if (LINKER_LOOKUP_SYMBOL(file,
name, &
sym) == 0) {
853 LINKER_SYMBOL_VALUES(file,
sym, &symval);
854 if (symval.value == 0)
860 common_size = symval.size;
862 KLD_DPF(SYM, (
"linker_file_lookup_symbol: symbol"
863 ".value=%p\n", symval.value));
864 return (symval.value);
868 for (i = 0; i < file->ndeps; i++) {
870 file->deps[i],
name, 0);
872 KLD_DPF(SYM, (
"linker_file_lookup_symbol:"
873 " deps value=%p\n", address));
878 if (common_size > 0) {
884 struct common_symbol *cp;
886 STAILQ_FOREACH(cp, &file->common, link) {
887 if (strcmp(cp->name,
name) == 0) {
888 KLD_DPF(SYM, (
"linker_file_lookup_symbol:"
889 " old common value=%p\n", cp->address));
890 return (cp->address);
896 common_size = (common_size +
sizeof(int) - 1) & -
sizeof(int);
897 cp =
malloc(
sizeof(
struct common_symbol)
898 + common_size + strlen(
name) + 1, M_LINKER,
900 cp->address = (caddr_t)(cp + 1);
901 cp->name = cp->address + common_size;
902 strcpy(cp->name,
name);
903 bzero(cp->address, common_size);
904 STAILQ_INSERT_TAIL(&file->common, cp, link);
906 KLD_DPF(SYM, (
"linker_file_lookup_symbol: new common"
907 " value=%p\n", cp->address));
908 return (cp->address);
910 KLD_DPF(SYM, (
"linker_file_lookup_symbol: fail\n"));
925linker_debug_lookup(
const char *symstr, c_linker_sym_t *
sym)
930 if (LINKER_LOOKUP_DEBUG_SYMBOL(lf, symstr,
sym) == 0)
941 c_linker_sym_t best, es;
942 u_long diff, bestdiff, off;
945 off = (uintptr_t)
value;
948 if (LINKER_SEARCH_SYMBOL(lf,
value, &es, &diff) != 0)
950 if (es != 0 && diff < bestdiff) {
974 if (LINKER_DEBUG_SYMBOL_VALUES(lf,
sym, symval) == 0)
984 linker_symval_t symval;
995 strlcpy(
buf, symval.name, buflen);
1009linker_ddb_lookup(
const char *symstr, c_linker_sym_t *
sym)
1012 return (linker_debug_lookup(symstr,
sym));
1044 long *offset,
int flags)
1048 KASSERT((
flags & (M_NOWAIT | M_WAITOK)) != 0 &&
1049 (
flags & (M_NOWAIT | M_WAITOK)) != (M_NOWAIT | M_WAITOK),
1050 (
"%s: bad flags: 0x%x", __func__,
flags));
1052 if (
flags & M_NOWAIT) {
1053 if (!sx_try_slock(&
kld_sx))
1054 return (EWOULDBLOCK);
1077 MPASS((
flags & ~(LINKER_UB_UNLOCK | LINKER_UB_LOCKED |
1078 LINKER_UB_PCATCH)) == 0);
1079 if ((
flags & LINKER_UB_LOCKED) != 0)
1080 sx_assert(&
kld_sx, SA_XLOCKED);
1082 if ((
flags & LINKER_UB_LOCKED) == 0)
1088 (
flags & LINKER_UB_PCATCH) != 0 ? PCATCH : 0,
1091 if ((
flags & LINKER_UB_UNLOCK) != 0)
1098 if ((
flags & LINKER_UB_UNLOCK) != 0)
1106 MPASS((
flags & ~LINKER_UB_LOCKED) == 0);
1107 if ((
flags & LINKER_UB_LOCKED) != 0)
1108 sx_assert(&
kld_sx, SA_XLOCKED);
1110 if ((
flags & LINKER_UB_LOCKED) == 0)
1114 panic(
"linker_kldload_unbusy done by not owning thread %p",
1130 const char *kldname, *modname;
1137 if ((error =
priv_check(td, PRIV_KLD_LOAD)) != 0)
1145 if (strchr(file,
'/') || strchr(file,
'.')) {
1163 CURVNET_SET(TD_TO_VNET(td));
1180 char *pathname = NULL;
1183 td->td_retval[0] = -1;
1185 pathname =
malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
1186 error = copyinstr(uap->file, pathname, MAXPATHLEN, NULL);
1190 td->td_retval[0] = fileid;
1192 free(pathname, M_TEMP);
1205 if ((error =
priv_check(td, PRIV_KLD_UNLOAD)) != 0)
1214 CURVNET_SET(TD_TO_VNET(td));
1217 KLD_DPF(FILE, (
"kldunload: lf->userrefs=%d\n", lf->userrefs));
1219 if (lf->userrefs == 0) {
1223 printf(
"kldunload: attempt to unload file that was"
1224 " loaded by the kernel\n");
1250 if (uap->flags != LINKER_UNLOAD_NORMAL &&
1251 uap->flags != LINKER_UNLOAD_FORCE)
1265 error = mac_kld_check_stat(td->td_ucred);
1270 td->td_retval[0] = -1;
1272 pathname =
malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
1273 if ((error = copyinstr(uap->file, pathname, MAXPATHLEN, NULL)) != 0)
1280 td->td_retval[0] = lf->id;
1285 free(pathname, M_TEMP);
1296 error = mac_kld_check_stat(td->td_ucred);
1302 if (uap->fileid == 0)
1310 lf = TAILQ_NEXT(lf, link);
1314 while (lf != NULL && !(lf->flags & LINKER_FILE_LINKED))
1315 lf = TAILQ_NEXT(lf, link);
1318 td->td_retval[0] = lf->id;
1320 td->td_retval[0] = 0;
1329 struct kld_file_stat *stat;
1335 if ((error = copyin(&uap->stat->version, &version,
sizeof(version)))
1338 if (version !=
sizeof(
struct kld_file_stat_1) &&
1339 version !=
sizeof(
struct kld_file_stat))
1342 stat =
malloc(
sizeof(*stat), M_TEMP, M_WAITOK | M_ZERO);
1345 error = copyout(stat, uap->stat, version);
1358 error = mac_kld_check_stat(td->td_ucred);
1371 namelen = strlen(lf->filename) + 1;
1372 if (namelen >
sizeof(stat->name))
1373 namelen =
sizeof(stat->name);
1374 bcopy(lf->filename, &stat->name[0], namelen);
1375 stat->refs = lf->refs;
1377 stat->address = lf->address;
1378 stat->size = lf->size;
1380 namelen = strlen(lf->pathname) + 1;
1381 if (namelen >
sizeof(stat->pathname))
1382 namelen =
sizeof(stat->pathname);
1383 bcopy(lf->pathname, &stat->pathname[0], namelen);
1386 td->td_retval[0] = 0;
1391DB_COMMAND(kldstat, db_kldstat)
1395#define POINTER_WIDTH ((int)(sizeof(void *) * 2 + 2))
1396 db_printf(
"Id Refs Address%*c Size Name\n", POINTER_WIDTH - 7,
' ');
1401 db_printf(
"%2d %4d %p %-8zx %s\n", lf->id, lf->refs,
1402 lf->address, lf->size, lf->filename);
1415 error = mac_kld_check_stat(td->td_ucred);
1424 mp = TAILQ_FIRST(&lf->modules);
1428 td->td_retval[0] = 0;
1439 char *symstr = NULL;
1441 linker_symval_t symval;
1443 struct kld_sym_lookup lookup;
1447 error = mac_kld_check_stat(td->td_ucred);
1452 if ((error = copyin(uap->data, &lookup,
sizeof(lookup))) != 0)
1454 if (lookup.version !=
sizeof(lookup) ||
1455 uap->cmd != KLDSYM_LOOKUP)
1457 symstr =
malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
1458 if ((error = copyinstr(lookup.symname, symstr, MAXPATHLEN, NULL)) != 0)
1461 if (uap->fileid != 0) {
1465 else if (LINKER_LOOKUP_SYMBOL(lf, symstr, &
sym) == 0 &&
1466 LINKER_SYMBOL_VALUES(lf,
sym, &symval) == 0) {
1467 lookup.symvalue = (uintptr_t) symval.value;
1468 lookup.symsize = symval.size;
1469 error = copyout(&lookup, uap->data,
sizeof(lookup));
1474 if (LINKER_LOOKUP_SYMBOL(lf, symstr, &
sym) == 0 &&
1475 LINKER_SYMBOL_VALUES(lf,
sym, &symval) == 0) {
1476 lookup.symvalue = (uintptr_t)symval.value;
1477 lookup.symsize = symval.size;
1478 error = copyout(&lookup, uap->data,
1488 free(symstr, M_TEMP);
1502 if (strcmp(mod->name,
name) == 0 &&
1503 (ver == 0 || mod->version == ver))
1515 if (verinfo == NULL)
1519 if (strcmp(mod->name,
name) != 0)
1522 if (ver == verinfo->md_ver_preferred)
1524 if (ver >= verinfo->md_ver_minimum &&
1525 ver <= verinfo->md_ver_maximum &&
1526 (bestmod == NULL || ver > bestmod->version))
1537 mod =
malloc(
sizeof(
struct modlist), M_LINKER, M_NOWAIT | M_ZERO);
1539 panic(
"no memory for module list");
1540 mod->container = container;
1541 mod->name = modname;
1542 mod->version = version;
1549 struct mod_metadata **
stop,
int preload)
1551 struct mod_metadata *mp, **mdp;
1552 const char *modname;
1557 if (mp->md_type != MDT_VERSION)
1559 modname = mp->md_cval;
1560 ver = ((
const struct mod_version *)mp->md_data)->mv_version;
1562 printf(
"module %s already present!\n", modname);
1574 const char *modname, *nmodname;
1576 linker_file_t lf, nlf;
1579 linker_file_list_t loaded_files;
1580 linker_file_list_t depended_files;
1581 struct mod_metadata *mp, *nmp;
1582 struct mod_metadata **
start, **
stop, **mdp, **nmdp;
1583 const struct mod_depend *verinfo;
1587 struct sysinit **si_start, **si_stop;
1589 TAILQ_INIT(&loaded_files);
1590 TAILQ_INIT(&depended_files);
1599 if (modname == NULL) {
1600 printf(
"Preloaded module at %p does not have a"
1601 " name!\n", modptr);
1604 if (modtype == NULL) {
1605 printf(
"Preloaded module at %p does not have a type!\n",
1610 printf(
"Preloaded %s \"%s\" at %p.\n", modtype, modname,
1614 error = LINKER_LINK_PRELOAD(
lc, modname, &lf);
1620 TAILQ_INSERT_TAIL(&loaded_files, lf, loaded);
1635 TAILQ_FOREACH(lf, &loaded_files, loaded) {
1646 if (mp->md_type != MDT_DEPEND)
1648 modname = mp->md_cval;
1649 verinfo = mp->md_data;
1650 for (nmdp =
start; nmdp <
stop; nmdp++) {
1652 if (nmp->md_type != MDT_VERSION)
1654 nmodname = nmp->md_cval;
1655 if (strcmp(modname, nmodname) == 0)
1678 if (mp->md_type != MDT_VERSION)
1680 modname = mp->md_cval;
1681 nver = ((
const struct mod_version *)
1682 mp->md_data)->mv_version;
1685 printf(
"module %s already"
1686 " present!\n", modname);
1687 TAILQ_REMOVE(&loaded_files,
1690 LINKER_UNLOAD_FORCE);
1697 TAILQ_REMOVE(&loaded_files, lf, loaded);
1698 TAILQ_INSERT_TAIL(&depended_files, lf, loaded);
1712 while ((lf = TAILQ_FIRST(&loaded_files)) != NULL) {
1713 TAILQ_REMOVE(&loaded_files, lf, loaded);
1714 printf(
"KLD file %s is missing dependencies\n", lf->filename);
1721 TAILQ_FOREACH_SAFE(lf, &depended_files, loaded, nlf) {
1727 panic(
"cannot add dependency");
1734 if (mp->md_type != MDT_DEPEND)
1736 modname = mp->md_cval;
1737 verinfo = mp->md_data;
1740 printf(
"KLD file %s - cannot find "
1741 "dependency \"%s\"\n",
1742 lf->filename, modname);
1746 if (lf == mod->container)
1748 mod->container->refs++;
1752 panic(
"cannot add dependency");
1759 error = LINKER_LINK_PRELOAD_FINISH(lf);
1761 printf(
"KLD file %s - could not finalize loading\n",
1766 if (!TAILQ_EMPTY(&lf->modules))
1767 lf->flags |= LINKER_FILE_MODULES;
1769 &si_stop, NULL) == 0)
1772 lf->flags |= LINKER_FILE_LINKED;
1775 TAILQ_REMOVE(&depended_files, lf, loaded);
1790 linker_file_t lf, nlf;
1799 if ((lf->flags & LINKER_FILE_MODULES) != 0 &&
1800 TAILQ_EMPTY(&lf->modules)) {
1805 lf->flags &= ~LINKER_FILE_MODULES;
1816SYSINIT(preload_finish, SI_SUB_KTHREAD_INIT - 100, SI_ORDER_MIDDLE,
1855 int namelen,
struct vattr *vap)
1857 struct nameidata nd;
1858 struct thread *td = curthread;
1859 const char *
const *cpp, *sep;
1861 int error, len, extlen, reclen,
flags;
1871 sep = (
path[pathlen - 1] !=
'/') ?
"/" :
"";
1873 reclen = pathlen + strlen(sep) + namelen + extlen + 1;
1877 namelen,
name, *cpp);
1882 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE,
result);
1886 NDFREE(&nd, NDF_ONLY_PNBUF);
1887 type = nd.ni_vp->v_type;
1889 VOP_GETATTR(nd.ni_vp, vap, td->td_ucred);
1890 VOP_UNLOCK(nd.ni_vp);
1891 vn_close(nd.ni_vp, FREAD, td->td_ucred, td);
1900#define INT_ALIGN(base, ptr) ptr = \
1901 (base) + roundup2((ptr) - (base), sizeof(int))
1910 int modnamelen,
const struct mod_depend *verinfo)
1912 struct thread *td = curthread;
1913 struct ucred *cred = td ? td->td_ucred : NULL;
1914 struct nameidata nd;
1915 struct vattr vattr, mattr;
1916 const char *best, *sep;
1917 u_char *hints = NULL;
1918 u_char *cp, *recptr, *bufend, *
result, *pathbuf;
1919 int error, ival, bestver, *intp, found,
flags, clen, blen;
1923 bestver = found = 0;
1925 sep = (
path[pathlen - 1] !=
'/') ?
"/" :
"";
1928 pathbuf =
malloc(reclen, M_LINKER, M_WAITOK);
1929 snprintf(pathbuf, reclen,
"%.*s%s%s", pathlen,
path, sep,
1932 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, pathbuf);
1937 NDFREE(&nd, NDF_ONLY_PNBUF);
1938 if (nd.ni_vp->v_type != VREG)
1941 error = VOP_GETATTR(nd.ni_vp, &vattr, cred);
1947 if (vattr.va_size > LINKER_HINTS_MAX) {
1948 printf(
"linker.hints file too large %ld\n", (
long)vattr.va_size);
1951 hints =
malloc(vattr.va_size, M_TEMP, M_WAITOK);
1952 error =
vn_rdwr(UIO_READ, nd.ni_vp, (caddr_t)hints, vattr.va_size, 0,
1953 UIO_SYSSPACE, IO_NODELOCKED, cred, NOCRED, &reclen, td);
1956 VOP_UNLOCK(nd.ni_vp);
1957 vn_close(nd.ni_vp, FREAD, cred, td);
1960 printf(
"can't read %zd\n", reclen);
1963 intp = (
int *)hints;
1965 if (ival != LINKER_HINTS_VERSION) {
1966 printf(
"linker.hints file version mismatch %d\n", ival);
1969 bufend = hints + vattr.va_size;
1970 recptr = (u_char *)intp;
1972 while (recptr < bufend && !found) {
1973 intp = (
int *)recptr;
1980 if (clen != modnamelen || bcmp(cp, modname, clen) != 0)
1987 if (verinfo == NULL ||
1988 ival == verinfo->md_ver_preferred) {
1992 if (ival >= verinfo->md_ver_minimum &&
1993 ival <= verinfo->md_ver_maximum &&
2003 recptr += reclen +
sizeof(int);
2016 if (
result && timespeccmp(&mattr.va_mtime, &vattr.va_mtime, >))
2017 printf(
"warning: KLD '%s' is newer than the linker.hints"
2020 free(pathbuf, M_LINKER);
2022 free(hints, M_TEMP);
2023 if (nd.ni_vp != NULL) {
2024 VOP_UNLOCK(nd.ni_vp);
2025 vn_close(nd.ni_vp, FREAD, cred, td);
2031 if (!found && !bestver &&
result == NULL)
2042 const struct mod_depend *verinfo)
2051 for (ep = cp; (*ep != 0) && (*ep !=
';'); ep++);
2053 modnamelen, verinfo);
2072 if (strchr(
name,
'/'))
2073 return (strdup(
name, M_LINKER));
2080 for (; *ep != 0 && *ep !=
';'; ep++);
2106linker_hwpmc_list_objects(
void)
2109 struct pmckern_map_in *kobase;
2118 kobase =
malloc((nmappings + 1) *
sizeof(
struct pmckern_map_in),
2119 M_LINKER, M_WAITOK | M_ZERO);
2123 kobase[i].pm_file = lf->filename;
2124 kobase[i].pm_address = (uintptr_t)lf->address;
2129 KASSERT(i > 0, (
"linker_hpwmc_list_objects: no kernel objects?"));
2132 KASSERT(kobase[i].pm_file == NULL,
2133 (
"linker_hwpmc_list_objects: last object not NULL"));
2135 return ((
void *)kobase);
2150 ret = pwd->pwd_rdir != NULL;
2161 struct linker_file *
parent,
const struct mod_depend *verinfo,
2162 struct linker_file **lfpp)
2164 linker_file_t lfdep;
2169 sx_assert(&
kld_sx, SA_XLOCKED);
2170 if (modname == NULL) {
2174 KASSERT(verinfo == NULL, (
"linker_load_module: verinfo"
2184 if (kldname != NULL)
2185 pathname = strdup(kldname, M_LINKER);
2191 strlen(modname), verinfo);
2193 if (pathname == NULL)
2209 if (modname && verinfo &&
2223 free(pathname, M_LINKER);
2234 linker_file_t lfdep;
2235 struct mod_metadata **
start, **
stop, **mdp, **nmdp;
2236 struct mod_metadata *mp, *nmp;
2237 const struct mod_depend *verinfo;
2239 const char *modname, *nmodname;
2245 sx_assert(&
kld_sx, SA_XLOCKED);
2257 if (mp->md_type != MDT_VERSION)
2259 modname = mp->md_cval;
2260 ver = ((
const struct mod_version *)mp->md_data)->mv_version;
2263 printf(
"interface %s.%d already present in the KLD"
2264 " '%s'!\n", modname, ver,
2265 mod->container->filename);
2272 if (mp->md_type != MDT_DEPEND)
2274 modname = mp->md_cval;
2275 verinfo = mp->md_data;
2277 for (nmdp =
start; nmdp <
stop; nmdp++) {
2279 if (nmp->md_type != MDT_VERSION)
2281 nmodname = nmp->md_cval;
2282 if (strcmp(modname, nmodname) == 0)
2289 lfdep = mod->container;
2298 printf(
"KLD %s: depends on %s - not available or"
2299 " version mismatch\n", lf->filename, modname);
2313 struct sysctl_req *req;
2316 return (SYSCTL_OUT(req,
name, strlen(
name) + 1));
2330 error = mac_kld_check_stat(req->td->td_ucred);
2339 error = LINKER_EACH_FUNCTION_NAME(lf,
2347 return (SYSCTL_OUT(req,
"", 1));
2351 CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0,
2353 "kernel function list");
device_property_type_t type
SYSCTL_INT(ASLR_NODE_OID, OID_AUTO, enable, CTLFLAG_RWTUN, &__elfN(aslr_enabled), 0, ": enable address map randomization")
void sysinit_add(struct sysinit **set, struct sysinit **set_end)
struct sysinit ** sysinit
struct pwd * pwd_hold(struct thread *td)
void pwd_drop(struct pwd *pwd)
int linker_ctf_get(linker_file_t file, linker_ctf_t *lc)
static char * linker_search_module(const char *modname, int modnamelen, const struct mod_depend *verinfo)
SYSCTL_STRING(_kern, OID_AUTO, module_path, CTLFLAG_RWTUN, linker_path, sizeof(linker_path), "module load search path")
const int kld_off_filename
void linker_kldload_unbusy(int flags)
static void linker_file_sysuninit(linker_file_t lf)
static void linker_file_sysinit(linker_file_t lf)
static char * linker_lookup_file(const char *path, int pathlen, const char *name, int namelen, struct vattr *vap)
int kern_kldload(struct thread *td, const char *file, int *fileid)
int sys_kldload(struct thread *td, struct kldload_args *uap)
int linker_ddb_search_symbol(caddr_t value, c_linker_sym_t *sym, long *diffp)
static modlist_t modlist_newmodule(const char *modname, int version, linker_file_t container)
static int linker_debug_symbol_values(c_linker_sym_t sym, linker_symval_t *symval)
static caddr_t linker_file_lookup_symbol_internal(linker_file_t file, const char *name, int deps)
SET_DECLARE(modmetadata_set, struct mod_metadata)
static void linker_preload_finish(void *arg)
const int kld_off_address
static int sysctl_kern_function_list_iterate(const char *name, void *opaque)
static int linker_debug_search_symbol(caddr_t value, c_linker_sym_t *sym, long *diffp)
static void linker_addmodules(linker_file_t lf, struct mod_metadata **start, struct mod_metadata **stop, int preload)
int linker_reference_module(const char *modname, struct mod_depend *verinfo, linker_file_t *result)
typedef TAILQ_HEAD(modlist)
TUNABLE_STR("module_path", linker_path, sizeof(linker_path))
static int linker_load_module(const char *kldname, const char *modname, struct linker_file *parent, const struct mod_depend *verinfo, struct linker_file **lfpp)
int linker_ddb_symbol_values(c_linker_sym_t sym, linker_symval_t *symval)
const int kld_off_pathname
static void linker_init_kernel_modules(void)
static char * linker_search_kld(const char *name)
linker_file_t linker_kernel_file
int linker_file_foreach(linker_predicate_t *predicate, void *context)
SYSINIT(linker, SI_SUB_KLD, SI_ORDER_FIRST, linker_init, NULL)
static int linker_file_register_modules(linker_file_t lf)
int linker_file_lookup_set(linker_file_t file, const char *name, void *firstp, void *lastp, int *countp)
int linker_file_unload(linker_file_t file, int flags)
static int linker_no_more_classes
struct modlist * modlist_t
static linker_file_list_t linker_files
caddr_t linker_file_lookup_symbol(linker_file_t file, const char *name, int deps)
int sys_kldunload(struct thread *td, struct kldunload_args *uap)
static int linker_load_file(const char *filename, linker_file_t *result)
static int linker_debug_search_symbol_name(caddr_t value, char *buf, u_int buflen, long *offset)
static const char *const linker_ext_list[]
int linker_file_function_listall(linker_file_t lf, linker_function_nameval_callback_t callback_func, void *arg)
int kern_kldstat(struct thread *td, int fileid, struct kld_file_stat *stat)
#define LINKER_GET_NEXT_FILE_ID(a)
MALLOC_DEFINE(M_LINKER, "linker", "kernel linker")
static linker_class_list_t classes
static char linker_hintfile[]
SYSCTL_PROC(_kern, OID_AUTO, function_list, CTLTYPE_OPAQUE|CTLFLAG_RD|CTLFLAG_MPSAFE, NULL, 0, sysctl_kern_function_list, "", "kernel function list")
int linker_ddb_search_symbol_name(caddr_t value, char *buf, u_int buflen, long *offset)
static void linker_file_unregister_sysctls(linker_file_t lf)
static char linker_path[MAXPATHLEN]
#define INT_ALIGN(base, ptr)
int linker_load_dependencies(linker_file_t lf)
static int sysctl_kern_function_list(SYSCTL_HANDLER_ARGS)
static char * linker_hints_lookup(const char *path, int pathlen, const char *modname, int modnamelen, const struct mod_depend *verinfo)
static linker_file_t linker_find_file_by_id(int _fileid)
static bool linker_root_mounted(void)
int sys_kldsym(struct thread *td, struct kldsym_args *uap)
int sys_kldstat(struct thread *td, struct kldstat_args *uap)
int sys_kldfirstmod(struct thread *td, struct kldfirstmod_args *uap)
int kern_kldunload(struct thread *td, int fileid, int flags)
static modlist_t modlist_lookup2(const char *name, const struct mod_depend *verinfo)
static int linker_file_add_dependency(linker_file_t file, linker_file_t dep)
int sys_kldnext(struct thread *td, struct kldnext_args *uap)
linker_file_t linker_make_file(const char *pathname, linker_class_t lc)
static modlist_t modlist_lookup(const char *name, int ver)
static linker_file_t linker_find_file_by_name(const char *_filename)
int sys_kldfind(struct thread *td, struct kldfind_args *uap)
int linker_release_module(const char *modname, struct mod_depend *verinfo, linker_file_t lf)
static modlisthead_t found_modules
static struct thread * kld_busy_owner
static void linker_file_enable_sysctls(linker_file_t lf)
int sys_kldunloadf(struct thread *td, struct kldunloadf_args *uap)
int linker_kldload_busy(int flags)
int linker_search_symbol_name(caddr_t value, char *buf, u_int buflen, long *offset)
static void linker_stop_class_add(void *arg)
static const char * linker_basename(const char *path)
int linker_add_class(linker_class_t lc)
static void linker_file_register_sysctls(linker_file_t lf, bool enable)
int linker_search_symbol_name_flags(caddr_t value, char *buf, u_int buflen, long *offset, int flags)
static void linker_preload(void *arg)
static void linker_init(void *arg)
void *() malloc(size_t size, struct malloc_type *mtp, int flags)
void * realloc(void *addr, size_t size, struct malloc_type *mtp, int flags)
void free(void *addr, struct malloc_type *mtp)
int module_register(const moduledata_t *data, linker_file_t container)
int module_getid(module_t mod)
int module_quiesce(module_t mod)
void module_release(module_t mod)
int module_unload(module_t mod)
const char * module_getname(module_t mod)
module_t module_getfnext(module_t mod)
struct mtx __exclusive_cache_line Giant
int priv_check(struct thread *td, int priv)
int securelevel_gt(struct ucred *cr, int level)
void panic(const char *fmt,...)
void wakeup(const void *ident)
void sysctl_unregister_oid(struct sysctl_oid *oidp)
void sysctl_enable_oid(struct sysctl_oid *oidp)
void sysctl_wunlock(void)
int sysctl_wire_old_buffer(struct sysctl_req *req, size_t len)
void sysctl_register_oid(struct sysctl_oid *oidp)
void sysctl_register_disabled_oid(struct sysctl_oid *oidp)
kobj_t kobj_create(kobj_class_t cls, struct malloc_type *mtype, int mflags)
void kobj_delete(kobj_t obj, struct malloc_type *mtype)
void kobj_class_compile(kobj_class_t cls)
caddr_t preload_search_info(caddr_t mod, int inf)
caddr_t preload_search_next_name(caddr_t base)
int printf(const char *fmt,...)
int sprintf(char *buf, const char *cfmt,...)
int snprintf(char *str, size_t size, const char *format,...)
void() NDFREE(struct nameidata *ndp, const u_int flags)
int vn_rdwr(enum uio_rw rw, struct vnode *vp, void *base, int len, off_t offset, enum uio_seg segflg, int ioflg, struct ucred *active_cred, struct ucred *file_cred, ssize_t *aresid, struct thread *td)
int vn_open(struct nameidata *ndp, int *flagp, int cmode, struct file *fp)
int vn_close(struct vnode *vp, int flags, struct ucred *file_cred, struct thread *td)