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

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