root/kernel/module.c

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

DEFINITIONS

This source file includes following definitions.
  1. sys_create_module
  2. sys_init_module
  3. sys_delete_module
  4. sys_get_kernel_syms
  5. get_mod_name
  6. find_module
  7. free_modules
  8. get_module_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 struct module *module_list = NULL;
  11 int freeing_modules;            /* true if some modules are marked for deletion */
  12 
  13 struct module *find_module( const char *name);
  14 int get_mod_name( char *user_name, char *buf);
  15 int free_modules( void);
  16 
  17 /*
  18  * Allocate space for a module.
  19  */
  20 asmlinkage int
  21 sys_create_module(char *module_name, unsigned long size)
     /* [previous][next][first][last][top][bottom][index][help] */
  22 {
  23         int npages;
  24         void* addr;
  25         int len;
  26         char name[MOD_MAX_NAME];
  27         char *savename;
  28         struct module *mp;
  29         int error;
  30 
  31         if (!suser())
  32                 return -EPERM;
  33         if (module_name == NULL || size == 0)
  34                 return -EINVAL;
  35         if ((error = get_mod_name(module_name, name)) != 0)
  36                 return error;
  37         if (find_module(name) != NULL) {
  38                 return -EEXIST;
  39         }
  40         len = strlen(name) + 1;
  41         if ((savename = (char*) kmalloc(len, GFP_KERNEL)) == NULL)
  42                 return -ENOMEM;
  43         memcpy(savename, name, len);
  44         if ((mp = (struct module*) kmalloc(sizeof *mp, GFP_KERNEL)) == NULL) {
  45                 kfree(savename);
  46                 return -ENOMEM;
  47         }
  48         npages = (size + sizeof (int) + 4095) / 4096;
  49         if ((addr = vmalloc(npages * 4096)) == 0) {
  50                 kfree_s(mp, sizeof *mp);
  51                 kfree(savename);
  52                 return -ENOMEM;
  53         }
  54         mp->name = savename;
  55         mp->size = npages;
  56         mp->addr = addr;
  57         mp->state = MOD_UNINITIALIZED;
  58         * (int *) addr = 0;             /* set use count to zero */
  59         mp->cleanup = NULL;
  60         mp->next = module_list;
  61         module_list = mp;
  62         printk("module `%s' (%lu pages @ 0x%08lx) created\n",
  63                 mp->name, (unsigned long) mp->size, (unsigned long) mp->addr);
  64         return (int) addr;
  65 }
  66 
  67 /*
  68  * Initialize a module.
  69  */
  70 asmlinkage int
  71 sys_init_module(char *module_name, char *code, unsigned codesize,
     /* [previous][next][first][last][top][bottom][index][help] */
  72                 struct mod_routines *routines)
  73 {
  74         struct module *mp;
  75         char name[MOD_MAX_NAME];
  76         int error;
  77         struct mod_routines rt;
  78 
  79         if (!suser())
  80                 return -EPERM;
  81         /*
  82          * First reclaim any memory from dead modules that where not
  83          * freed when deleted. Should I think be done by timers when
  84          * the module was deleted - Jon.
  85          */
  86         free_modules();
  87 
  88         if ((error = get_mod_name(module_name, name)) != 0)
  89                 return error;
  90         printk( "initializing module `%s', %d (0x%x) bytes\n",
  91                 name, codesize, codesize);
  92         memcpy_fromfs(&rt, routines, sizeof rt);
  93         if ((mp = find_module(name)) == NULL)
  94                 return -ENOENT;
  95         if ((codesize + sizeof (int) + 4095) / 4096 > mp->size)
  96                 return -EINVAL;
  97         memcpy_fromfs((char *)mp->addr + sizeof (int), code, codesize);
  98         memset((char *)mp->addr + sizeof (int) + codesize, 0,
  99                 mp->size * 4096 - (codesize + sizeof (int)));
 100         printk( "  init entry @ 0x%08lx, cleanup entry @ 0x%08lx\n",
 101                 (unsigned long) rt.init, (unsigned long) rt.cleanup);
 102         mp->cleanup = rt.cleanup;
 103         if ((*rt.init)() != 0)
 104                 return -EBUSY;
 105         mp->state = MOD_RUNNING;
 106         return 0;
 107 }
 108 
 109 asmlinkage int
 110 sys_delete_module(char *module_name)
     /* [previous][next][first][last][top][bottom][index][help] */
 111 {
 112         struct module *mp;
 113         char name[MOD_MAX_NAME];
 114         int error;
 115 
 116         if (!suser())
 117                 return -EPERM;
 118         if (module_name != NULL) {
 119                 if ((error = get_mod_name(module_name, name)) != 0)
 120                         return error;
 121                 if ((mp = find_module(name)) == NULL)
 122                         return -ENOENT;
 123                 if (mp->state == MOD_RUNNING)
 124                         (*mp->cleanup)();
 125                 mp->state = MOD_DELETED;
 126         }
 127         free_modules();
 128         return 0;
 129 }
 130 
 131 /*
 132  * Copy the kernel symbol table to user space.  If the argument is null,
 133  * just return the size of the table.
 134  */
 135 asmlinkage int
 136 sys_get_kernel_syms(struct kernel_sym *table)
     /* [previous][next][first][last][top][bottom][index][help] */
 137 {
 138         struct symbol {
 139                 unsigned long addr;
 140                 char *name;
 141         };
 142         extern int symbol_table_size;
 143         extern struct symbol symbol_table[];
 144         int i;
 145         struct symbol *from;
 146         struct kernel_sym *to;
 147         struct kernel_sym sym;
 148 
 149         if (table != NULL) {
 150                 from = symbol_table;
 151                 to = table;
 152                 i = verify_area(VERIFY_WRITE, to, symbol_table_size * sizeof *table);
 153                 if (i)
 154                         return i;
 155                 for (i = symbol_table_size ; --i >= 0 ; ) {
 156                         sym.value = from->addr;
 157                         strncpy(sym.name, from->name, sizeof sym.name);
 158                         memcpy_tofs(to, &sym, sizeof sym);
 159                         from++, to++;
 160                 }
 161         }
 162         return symbol_table_size;
 163 }
 164 
 165 
 166 /*
 167  * Copy the name of a module from user space.
 168  */
 169 int
 170 get_mod_name(char *user_name, char *buf)
     /* [previous][next][first][last][top][bottom][index][help] */
 171 {
 172         int i;
 173 
 174         i = 0;
 175         for (i = 0 ; (buf[i] = get_fs_byte(user_name + i)) != '\0' ; ) {
 176                 if (++i >= MOD_MAX_NAME)
 177                         return -E2BIG;
 178         }
 179         return 0;
 180 }
 181 
 182 
 183 /*
 184  * Look for a module by name, ignoring modules marked for deletion.
 185  */
 186 struct module *
 187 find_module( const char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
 188 {
 189         struct module *mp;
 190 
 191         for (mp = module_list ; mp ; mp = mp->next) {
 192                 if (mp->state == MOD_DELETED)
 193                         continue;
 194                 if (!strcmp(mp->name, name))
 195                         break;
 196         }
 197         return mp;
 198 }
 199 
 200 
 201 /*
 202  * Try to free modules which have been marked for deletion.  Returns nonzero
 203  * if a module was actually freed.
 204  */
 205 int
 206 free_modules( void)
     /* [previous][next][first][last][top][bottom][index][help] */
 207 {
 208         struct module *mp;
 209         struct module **mpp;
 210         int did_deletion;
 211 
 212         did_deletion = 0;
 213         freeing_modules = 0;
 214         mpp = &module_list;
 215         while ((mp = *mpp) != NULL) {
 216                 if (mp->state != MOD_DELETED) {
 217                         mpp = &mp->next;
 218                 } else if (GET_USE_COUNT(mp) != 0) {
 219                         freeing_modules = 1;
 220                         mpp = &mp->next;
 221                 } else {        /* delete it */
 222                         *mpp = mp->next;
 223                         vfree(mp->addr);
 224                         kfree(mp->name);
 225                         kfree_s(mp, sizeof *mp);
 226                         did_deletion = 1;
 227                 }
 228         }
 229         return did_deletion;
 230 }
 231 
 232 
 233 /*
 234  * Called by the /proc file system to return a current list of modules.
 235  */
 236 int get_module_list(char *buf)
     /* [previous][next][first][last][top][bottom][index][help] */
 237 {
 238         char *p;
 239         char *q;
 240         int i;
 241         struct module *mp;
 242         char size[32];
 243 
 244         p = buf;
 245         for (mp = module_list ; mp ; mp = mp->next) {
 246                 if (p - buf > 4096 - 100)
 247                         break;                  /* avoid overflowing buffer */
 248                 q = mp->name;
 249                 i = 20;
 250                 while (*q) {
 251                         *p++ = *q++;
 252                         i--;
 253                 }
 254                 sprintf(size, "%d", mp->size);
 255                 i -= strlen(size);
 256                 if (i <= 0)
 257                         i = 1;
 258                 while (--i >= 0)
 259                         *p++ = ' ';
 260                 q = size;
 261                 while (*q)
 262                         *p++ = *q++;
 263                 if (mp->state == MOD_UNINITIALIZED)
 264                         q = "  (uninitialized)";
 265                 else if (mp->state == MOD_RUNNING)
 266                         q = "";
 267                 else if (mp->state == MOD_DELETED)
 268                         q = "  (deleted)";
 269                 else
 270                         q = "  (bad state)";
 271                 while (*q)
 272                         *p++ = *q++;
 273                 *p++ = '\n';
 274         }
 275         return p - buf;
 276 }

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