root/kernel/module.c

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

DEFINITIONS

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

   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 /*
  10  * Heavily modified by Bjorn Ekwall <bj0rn@blox.se> May 1994 (C)
  11  * This source is covered by the GNU GPL, the same as all kernel sources.
  12  *
  13  * Features:
  14  *      - Supports stacked modules (removable only of there are no dependents).
  15  *      - Supports table of symbols defined by the modules.
  16  *      - Supports /proc/ksyms, showing value, name and owner of all
  17  *        the symbols defined by all modules (in stack order).
  18  *      - Added module dependencies information into /proc/modules
  19  *      - Supports redefines of all symbols, for streams-like behaviour.
  20  *      - Compatible with older versions of insmod.
  21  *
  22  */
  23 
  24 #ifdef DEBUG_MODULE
  25 #define PRINTK(a) printk a
  26 #else
  27 #define PRINTK(a) /* */
  28 #endif
  29 
  30 static struct module kernel_module;
  31 static struct module *module_list = &kernel_module;
  32 
  33 static int freeing_modules; /* true if some modules are marked for deletion */
  34 
  35 static struct module *find_module( const char *name);
  36 static int get_mod_name( char *user_name, char *buf);
  37 static int free_modules( void);
  38 
  39 
  40 /*
  41  * Called at boot time
  42  */
  43 void init_modules(void) {
     /* [previous][next][first][last][top][bottom][index][help] */
  44         extern struct symbol_table symbol_table; /* in kernel/ksyms.c */
  45         struct internal_symbol *sym;
  46         int i;
  47 
  48         for (i = 0, sym = symbol_table.symbol; sym->name; ++sym, ++i)
  49                 ;
  50         symbol_table.n_symbols = i;
  51 
  52         kernel_module.symtab = &symbol_table;
  53         kernel_module.state = MOD_RUNNING; /* Hah! */
  54         kernel_module.name = "";
  55 }
  56 
  57 int
  58 rename_module_symbol(char *old_name, char *new_name)
     /* [previous][next][first][last][top][bottom][index][help] */
  59 {
  60         struct internal_symbol *sym;
  61         int i = 0; /* keep gcc silent */
  62 
  63         if (module_list->symtab) {
  64                 sym = module_list->symtab->symbol;
  65                 for (i = module_list->symtab->n_symbols; i > 0; ++sym, --i) {
  66                         if (strcmp(sym->name, old_name) == 0) { /* found it! */
  67                                 sym->name = new_name; /* done! */
  68                                 PRINTK(("renamed %s to %s\n", old_name, new_name));
  69                                 return 1; /* it worked! */
  70                         }
  71                 }
  72         }
  73         printk("rename %s to %s failed!\n", old_name, new_name);
  74         return 0; /* not there... */
  75 
  76         /*
  77          * This one will change the name of the first matching symbol!
  78          *
  79          * With this function, you can replace the name of a symbol defined
  80          * in the current module with a new name, e.g. when you want to insert
  81          * your own function instead of a previously defined function
  82          * with the same name.
  83          *
  84          * "Normal" usage:
  85          *
  86          * bogus_function(int params)
  87          * {
  88          *      do something "smart";
  89          *      return real_function(params);
  90          * }
  91          *
  92          * ...
  93          *
  94          * init_module()
  95          * {
  96          *      if (rename_module_symbol("_bogus_function", "_real_function"))
  97          *              printk("yep!\n");
  98          *      else
  99          *              printk("no way!\n");
 100          * ...
 101          * }
 102          *
 103          * When loading this module, real_function will be resolved
 104          * to the real function address.
 105          * All later loaded modules that refer to "real_function()" will
 106          * then really call "bogus_function()" instead!!!
 107          *
 108          * This feature will give you ample opportunities to get to know
 109          * the taste of your foot when you stuff it into your mouth!!!
 110          */
 111 }
 112 
 113 /*
 114  * Allocate space for a module.
 115  */
 116 asmlinkage int
 117 sys_create_module(char *module_name, unsigned long size)
     /* [previous][next][first][last][top][bottom][index][help] */
 118 {
 119         struct module *mp;
 120         void* addr;
 121         int error;
 122         int npages;
 123         int sspace = sizeof(struct module) + MOD_MAX_NAME;
 124         char name[MOD_MAX_NAME];
 125 
 126         if (!suser())
 127                 return -EPERM;
 128         if (module_name == NULL || size == 0)
 129                 return -EINVAL;
 130         if ((error = get_mod_name(module_name, name)) != 0)
 131                 return error;
 132         if (find_module(name) != NULL) {
 133                 return -EEXIST;
 134         }
 135 
 136         if ((mp = (struct module*) kmalloc(sspace, GFP_KERNEL)) == NULL) {
 137                 return -ENOMEM;
 138         }
 139         strcpy((char *)(mp + 1), name); /* why not? */
 140 
 141         npages = (size + sizeof (int) + 4095) / 4096;
 142         if ((addr = vmalloc(npages * 4096)) == 0) {
 143                 kfree_s(mp, sspace);
 144                 return -ENOMEM;
 145         }
 146 
 147         mp->next = module_list;
 148         mp->ref = NULL;
 149         mp->symtab = NULL;
 150         mp->name = (char *)(mp + 1);
 151         mp->size = npages;
 152         mp->addr = addr;
 153         mp->state = MOD_UNINITIALIZED;
 154         mp->cleanup = NULL;
 155 
 156         * (int *) addr = 0;     /* set use count to zero */
 157         module_list = mp;       /* link it in */
 158 
 159         PRINTK(("module `%s' (%lu pages @ 0x%08lx) created\n",
 160                 mp->name, (unsigned long) mp->size, (unsigned long) mp->addr));
 161         return (int) addr;
 162 }
 163 
 164 /*
 165  * Initialize a module.
 166  */
 167 asmlinkage int
 168 sys_init_module(char *module_name, char *code, unsigned codesize,
     /* [previous][next][first][last][top][bottom][index][help] */
 169                 struct mod_routines *routines,
 170                 struct symbol_table *symtab)
 171 {
 172         struct module *mp;
 173         struct symbol_table *newtab;
 174         char name[MOD_MAX_NAME];
 175         int error;
 176         struct mod_routines rt;
 177 
 178         if (!suser())
 179                 return -EPERM;
 180 
 181         /* A little bit of protection... we "know" where the user stack is... */
 182         if (symtab && ((unsigned long)symtab > 0xb0000000)) {
 183                 printk("warning: you are using an old insmod, no symbols will be inserted!\n");
 184                 symtab = NULL;
 185         }
 186 
 187         /*
 188          * First reclaim any memory from dead modules that where not
 189          * freed when deleted. Should I think be done by timers when
 190          * the module was deleted - Jon.
 191          */
 192         free_modules();
 193 
 194         if ((error = get_mod_name(module_name, name)) != 0)
 195                 return error;
 196         PRINTK(("initializing module `%s', %d (0x%x) bytes\n",
 197                 name, codesize, codesize));
 198         memcpy_fromfs(&rt, routines, sizeof rt);
 199         if ((mp = find_module(name)) == NULL)
 200                 return -ENOENT;
 201         if ((codesize + sizeof (int) + 4095) / 4096 > mp->size)
 202                 return -EINVAL;
 203         memcpy_fromfs((char *)mp->addr + sizeof (int), code, codesize);
 204         memset((char *)mp->addr + sizeof (int) + codesize, 0,
 205                 mp->size * 4096 - (codesize + sizeof (int)));
 206         PRINTK(( "module init entry = 0x%08lx, cleanup entry = 0x%08lx\n",
 207                 (unsigned long) rt.init, (unsigned long) rt.cleanup));
 208         mp->cleanup = rt.cleanup;
 209 
 210         /* update kernel symbol table */
 211         if (symtab) { /* symtab == NULL means no new entries to handle */
 212                 struct internal_symbol *sym;
 213                 struct module_ref *ref;
 214                 int size;
 215                 int i;
 216 
 217                 if ((error = verify_area(VERIFY_READ, symtab, sizeof(int))))
 218                         return error;
 219                 memcpy_fromfs((char *)(&(size)), symtab, sizeof(int));
 220 
 221                 if ((newtab = (struct symbol_table*) kmalloc(size, GFP_KERNEL)) == NULL) {
 222                         return -ENOMEM;
 223                 }
 224 
 225                 if ((error = verify_area(VERIFY_READ, symtab, size)))
 226                         return error;
 227                 memcpy_fromfs((char *)(newtab), symtab, size);
 228 
 229                 /* relocate name pointers, index referred from start of table */
 230                 for (sym = &(newtab->symbol[0]), i = 0;
 231                         i < newtab->n_symbols; ++sym, ++i) {
 232                         sym->name += (long)newtab;
 233                 }
 234                 mp->symtab = newtab;
 235 
 236                 /* Update module references.
 237                  * On entry, from "insmod", ref->module points to
 238                  * the referenced module!
 239                  * Also, "sym" from above, points to the first ref entry!!!
 240                  */
 241                 for (ref = (struct module_ref *)sym, i = 0;
 242                         i < newtab->n_refs; ++ref, ++i) {
 243                         ref->next = ref->module->ref;
 244                         ref->module->ref = ref;
 245                         ref->module = mp;
 246                 }
 247         }
 248 
 249         if ((*rt.init)() != 0)
 250                 return -EBUSY;
 251         mp->state = MOD_RUNNING;
 252 
 253         return 0;
 254 }
 255 
 256 asmlinkage int
 257 sys_delete_module(char *module_name)
     /* [previous][next][first][last][top][bottom][index][help] */
 258 {
 259         struct module *mp;
 260         char name[MOD_MAX_NAME];
 261         int error;
 262 
 263         if (!suser())
 264                 return -EPERM;
 265         /* else */
 266         if (module_name != NULL) {
 267                 if ((error = get_mod_name(module_name, name)) != 0)
 268                         return error;
 269                 if ((mp = find_module(name)) == NULL)
 270                         return -ENOENT;
 271                 if ((mp->ref != NULL) || (GET_USE_COUNT(mp) != 0))
 272                         return -EBUSY;
 273                 if (mp->state == MOD_RUNNING)
 274                         (*mp->cleanup)();
 275                 mp->state = MOD_DELETED;
 276         }
 277         free_modules();
 278         return 0;
 279 }
 280 
 281 
 282 /*
 283  * Copy the kernel symbol table to user space.  If the argument is null,
 284  * just return the size of the table.
 285  *
 286  * Note that the transient module symbols are copied _first_,
 287  * in lifo order!!!
 288  *
 289  * The symbols to "insmod" are according to the "old" format: struct kernel_sym,
 290  * which is actually quite handy for this purpose.
 291  * Note that insmod inserts a struct symbol_table later on...
 292  * (as that format is quite handy for the kernel...)
 293  *
 294  * For every module, the first (pseudo)symbol copied is the module name
 295  * and the address of the module struct.
 296  * This lets "insmod" keep track of references, and build the array of
 297  * struct module_refs in the symbol table.
 298  * The format of the module name is "#module", so that "insmod" can easily
 299  * notice when a module name comes along. Also, this will make it possible
 300  * to use old versions of "insmod", albeit with reduced functionality...
 301  * The "kernel" module has an empty name.
 302  */
 303 asmlinkage int
 304 sys_get_kernel_syms(struct kernel_sym *table)
     /* [previous][next][first][last][top][bottom][index][help] */
 305 {
 306         struct internal_symbol *from;
 307         struct kernel_sym isym;
 308         struct kernel_sym *to;
 309         struct module *mp = module_list;
 310         int i;
 311         int nmodsyms = 0;
 312 
 313         for (mp = module_list; mp; mp = mp->next) {
 314                 if (mp->symtab && mp->symtab->n_symbols) {
 315                         /* include the count for the module name! */
 316                         nmodsyms += mp->symtab->n_symbols + 1;
 317                 }
 318         }
 319 
 320         if (table != NULL) {
 321                 to = table;
 322 
 323                 if ((i = verify_area(VERIFY_WRITE, to, nmodsyms * sizeof(*table))))
 324                         return i;
 325 
 326                 /* copy all module symbols first (always LIFO order) */
 327                 for (mp = module_list; mp; mp = mp->next) {
 328                         if ((mp->state == MOD_RUNNING) &&
 329                                 (mp->symtab != NULL) && (mp->symtab->n_symbols > 0)) {
 330                                 /* magic: write module info as a pseudo symbol */
 331                                 isym.value = (unsigned long)mp;
 332                                 sprintf(isym.name, "#%s", mp->name);
 333                                 memcpy_tofs(to, &isym, sizeof isym);
 334                                 ++to;
 335 
 336                                 for (i = mp->symtab->n_symbols,
 337                                         from = mp->symtab->symbol;
 338                                         i > 0; --i, ++from, ++to) {
 339 
 340                                         isym.value = (unsigned long)from->addr;
 341                                         strncpy(isym.name, from->name, sizeof isym.name);
 342                                         memcpy_tofs(to, &isym, sizeof isym);
 343                                 }
 344                         }
 345                 }
 346         }
 347 
 348         return nmodsyms;
 349 }
 350 
 351 
 352 /*
 353  * Copy the name of a module from user space.
 354  */
 355 int
 356 get_mod_name(char *user_name, char *buf)
     /* [previous][next][first][last][top][bottom][index][help] */
 357 {
 358         int i;
 359 
 360         i = 0;
 361         for (i = 0 ; (buf[i] = get_fs_byte(user_name + i)) != '\0' ; ) {
 362                 if (++i >= MOD_MAX_NAME)
 363                         return -E2BIG;
 364         }
 365         return 0;
 366 }
 367 
 368 
 369 /*
 370  * Look for a module by name, ignoring modules marked for deletion.
 371  */
 372 struct module *
 373 find_module( const char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
 374 {
 375         struct module *mp;
 376 
 377         for (mp = module_list ; mp ; mp = mp->next) {
 378                 if (mp->state == MOD_DELETED)
 379                         continue;
 380                 if (!strcmp(mp->name, name))
 381                         break;
 382         }
 383         return mp;
 384 }
 385 
 386 static void
 387 drop_refs(struct module *mp)
     /* [previous][next][first][last][top][bottom][index][help] */
 388 {
 389         struct module *step;
 390         struct module_ref *prev;
 391         struct module_ref *ref;
 392 
 393         for (step = module_list; step; step = step->next) {
 394                 for (prev = ref = step->ref; ref; ref = prev->next) {
 395                         if (ref->module == mp) {
 396                                 if (ref == step->ref)
 397                                         step->ref = ref->next;
 398                                 else
 399                                         prev->next = ref->next;
 400                                 break; /* every module only references once! */
 401                         }
 402                         else
 403                                 prev = ref;
 404                 }
 405         }
 406 }
 407 
 408 /*
 409  * Try to free modules which have been marked for deletion.  Returns nonzero
 410  * if a module was actually freed.
 411  */
 412 int
 413 free_modules( void)
     /* [previous][next][first][last][top][bottom][index][help] */
 414 {
 415         struct module *mp;
 416         struct module **mpp;
 417         int did_deletion;
 418 
 419         did_deletion = 0;
 420         freeing_modules = 0;
 421         mpp = &module_list;
 422         while ((mp = *mpp) != NULL) {
 423                 if (mp->state != MOD_DELETED) {
 424                         mpp = &mp->next;
 425                 } else {
 426                         if (GET_USE_COUNT(mp) != 0) {
 427                                 freeing_modules = 1;
 428                                 mpp = &mp->next;
 429                         } else {        /* delete it */
 430                                 *mpp = mp->next;
 431                                 if (mp->symtab) {
 432                                         if (mp->symtab->n_refs)
 433                                                 drop_refs(mp);
 434                                         if (mp->symtab->size)
 435                                                 kfree_s(mp->symtab, mp->symtab->size);
 436                                 }
 437                                 vfree(mp->addr);
 438                                 kfree_s(mp, sizeof(struct module) + MOD_MAX_NAME);
 439                                 did_deletion = 1;
 440                         }
 441                 }
 442         }
 443         return did_deletion;
 444 }
 445 
 446 
 447 /*
 448  * Called by the /proc file system to return a current list of modules.
 449  */
 450 int get_module_list(char *buf)
     /* [previous][next][first][last][top][bottom][index][help] */
 451 {
 452         char *p;
 453         char *q;
 454         int i;
 455         struct module *mp;
 456         struct module_ref *ref;
 457         char size[32];
 458 
 459         p = buf;
 460         /* Do not show the kernel pseudo module */
 461         for (mp = module_list ; mp && mp->next; mp = mp->next) {
 462                 if (p - buf > 4096 - 100)
 463                         break;                  /* avoid overflowing buffer */
 464                 q = mp->name;
 465                 i = 20;
 466                 while (*q) {
 467                         *p++ = *q++;
 468                         i--;
 469                 }
 470                 sprintf(size, "%d", mp->size);
 471                 i -= strlen(size);
 472                 if (i <= 0)
 473                         i = 1;
 474                 while (--i >= 0)
 475                         *p++ = ' ';
 476                 q = size;
 477                 while (*q)
 478                         *p++ = *q++;
 479                 if (mp->state == MOD_UNINITIALIZED)
 480                         q = "  (uninitialized)";
 481                 else if (mp->state == MOD_RUNNING)
 482                         q = "";
 483                 else if (mp->state == MOD_DELETED)
 484                         q = "  (deleted)";
 485                 else
 486                         q = "  (bad state)";
 487                 while (*q)
 488                         *p++ = *q++;
 489 
 490                 if ((ref = mp->ref) != NULL) {
 491                         *p++ = '\t';
 492                         *p++ = '[';
 493                         for (; ref; ref = ref->next) {
 494                                 q = ref->module->name;
 495                                 while (*q)
 496                                         *p++ = *q++;
 497                                 if (ref->next)
 498                                         *p++ = ' ';
 499                         }
 500                         *p++ = ']';
 501                 }
 502                 *p++ = '\n';
 503         }
 504         return p - buf;
 505 }
 506 
 507 
 508 /*
 509  * Called by the /proc file system to return a current list of ksyms.
 510  */
 511 int get_ksyms_list(char *buf)
     /* [previous][next][first][last][top][bottom][index][help] */
 512 {
 513         struct module *mp;
 514         struct internal_symbol *sym;
 515         int i;
 516         char *p = buf;
 517 
 518         for (mp = module_list; mp; mp = mp->next) {
 519                 if ((mp->state == MOD_RUNNING) &&
 520                         (mp->symtab != NULL) && (mp->symtab->n_symbols > 0)) {
 521                         for (i = mp->symtab->n_symbols,
 522                                 sym = mp->symtab->symbol;
 523                                 i > 0; --i, ++sym) {
 524 
 525                                 if (p - buf > 4096 - 100) {
 526                                         strcat(p, "...\n");
 527                                         p += strlen(p);
 528                                         return p - buf; /* avoid overflowing buffer */
 529                                 }
 530 
 531                                 if (mp->name[0]) {
 532                                         sprintf(p, "%08lx %s\t[%s]\n",
 533                                                 (long)sym->addr, sym->name, mp->name);
 534                                 }
 535                                 else {
 536                                         sprintf(p, "%08lx %s\n",
 537                                                 (long)sym->addr, sym->name);
 538                                 }
 539                                 p += strlen(p);
 540                         }
 541                 }
 542         }
 543 
 544         return p - buf;
 545 }

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