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 (GET_USE_COUNT(mp) != 0)
 124                         return -EBUSY;
 125                 if (mp->state == MOD_RUNNING)
 126                         (*mp->cleanup)();
 127                 mp->state = MOD_DELETED;
 128         }
 129         free_modules();
 130         return 0;
 131 }
 132 
 133 /*
 134  * Copy the kernel symbol table to user space.  If the argument is null,
 135  * just return the size of the table.
 136  */
 137 asmlinkage int
 138 sys_get_kernel_syms(struct kernel_sym *table)
     /* [previous][next][first][last][top][bottom][index][help] */
 139 {
 140         struct symbol {
 141                 unsigned long addr;
 142                 char *name;
 143         };
 144         extern int symbol_table_size;
 145         extern struct symbol symbol_table[];
 146         int i;
 147         struct symbol *from;
 148         struct kernel_sym *to;
 149         struct kernel_sym sym;
 150 
 151         if (table != NULL) {
 152                 from = symbol_table;
 153                 to = table;
 154                 i = verify_area(VERIFY_WRITE, to, symbol_table_size * sizeof *table);
 155                 if (i)
 156                         return i;
 157                 for (i = symbol_table_size ; --i >= 0 ; ) {
 158                         sym.value = from->addr;
 159                         strncpy(sym.name, from->name, sizeof sym.name);
 160                         memcpy_tofs(to, &sym, sizeof sym);
 161                         from++, to++;
 162                 }
 163         }
 164         return symbol_table_size;
 165 }
 166 
 167 
 168 /*
 169  * Copy the name of a module from user space.
 170  */
 171 int
 172 get_mod_name(char *user_name, char *buf)
     /* [previous][next][first][last][top][bottom][index][help] */
 173 {
 174         int i;
 175 
 176         i = 0;
 177         for (i = 0 ; (buf[i] = get_fs_byte(user_name + i)) != '\0' ; ) {
 178                 if (++i >= MOD_MAX_NAME)
 179                         return -E2BIG;
 180         }
 181         return 0;
 182 }
 183 
 184 
 185 /*
 186  * Look for a module by name, ignoring modules marked for deletion.
 187  */
 188 struct module *
 189 find_module( const char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
 190 {
 191         struct module *mp;
 192 
 193         for (mp = module_list ; mp ; mp = mp->next) {
 194                 if (mp->state == MOD_DELETED)
 195                         continue;
 196                 if (!strcmp(mp->name, name))
 197                         break;
 198         }
 199         return mp;
 200 }
 201 
 202 
 203 /*
 204  * Try to free modules which have been marked for deletion.  Returns nonzero
 205  * if a module was actually freed.
 206  */
 207 int
 208 free_modules( void)
     /* [previous][next][first][last][top][bottom][index][help] */
 209 {
 210         struct module *mp;
 211         struct module **mpp;
 212         int did_deletion;
 213 
 214         did_deletion = 0;
 215         freeing_modules = 0;
 216         mpp = &module_list;
 217         while ((mp = *mpp) != NULL) {
 218                 if (mp->state != MOD_DELETED) {
 219                         mpp = &mp->next;
 220                 } else if (GET_USE_COUNT(mp) != 0) {
 221                         freeing_modules = 1;
 222                         mpp = &mp->next;
 223                 } else {        /* delete it */
 224                         *mpp = mp->next;
 225                         vfree(mp->addr);
 226                         kfree(mp->name);
 227                         kfree_s(mp, sizeof *mp);
 228                         did_deletion = 1;
 229                 }
 230         }
 231         return did_deletion;
 232 }
 233 
 234 
 235 /*
 236  * Called by the /proc file system to return a current list of modules.
 237  */
 238 int get_module_list(char *buf)
     /* [previous][next][first][last][top][bottom][index][help] */
 239 {
 240         char *p;
 241         char *q;
 242         int i;
 243         struct module *mp;
 244         char size[32];
 245 
 246         p = buf;
 247         for (mp = module_list ; mp ; mp = mp->next) {
 248                 if (p - buf > 4096 - 100)
 249                         break;                  /* avoid overflowing buffer */
 250                 q = mp->name;
 251                 i = 20;
 252                 while (*q) {
 253                         *p++ = *q++;
 254                         i--;
 255                 }
 256                 sprintf(size, "%d", mp->size);
 257                 i -= strlen(size);
 258                 if (i <= 0)
 259                         i = 1;
 260                 while (--i >= 0)
 261                         *p++ = ' ';
 262                 q = size;
 263                 while (*q)
 264                         *p++ = *q++;
 265                 if (mp->state == MOD_UNINITIALIZED)
 266                         q = "  (uninitialized)";
 267                 else if (mp->state == MOD_RUNNING)
 268                         q = "";
 269                 else if (mp->state == MOD_DELETED)
 270                         q = "  (deleted)";
 271                 else
 272                         q = "  (bad state)";
 273                 while (*q)
 274                         *p++ = *q++;
 275                 *p++ = '\n';
 276         }
 277         return p - buf;
 278 }

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