1 /*- 2 * Copyright (c) 1997 Doug Rabson 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $Id$ 27 */ 28 29 #include <sys/param.h> 30 #include <sys/kernel.h> 31 #include <sys/systm.h> 32 #include <sys/sysctl.h> 33 #include <sys/queue.h> 34 #include <sys/libkern.h> 35 #include <sys/malloc.h> 36 #include <sys/sysproto.h> 37 #include <sys/sysent.h> 38 #include <sys/proc.h> 39 #include <sys/lock.h> 40 #include <machine/cpu.h> 41 #include <sys/module.h> 42 #include <sys/linker.h> 43 44 static struct lock lock; /* lock for the file list */ 45 static linker_class_list_t classes; 46 static linker_file_list_t files; 47 static int next_file_id = 1; 48 49 static void 50 linker_init(void* arg) 51 { 52 lockinit(&lock, PVM, "klink", 0, 0); 53 TAILQ_INIT(&classes); 54 TAILQ_INIT(&files); 55 } 56 57 SYSINIT(linker, SI_SUB_KMEM, SI_ORDER_SECOND, linker_init, 0); 58 59 int 60 linker_add_class(const char* desc, void* priv, 61 struct linker_class_ops* ops) 62 { 63 linker_class_t lc; 64 65 lc = malloc(sizeof(struct linker_class), M_LINKER, M_NOWAIT); 66 if (!lc) 67 return ENOMEM; 68 69 lc->desc = desc; 70 lc->priv = priv; 71 lc->ops = ops; 72 TAILQ_INSERT_HEAD(&classes, lc, link); 73 74 return 0; 75 } 76 77 static void 78 linker_file_sysinit(linker_file_t lf) 79 { 80 struct linker_set* sysinits; 81 struct sysinit** sipp; 82 struct sysinit** xipp; 83 struct sysinit* save; 84 int rval[2]; /* SI_TYPE_KTHREAD support*/ 85 86 linker_current_file = lf; 87 88 KLD_DPF(FILE, ("linker_file_sysinit: calling SYSINITs for %s\n", 89 lf->filename)); 90 91 sysinits = (struct linker_set*) 92 linker_file_lookup_symbol(lf, "sysinit_set", 0); 93 if (!sysinits) 94 return; 95 96 /* 97 * Perform a bubble sort of the system initialization objects by 98 * their subsystem (primary key) and order (secondary key). 99 * 100 * Since some things care about execution order, this is the 101 * operation which ensures continued function. 102 */ 103 for( sipp = (struct sysinit **)sysinits->ls_items; *sipp; sipp++) { 104 for( xipp = sipp + 1; *xipp; xipp++) { 105 if( (*sipp)->subsystem < (*xipp)->subsystem || 106 ( (*sipp)->subsystem == (*xipp)->subsystem && 107 (*sipp)->order < (*xipp)->order)) 108 continue; /* skip*/ 109 save = *sipp; 110 *sipp = *xipp; 111 *xipp = save; 112 } 113 } 114 115 116 /* 117 * Traverse the (now) ordered list of system initialization tasks. 118 * Perform each task, and continue on to the next task. 119 * 120 * The last item on the list is expected to be the scheduler, 121 * which will not return. 122 */ 123 for( sipp = (struct sysinit **)sysinits->ls_items; *sipp; sipp++) { 124 if( (*sipp)->subsystem == SI_SUB_DUMMY) 125 continue; /* skip dummy task(s)*/ 126 127 switch( (*sipp)->type) { 128 case SI_TYPE_DEFAULT: 129 /* no special processing*/ 130 (*((*sipp)->func))( (*sipp)->udata); 131 break; 132 133 case SI_TYPE_KTHREAD: 134 /* kernel thread*/ 135 if (fork(&proc0, NULL, rval)) 136 panic("fork kernel process"); 137 cpu_set_fork_handler(pfind(rval[0]), (*sipp)->func, (*sipp)->udata); 138 break; 139 140 default: 141 panic( "linker_file_sysinit: unrecognized init type"); 142 } 143 } 144 } 145 146 int 147 linker_load_file(const char* filename, linker_file_t* result) 148 { 149 linker_class_t lc; 150 linker_file_t lf; 151 int error = 0; 152 153 lf = linker_find_file_by_name(filename); 154 if (lf) { 155 KLD_DPF(FILE, ("linker_load_file: file %s is already loaded, incrementing refs\n", filename)); 156 *result = lf; 157 lf->refs++; 158 goto out; 159 } 160 161 lf = NULL; 162 for (lc = TAILQ_FIRST(&classes); lc; lc = TAILQ_NEXT(lc, link)) { 163 KLD_DPF(FILE, ("linker_load_file: trying to load %s as %s\n", 164 filename, lc->desc)); 165 if (error = lc->ops->load_file(filename, &lf)) 166 goto out; 167 if (lf) { 168 linker_file_sysinit(lf); 169 170 *result = lf; 171 goto out; 172 } 173 } 174 175 error = ENOEXEC; /* format not recognised */ 176 177 out: 178 return error; 179 } 180 181 linker_file_t 182 linker_find_file_by_name(const char* filename) 183 { 184 linker_file_t lf = 0; 185 186 lockmgr(&lock, LK_SHARED, 0, curproc); 187 for (lf = TAILQ_FIRST(&files); lf; lf = TAILQ_NEXT(lf, link)) 188 if (!strcmp(lf->filename, filename)) 189 break; 190 lockmgr(&lock, LK_RELEASE, 0, curproc); 191 192 return lf; 193 } 194 195 linker_file_t 196 linker_find_file_by_id(int fileid) 197 { 198 linker_file_t lf = 0; 199 200 lockmgr(&lock, LK_SHARED, 0, curproc); 201 for (lf = TAILQ_FIRST(&files); lf; lf = TAILQ_NEXT(lf, link)) 202 if (lf->id == fileid) 203 break; 204 lockmgr(&lock, LK_RELEASE, 0, curproc); 205 206 return lf; 207 } 208 209 linker_file_t 210 linker_make_file(const char* filename, void* priv, struct linker_file_ops* ops) 211 { 212 linker_file_t lf = 0; 213 int namelen; 214 215 KLD_DPF(FILE, ("linker_make_file: new file, filename=%s\n", filename)); 216 lockmgr(&lock, LK_EXCLUSIVE|LK_RETRY, 0, curproc); 217 namelen = strlen(filename) + 1; 218 lf = malloc(sizeof(struct linker_file) + namelen, M_LINKER, M_WAITOK); 219 if (!lf) 220 goto out; 221 222 lf->refs = 1; 223 lf->userrefs = 0; 224 lf->filename = (char*) (lf + 1); 225 strcpy(lf->filename, filename); 226 lf->id = next_file_id++; 227 lf->ndeps = 0; 228 lf->deps = NULL; 229 STAILQ_INIT(&lf->common); 230 TAILQ_INIT(&lf->modules); 231 232 lf->priv = priv; 233 lf->ops = ops; 234 TAILQ_INSERT_TAIL(&files, lf, link); 235 236 out: 237 lockmgr(&lock, LK_RELEASE, 0, curproc); 238 return lf; 239 } 240 241 int 242 linker_file_unload(linker_file_t file) 243 { 244 module_t mod, next; 245 struct common_symbol* cp; 246 int error = 0; 247 int i; 248 249 KLD_DPF(FILE, ("linker_file_unload: lf->refs=%d\n", lf->refs)); 250 lockmgr(&lock, LK_EXCLUSIVE|LK_RETRY, 0, curproc); 251 if (file->refs == 1) { 252 KLD_DPF(FILE, ("linker_file_unload: file is unloading, informing modules\n")); 253 /* 254 * Inform any modules associated with this file. 255 */ 256 for (mod = TAILQ_FIRST(&file->modules); mod; mod = next) { 257 next = module_getfnext(mod); 258 259 /* 260 * Give the module a chance to veto the unload. 261 */ 262 if (error = module_unload(mod)) { 263 KLD_DPF(FILE, ("linker_file_unload: module %x vetoes unload\n", 264 mod)); 265 lockmgr(&lock, LK_RELEASE, 0, curproc); 266 goto out; 267 } 268 269 module_release(mod); 270 } 271 } 272 273 file->refs--; 274 if (file->refs > 0) { 275 lockmgr(&lock, LK_RELEASE, 0, curproc); 276 goto out; 277 } 278 279 TAILQ_REMOVE(&files, file, link); 280 lockmgr(&lock, LK_RELEASE, 0, curproc); 281 282 for (i = 0; i < file->ndeps; i++) 283 linker_file_unload(file->deps[i]); 284 free(file->deps, M_LINKER); 285 286 for (cp = STAILQ_FIRST(&file->common); cp; 287 cp = STAILQ_FIRST(&file->common)) { 288 STAILQ_REMOVE(&file->common, cp, common_symbol, link); 289 free(cp, M_LINKER); 290 } 291 292 file->ops->unload(file); 293 free(file, M_LINKER); 294 295 out: 296 return error; 297 } 298 299 int 300 linker_file_add_dependancy(linker_file_t file, linker_file_t dep) 301 { 302 linker_file_t* newdeps; 303 304 newdeps = malloc((file->ndeps + 1) * sizeof(linker_file_t*), 305 M_LINKER, M_WAITOK); 306 if (newdeps == NULL) 307 return ENOMEM; 308 309 if (file->deps) { 310 bcopy(file->deps, newdeps, file->ndeps * sizeof(linker_file_t*)); 311 free(file->deps, M_LINKER); 312 } 313 file->deps = newdeps; 314 file->deps[file->ndeps] = dep; 315 file->ndeps++; 316 317 return 0; 318 } 319 320 caddr_t 321 linker_file_lookup_symbol(linker_file_t file, const char* name, int deps) 322 { 323 caddr_t address; 324 size_t size; 325 size_t common_size = 0; 326 int i; 327 328 KLD_DPF(SYM, ("linker_file_lookup_symbol: file=%x, name=%s, deps=%d", 329 file, name, deps)); 330 331 if (file->ops->lookup_symbol(file, name, &address, &size) == 0) 332 if (address == 0) 333 /* 334 * For commons, first look them up in the dependancies and 335 * only allocate space if not found there. 336 */ 337 common_size = size; 338 else 339 return address; 340 341 if (deps) 342 for (i = 0; i < file->ndeps; i++) { 343 address = linker_file_lookup_symbol(file->deps[i], name, 0); 344 if (address) 345 return address; 346 } 347 348 if (common_size > 0) { 349 /* 350 * This is a common symbol which was not found in the 351 * dependancies. We maintain a simple common symbol table in 352 * the file object. 353 */ 354 struct common_symbol* cp; 355 356 for (cp = STAILQ_FIRST(&file->common); cp; 357 cp = STAILQ_NEXT(cp, link)) 358 if (!strcmp(cp->name, name)) 359 return cp->address; 360 361 /* 362 * Round the symbol size up to align. 363 */ 364 common_size = (common_size + sizeof(int) - 1) & -sizeof(int); 365 cp = malloc(sizeof(struct common_symbol) 366 + common_size 367 + strlen(name) + 1, 368 M_LINKER, M_WAITOK); 369 if (!cp) 370 return 0; 371 372 cp->address = (caddr_t) (cp + 1); 373 cp->name = cp->address + common_size; 374 strcpy(cp->name, name); 375 bzero(cp->address, common_size); 376 STAILQ_INSERT_TAIL(&file->common, cp, link); 377 378 return cp->address; 379 } 380 381 return 0; 382 } 383 384 /* 385 * Syscalls. 386 */ 387 388 int 389 kldload(struct proc* p, struct kldload_args* uap, int* retval) 390 { 391 char* filename = NULL; 392 linker_file_t lf; 393 int error = 0; 394 395 *retval = -1; 396 397 if (securelevel > 0) 398 return EPERM; 399 400 if (error = suser(p->p_ucred, &p->p_acflag)) 401 return error; 402 403 filename = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); 404 if (error = copyinstr(SCARG(uap, file), filename, MAXPATHLEN, NULL)) 405 goto out; 406 407 if (error = linker_load_file(uap->file, &lf)) 408 goto out; 409 410 lf->userrefs++; 411 *retval = lf->id; 412 413 out: 414 if (filename) 415 free(filename, M_TEMP); 416 return error; 417 } 418 419 int 420 kldunload(struct proc* p, struct kldunload_args* uap, int* retval) 421 { 422 linker_file_t lf; 423 int error = 0; 424 425 if (securelevel > 0) 426 return EPERM; 427 428 if (error = suser(p->p_ucred, &p->p_acflag)) 429 return error; 430 431 lf = linker_find_file_by_id(SCARG(uap, fileid)); 432 if (lf) { 433 KLD_DPF(FILE, ("kldunload: lf->userrefs=%d\n", lf->userrefs)); 434 if (lf->userrefs == 0) { 435 printf("linkerunload: attempt to unload file which was not loaded by user\n"); 436 error = EBUSY; 437 goto out; 438 } 439 lf->userrefs--; 440 error = linker_file_unload(lf); 441 } else 442 error = ENOENT; 443 444 out: 445 return error; 446 } 447 448 int 449 kldfind(struct proc* p, struct kldfind_args* uap, int* retval) 450 { 451 char* filename = NULL; 452 linker_file_t lf; 453 int error = 0; 454 455 *retval = -1; 456 457 filename = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); 458 if (error = copyinstr(SCARG(uap, file), filename, MAXPATHLEN, NULL)) 459 goto out; 460 461 lf = linker_find_file_by_name(filename); 462 if (lf) 463 *retval = lf->id; 464 else 465 error = ENOENT; 466 467 out: 468 if (filename) 469 free(filename, M_TEMP); 470 return error; 471 } 472 473 int 474 kldnext(struct proc* p, struct kldnext_args* uap, int* retval) 475 { 476 linker_file_t lf; 477 int error = 0; 478 479 if (SCARG(uap, fileid) == 0) { 480 if (TAILQ_FIRST(&files)) 481 *retval = TAILQ_FIRST(&files)->id; 482 else 483 *retval = 0; 484 return 0; 485 } 486 487 lf = linker_find_file_by_id(SCARG(uap, fileid)); 488 if (lf) { 489 if (TAILQ_NEXT(lf, link)) 490 *retval = TAILQ_NEXT(lf, link)->id; 491 else 492 *retval = 0; 493 } else 494 error = ENOENT; 495 496 return error; 497 } 498 499 int 500 kldstat(struct proc* p, struct kldstat_args* uap, int* retval) 501 { 502 linker_file_t lf; 503 int error = 0; 504 int version; 505 struct kld_file_stat* stat; 506 int namelen; 507 508 lf = linker_find_file_by_id(SCARG(uap, fileid)); 509 if (!lf) { 510 error = ENOENT; 511 goto out; 512 } 513 514 stat = SCARG(uap, stat); 515 516 /* 517 * Check the version of the user's structure. 518 */ 519 if (error = copyin(&stat->version, &version, sizeof(version))) 520 goto out; 521 if (version != sizeof(struct kld_file_stat)) { 522 error = EINVAL; 523 goto out; 524 } 525 526 namelen = strlen(lf->filename) + 1; 527 if (namelen > MAXPATHLEN) 528 namelen = MAXPATHLEN; 529 if (error = copyout(lf->filename, &stat->name[0], namelen)) 530 goto out; 531 if (error = copyout(&lf->refs, &stat->refs, sizeof(int))) 532 goto out; 533 if (error = copyout(&lf->id, &stat->id, sizeof(int))) 534 goto out; 535 if (error = copyout(&lf->address, &stat->address, sizeof(caddr_t))) 536 goto out; 537 if (error = copyout(&lf->size, &stat->size, sizeof(size_t))) 538 goto out; 539 540 *retval = 0; 541 542 out: 543 return error; 544 } 545 546 int 547 kldfirstmod(struct proc* p, struct kldfirstmod_args* uap, int* retval) 548 { 549 linker_file_t lf; 550 int error = 0; 551 552 lf = linker_find_file_by_id(SCARG(uap, fileid)); 553 if (lf) { 554 if (TAILQ_FIRST(&lf->modules)) 555 *retval = module_getid(TAILQ_FIRST(&lf->modules)); 556 else 557 *retval = 0; 558 } else 559 error = ENOENT; 560 561 return error; 562 } 563