X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/blobdiff_plain/dca28c5fc381b4ede81e92bab31bcb8f96b4ea1a..6ef6faeb19268917889c5a06b0fa523ae6d67ccd:/sys/kern/kern_linker.c diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c index a7ec7060a2..c1159f346b 100644 --- a/sys/kern/kern_linker.c +++ b/sys/kern/kern_linker.c @@ -24,7 +24,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/kern/kern_linker.c,v 1.41.2.3 2001/11/21 17:50:35 luigi Exp $ - * $DragonFly: src/sys/kern/kern_linker.c,v 1.30 2006/09/05 03:48:12 dillon Exp $ + * $DragonFly: src/sys/kern/kern_linker.c,v 1.38 2007/06/07 22:58:11 corecode Exp $ */ #include "opt_ddb.h" @@ -47,6 +47,10 @@ #include +#ifdef _KERNEL_VIRTUAL +#include +#endif + #ifdef KLD_DEBUG int kld_debug = 0; #endif @@ -71,7 +75,7 @@ linker_init(void* arg) TAILQ_INIT(&linker_files); } -SYSINIT(linker, SI_SUB_KLD, SI_ORDER_FIRST, linker_init, 0); +SYSINIT(linker, SI_BOOT2_KLD, SI_ORDER_FIRST, linker_init, 0); int linker_add_class(const char* desc, void* priv, @@ -114,7 +118,7 @@ linker_file_sysinit(linker_file_t lf) moddata = (*sipp)->udata; error = module_register(moddata, lf); if (error) { - printf("linker_file_sysinit \"%s\" failed to register! %d\n", + kprintf("linker_file_sysinit \"%s\" failed to register! %d\n", lf->filename, error); return error; } @@ -146,7 +150,7 @@ linker_file_sysinit(linker_file_t lf) * Perform each task, and continue on to the next task. */ for (sipp = start; sipp < stop; sipp++) { - if ((*sipp)->subsystem == SI_SUB_DUMMY) + if ((*sipp)->subsystem == SI_SPECIAL_DUMMY) continue; /* skip dummy task(s)*/ /* Call function */ @@ -194,7 +198,7 @@ linker_file_sysuninit(linker_file_t lf) * Perform each task, and continue on to the next task. */ for (sipp = start; sipp < stop; sipp++) { - if ((*sipp)->subsystem == SI_SUB_DUMMY) + if ((*sipp)->subsystem == SI_SPECIAL_DUMMY) continue; /* skip dummy task(s)*/ /* Call function */ @@ -239,7 +243,7 @@ linker_load_file(const char* filename, linker_file_t* result) char *koname = NULL; /* Refuse to load modules if securelevel raised */ - if (securelevel > 0) + if (securelevel > 0 || kernel_mem_readonly) return EPERM; lf = linker_find_file_by_name(filename); @@ -261,7 +265,7 @@ linker_load_file(const char* filename, linker_file_t* result) error = ENOMEM; goto out; } - sprintf(koname, "%s.ko", filename); + ksprintf(koname, "%s.ko", filename); lf = NULL; foundfile = 0; for (lc = TAILQ_FIRST(&classes); lc; lc = TAILQ_NEXT(lc, link)) { @@ -324,7 +328,7 @@ linker_find_file_by_name(const char* filename) koname = kmalloc(strlen(filename) + 4, M_LINKER, M_WAITOK); if (koname == NULL) goto out; - sprintf(koname, "%s.ko", filename); + ksprintf(koname, "%s.ko", filename); lockmgr(&lock, LK_SHARED); for (lf = TAILQ_FIRST(&linker_files); lf; lf = TAILQ_NEXT(lf, link)) { @@ -405,7 +409,7 @@ linker_file_unload(linker_file_t file) int i; /* Refuse to unload modules if securelevel raised */ - if (securelevel > 0) + if (securelevel > 0 || kernel_mem_readonly) return EPERM; KLD_DPF(FILE, ("linker_file_unload: lf->refs=%d\n", file->refs)); @@ -453,7 +457,7 @@ linker_file_unload(linker_file_t file) mod; mod = module_getfnext(mod) ) { - printf("linker_file_unload: module %p still has refs!\n", mod); + kprintf("linker_file_unload: module %p still has refs!\n", mod); } --file->refs; } @@ -622,6 +626,14 @@ linker_file_lookup_symbol(linker_file_t file, const char* name, int deps, caddr_ return 0; } +#ifdef _KERNEL_VIRTUAL + *raddr = dlsym(RTLD_NEXT, name); + if (*raddr != NULL) { + KLD_DPF(SYM, ("linker_file_lookup_symbol: found dlsym=%x\n", *raddr)); + return 0; + } +#endif + KLD_DPF(SYM, ("linker_file_lookup_symbol: fail\n")); return ENOENT; } @@ -708,7 +720,7 @@ sys_kldload(struct kldload_args *uap) uap->sysmsg_result = -1; - if (securelevel > 0) /* redundant, but that's OK */ + if (securelevel > 0 || kernel_mem_readonly) /* redundant, but that's OK */ return EPERM; if ((error = suser(td)) != 0) @@ -748,7 +760,7 @@ sys_kldunload(struct kldunload_args *uap) linker_file_t lf; int error = 0; - if (securelevel > 0) /* redundant, but that's OK */ + if (securelevel > 0 || kernel_mem_readonly) /* redundant, but that's OK */ return EPERM; if ((error = suser(td)) != 0) @@ -758,7 +770,7 @@ sys_kldunload(struct kldunload_args *uap) if (lf) { KLD_DPF(FILE, ("kldunload: lf->userrefs=%d\n", lf->userrefs)); if (lf->userrefs == 0) { - printf("linkerunload: attempt to unload file that was loaded by the kernel\n"); + kprintf("linkerunload: attempt to unload file that was loaded by the kernel\n"); error = EBUSY; goto out; } @@ -1004,11 +1016,11 @@ linker_preload(void* arg) modname = (char *)preload_search_info(modptr, MODINFO_NAME); modtype = (char *)preload_search_info(modptr, MODINFO_TYPE); if (modname == NULL) { - printf("Preloaded module at %p does not have a name!\n", modptr); + kprintf("Preloaded module at %p does not have a name!\n", modptr); continue; } if (modtype == NULL) { - printf("Preloaded module at %p does not have a type!\n", modptr); + kprintf("Preloaded module at %p does not have a type!\n", modptr); continue; } @@ -1016,12 +1028,12 @@ linker_preload(void* arg) * This is a hack at the moment, but what's in FreeBSD-5 is even * worse so I'd rather the hack. */ - printf("Preloaded %s \"%s\" at %p", modtype, modname, modptr); + kprintf("Preloaded %s \"%s\" at %p", modtype, modname, modptr); if (find_mod_metadata(modname)) { - printf(" (ignored, already in static kernel)\n"); + kprintf(" (ignored, already in static kernel)\n"); continue; } - printf(".\n"); + kprintf(".\n"); lf = linker_find_file_by_name(modname); if (lf) { @@ -1051,7 +1063,7 @@ linker_preload(void* arg) moddata = (*sipp)->udata; error = module_register(moddata, lf); if (error) - printf("Preloaded %s \"%s\" failed to register: %d\n", + kprintf("Preloaded %s \"%s\" failed to register: %d\n", modtype, modname, error); } } @@ -1062,7 +1074,7 @@ linker_preload(void* arg) } } -SYSINIT(preload, SI_SUB_KLD, SI_ORDER_MIDDLE, linker_preload, 0); +SYSINIT(preload, SI_BOOT2_KLD, SI_ORDER_MIDDLE, linker_preload, 0); /* * Search for a not-loaded module by name. @@ -1079,10 +1091,11 @@ SYSINIT(preload, SI_SUB_KLD, SI_ORDER_MIDDLE, linker_preload, 0); * character as a separator to be consistent with the bootloader. */ -static char linker_path[MAXPATHLEN] = "/;/boot/;/modules/"; +static char linker_path[MAXPATHLEN] = "/;/boot;/modules"; SYSCTL_STRING(_kern, OID_AUTO, module_path, CTLFLAG_RW, linker_path, sizeof(linker_path), "module load search path"); +TUNABLE_STR("module_path", linker_path, sizeof(linker_path)); static char * linker_strdup(const char *str) @@ -1099,6 +1112,8 @@ linker_search_path(const char *name) { struct nlookupdata nd; char *cp, *ep, *result; + size_t name_len, prefix_len; + int sep; int error; enum vtype type; @@ -1108,17 +1123,28 @@ linker_search_path(const char *name) /* traverse the linker path */ cp = linker_path; + name_len = strlen(name); for (;;) { /* find the end of this component */ for (ep = cp; (*ep != 0) && (*ep != ';'); ep++) ; - result = kmalloc((strlen(name) + (ep - cp) + 1), M_LINKER, M_WAITOK); - if (result == NULL) /* actually ENOMEM */ - return(NULL); + prefix_len = ep - cp; + /* if this component doesn't end with a slash, add one */ + if (ep == cp || *(ep - 1) != '/') + sep = 1; + else + sep = 0; + + /* + * +2 : possible separator, plus terminator. + */ + result = kmalloc(prefix_len + name_len + 2, M_LINKER, M_WAITOK); - strncpy(result, cp, ep - cp); - strcpy(result + (ep - cp), name); + strncpy(result, cp, prefix_len); + if (sep) + result[prefix_len++] = '/'; + strcpy(result + prefix_len, name); /* * Attempt to open the file, and return the path if we succeed and it's