root/kernel/module.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. init_modules
  2. sys_create_module
  3. sys_init_module
  4. sys_delete_module
  5. sys_get_kernel_syms
  6. get_mod_name
  7. find_module
  8. drop_refs
  9. free_modules
  10. get_module_list
  11. get_ksyms_list
  12. register_symtab
  13. sys_create_module
  14. sys_init_module
  15. sys_delete_module
  16. sys_get_kernel_syms
  17. register_symtab

   1 #include <linux/errno.h>
   2 #include <linux/kernel.h>
   3 #include <asm/segment.h>
   4 #include <linux/mm.h>           /* defines GFP_KERNEL */
   5 #include <linux/string.h>
   6 #include <linux/module.h>
   7 #include <linux/sched.h>
   8 #include <linux/malloc.h>
   9 #include <linux/config.h>
  10 /*
  11  * Originally by Anonymous (as far as I know...)
  12  * Linux version by Bas Laarhoven <bas@vimec.nl>
  13  * 0.99.14 version by Jon Tombs <jon@gtex02.us.es>,
  14  *
  15  * Heavily modified by Bjorn Ekwall <bj0rn@blox.se> May 1994 (C)
  16  * This source is covered by the GNU GPL, the same as all kernel sources.
  17  *
  18  * Features:
  19  *      - Supports stacked modules (removable only of there are no dependents).
  20  *      - Supports table of symbols defined by the modules.
  21  *      - Supports /proc/ksyms, showing value, name and owner of all
  22  *        the symbols defined by all modules (in stack order).
  23  *      - Added module dependencies information into /proc/modules
  24  *      - Supports redefines of all symbols, for streams-like behaviour.
  25  *      - Compatible with older versions of insmod.
  26  *
  27  * New addition in December 1994: (Bjorn Ekwall, idea from Jacques Gelinas)
  28  *      - Externally callable function:
  29  *
  30  *              "int register_symtab(struct symbol_table *)"
  31  *
  32  *        This function can be called from within the kernel,
  33  *        and ALSO from loadable modules.
  34  *        The goal is to assist in modularizing the kernel even more,
  35  *        and finally: reducing the number of entries in ksyms.c
  36  *        since every subsystem should now be able to decide and
  37  *        control exactly what symbols it wants to export, locally!
  38  *
  39  * On 1-Aug-95:  <Matti.Aarnio@utu.fi>  altered code to use same style as
  40  *               do  /proc/net/XXX  "files".  Namely allow more than 4kB
  41  *               (or what the block size is) output.
  42  *
  43  *      - Use dummy syscall functions for users who disable all
  44  *        module support. Similar to kernel/sys.c (Paul Gortmaker)
  45  */
  46 
  47 #ifdef CONFIG_MODULES           /* a *big* #ifdef block... */
  48 
  49 #ifdef DEBUG_MODULE
  50 #define PRINTK(a) printk a
  51 #else
  52 #define PRINTK(a) /* */
  53 #endif
  54 
  55 static struct module kernel_module;
  56 static struct module *module_list = &kernel_module;
  57 
  58 static int freeing_modules; /* true if some modules are marked for deletion */
  59 
  60 static struct module *find_module( const char *name);
  61 static int get_mod_name( char *user_name, char *buf);
  62 static int free_modules( void);
  63 
  64 static int module_init_flag = 0; /* Hmm... */
  65 
  66 extern struct symbol_table symbol_table; /* in kernel/ksyms.c */
  67 
  68 /*
  69  * Called at boot time
  70  */
  71 void init_modules(void) {
     /* [previous][next][first][last][top][bottom][index][help] */
  72         struct internal_symbol *sym;
  73         int i;
  74 
  75         for (i = 0, sym = symbol_table.symbol; sym->name; ++sym, ++i)
  76                 ;
  77         symbol_table.n_symbols = i;
  78 
  79         kernel_module.symtab = &symbol_table;
  80         kernel_module.state = MOD_RUNNING; /* Hah! */
  81         kernel_module.name = "";
  82 }
  83 
  84 /*
  85  * Allocate space for a module.
  86  */
  87 asmlinkage unsigned long
  88 sys_create_module(char *module_name, unsigned long size)
     /* [previous][next][first][last][top][bottom][index][help] */
  89 {
  90         struct module *mp;
  91         void* addr;
  92         int error;
  93         int npages;
  94         int sspace = sizeof(struct module) + MOD_MAX_NAME;
  95         char name[MOD_MAX_NAME];
  96 
  97         if (!suser())
  98                 return -EPERM;
  99         if (module_name == NULL || size == 0)
 100                 return -EINVAL;
 101         if ((error = get_mod_name(module_name, name)) != 0)
 102                 return error;
 103         if (find_module(name) != NULL) {
 104                 return -EEXIST;
 105         }
 106 
 107         if ((mp = (struct module*) kmalloc(sspace, GFP_KERNEL)) == NULL) {
 108                 return -ENOMEM;
 109         }
 110         strcpy((char *)(mp + 1), name); /* why not? */
 111 
 112         npages = (size + sizeof (long) + PAGE_SIZE - 1) / PAGE_SIZE;
 113         if ((addr = vmalloc(npages * PAGE_SIZE)) == 0) {
 114                 kfree_s(mp, sspace);
 115                 return -ENOMEM;
 116         }
 117 
 118         mp->next = module_list;
 119         mp->ref = NULL;
 120         mp->symtab = NULL;
 121         mp->name = (char *)(mp + 1);
 122         mp->size = npages;
 123         mp->addr = addr;
 124         mp->state = MOD_UNINITIALIZED;
 125         mp->cleanup = NULL;
 126 
 127         * (long *) addr = 0;    /* set use count to zero */
 128         module_list = mp;       /* link it in */
 129 
 130         PRINTK(("module `%s' (%lu pages @ 0x%08lx) created\n",
 131                 mp->name, (unsigned long) mp->size, (unsigned long) mp->addr));
 132         return (unsigned long) addr;
 133 }
 134 
 135 /*
 136  * Initialize a module.
 137  */
 138 asmlinkage int
 139 sys_init_module(char *module_name, char *code, unsigned codesize,
     /* [previous][next][first][last][top][bottom][index][help] */
 140                 struct mod_routines *routines,
 141                 struct symbol_table *symtab)
 142 {
 143         struct module *mp;
 144         struct symbol_table *newtab;
 145         char name[MOD_MAX_NAME];
 146         int error;
 147         struct mod_routines rt;
 148 
 149         if (!suser())
 150                 return -EPERM;
 151 
 152 #ifdef __i386__
 153         /* A little bit of protection... we "know" where the user stack is... */
 154 
 155         if (symtab && ((unsigned long)symtab > 0xb0000000)) {
 156                 printk("warning: you are using an old insmod, no symbols will be inserted!\n");
 157                 symtab = NULL;
 158         }
 159 #endif
 160 
 161         /*
 162          * First reclaim any memory from dead modules that where not
 163          * freed when deleted. Should I think be done by timers when
 164          * the module was deleted - Jon.
 165          */
 166         free_modules();
 167 
 168         if ((error = get_mod_name(module_name, name)) != 0)
 169                 return error;
 170         PRINTK(("initializing module `%s', %d (0x%x) bytes\n",
 171                 name, codesize, codesize));
 172         memcpy_fromfs(&rt, routines, sizeof rt);
 173         if ((mp = find_module(name)) == NULL)
 174                 return -ENOENT;
 175         if (codesize & MOD_AUTOCLEAN) {
 176                 /*
 177                  * set autoclean marker from codesize...
 178                  * set useage count to "zero"
 179                  */
 180                 codesize &= ~MOD_AUTOCLEAN;
 181                 GET_USE_COUNT(mp) = MOD_AUTOCLEAN;
 182         }
 183         if ((codesize + sizeof (long) + PAGE_SIZE - 1) / PAGE_SIZE > mp->size)
 184                 return -EINVAL;
 185         memcpy_fromfs((char *)mp->addr + sizeof (long), code, codesize);
 186         memset((char *)mp->addr + sizeof (long) + codesize, 0,
 187                 mp->size * PAGE_SIZE - (codesize + sizeof (long)));
 188         PRINTK(( "module init entry = 0x%08lx, cleanup entry = 0x%08lx\n",
 189                 (unsigned long) rt.init, (unsigned long) rt.cleanup));
 190         mp->cleanup = rt.cleanup;
 191 
 192         /* update kernel symbol table */
 193         if (symtab) { /* symtab == NULL means no new entries to handle */
 194                 struct internal_symbol *sym;
 195                 struct module_ref *ref;
 196                 int size;
 197                 int i;
 198                 int legal_start;
 199 
 200                 if ((error = verify_area(VERIFY_READ, &symtab->size, sizeof(symtab->size))))
 201                         return error;
 202                 size = get_user(&symtab->size);
 203 
 204                 if ((newtab = (struct symbol_table*) kmalloc(size, GFP_KERNEL)) == NULL) {
 205                         return -ENOMEM;
 206                 }
 207 
 208                 if ((error = verify_area(VERIFY_READ, symtab, size))) {
 209                         kfree_s(newtab, size);
 210                         return error;
 211                 }
 212                 memcpy_fromfs((char *)(newtab), symtab, size);
 213 
 214                 /* sanity check */
 215                 legal_start = sizeof(struct symbol_table) +
 216                         newtab->n_symbols * sizeof(struct internal_symbol) +
 217                         newtab->n_refs * sizeof(struct module_ref);
 218 
 219                 if ((newtab->n_symbols < 0) || (newtab->n_refs < 0) || (legal_start > size)) {
 220                         printk("Rejecting illegal symbol table (n_symbols=%d,n_refs=%d)\n",
 221                                newtab->n_symbols, newtab->n_refs);
 222                         kfree_s(newtab, size);
 223                         return -EINVAL;
 224                 }
 225 
 226                 /* relocate name pointers, index referred from start of table */
 227                 for (sym = &(newtab->symbol[0]), i = 0; i < newtab->n_symbols; ++sym, ++i) {
 228                         if ((unsigned long)sym->name < legal_start || size <= (unsigned long)sym->name) {
 229                                 printk("Rejecting illegal symbol table\n");
 230                                 kfree_s(newtab, size);
 231                                 return -EINVAL;
 232                         }
 233                         /* else */
 234                         sym->name += (long)newtab;
 235                 }
 236                 mp->symtab = newtab;
 237 
 238                 /* Update module references.
 239                  * On entry, from "insmod", ref->module points to
 240                  * the referenced module!
 241                  * Now it will point to the current module instead!
 242                  * The ref structure becomes the first link in the linked
 243                  * list of references to the referenced module.
 244                  * Also, "sym" from above, points to the first ref entry!!!
 245                  */
 246                 for (ref = (struct module_ref *)sym, i = 0;
 247                         i < newtab->n_refs; ++ref, ++i) {
 248 
 249                         /* Check for valid reference */
 250                         struct module *link = module_list;
 251                         while (link && (ref->module != link))
 252                                 link = link->next;
 253 
 254                         if (link == (struct module *)0) {
 255                                 printk("Non-module reference! Rejected!\n");
 256                                 return -EINVAL;
 257                         }
 258 
 259                         ref->next = ref->module->ref;
 260                         ref->module->ref = ref;
 261                         ref->module = mp;
 262                 }
 263         }
 264 
 265         module_init_flag = 1; /* Hmm... */
 266         if ((*rt.init)() != 0) {
 267                 module_init_flag = 0; /* Hmm... */
 268                 return -EBUSY;
 269         }
 270         module_init_flag = 0; /* Hmm... */
 271         mp->state = MOD_RUNNING;
 272 
 273         return 0;
 274 }
 275 
 276 asmlinkage int
 277 sys_delete_module(char *module_name)
     /* [previous][next][first][last][top][bottom][index][help] */
 278 {
 279         struct module *mp;
 280         char name[MOD_MAX_NAME];
 281         int error;
 282 
 283         if (!suser())
 284                 return -EPERM;
 285         /* else */
 286         if (module_name != NULL) {
 287                 if ((error = get_mod_name(module_name, name)) != 0)
 288                         return error;
 289                 if ((mp = find_module(name)) == NULL)
 290                         return -ENOENT;
 291                 if ((mp->ref != NULL) || ((GET_USE_COUNT(mp) & ~MOD_AUTOCLEAN) != 0))
 292                         return -EBUSY;
 293                 GET_USE_COUNT(mp) &= ~MOD_AUTOCLEAN;
 294                 if (mp->state == MOD_RUNNING)
 295                         (*mp->cleanup)();
 296                 mp->state = MOD_DELETED;
 297                 free_modules();
 298         }
 299         /* for automatic reaping */
 300         else {
 301                 for (mp = module_list; mp != &kernel_module; mp = mp->next) {
 302                         if ((mp->ref == NULL) && (GET_USE_COUNT(mp) == MOD_AUTOCLEAN) &&
 303                             (mp->state == MOD_RUNNING)) {
 304                                 GET_USE_COUNT(mp) &= ~MOD_AUTOCLEAN;
 305                                 (*mp->cleanup)();
 306                                 mp->state = MOD_DELETED;
 307                                 free_modules();
 308                         }
 309                 }
 310         }
 311         return 0;
 312 }
 313 
 314 
 315 /*
 316  * Copy the kernel symbol table to user space.  If the argument is null,
 317  * just return the size of the table.
 318  *
 319  * Note that the transient module symbols are copied _first_,
 320  * in lifo order!!!
 321  *
 322  * The symbols to "insmod" are according to the "old" format: struct kernel_sym,
 323  * which is actually quite handy for this purpose.
 324  * Note that insmod inserts a struct symbol_table later on...
 325  * (as that format is quite handy for the kernel...)
 326  *
 327  * For every module, the first (pseudo)symbol copied is the module name
 328  * and the address of the module struct.
 329  * This lets "insmod" keep track of references, and build the array of
 330  * struct module_refs in the symbol table.
 331  * The format of the module name is "#module", so that "insmod" can easily
 332  * notice when a module name comes along. Also, this will make it possible
 333  * to use old versions of "insmod", albeit with reduced functionality...
 334  * The "kernel" module has an empty name.
 335  */
 336 asmlinkage int
 337 sys_get_kernel_syms(struct kernel_sym *table)
     /* [previous][next][first][last][top][bottom][index][help] */
 338 {
 339         struct internal_symbol *from;
 340         struct kernel_sym isym;
 341         struct kernel_sym *to;
 342         struct module *mp = module_list;
 343         int i;
 344         int nmodsyms = 0;
 345 
 346         for (mp = module_list; mp; mp = mp->next) {
 347                 if (mp->symtab && mp->symtab->n_symbols) {
 348                         /* include the count for the module name! */
 349                         nmodsyms += mp->symtab->n_symbols + 1;
 350                 }
 351                 else
 352                         /* include the count for the module name! */
 353                         nmodsyms += 1; /* return modules without symbols too */
 354         }
 355 
 356         if (table != NULL) {
 357                 to = table;
 358 
 359                 if ((i = verify_area(VERIFY_WRITE, to, nmodsyms * sizeof(*table))))
 360                         return i;
 361 
 362                 /* copy all module symbols first (always LIFO order) */
 363                 for (mp = module_list; mp; mp = mp->next) {
 364                         if (mp->state == MOD_RUNNING) {
 365                                 /* magic: write module info as a pseudo symbol */
 366                                 isym.value = (unsigned long)mp;
 367                                 sprintf(isym.name, "#%s", mp->name);
 368                                 memcpy_tofs(to, &isym, sizeof isym);
 369                                 ++to;
 370 
 371                                 if (mp->symtab != NULL) {
 372                                         for (i = mp->symtab->n_symbols,
 373                                                 from = mp->symtab->symbol;
 374                                                 i > 0; --i, ++from, ++to) {
 375 
 376                                                 isym.value = (unsigned long)from->addr;
 377                                                 strncpy(isym.name, from->name, sizeof isym.name);
 378                                                 memcpy_tofs(to, &isym, sizeof isym);
 379                                         }
 380                                 }
 381                         }
 382                 }
 383         }
 384 
 385         return nmodsyms;
 386 }
 387 
 388 
 389 /*
 390  * Copy the name of a module from user space.
 391  */
 392 int
 393 get_mod_name(char *user_name, char *buf)
     /* [previous][next][first][last][top][bottom][index][help] */
 394 {
 395         int i;
 396 
 397         i = 0;
 398         for (i = 0 ; (buf[i] = get_user(user_name + i)) != '\0' ; ) {
 399                 if (++i >= MOD_MAX_NAME)
 400                         return -E2BIG;
 401         }
 402         return 0;
 403 }
 404 
 405 
 406 /*
 407  * Look for a module by name, ignoring modules marked for deletion.
 408  */
 409 struct module *
 410 find_module( const char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
 411 {
 412         struct module *mp;
 413 
 414         for (mp = module_list ; mp ; mp = mp->next) {
 415                 if (mp->state == MOD_DELETED)
 416                         continue;
 417                 if (!strcmp(mp->name, name))
 418                         break;
 419         }
 420         return mp;
 421 }
 422 
 423 static void
 424 drop_refs(struct module *mp)
     /* [previous][next][first][last][top][bottom][index][help] */
 425 {
 426         struct module *step;
 427         struct module_ref *prev;
 428         struct module_ref *ref;
 429 
 430         for (step = module_list; step; step = step->next) {
 431                 for (prev = ref = step->ref; ref; ref = prev->next) {
 432                         if (ref->module == mp) {
 433                                 if (ref == step->ref)
 434                                         step->ref = ref->next;
 435                                 else
 436                                         prev->next = ref->next;
 437                                 break; /* every module only references once! */
 438                         }
 439                         else
 440                                 prev = ref;
 441                 }
 442         }
 443 }
 444 
 445 /*
 446  * Try to free modules which have been marked for deletion.  Returns nonzero
 447  * if a module was actually freed.
 448  */
 449 int
 450 free_modules( void)
     /* [previous][next][first][last][top][bottom][index][help] */
 451 {
 452         struct module *mp;
 453         struct module **mpp;
 454         int did_deletion;
 455 
 456         did_deletion = 0;
 457         freeing_modules = 0;
 458         mpp = &module_list;
 459         while ((mp = *mpp) != NULL) {
 460                 if (mp->state != MOD_DELETED) {
 461                         mpp = &mp->next;
 462                 } else {
 463                         if ((GET_USE_COUNT(mp) != 0) || (mp->ref != NULL)) {
 464                                 freeing_modules = 1;
 465                                 mpp = &mp->next;
 466                         } else {        /* delete it */
 467                                 *mpp = mp->next;
 468                                 if (mp->symtab) {
 469                                         if (mp->symtab->n_refs)
 470                                                 drop_refs(mp);
 471                                         if (mp->symtab->size)
 472                                                 kfree_s(mp->symtab, mp->symtab->size);
 473                                 }
 474                                 vfree(mp->addr);
 475                                 kfree_s(mp, sizeof(struct module) + MOD_MAX_NAME);
 476                                 did_deletion = 1;
 477                         }
 478                 }
 479         }
 480         return did_deletion;
 481 }
 482 
 483 
 484 /*
 485  * Called by the /proc file system to return a current list of modules.
 486  */
 487 int get_module_list(char *buf)
     /* [previous][next][first][last][top][bottom][index][help] */
 488 {
 489         char *p;
 490         const char *q;
 491         int i;
 492         struct module *mp;
 493         struct module_ref *ref;
 494         char size[32];
 495 
 496         p = buf;
 497         /* Do not show the kernel pseudo module */
 498         for (mp = module_list ; mp && mp->next; mp = mp->next) {
 499                 if (p - buf > 4096 - 100)
 500                         break;                  /* avoid overflowing buffer */
 501                 q = mp->name;
 502                 if (*q == '\0' && mp->size == 0 && mp->ref == NULL)
 503                         continue; /* don't list modules for kernel syms */
 504                 i = 20;
 505                 while (*q) {
 506                         *p++ = *q++;
 507                         i--;
 508                 }
 509                 sprintf(size, "%d", mp->size);
 510                 i -= strlen(size);
 511                 if (i <= 0)
 512                         i = 1;
 513                 while (--i >= 0)
 514                         *p++ = ' ';
 515                 q = size;
 516                 while (*q)
 517                         *p++ = *q++;
 518                 if (mp->state == MOD_UNINITIALIZED)
 519                         q = "  (uninitialized)";
 520                 else if (mp->state == MOD_RUNNING)
 521                         q = "";
 522                 else if (mp->state == MOD_DELETED)
 523                         q = "  (deleted)";
 524                 else
 525                         q = "  (bad state)";
 526                 while (*q)
 527                         *p++ = *q++;
 528 
 529                 if ((ref = mp->ref) != NULL) {
 530                         *p++ = '\t';
 531                         *p++ = '[';
 532                         for (; ref; ref = ref->next) {
 533                                 q = ref->module->name;
 534                                 while (*q)
 535                                         *p++ = *q++;
 536                                 if (ref->next)
 537                                         *p++ = ' ';
 538                         }
 539                         *p++ = ']';
 540                 }
 541                 if (mp->state == MOD_RUNNING) {
 542                         sprintf(size,"\t%ld%s",
 543                                 GET_USE_COUNT(mp) & ~MOD_AUTOCLEAN,
 544                                 ((GET_USE_COUNT(mp) & MOD_AUTOCLEAN)?
 545                                         " (autoclean)":""));
 546                         q = size;
 547                         while (*q)
 548                                 *p++ = *q++;
 549                 }
 550                 *p++ = '\n';
 551         }
 552         return p - buf;
 553 }
 554 
 555 
 556 /*
 557  * Called by the /proc file system to return a current list of ksyms.
 558  */
 559 int get_ksyms_list(char *buf, char **start, off_t offset, int length)
     /* [previous][next][first][last][top][bottom][index][help] */
 560 {
 561         struct module *mp;
 562         struct internal_symbol *sym;
 563         int i;
 564         char *p = buf;
 565         int len     = 0;        /* code from  net/ipv4/proc.c */
 566         off_t pos   = 0;
 567         off_t begin = 0;
 568 
 569         for (mp = module_list; mp; mp = mp->next) {
 570                 if ((mp->state == MOD_RUNNING) &&
 571                     (mp->symtab != NULL) &&
 572                     (mp->symtab->n_symbols > 0)) {
 573                         for (i = mp->symtab->n_symbols,
 574                                 sym = mp->symtab->symbol;
 575                                 i > 0; --i, ++sym) {
 576 
 577                                 p = buf + len;
 578                                 if (mp->name[0]) {
 579                                         len += sprintf(p, "%08lx %s\t[%s]\n",
 580                                                        (long)sym->addr,
 581                                                        sym->name, mp->name);
 582                                 } else {
 583                                         len += sprintf(p, "%08lx %s\n",
 584                                                        (long)sym->addr,
 585                                                        sym->name);
 586                                 }
 587                                 pos = begin + len;
 588                                 if (pos < offset) {
 589                                         len   = 0;
 590                                         begin = pos;
 591                                 }
 592                                 pos = begin + len;
 593                                 if (pos > offset+length)
 594                                         goto leave_the_loop;
 595                         }
 596                 }
 597         }
 598     leave_the_loop:
 599         *start = buf + (offset - begin);
 600         len -= (offset - begin);
 601         if (len > length)
 602                 len = length;
 603         return len;
 604 }
 605 
 606 /*
 607  * Rules:
 608  * - The new symbol table should be statically allocated, or else you _have_
 609  *   to set the "size" field of the struct to the number of bytes allocated.
 610  *
 611  * - The strings that name the symbols will not be copied, maybe the pointers
 612  *
 613  * - For a loadable module, the function should only be called in the
 614  *   context of init_module
 615  *
 616  * Those are the only restrictions! (apart from not being reentrant...)
 617  *
 618  * If you want to remove a symbol table for a loadable module,
 619  * the call looks like: "register_symtab(0)".
 620  *
 621  * The look of the code is mostly dictated by the format of
 622  * the frozen struct symbol_table, due to compatibility demands.
 623  */
 624 #define INTSIZ sizeof(struct internal_symbol)
 625 #define REFSIZ sizeof(struct module_ref)
 626 #define SYMSIZ sizeof(struct symbol_table)
 627 #define MODSIZ sizeof(struct module)
 628 static struct symbol_table nulltab;
 629 
 630 int
 631 register_symtab(struct symbol_table *intab)
     /* [previous][next][first][last][top][bottom][index][help] */
 632 {
 633         struct module *mp;
 634         struct module *link;
 635         struct symbol_table *oldtab;
 636         struct symbol_table *newtab;
 637         struct module_ref *newref;
 638         int size;
 639 
 640         if (intab && (intab->n_symbols == 0)) {
 641                 struct internal_symbol *sym;
 642                 /* How many symbols, really? */
 643 
 644                 for (sym = intab->symbol; sym->name; ++sym)
 645                         intab->n_symbols +=1;
 646         }
 647 
 648 #if 1
 649         if (module_init_flag == 0) { /* Hmm... */
 650 #else
 651         if (module_list == &kernel_module) {
 652 #endif
 653                 /* Aha! Called from an "internal" module */
 654                 if (!intab)
 655                         return 0; /* or -ESILLY_PROGRAMMER :-) */
 656 
 657                 /* create a pseudo module! */
 658                 if (!(mp = (struct module*) kmalloc(MODSIZ, GFP_KERNEL))) {
 659                         /* panic time! */
 660                         printk("Out of memory for new symbol table!\n");
 661                         return -ENOMEM;
 662                 }
 663                 /* else  OK */
 664                 memset(mp, 0, MODSIZ);
 665                 mp->state = MOD_RUNNING; /* Since it is resident... */
 666                 mp->name = ""; /* This is still the "kernel" symbol table! */
 667                 mp->symtab = intab;
 668 
 669                 /* link it in _after_ the resident symbol table */
 670                 mp->next = kernel_module.next;
 671                 kernel_module.next = mp;
 672 
 673                 return 0;
 674         }
 675 
 676         /* else ******** Called from a loadable module **********/
 677 
 678         /*
 679          * This call should _only_ be done in the context of the
 680          * call to  init_module  i.e. when loading the module!!
 681          * Or else...
 682          */
 683         mp = module_list; /* true when doing init_module! */
 684 
 685         /* Any table there before? */
 686         if ((oldtab = mp->symtab) == (struct symbol_table*)0) {
 687                 /* No, just insert it! */
 688                 mp->symtab = intab;
 689                 return 0;
 690         }
 691 
 692         /* else  ****** we have to replace the module symbol table ******/
 693 #if 0
 694         if (oldtab->n_symbols > 0) {
 695                 /* Oh dear, I have to drop the old ones... */
 696                 printk("Warning, dropping old symbols\n");
 697         }
 698 #endif
 699 
 700         if (oldtab->n_refs == 0) { /* no problems! */
 701                 mp->symtab = intab;
 702                 /* if the old table was kmalloc-ed, drop it */
 703                 if (oldtab->size > 0)
 704                         kfree_s(oldtab, oldtab->size);
 705 
 706                 return 0;
 707         }
 708 
 709         /* else */
 710         /***** The module references other modules... insmod said so! *****/
 711         /* We have to allocate a new symbol table, or we lose them! */
 712         if (intab == (struct symbol_table*)0)
 713                 intab = &nulltab; /* easier code with zeroes in place */
 714 
 715         /* the input symbol table space does not include the string table */
 716         /* (it does for symbol tables that insmod creates) */
 717 
 718         if (!(newtab = (struct symbol_table*)kmalloc(
 719                 size = SYMSIZ + intab->n_symbols * INTSIZ +
 720                         oldtab->n_refs * REFSIZ,
 721                 GFP_KERNEL))) {
 722                 /* panic time! */
 723                 printk("Out of memory for new symbol table!\n");
 724                 return -ENOMEM;
 725         }
 726 
 727         /* copy up to, and including, the new symbols */
 728         memcpy(newtab, intab, SYMSIZ + intab->n_symbols * INTSIZ);
 729 
 730         newtab->size = size;
 731         newtab->n_refs = oldtab->n_refs;
 732 
 733         /* copy references */
 734         memcpy( ((char *)newtab) + SYMSIZ + intab->n_symbols * INTSIZ,
 735                 ((char *)oldtab) + SYMSIZ + oldtab->n_symbols * INTSIZ,
 736                 oldtab->n_refs * REFSIZ);
 737 
 738         /* relink references from the old table to the new one */
 739 
 740         /* pointer to the first reference entry in newtab! Really! */
 741         newref = (struct module_ref*) &(newtab->symbol[newtab->n_symbols]);
 742 
 743         /* check for reference links from previous modules */
 744         for (   link = module_list;
 745                 link && (link != &kernel_module);
 746                 link = link->next) {
 747 
 748                 if (link->ref && (link->ref->module == mp))
 749                         link->ref = newref++;
 750         }
 751 
 752         mp->symtab = newtab;
 753 
 754         /* all references (if any) have been handled */
 755 
 756         /* if the old table was kmalloc-ed, drop it */
 757         if (oldtab->size > 0)
 758                 kfree_s(oldtab, oldtab->size);
 759 
 760         return 0;
 761 }
 762 
 763 #else           /* CONFIG_MODULES */
 764 
 765 /* Dummy syscalls for people who don't want modules */
 766 
 767 asmlinkage unsigned long sys_create_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 768 {
 769         return -ENOSYS;
 770 }
 771 
 772 asmlinkage int sys_init_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 773 {
 774         return -ENOSYS;
 775 }
 776 
 777 asmlinkage int sys_delete_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 778 {
 779         return -ENOSYS;
 780 }
 781 
 782 asmlinkage int sys_get_kernel_syms(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 783 {
 784         return -ENOSYS;
 785 }
 786 
 787 int register_symtab(struct symbol_table *intab)
     /* [previous][next][first][last][top][bottom][index][help] */
 788 {
 789         return 0;
 790 }
 791 
 792 #endif  /* CONFIG_MODULES */
 793 

/* [previous][next][first][last][top][bottom][index][help] */