netlib.narod.ru< Назад | Оглавление | Далее >

kernel/module.c

24476 #include <linux/config.h>
24477 #include <linux/mm.h>
24478 #include <linux/module.h>
24479 #include <asm/uaccess.h>
24480 #include <linux/vmalloc.h>
24481 #include <linux/smp_lock.h>
24482 #include <asm/pgtable.h>
24483 #include <linux/init.h>
24484 
24485 /* Originally by Anonymous (as far as I know...)
24486  * Linux version by Bas Laarhoven <bas@vimec.nl>
24487  * 0.99.14 version by Jon Tombs <jon@gtex02.us.es>,
24488  * Heavily modified by Bjorn Ekwall <bj0rn@blox.se> May
24489  * 1994 (C)
24490  * Rewritten by Richard Henderson <rth@tamu.edu> Dec 1996
24491  *
24492  * This source is covered by the GNU GPL, the same as all
24493  * kernel sources.  */
24494 
24495 #ifdef CONFIG_MODULES  /* a *big* #ifdef block... */
24496 
24497 extern struct module_symbol __start___ksymtab[];
24498 extern struct module_symbol __stop___ksymtab[];
24499 
24500 extern const struct exception_table_entry
24501   __start___ex_table[];
24502 extern const struct exception_table_entry
24503   __stop___ex_table[];
24504 
24505 static struct module kernel_module =
24506 {
24507   sizeof(struct module),  /* size_of_struct */
24508   NULL,                   /* next */
24509   "",                     /* name */
24510   0,                      /* size */
24511   {ATOMIC_INIT(1)},       /* usecount */
24512   MOD_RUNNING,            /* flags */
24513   0,             /* nsyms -- filled in in init_modules */
24514   0,                      /* ndeps */
24515   __start___ksymtab,      /* syms */
24516   NULL,                   /* deps */
24517   NULL,                   /* refs */
24518   NULL,                   /* init */
24519   NULL,                   /* cleanup */
24520   __start___ex_table,     /* ex_table_start */
24521   __stop___ex_table,      /* ex_table_end */
24522   /* Rest are NULL */
24523 };
24524 
24525 struct module *module_list = &kernel_module;
24526 
24527 static long get_mod_name(const char *user_name,
24528                          char **buf);
24529 static void put_mod_name(char *buf);
24530 static struct module *find_module(const char *name);
24531 static void free_module(struct module *, int tag_freed);
24532 
24533 
24534 /* Called at boot time */
24535 
24536 __initfunc(void init_modules(void))
24537 {
24538   kernel_module.nsyms =
24539     __stop___ksymtab - __start___ksymtab;
24540 
24541 #ifdef __alpha__
24542   __asm__("stq $29,%0" : "=m"(kernel_module.gp));
24543 #endif
24544 }
24545 
24546 /* Copy the name of a module from user space. */
24547 
24548 static inline long
24549 get_mod_name(const char *user_name, char **buf)
24550 {
24551   unsigned long page;
24552   long retval;
24553 
24554   if ((unsigned long)user_name >= TASK_SIZE
24555       && !segment_eq(get_fs (), KERNEL_DS))
24556     return -EFAULT;
24557 
24558   page = __get_free_page(GFP_KERNEL);
24559   if (!page)
24560     return -ENOMEM;
24561 
24562   retval = strncpy_from_user((char *)page, user_name,
24563                              PAGE_SIZE);
24564   if (retval > 0) {
24565     if (retval < PAGE_SIZE) {
24566       *buf = (char *)page;
24567       return retval;
24568     }
24569     retval = -ENAMETOOLONG;
24570   } else if (!retval)
24571     retval = -EINVAL;
24572 
24573   free_page(page);
24574   return retval;
24575 }
24576 
24577 static inline void
24578 put_mod_name(char *buf)
24579 {
24580   free_page((unsigned long)buf);
24581 }
24582 
24583 /* Allocate space for a module. */
24584 
24585 asmlinkage unsigned long
24586 sys_create_module(const char *name_user, size_t size)
24587 {
24588   char *name;
24589   long namelen, error;
24590   struct module *mod;
24591 
24592   lock_kernel();
24593   if (!capable(CAP_SYS_MODULE)) {
24594     error = -EPERM;
24595     goto err0;
24596   }
24597   if ((namelen = get_mod_name(name_user, &name)) < 0) {
24598     error = namelen;
24599     goto err0;
24600   }
24601   if (size < sizeof(struct module)+namelen) {
24602     error = -EINVAL;
24603     goto err1;
24604   }
24605   if (find_module(name) != NULL) {
24606     error = -EEXIST;
24607     goto err1;
24608   }
24609   if ((mod = (struct module *)module_map(size)) == NULL){
24610     error = -ENOMEM;
24611     goto err1;
24612   }
24613 
24614   memset(mod, 0, sizeof(*mod));
24615   mod->size_of_struct = sizeof(*mod);
24616   mod->next = module_list;
24617   mod->name = (char *)(mod + 1);
24618   mod->size = size;
24619   memcpy((char*)(mod+1), name, namelen+1);
24620 
24621   put_mod_name(name);
24622 
24623   module_list = mod;      /* link it in */
24624 
24625   error = (long) mod;
24626   goto err0;
24627 err1:
24628   put_mod_name(name);
24629 err0:
24630   unlock_kernel();
24631   return error;
24632 }
24633 
24634 /* Initialize a module. */
24635 
24636 asmlinkage int
24637 sys_init_module(const char *name_user,
24638                 struct module *mod_user)
24639 {
24640   struct module mod_tmp, *mod;
24641   char *name, *n_name;
24642   long namelen, n_namelen, i, error = -EPERM;
24643   unsigned long mod_user_size;
24644   struct module_ref *dep;
24645 
24646   lock_kernel();
24647   if (!capable(CAP_SYS_MODULE))
24648     goto err0;
24649   if ((namelen = get_mod_name(name_user, &name)) < 0) {
24650     error = namelen;
24651     goto err0;
24652   }
24653   if ((mod = find_module(name)) == NULL) {
24654     error = -ENOENT;
24655     goto err1;
24656   }
24657 
24658   /* Check module header size.  We allow a bit of slop
24659    * over the size we are familiar with to cope with a
24660    * version of insmod for a newer kernel.  But don't
24661    * over do it. */
24662   if ((error = get_user(mod_user_size,
24663                         &mod_user->size_of_struct)) != 0)
24664     goto err1;
24665   if (mod_user_size <
24666      (unsigned long)&((struct module *)0L)->persist_start
24667       || mod_user_size >
24668            sizeof(struct module) + 16*sizeof(void*)) {
24669     printk(KERN_ERR
24670            "init_module: Invalid module header size.\n"
24671            KERN_ERR
24672            "A new version of the modutils is likely "
24673            "needed.\n");
24674     error = -EINVAL;
24675     goto err1;
24676   }
24677 
24678   /* Hold the current contents while we play with the
24679    * user's idea of righteousness.  */
24680   mod_tmp = *mod;
24681 
24682   error = copy_from_user(mod, mod_user,
24683                          sizeof(struct module));
24684   if (error) {
24685     error = -EFAULT;
24686     goto err2;
24687   }
24688 
24689   /* Sanity check the size of the module.  */
24690   error = -EINVAL;
24691 
24692   if (mod->size > mod_tmp.size) {
24693     printk(KERN_ERR
24694            "init_module: Size of initialized module "
24695            "exceeds size of created module.\n");
24696     goto err2;
24697   }
24698 
24699   /* Make sure all interesting pointers are sane.  */
24700 
24701 #define bound(p, n, m)                                  \
24702   ((unsigned long)(p) >= (unsigned long)(m+1) &&        \
24703    (unsigned long)((p)+(n)) <=                          \
24704      (unsigned long)(m) + (m)->size)
24705 
24706   if (!bound(mod->name, namelen, mod)) {
24707     printk(KERN_ERR
24708            "init_module: mod->name out of bounds.\n");
24709     goto err2;
24710   }
24711   if (mod->nsyms && !bound(mod->syms, mod->nsyms, mod)) {
24712     printk(KERN_ERR
24713            "init_module: mod->syms out of bounds.\n");
24714     goto err2;
24715   }
24716   if (mod->ndeps && !bound(mod->deps, mod->ndeps, mod)) {
24717     printk(KERN_ERR
24718            "init_module: mod->deps out of bounds.\n");
24719     goto err2;
24720   }
24721   if (mod->init && !bound(mod->init, 0, mod)) {
24722     printk(KERN_ERR
24723            "init_module: mod->init out of bounds.\n");
24724     goto err2;
24725   }
24726   if (mod->cleanup && !bound(mod->cleanup, 0, mod)) {
24727     printk(KERN_ERR
24728            "init_module: mod->cleanup out of bounds.\n");
24729     goto err2;
24730   }
24731   if (mod->ex_table_start > mod->ex_table_end
24732       || (mod->ex_table_start &&
24733           !((unsigned long)mod->ex_table_start >=
24734             (unsigned long)(mod+1)
24735             && ((unsigned long)mod->ex_table_end
24736                 < (unsigned long)mod + mod->size)))
24737       || (((unsigned long)mod->ex_table_start
24738            - (unsigned long)mod->ex_table_end)
24739           % sizeof(struct exception_table_entry))) {
24740     printk(KERN_ERR
24741            "init_module: mod->ex_table_* invalid.\n");
24742     goto err2;
24743   }
24744   if (mod->flags & ~MOD_AUTOCLEAN) {
24745     printk(KERN_ERR
24746            "init_module: mod->flags invalid.\n");
24747     goto err2;
24748   }
24749 #ifdef __alpha__
24750   if (!bound(mod->gp - 0x8000, 0, mod)) {
24751     printk(KERN_ERR
24752            "init_module: mod->gp out of bounds.\n");
24753     goto err2;
24754   }
24755 #endif
24756   if (mod_member_present(mod, can_unload) &&
24757       mod->can_unload &&
24758       !bound(mod->can_unload, 0, mod)) {
24759     printk(KERN_ERR "init_module: mod->can_unload out "
24760            "of bounds.\n");
24761     goto err2;
24762   }
24763 
24764 #undef bound
24765 
24766   /* Check that the user isn't doing something silly with
24767    * the name.  */
24768 
24769   if ((n_namelen =
24770        get_mod_name(mod->name - (unsigned long) mod
24771                     + (unsigned long) mod_user,
24772                     &n_name)) < 0) {
24773     error = n_namelen;
24774     goto err2;
24775   }
24776   if (namelen != n_namelen ||
24777       strcmp(n_name, mod_tmp.name) != 0) {
24778     printk(KERN_ERR
24779            "init_module: changed module name to "
24780            "`%s' from `%s'\n", n_name, mod_tmp.name);
24781     goto err3;
24782   }
24783 
24784   /* Ok, that's about all the sanity we can stomach; copy
24785    * the rest.  */
24786   if (copy_from_user(mod+1, mod_user+1,
24787                      mod->size - sizeof(*mod))) {
24788     error = -EFAULT;
24789     goto err3;
24790   }
24791 
24792   /* On some machines it is necessary to do something
24793      here to make the I and D caches consistent.  */
24794   flush_icache_range((unsigned long)mod,
24795                      (unsigned long)mod + mod->size);
24796 
24797   /* Update module references.  */
24798   mod->next = mod_tmp.next;
24799   mod->refs = NULL;
24800   for (i = 0, dep = mod->deps; i < mod->ndeps;
24801        ++i, ++dep) {
24802     struct module *o, *d = dep->dep;
24803 
24804     /* Make sure the indicated dependencies are really
24805      * modules.  */
24806     if (d == mod) {
24807       printk(KERN_ERR "init_module: self-referential "
24808           "dependency in mod->deps.\n");
24809       goto err3;
24810     }
24811 
24812     for (o = module_list; o != &kernel_module;
24813          o = o->next)
24814       if (o == d) goto found_dep;
24815 
24816     printk(KERN_ERR
24817            "init_module: found dependency that is "
24818            "(no longer?) a module.\n");
24819     goto err3;
24820 
24821   found_dep:
24822     dep->ref = mod;
24823     dep->next_ref = d->refs;
24824     d->refs = dep;
24825     /* Being referenced by a dependent module counts as a
24826      * use as far as kmod is concerned.  */
24827     d->flags |= MOD_USED_ONCE;
24828   }
24829 
24830   /* Free our temporary memory.  */
24831   put_mod_name(n_name);
24832   put_mod_name(name);
24833 
24834   /* Initialize the module.  */
24835   atomic_set(&mod->uc.usecount,1);
24836   if (mod->init && mod->init() != 0) {
24837     atomic_set(&mod->uc.usecount,0);
24838     error = -EBUSY;
24839     goto err0;
24840   }
24841   atomic_dec(&mod->uc.usecount);
24842 
24843   /* And set it running.  */
24844   mod->flags |= MOD_RUNNING;
24845   error = 0;
24846   goto err0;
24847 
24848 err3:
24849   put_mod_name(n_name);
24850 err2:
24851   *mod = mod_tmp;
24852 err1:
24853   put_mod_name(name);
24854 err0:
24855   unlock_kernel();
24856   return error;
24857 }
24858 
24859 asmlinkage int
24860 sys_delete_module(const char *name_user)
24861 {
24862   struct module *mod, *next;
24863   char *name;
24864   long error = -EPERM;
24865   int something_changed;
24866 
24867   lock_kernel();
24868   if (!capable(CAP_SYS_MODULE))
24869     goto out;
24870 
24871   if (name_user) {
24872     if ((error = get_mod_name(name_user, &name)) < 0)
24873       goto out;
24874     if (error == 0) {
24875       error = -EINVAL;
24876       put_mod_name(name);
24877       goto out;
24878     }
24879     error = -ENOENT;
24880     if ((mod = find_module(name)) == NULL) {
24881       put_mod_name(name);
24882       goto out;
24883     }
24884     put_mod_name(name);
24885     error = -EBUSY;
24886     if (mod->refs != NULL || __MOD_IN_USE(mod))
24887       goto out;
24888 
24889     free_module(mod, 0);
24890     error = 0;
24891     goto out;
24892   }
24893 
24894   /* Do automatic reaping */
24895 restart:
24896   something_changed = 0;
24897   for (mod = module_list; mod != &kernel_module;
24898        mod = next) {
24899     next = mod->next;
24900     if (mod->refs == NULL
24901         && (mod->flags & MOD_AUTOCLEAN)
24902         && (mod->flags & MOD_RUNNING)
24903         && !(mod->flags & MOD_DELETED)
24904         && (mod->flags & MOD_USED_ONCE)
24905         && !__MOD_IN_USE(mod)) {
24906       if ((mod->flags & MOD_VISITED)
24907           && !(mod->flags & MOD_JUST_FREED)) {
24908         mod->flags &= ~MOD_VISITED;
24909       } else {
24910         free_module(mod, 1);
24911         something_changed = 1;
24912       }
24913     }
24914   }
24915   if (something_changed)
24916     goto restart;
24917   for (mod = module_list; mod != &kernel_module;
24918        mod = mod->next)
24919     mod->flags &= ~MOD_JUST_FREED;
24920   error = 0;
24921 out:
24922   unlock_kernel();
24923   return error;
24924 }
24925 
24926 /* Query various bits about modules.  */
24927 
24928 static int
24929 qm_modules(char *buf, size_t bufsize, size_t *ret)
24930 {
24931   struct module *mod;
24932   size_t nmod, space, len;
24933 
24934   nmod = space = 0;
24935 
24936   for (mod = module_list; mod != &kernel_module;
24937        mod = mod->next, ++nmod) {
24938     len = strlen(mod->name)+1;
24939     if (len > bufsize)
24940       goto calc_space_needed;
24941     if (copy_to_user(buf, mod->name, len))
24942       return -EFAULT;
24943     buf += len;
24944     bufsize -= len;
24945     space += len;
24946   }
24947 
24948   if (put_user(nmod, ret))
24949     return -EFAULT;
24950   else
24951     return 0;
24952 
24953 calc_space_needed:
24954   space += len;
24955   while ((mod = mod->next) != &kernel_module)
24956     space += strlen(mod->name)+1;
24957 
24958   if (put_user(space, ret))
24959     return -EFAULT;
24960   else
24961     return -ENOSPC;
24962 }
24963 
24964 static int
24965 qm_deps(struct module *mod, char *buf, size_t bufsize,
24966         size_t *ret)
24967 {
24968   size_t i, space, len;
24969 
24970   if (mod == &kernel_module)
24971     return -EINVAL;
24972   if ((mod->flags & (MOD_RUNNING | MOD_DELETED)) != MOD_
24973       RUNNING)
24974     if (put_user(0, ret))
24975       return -EFAULT;
24976     else
24977       return 0;
24978 
24979   space = 0;
24980   for (i = 0; i < mod->ndeps; ++i) {
24981     const char *dep_name = mod->deps[i].dep->name;
24982 
24983     len = strlen(dep_name)+1;
24984     if (len > bufsize)
24985       goto calc_space_needed;
24986     if (copy_to_user(buf, dep_name, len))
24987       return -EFAULT;
24988     buf += len;
24989     bufsize -= len;
24990     space += len;
24991   }
24992 
24993   if (put_user(i, ret))
24994     return -EFAULT;
24995   else
24996     return 0;
24997 
24998 calc_space_needed:
24999   space += len;
25000   while (++i < mod->ndeps)
25001     space += strlen(mod->deps[i].dep->name)+1;
25002 
25003   if (put_user(space, ret))
25004     return -EFAULT;
25005   else
25006     return -ENOSPC;
25007 }
25008 
25009 static int
25010 qm_refs(struct module *mod, char *buf, size_t bufsize,
25011         size_t *ret)
25012 {
25013   size_t nrefs, space, len;
25014   struct module_ref *ref;
25015 
25016   if (mod == &kernel_module)
25017     return -EINVAL;
25018   if ((mod->flags & (MOD_RUNNING | MOD_DELETED)) !=
25019       MOD_RUNNING)
25020     if (put_user(0, ret))
25021       return -EFAULT;
25022     else
25023       return 0;
25024 
25025   space = 0;
25026   for (nrefs = 0, ref = mod->refs; ref;
25027        ++nrefs, ref = ref->next_ref) {
25028     const char *ref_name = ref->ref->name;
25029 
25030     len = strlen(ref_name)+1;
25031     if (len > bufsize)
25032       goto calc_space_needed;
25033     if (copy_to_user(buf, ref_name, len))
25034       return -EFAULT;
25035     buf += len;
25036     bufsize -= len;
25037     space += len;
25038   }
25039 
25040   if (put_user(nrefs, ret))
25041     return -EFAULT;
25042   else
25043     return 0;
25044 
25045 calc_space_needed:
25046   space += len;
25047   while ((ref = ref->next_ref) != NULL)
25048     space += strlen(ref->ref->name)+1;
25049 
25050   if (put_user(space, ret))
25051     return -EFAULT;
25052   else
25053     return -ENOSPC;
25054 }
25055 
25056 static int
25057 qm_symbols(struct module *mod, char *buf, size_t bufsize,
25058            size_t *ret)
25059 {
25060   size_t i, space, len;
25061   struct module_symbol *s;
25062   char *strings;
25063   unsigned long *vals;
25064 
25065   if ((mod->flags & (MOD_RUNNING | MOD_DELETED)) !=
25066       MOD_RUNNING)
25067     if (put_user(0, ret))
25068       return -EFAULT;
25069     else
25070       return 0;
25071 
25072   space = mod->nsyms * 2*sizeof(void *);
25073 
25074   i = len = 0;
25075   s = mod->syms;
25076 
25077   if (space > bufsize)
25078     goto calc_space_needed;
25079 
25080   if (!access_ok(VERIFY_WRITE, buf, space))
25081     return -EFAULT;
25082 
25083   bufsize -= space;
25084   vals = (unsigned long *)buf;
25085   strings = buf+space;
25086 
25087   for (; i < mod->nsyms ; ++i, ++s, vals += 2) {
25088     len = strlen(s->name)+1;
25089     if (len > bufsize)
25090       goto calc_space_needed;
25091 
25092     if (copy_to_user(strings, s->name, len)
25093         || __put_user(s->value, vals+0)
25094         || __put_user(space, vals+1))
25095       return -EFAULT;
25096 
25097     strings += len;
25098     bufsize -= len;
25099     space += len;
25100   }
25101 
25102   if (put_user(i, ret))
25103     return -EFAULT;
25104   else
25105     return 0;
25106 
25107 calc_space_needed:
25108   for (; i < mod->nsyms; ++i, ++s)
25109     space += strlen(s->name)+1;
25110 
25111   if (put_user(space, ret))
25112     return -EFAULT;
25113   else
25114     return -ENOSPC;
25115 }
25116 
25117 static int
25118 qm_info(struct module *mod, char *buf, size_t bufsize,
25119         size_t *ret)
25120 {
25121   int error = 0;
25122 
25123   if (mod == &kernel_module)
25124     return -EINVAL;
25125 
25126   if (sizeof(struct module_info) <= bufsize) {
25127     struct module_info info;
25128     info.addr = (unsigned long)mod;
25129     info.size = mod->size;
25130     info.flags = mod->flags;
25131     info.usecount = (mod_member_present(mod, can_unload)
25132          && mod->can_unload
25133             ? -1 : atomic_read(&mod->uc.usecount));
25134 
25135     if (copy_to_user(buf, &info,
25136                      sizeof(struct module_info)))
25137       return -EFAULT;
25138   } else
25139     error = -ENOSPC;
25140 
25141   if (put_user(sizeof(struct module_info), ret))
25142     return -EFAULT;
25143 
25144   return error;
25145 }
25146 
25147 asmlinkage int
25148 sys_query_module(const char *name_user, int which,
25149                  char *buf, size_t bufsize, size_t *ret)
25150 {
25151   struct module *mod;
25152   int err;
25153 
25154   lock_kernel();
25155   if (name_user == NULL)
25156     mod = &kernel_module;
25157   else {
25158     long namelen;
25159     char *name;
25160 
25161     if ((namelen = get_mod_name(name_user, &name)) < 0) {
25162       err = namelen;
25163       goto out;
25164     }
25165     err = -ENOENT;
25166     if (namelen == 0)
25167       mod = &kernel_module;
25168     else if ((mod = find_module(name)) == NULL) {
25169       put_mod_name(name);
25170       goto out;
25171     }
25172     put_mod_name(name);
25173   }
25174 
25175   switch (which)
25176   {
25177   case 0:
25178     err = 0;
25179     break;
25180   case QM_MODULES:
25181     err = qm_modules(buf, bufsize, ret);
25182     break;
25183   case QM_DEPS:
25184     err = qm_deps(mod, buf, bufsize, ret);
25185     break;
25186   case QM_REFS:
25187     err = qm_refs(mod, buf, bufsize, ret);
25188     break;
25189   case QM_SYMBOLS:
25190     err = qm_symbols(mod, buf, bufsize, ret);
25191     break;
25192   case QM_INFO:
25193     err = qm_info(mod, buf, bufsize, ret);
25194     break;
25195   default:
25196     err = -EINVAL;
25197     break;
25198   }
25199 out:
25200   unlock_kernel();
25201   return err;
25202 }
25203 
25204 /* Copy the kernel symbol table to user space.  If the
25205  * argument is NULL, just return the size of the table.
25206  *
25207  * This call is obsolete.  New programs should use
25208  * query_module+QM_SYMBOLS which does not arbitrarily
25209  * limit the length of symbols.  */
25210 asmlinkage int
25211 sys_get_kernel_syms(struct kernel_sym *table)
25212 {
25213   struct module *mod;
25214   int i;
25215   struct kernel_sym ksym;
25216 
25217   lock_kernel();
25218   for (mod = module_list, i = 0; mod; mod = mod->next) {
25219     /* include the count for the module name! */
25220     i += mod->nsyms + 1;
25221   }
25222 
25223   if (table == NULL)
25224     goto out;
25225 
25226   /* So that we don't give the user our stack content */
25227   memset (&ksym, 0, sizeof (ksym));
25228 
25229   for (mod = module_list, i = 0; mod; mod = mod->next) {
25230     struct module_symbol *msym;
25231     unsigned int j;
25232 
25233     if ((mod->flags & (MOD_RUNNING|MOD_DELETED)) !=
25234         MOD_RUNNING)
25235       continue;
25236 
25237     /* magic: write module info as a pseudo symbol */
25238     ksym.value = (unsigned long)mod;
25239     ksym.name[0] = '#';
25240     strncpy(ksym.name+1, mod->name, sizeof(ksym.name)-1);
25241     ksym.name[sizeof(ksym.name)-1] = '\0';
25242 
25243     if (copy_to_user(table, &ksym, sizeof(ksym)) != 0)
25244       goto out;
25245     ++i, ++table;
25246 
25247     if (mod->nsyms == 0)
25248       continue;
25249 
25250     for (j = 0, msym = mod->syms; j < mod->nsyms;
25251          ++j, ++msym) {
25252       ksym.value = msym->value;
25253       strncpy(ksym.name, msym->name, sizeof(ksym.name));
25254       ksym.name[sizeof(ksym.name)-1] = '\0';
25255 
25256       if (copy_to_user(table, &ksym, sizeof(ksym)) != 0)
25257         goto out;
25258       ++i, ++table;
25259     }
25260   }
25261 out:
25262   unlock_kernel();
25263   return i;
25264 }
25265 
25266 /* Look for a module by name, ignoring modules marked for
25267  * deletion.  */
25268 static struct module *
25269 find_module(const char *name)
25270 {
25271   struct module *mod;
25272 
25273   for (mod = module_list; mod ; mod = mod->next) {
25274     if (mod->flags & MOD_DELETED)
25275       continue;
25276     if (!strcmp(mod->name, name))
25277       break;
25278   }
25279 
25280   return mod;
25281 }
25282 
25283 /* Free the given module. */
25284 
25285 static void
25286 free_module(struct module *mod, int tag_freed)
25287 {
25288   struct module_ref *dep;
25289   unsigned i;
25290 
25291   /* Let the module clean up.  */
25292 
25293   mod->flags |= MOD_DELETED;
25294   if (mod->flags & MOD_RUNNING)
25295   {
25296     if(mod->cleanup)
25297       mod->cleanup();
25298     mod->flags &= ~MOD_RUNNING;
25299   }
25300 
25301   /* Remove the module from the dependency lists.  */
25302 
25303   for (i = 0, dep = mod->deps; i < mod->ndeps;
25304        ++i, ++dep) {
25305     struct module_ref **pp;
25306     for (pp = &dep->dep->refs; *pp != dep;
25307          pp = &(*pp)->next_ref)
25308       continue;
25309     *pp = dep->next_ref;
25310     if (tag_freed && dep->dep->refs == NULL)
25311       dep->dep->flags |= MOD_JUST_FREED;
25312   }
25313 
25314   /* And from the main module list.  */
25315 
25316   if (mod == module_list) {
25317     module_list = mod->next;
25318   } else {
25319     struct module *p;
25320     for (p = module_list; p->next != mod; p = p->next)
25321       continue;
25322     p->next = mod->next;
25323   }
25324 
25325   /* And free the memory.  */
25326 
25327   module_unmap(mod);
25328 }
25329 
25330 /* Called by the /proc file system to return a current
25331  * list of modules.  */
25332 int get_module_list(char *p)
25333 {
25334   size_t left = PAGE_SIZE;
25335   struct module *mod;
25336   char tmpstr[64];
25337   struct module_ref *ref;
25338 
25339   for (mod = module_list; mod != &kernel_module;
25340        mod = mod->next) {
25341     long len;
25342     const char *q;
25343 
25344 #define safe_copy_str(str, len)                         \
25345     do {                                                \
25346       if (left < len)                                   \
25347         goto fini;                                      \
25348       memcpy(p, str, len); p += len, left -= len;       \
25349     } while (0)
25350 #define safe_copy_cstr(str)                             \
25351     safe_copy_str(str, sizeof(str)-1)
25352 
25353     len = strlen(mod->name);
25354     safe_copy_str(mod->name, len);
25355 
25356     if ((len = 20 - len) > 0) {
25357       if (left < len)
25358         goto fini;
25359       memset(p, ' ', len);
25360       p += len;
25361       left -= len;
25362     }
25363 
25364     len = sprintf(tmpstr, "%8lu", mod->size);
25365     safe_copy_str(tmpstr, len);
25366 
25367     if (mod->flags & MOD_RUNNING) {
25368       len = sprintf(tmpstr, "%4ld",
25369               (mod_member_present(mod, can_unload)
25370                && mod->can_unload
25371                 ? -1L
25372                 : (long)atomic_read(&mod->uc.usecount)));
25373       safe_copy_str(tmpstr, len);
25374     }
25375 
25376     if (mod->flags & MOD_DELETED)
25377       safe_copy_cstr(" (deleted)");
25378     else if (mod->flags & MOD_RUNNING) {
25379       if (mod->flags & MOD_AUTOCLEAN)
25380         safe_copy_cstr(" (autoclean)");
25381       if (!(mod->flags & MOD_USED_ONCE))
25382         safe_copy_cstr(" (unused)");
25383     } else
25384       safe_copy_cstr(" (uninitialized)");
25385 
25386     if ((ref = mod->refs) != NULL) {
25387       safe_copy_cstr(" [");
25388       while (1) {
25389         q = ref->ref->name;
25390         len = strlen(q);
25391         safe_copy_str(q, len);
25392 
25393         if ((ref = ref->next_ref) != NULL)
25394           safe_copy_cstr(" ");
25395         else
25396           break;
25397       }
25398       safe_copy_cstr("]");
25399     }
25400     safe_copy_cstr("\n");
25401 
25402 #undef safe_copy_str
25403 #undef safe_copy_cstr
25404   }
25405 
25406 fini:
25407   return PAGE_SIZE - left;
25408 }
25409 
25410 /* Called by the /proc file system to return a current
25411  * list of ksyms.  */
25412 int
25413 get_ksyms_list(char *buf, char **start, off_t offset,
25414                int length)
25415 {
25416   struct module *mod;
25417   char *p = buf;
25418   int len     = 0;       /* code from  net/ipv4/proc.c */
25419   off_t pos   = 0;
25420   off_t begin = 0;
25421 
25422   for (mod = module_list; mod; mod = mod->next) {
25423     unsigned i;
25424     struct module_symbol *sym;
25425 
25426     if (!(mod->flags & MOD_RUNNING) ||
25427          (mod->flags & MOD_DELETED))
25428       continue;
25429 
25430     for (i = mod->nsyms, sym = mod->syms; i > 0;
25431          --i, ++sym) {
25432       p = buf + len;
25433       if (*mod->name) {
25434         len += sprintf(p, "%0*lx %s\t[%s]\n",
25435                  (int)(2*sizeof(void*)),
25436                  sym->value, sym->name,
25437                  mod->name);
25438       } else {
25439         len += sprintf(p, "%0*lx %s\n",
25440                  (int)(2*sizeof(void*)),
25441                  sym->value, sym->name);
25442       }
25443       pos = begin + len;
25444       if (pos < offset) {
25445         len = 0;
25446         begin = pos;
25447       }
25448       pos = begin + len;
25449       if (pos > offset+length)
25450         goto leave_the_loop;
25451     }
25452   }
25453 leave_the_loop:
25454   *start = buf + (offset - begin);
25455   len -= (offset - begin);
25456   if (len > length)
25457     len = length;
25458   return len;
25459 }
25460 
25461 /* Gets the address for a symbol in the given module.  If
25462  * modname is NULL, it looks for the name in any
25463  * registered symbol table.  If the modname is an empty
25464  * string, it looks for the symbol in kernel exported
25465  * symbol tables.  */
25466 unsigned long
25467 get_module_symbol(char *modname, char *symname)
25468 {
25469   struct module *mp;
25470   struct module_symbol *sym;
25471   int i;
25472 
25473   for (mp = module_list; mp; mp = mp->next) {
25474     if (((modname == NULL) ||
25475          (strcmp(mp->name, modname) == 0)) &&
25476         (mp->flags & (MOD_RUNNING | MOD_DELETED)) ==
25477         MOD_RUNNING && (mp->nsyms > 0)) {
25478       for (i = mp->nsyms, sym = mp->syms;
25479         i > 0; --i, ++sym) {
25480 
25481         if (strcmp(sym->name, symname) == 0) {
25482           return sym->value;
25483         }
25484       }
25485     }
25486   }
25487   return 0;
25488 }
25489 
25490 #else           /* CONFIG_MODULES */
25491 
25492 /* Dummy syscalls for people who don't want modules */
25493 
25494 asmlinkage unsigned long
25495 sys_create_module(const char *name_user, size_t size)
25496 {
25497   return -ENOSYS;
25498 }
25499 
25500 asmlinkage int
25501 sys_init_module(const char *name_user,
25502                 struct module *mod_user)
25503 {
25504   return -ENOSYS;
25505 }
25506 
25507 asmlinkage int
25508 sys_delete_module(const char *name_user)
25509 {
25510   return -ENOSYS;
25511 }
25512 
25513 asmlinkage int
25514 sys_query_module(const char *name_user, int which,
25515                  char *buf, size_t bufsize, size_t *ret)
25516 {
25517   /* Let the program know about the new interface.  Not
25518    * that it'll do them much good.  */
25519   if (which == 0)
25520     return 0;
25521 
25522   return -ENOSYS;
25523 }
25524 
25525 asmlinkage int
25526 sys_get_kernel_syms(struct kernel_sym *table)
25527 {
25528   return -ENOSYS;
25529 }
25530 
25531 #endif  /* CONFIG_MODULES */

netlib.narod.ru< Назад | Оглавление | Далее >

Сайт управляется системой uCoz