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

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