#include <linux/config.h>
      #include <linux/mm.h>
      #include <linux/module.h>
      #include <asm/module.h>
      #include <asm/uaccess.h>
      #include <linux/vmalloc.h>
      #include <linux/smp_lock.h>
      #include <asm/pgalloc.h>
      #include <linux/init.h>
      #include <linux/slab.h>
      #include <linux/kmod.h>
      
      /*
       * Originally by Anonymous (as far as I know...)
       * Linux version by Bas Laarhoven <bas@vimec.nl>
       * 0.99.14 version by Jon Tombs <jon@gtex02.us.es>,
       * Heavily modified by Bjorn Ekwall <bj0rn@blox.se> May 1994 (C)
       * Rewritten by Richard Henderson <rth@tamu.edu> Dec 1996
       * Add MOD_INITIALIZING Keith Owens <kaos@ocs.com.au> Nov 1999
       * Add kallsyms support, Keith Owens <kaos@ocs.com.au> Apr 2000
       * Add asm/module support, IA64 has special requirements.  Keith Owens <kaos@ocs.com.au> Sep 2000
       * Fix assorted bugs in module verification.  Keith Owens <kaos@ocs.com.au> Sep 2000
       * Fix sys_init_module race, Andrew Morton <andrewm@uow.edu.au> Oct 2000
       *     http://www.uwsg.iu.edu/hypermail/linux/kernel/0008.3/0379.html
       * Replace xxx_module_symbol with inter_module_xxx.  Keith Owens <kaos@ocs.com.au> Oct 2000
       *
       * This source is covered by the GNU GPL, the same as all kernel sources.
       */
      
      #if defined(CONFIG_MODULES) || defined(CONFIG_KALLSYMS)
      
      extern struct module_symbol __start___ksymtab[];
      extern struct module_symbol __stop___ksymtab[];
      
      extern const struct exception_table_entry __start___ex_table[];
      extern const struct exception_table_entry __stop___ex_table[];
      
      extern const char __start___kallsyms[] __attribute__ ((weak));
      extern const char __stop___kallsyms[] __attribute__ ((weak));
      
      static struct module kernel_module =
      {
      	size_of_struct:		sizeof(struct module),
      	name: 			"",
      	uc:	 		{ATOMIC_INIT(1)},
      	flags:			MOD_RUNNING,
      	syms:			__start___ksymtab,
      	ex_table_start:		__start___ex_table,
      	ex_table_end:		__stop___ex_table,
      	kallsyms_start:		__start___kallsyms,
      	kallsyms_end:		__stop___kallsyms,
      };
      
      struct module *module_list = &kernel_module;
      
      #endif	/* defined(CONFIG_MODULES) || defined(CONFIG_KALLSYMS) */
      
      /* inter_module functions are always available, even when the kernel is
       * compiled without modules.  Consumers of inter_module_xxx routines
       * will always work, even when both are built into the kernel, this
       * approach removes lots of #ifdefs in mainline code.
       */
      
      static struct list_head ime_list = LIST_HEAD_INIT(ime_list);
      static spinlock_t ime_lock = SPIN_LOCK_UNLOCKED;
      static int kmalloc_failed;
      
      /**
       * inter_module_register - register a new set of inter module data.
       * @im_name: an arbitrary string to identify the data, must be unique
       * @owner: module that is registering the data, always use THIS_MODULE
       * @userdata: pointer to arbitrary userdata to be registered
       *
       * Description: Check that the im_name has not already been registered,
       * complain if it has.  For new data, add it to the inter_module_entry
       * list.
       */
  78  void inter_module_register(const char *im_name, struct module *owner, const void *userdata)
      {
      	struct list_head *tmp;
      	struct inter_module_entry *ime, *ime_new;
      
  83  	if (!(ime_new = kmalloc(sizeof(*ime), GFP_KERNEL))) {
      		/* Overloaded kernel, not fatal */
      		printk(KERN_ERR
      			"Aiee, inter_module_register: cannot kmalloc entry for '%s'\n",
      			im_name);
      		kmalloc_failed = 1;
  89  		return;
      	}
      	memset(ime_new, 0, sizeof(*ime_new));
      	ime_new->im_name = im_name;
      	ime_new->owner = owner;
      	ime_new->userdata = userdata;
      
      	spin_lock(&ime_lock);
  97  	list_for_each(tmp, &ime_list) {
      		ime = list_entry(tmp, struct inter_module_entry, list);
  99  		if (strcmp(ime->im_name, im_name) == 0) {
 100  			spin_unlock(&ime_lock);
      			kfree(ime_new);
      			/* Program logic error, fatal */
      			printk(KERN_ERR "inter_module_register: duplicate im_name '%s'", im_name);
 104  			BUG();
      		}
      	}
      	list_add(&(ime_new->list), &ime_list);
 108  	spin_unlock(&ime_lock);
      }
      
      /**
       * inter_module_unregister - unregister a set of inter module data.
       * @im_name: an arbitrary string to identify the data, must be unique
       *
       * Description: Check that the im_name has been registered, complain if
       * it has not.  For existing data, remove it from the
       * inter_module_entry list.
       */
 119  void inter_module_unregister(const char *im_name)
      {
      	struct list_head *tmp;
      	struct inter_module_entry *ime;
      
      	spin_lock(&ime_lock);
 125  	list_for_each(tmp, &ime_list) {
      		ime = list_entry(tmp, struct inter_module_entry, list);
 127  		if (strcmp(ime->im_name, im_name) == 0) {
      			list_del(&(ime->list));
 129  			spin_unlock(&ime_lock);
      			kfree(ime);
 131  			return;
      		}
      	}
 134  	spin_unlock(&ime_lock);
 135  	if (kmalloc_failed) {
      		printk(KERN_ERR
      			"inter_module_unregister: no entry for '%s', "
      			"probably caused by previous kmalloc failure\n",
      			im_name);
 140  		return;
      	}
 142  	else {
      		/* Program logic error, fatal */
      		printk(KERN_ERR "inter_module_unregister: no entry for '%s'", im_name);
 145  		BUG();
      	}
      }
      
      /**
       * inter_module_get - return arbitrary userdata from another module.
       * @im_name: an arbitrary string to identify the data, must be unique
       *
       * Description: If the im_name has not been registered, return NULL.
       * Try to increment the use count on the owning module, if that fails
       * then return NULL.  Otherwise return the userdata.
       */
 157  const void *inter_module_get(const char *im_name)
      {
      	struct list_head *tmp;
      	struct inter_module_entry *ime;
      	const void *result = NULL;
      
      	spin_lock(&ime_lock);
 164  	list_for_each(tmp, &ime_list) {
      		ime = list_entry(tmp, struct inter_module_entry, list);
 166  		if (strcmp(ime->im_name, im_name) == 0) {
 167  			if (try_inc_mod_count(ime->owner))
      				result = ime->userdata;
 169  			break;
      		}
      	}
 172  	spin_unlock(&ime_lock);
 173  	return(result);
      }
      
      /**
       * inter_module_get_request - im get with automatic request_module.
       * @im_name: an arbitrary string to identify the data, must be unique
       * @modname: module that is expected to register im_name
       *
       * Description: If inter_module_get fails, do request_module then retry.
       */
 183  const void *inter_module_get_request(const char *im_name, const char *modname)
      {
      	const void *result = inter_module_get(im_name);
 186  	if (!result) {
      		request_module(modname);
      		result = inter_module_get(im_name);
      	}
 190  	return(result);
      }
      
      /**
       * inter_module_put - release use of data from another module.
       * @im_name: an arbitrary string to identify the data, must be unique
       *
       * Description: If the im_name has not been registered, complain,
       * otherwise decrement the use count on the owning module.
       */
 200  void inter_module_put(const char *im_name)
      {
      	struct list_head *tmp;
      	struct inter_module_entry *ime;
      
      	spin_lock(&ime_lock);
 206  	list_for_each(tmp, &ime_list) {
      		ime = list_entry(tmp, struct inter_module_entry, list);
 208  		if (strcmp(ime->im_name, im_name) == 0) {
 209  			if (ime->owner)
      				__MOD_DEC_USE_COUNT(ime->owner);
 211  			spin_unlock(&ime_lock);
 212  			return;
      		}
      	}
 215  	spin_unlock(&ime_lock);
      	printk(KERN_ERR "inter_module_put: no entry for '%s'", im_name);
 217  	BUG();
      }
      
      
      #if defined(CONFIG_MODULES)	/* The rest of the source */
      
      static long get_mod_name(const char *user_name, char **buf);
      static void put_mod_name(char *buf);
      struct module *find_module(const char *name);
      void free_module(struct module *, int tag_freed);
      
      
      /*
       * Called at boot time
       */
      
 233  void __init init_modules(void)
      {
      	kernel_module.nsyms = __stop___ksymtab - __start___ksymtab;
      
      #ifdef __alpha__
      	__asm__("stq $29,%0" : "=m"(kernel_module.gp));
      #endif
      }
      
      /*
       * Copy the name of a module from user space.
       */
      
      static inline long
 247  get_mod_name(const char *user_name, char **buf)
      {
      	unsigned long page;
      	long retval;
      
      	page = __get_free_page(GFP_KERNEL);
 253  	if (!page)
 254  		return -ENOMEM;
      
      	retval = strncpy_from_user((char *)page, user_name, PAGE_SIZE);
 257  	if (retval > 0) {
 258  		if (retval < PAGE_SIZE) {
      			*buf = (char *)page;
 260  			return retval;
      		}
      		retval = -ENAMETOOLONG;
 263  	} else if (!retval)
      		retval = -EINVAL;
      
      	free_page(page);
 267  	return retval;
      }
      
      static inline void
 271  put_mod_name(char *buf)
      {
      	free_page((unsigned long)buf);
      }
      
      /*
       * Allocate space for a module.
       */
      
      asmlinkage unsigned long
 281  sys_create_module(const char *name_user, size_t size)
      {
      	char *name;
      	long namelen, error;
      	struct module *mod;
      
 287  	if (!capable(CAP_SYS_MODULE))
 288  		return -EPERM;
 289  	lock_kernel();
 290  	if ((namelen = get_mod_name(name_user, &name)) < 0) {
      		error = namelen;
 292  		goto err0;
      	}
 294  	if (size < sizeof(struct module)+namelen) {
      		error = -EINVAL;
 296  		goto err1;
      	}
 298  	if (find_module(name) != NULL) {
      		error = -EEXIST;
 300  		goto err1;
      	}
 302  	if ((mod = (struct module *)module_map(size)) == NULL) {
      		error = -ENOMEM;
 304  		goto err1;
      	}
      
      	memset(mod, 0, sizeof(*mod));
      	mod->size_of_struct = sizeof(*mod);
      	mod->next = module_list;
      	mod->name = (char *)(mod + 1);
      	mod->size = size;
      	memcpy((char*)(mod+1), name, namelen+1);
      
      	put_mod_name(name);
      
      	module_list = mod;	/* link it in */
      
      	error = (long) mod;
 319  	goto err0;
      err1:
      	put_mod_name(name);
      err0:
 323  	unlock_kernel();
 324  	return error;
      }
      
      /*
       * Initialize a module.
       */
      
      asmlinkage long
 332  sys_init_module(const char *name_user, struct module *mod_user)
      {
      	struct module mod_tmp, *mod;
      	char *name, *n_name, *name_tmp = NULL;
      	long namelen, n_namelen, i, error;
      	unsigned long mod_user_size;
      	struct module_ref *dep;
      
 340  	if (!capable(CAP_SYS_MODULE))
 341  		return -EPERM;
 342  	lock_kernel();
 343  	if ((namelen = get_mod_name(name_user, &name)) < 0) {
      		error = namelen;
 345  		goto err0;
      	}
 347  	if ((mod = find_module(name)) == NULL) {
      		error = -ENOENT;
 349  		goto err1;
      	}
      
      	/* Check module header size.  We allow a bit of slop over the
      	   size we are familiar with to cope with a version of insmod
      	   for a newer kernel.  But don't over do it. */
 355  	if ((error = get_user(mod_user_size, &mod_user->size_of_struct)) != 0)
 356  		goto err1;
      	if (mod_user_size < (unsigned long)&((struct module *)0L)->persist_start
 358  	    || mod_user_size > sizeof(struct module) + 16*sizeof(void*)) {
      		printk(KERN_ERR "init_module: Invalid module header size.\n"
      		       KERN_ERR "A new version of the modutils is likely "
      				"needed.\n");
      		error = -EINVAL;
 363  		goto err1;
      	}
      
      	/* Hold the current contents while we play with the user's idea
      	   of righteousness.  */
      	mod_tmp = *mod;
      	name_tmp = kmalloc(strlen(mod->name) + 1, GFP_KERNEL);	/* Where's kstrdup()? */
 370  	if (name_tmp == NULL) {
      		error = -ENOMEM;
 372  		goto err1;
      	}
      	strcpy(name_tmp, mod->name);
      
      	error = copy_from_user(mod, mod_user, mod_user_size);
 377  	if (error) {
      		error = -EFAULT;
 379  		goto err2;
      	}
      
      	/* Sanity check the size of the module.  */
      	error = -EINVAL;
      
 385  	if (mod->size > mod_tmp.size) {
      		printk(KERN_ERR "init_module: Size of initialized module "
      				"exceeds size of created module.\n");
 388  		goto err2;
      	}
      
      	/* Make sure all interesting pointers are sane.  */
      
 393  	if (!mod_bound(mod->name, namelen, mod)) {
      		printk(KERN_ERR "init_module: mod->name out of bounds.\n");
 395  		goto err2;
      	}
 397  	if (mod->nsyms && !mod_bound(mod->syms, mod->nsyms, mod)) {
      		printk(KERN_ERR "init_module: mod->syms out of bounds.\n");
 399  		goto err2;
      	}
 401  	if (mod->ndeps && !mod_bound(mod->deps, mod->ndeps, mod)) {
      		printk(KERN_ERR "init_module: mod->deps out of bounds.\n");
 403  		goto err2;
      	}
 405  	if (mod->init && !mod_bound(mod->init, 0, mod)) {
      		printk(KERN_ERR "init_module: mod->init out of bounds.\n");
 407  		goto err2;
      	}
 409  	if (mod->cleanup && !mod_bound(mod->cleanup, 0, mod)) {
      		printk(KERN_ERR "init_module: mod->cleanup out of bounds.\n");
 411  		goto err2;
      	}
      	if (mod->ex_table_start > mod->ex_table_end
      	    || (mod->ex_table_start &&
      		!((unsigned long)mod->ex_table_start >= ((unsigned long)mod + mod->size_of_struct)
      		  && ((unsigned long)mod->ex_table_end
      		      < (unsigned long)mod + mod->size)))
      	    || (((unsigned long)mod->ex_table_start
      		 - (unsigned long)mod->ex_table_end)
 420  		% sizeof(struct exception_table_entry))) {
      		printk(KERN_ERR "init_module: mod->ex_table_* invalid.\n");
 422  		goto err2;
      	}
 424  	if (mod->flags & ~MOD_AUTOCLEAN) {
      		printk(KERN_ERR "init_module: mod->flags invalid.\n");
 426  		goto err2;
      	}
      #ifdef __alpha__
      	if (!mod_bound(mod->gp - 0x8000, 0, mod)) {
      		printk(KERN_ERR "init_module: mod->gp out of bounds.\n");
      		goto err2;
      	}
      #endif
      	if (mod_member_present(mod, can_unload)
 435  	    && mod->can_unload && !mod_bound(mod->can_unload, 0, mod)) {
      		printk(KERN_ERR "init_module: mod->can_unload out of bounds.\n");
 437  		goto err2;
      	}
 439  	if (mod_member_present(mod, kallsyms_end)) {
      	    if (mod->kallsyms_end &&
      		(!mod_bound(mod->kallsyms_start, 0, mod) ||
 442  		 !mod_bound(mod->kallsyms_end, 0, mod))) {
      		printk(KERN_ERR "init_module: mod->kallsyms out of bounds.\n");
 444  		goto err2;
      	    }
 446  	    if (mod->kallsyms_start > mod->kallsyms_end) {
      		printk(KERN_ERR "init_module: mod->kallsyms invalid.\n");
 448  		goto err2;
      	    }
      	}
 451  	if (mod_member_present(mod, archdata_end)) {
      	    if (mod->archdata_end &&
      		(!mod_bound(mod->archdata_start, 0, mod) ||
 454  		 !mod_bound(mod->archdata_end, 0, mod))) {
      		printk(KERN_ERR "init_module: mod->archdata out of bounds.\n");
 456  		goto err2;
      	    }
 458  	    if (mod->archdata_start > mod->archdata_end) {
      		printk(KERN_ERR "init_module: mod->archdata invalid.\n");
 460  		goto err2;
      	    }
      	}
 463  	if (mod_member_present(mod, kernel_data) && mod->kernel_data) {
      	    printk(KERN_ERR "init_module: mod->kernel_data must be zero.\n");
 465  	    goto err2;
      	}
      
      	/* Check that the user isn't doing something silly with the name.  */
      
      	if ((n_namelen = get_mod_name(mod->name - (unsigned long)mod
      				      + (unsigned long)mod_user,
 472  				      &n_name)) < 0) {
      		printk(KERN_ERR "init_module: get_mod_name failure.\n");
      		error = n_namelen;
 475  		goto err2;
      	}
 477  	if (namelen != n_namelen || strcmp(n_name, mod_tmp.name) != 0) {
      		printk(KERN_ERR "init_module: changed module name to "
      				"`%s' from `%s'\n",
      		       n_name, mod_tmp.name);
 481  		goto err3;
      	}
      
      	/* Ok, that's about all the sanity we can stomach; copy the rest.  */
      
      	if (copy_from_user((char *)mod+mod_user_size,
      			   (char *)mod_user+mod_user_size,
 488  			   mod->size-mod_user_size)) {
      		error = -EFAULT;
 490  		goto err3;
      	}
      
 493  	if (module_arch_init(mod))
 494  		goto err3;
      
      	/* On some machines it is necessary to do something here
      	   to make the I and D caches consistent.  */
 498  	flush_icache_range((unsigned long)mod, (unsigned long)mod + mod->size);
      
      	mod->next = mod_tmp.next;
      	mod->refs = NULL;
      
      	/* Sanity check the module's dependents */
 504  	for (i = 0, dep = mod->deps; i < mod->ndeps; ++i, ++dep) {
      		struct module *o, *d = dep->dep;
      
      		/* Make sure the indicated dependencies are really modules.  */
 508  		if (d == mod) {
      			printk(KERN_ERR "init_module: self-referential "
      					"dependency in mod->deps.\n");
 511  			goto err3;
      		}
      
      		/* Scan the current modules for this dependency */
 515  		for (o = module_list; o != &kernel_module && o != d; o = o->next)
      			;
      
 518  		if (o != d) {
      			printk(KERN_ERR "init_module: found dependency that is "
      				"(no longer?) a module.\n");
 521  			goto err3;
      		}
      	}
      
      	/* Update module references.  */
 526  	for (i = 0, dep = mod->deps; i < mod->ndeps; ++i, ++dep) {
      		struct module *d = dep->dep;
      
      		dep->ref = mod;
      		dep->next_ref = d->refs;
      		d->refs = dep;
      		/* Being referenced by a dependent module counts as a
      		   use as far as kmod is concerned.  */
      		d->flags |= MOD_USED_ONCE;
      	}
      
      	/* Free our temporary memory.  */
      	put_mod_name(n_name);
      	put_mod_name(name);
      
      	/* Initialize the module.  */
      	mod->flags |= MOD_INITIALIZING;
      	atomic_set(&mod->uc.usecount,1);
 544  	if (mod->init && (error = mod->init()) != 0) {
      		atomic_set(&mod->uc.usecount,0);
      		mod->flags &= ~MOD_INITIALIZING;
 547  		if (error > 0)	/* Buggy module */
      			error = -EBUSY;
 549  		goto err0;
      	}
      	atomic_dec(&mod->uc.usecount);
      
      	/* And set it running.  */
      	mod->flags = (mod->flags | MOD_RUNNING) & ~MOD_INITIALIZING;
      	error = 0;
 556  	goto err0;
      
      err3:
      	put_mod_name(n_name);
      err2:
      	*mod = mod_tmp;
      	strcpy((char *)mod->name, name_tmp);	/* We know there is room for this */
      err1:
      	put_mod_name(name);
      err0:
 566  	unlock_kernel();
      	kfree(name_tmp);
 568  	return error;
      }
      
      static spinlock_t unload_lock = SPIN_LOCK_UNLOCKED;
 572  int try_inc_mod_count(struct module *mod)
      {
      	int res = 1;
 575  	if (mod) {
      		spin_lock(&unload_lock);
 577  		if (mod->flags & MOD_DELETED)
      			res = 0;
 579  		else
      			__MOD_INC_USE_COUNT(mod);
 581  		spin_unlock(&unload_lock);
      	}
 583  	return res;
      }
      
      asmlinkage long
 587  sys_delete_module(const char *name_user)
      {
      	struct module *mod, *next;
      	char *name;
      	long error;
      	int something_changed;
      
 594  	if (!capable(CAP_SYS_MODULE))
 595  		return -EPERM;
      
 597  	lock_kernel();
 598  	if (name_user) {
 599  		if ((error = get_mod_name(name_user, &name)) < 0)
 600  			goto out;
 601  		if (error == 0) {
      			error = -EINVAL;
      			put_mod_name(name);
 604  			goto out;
      		}
      		error = -ENOENT;
 607  		if ((mod = find_module(name)) == NULL) {
      			put_mod_name(name);
 609  			goto out;
      		}
      		put_mod_name(name);
      		error = -EBUSY;
 613  		if (mod->refs != NULL)
 614  			goto out;
      
      		spin_lock(&unload_lock);
 617  		if (!__MOD_IN_USE(mod)) {
      			mod->flags |= MOD_DELETED;
 619  			spin_unlock(&unload_lock);
      			free_module(mod, 0);
      			error = 0;
 622  		} else {
 623  			spin_unlock(&unload_lock);
      		}
 625  		goto out;
      	}
      
      	/* Do automatic reaping */
      restart:
      	something_changed = 0;
 631  	for (mod = module_list; mod != &kernel_module; mod = next) {
      		next = mod->next;
      		spin_lock(&unload_lock);
      		if (mod->refs == NULL
      		    && (mod->flags & MOD_AUTOCLEAN)
      		    && (mod->flags & MOD_RUNNING)
      		    && !(mod->flags & MOD_DELETED)
      		    && (mod->flags & MOD_USED_ONCE)
 639  		    && !__MOD_IN_USE(mod)) {
      			if ((mod->flags & MOD_VISITED)
 641  			    && !(mod->flags & MOD_JUST_FREED)) {
 642  				spin_unlock(&unload_lock);
      				mod->flags &= ~MOD_VISITED;
 644  			} else {
      				mod->flags |= MOD_DELETED;
 646  				spin_unlock(&unload_lock);
      				free_module(mod, 1);
      				something_changed = 1;
      			}
 650  		} else {
 651  			spin_unlock(&unload_lock);
      		}
      	}
 654  	if (something_changed)
 655  		goto restart;
 656  	for (mod = module_list; mod != &kernel_module; mod = mod->next)
      		mod->flags &= ~MOD_JUST_FREED;
      	error = 0;
      out:
 660  	unlock_kernel();
 661  	return error;
      }
      
      /* Query various bits about modules.  */
      
      static int
 667  qm_modules(char *buf, size_t bufsize, size_t *ret)
      {
      	struct module *mod;
      	size_t nmod, space, len;
      
      	nmod = space = 0;
      
 674  	for (mod=module_list; mod != &kernel_module; mod=mod->next, ++nmod) {
      		len = strlen(mod->name)+1;
 676  		if (len > bufsize)
 677  			goto calc_space_needed;
 678  		if (copy_to_user(buf, mod->name, len))
 679  			return -EFAULT;
      		buf += len;
      		bufsize -= len;
      		space += len;
      	}
      
 685  	if (put_user(nmod, ret))
 686  		return -EFAULT;
 687  	else
 688  		return 0;
      
      calc_space_needed:
      	space += len;
 692  	while ((mod = mod->next) != &kernel_module)
      		space += strlen(mod->name)+1;
      
 695  	if (put_user(space, ret))
 696  		return -EFAULT;
 697  	else
 698  		return -ENOSPC;
      }
      
      static int
 702  qm_deps(struct module *mod, char *buf, size_t bufsize, size_t *ret)
      {
      	size_t i, space, len;
      
 706  	if (mod == &kernel_module)
 707  		return -EINVAL;
 708  	if (!MOD_CAN_QUERY(mod))
 709  		if (put_user(0, ret))
 710  			return -EFAULT;
 711  		else
 712  			return 0;
      
      	space = 0;
 715  	for (i = 0; i < mod->ndeps; ++i) {
      		const char *dep_name = mod->deps[i].dep->name;
      
      		len = strlen(dep_name)+1;
 719  		if (len > bufsize)
 720  			goto calc_space_needed;
 721  		if (copy_to_user(buf, dep_name, len))
 722  			return -EFAULT;
      		buf += len;
      		bufsize -= len;
      		space += len;
      	}
      
 728  	if (put_user(i, ret))
 729  		return -EFAULT;
 730  	else
 731  		return 0;
      
      calc_space_needed:
      	space += len;
 735  	while (++i < mod->ndeps)
      		space += strlen(mod->deps[i].dep->name)+1;
      
 738  	if (put_user(space, ret))
 739  		return -EFAULT;
 740  	else
 741  		return -ENOSPC;
      }
      
      static int
 745  qm_refs(struct module *mod, char *buf, size_t bufsize, size_t *ret)
      {
      	size_t nrefs, space, len;
      	struct module_ref *ref;
      
 750  	if (mod == &kernel_module)
 751  		return -EINVAL;
 752  	if (!MOD_CAN_QUERY(mod))
 753  		if (put_user(0, ret))
 754  			return -EFAULT;
 755  		else
 756  			return 0;
      
      	space = 0;
 759  	for (nrefs = 0, ref = mod->refs; ref ; ++nrefs, ref = ref->next_ref) {
      		const char *ref_name = ref->ref->name;
      
      		len = strlen(ref_name)+1;
 763  		if (len > bufsize)
 764  			goto calc_space_needed;
 765  		if (copy_to_user(buf, ref_name, len))
 766  			return -EFAULT;
      		buf += len;
      		bufsize -= len;
      		space += len;
      	}
      
 772  	if (put_user(nrefs, ret))
 773  		return -EFAULT;
 774  	else
 775  		return 0;
      
      calc_space_needed:
      	space += len;
 779  	while ((ref = ref->next_ref) != NULL)
      		space += strlen(ref->ref->name)+1;
      
 782  	if (put_user(space, ret))
 783  		return -EFAULT;
 784  	else
 785  		return -ENOSPC;
      }
      
      static int
 789  qm_symbols(struct module *mod, char *buf, size_t bufsize, size_t *ret)
      {
      	size_t i, space, len;
      	struct module_symbol *s;
      	char *strings;
      	unsigned long *vals;
      
 796  	if (!MOD_CAN_QUERY(mod))
 797  		if (put_user(0, ret))
 798  			return -EFAULT;
 799  		else
 800  			return 0;
      
      	space = mod->nsyms * 2*sizeof(void *);
      
      	i = len = 0;
      	s = mod->syms;
      
 807  	if (space > bufsize)
 808  		goto calc_space_needed;
      
 810  	if (!access_ok(VERIFY_WRITE, buf, space))
 811  		return -EFAULT;
      
      	bufsize -= space;
      	vals = (unsigned long *)buf;
      	strings = buf+space;
      
 817  	for (; i < mod->nsyms ; ++i, ++s, vals += 2) {
      		len = strlen(s->name)+1;
 819  		if (len > bufsize)
 820  			goto calc_space_needed;
      
      		if (copy_to_user(strings, s->name, len)
      		    || __put_user(s->value, vals+0)
 824  		    || __put_user(space, vals+1))
 825  			return -EFAULT;
      
      		strings += len;
      		bufsize -= len;
      		space += len;
      	}
      
 832  	if (put_user(i, ret))
 833  		return -EFAULT;
 834  	else
 835  		return 0;
      
      calc_space_needed:
 838  	for (; i < mod->nsyms; ++i, ++s)
      		space += strlen(s->name)+1;
      
 841  	if (put_user(space, ret))
 842  		return -EFAULT;
 843  	else
 844  		return -ENOSPC;
      }
      
      static int
 848  qm_info(struct module *mod, char *buf, size_t bufsize, size_t *ret)
      {
      	int error = 0;
      
 852  	if (mod == &kernel_module)
 853  		return -EINVAL;
      
 855  	if (sizeof(struct module_info) <= bufsize) {
      		struct module_info info;
      		info.addr = (unsigned long)mod;
      		info.size = mod->size;
      		info.flags = mod->flags;
      		info.usecount = (mod_member_present(mod, can_unload)
      				 && mod->can_unload ? -1 : atomic_read(&mod->uc.usecount));
      
 863  		if (copy_to_user(buf, &info, sizeof(struct module_info)))
 864  			return -EFAULT;
 865  	} else
      		error = -ENOSPC;
      
 868  	if (put_user(sizeof(struct module_info), ret))
 869  		return -EFAULT;
      
 871  	return error;
      }
      
      asmlinkage long
 875  sys_query_module(const char *name_user, int which, char *buf, size_t bufsize,
      		 size_t *ret)
      {
      	struct module *mod;
      	int err;
      
 881  	lock_kernel();
 882  	if (name_user == NULL)
      		mod = &kernel_module;
 884  	else {
      		long namelen;
      		char *name;
      
 888  		if ((namelen = get_mod_name(name_user, &name)) < 0) {
      			err = namelen;
 890  			goto out;
      		}
      		err = -ENOENT;
 893  		if (namelen == 0)
      			mod = &kernel_module;
 895  		else if ((mod = find_module(name)) == NULL) {
      			put_mod_name(name);
 897  			goto out;
      		}
      		put_mod_name(name);
      	}
      
 902  	switch (which)
      	{
 904  	case 0:
      		err = 0;
 906  		break;
 907  	case QM_MODULES:
      		err = qm_modules(buf, bufsize, ret);
 909  		break;
 910  	case QM_DEPS:
      		err = qm_deps(mod, buf, bufsize, ret);
 912  		break;
 913  	case QM_REFS:
      		err = qm_refs(mod, buf, bufsize, ret);
 915  		break;
 916  	case QM_SYMBOLS:
      		err = qm_symbols(mod, buf, bufsize, ret);
 918  		break;
 919  	case QM_INFO:
      		err = qm_info(mod, buf, bufsize, ret);
 921  		break;
 922  	default:
      		err = -EINVAL;
 924  		break;
      	}
      out:
 927  	unlock_kernel();
 928  	return err;
      }
      
      /*
       * Copy the kernel symbol table to user space.  If the argument is
       * NULL, just return the size of the table.
       *
       * This call is obsolete.  New programs should use query_module+QM_SYMBOLS
       * which does not arbitrarily limit the length of symbols.
       */
      
      asmlinkage long
 940  sys_get_kernel_syms(struct kernel_sym *table)
      {
      	struct module *mod;
      	int i;
      	struct kernel_sym ksym;
      
 946  	lock_kernel();
 947  	for (mod = module_list, i = 0; mod; mod = mod->next) {
      		/* include the count for the module name! */
      		i += mod->nsyms + 1;
      	}
      
 952  	if (table == NULL)
 953  		goto out;
      
      	/* So that we don't give the user our stack content */
      	memset (&ksym, 0, sizeof (ksym));
      
 958  	for (mod = module_list, i = 0; mod; mod = mod->next) {
      		struct module_symbol *msym;
      		unsigned int j;
      
 962  		if (!MOD_CAN_QUERY(mod))
 963  			continue;
      
      		/* magic: write module info as a pseudo symbol */
      		ksym.value = (unsigned long)mod;
      		ksym.name[0] = '#';
      		strncpy(ksym.name+1, mod->name, sizeof(ksym.name)-1);
      		ksym.name[sizeof(ksym.name)-1] = '\0';
      
 971  		if (copy_to_user(table, &ksym, sizeof(ksym)) != 0)
 972  			goto out;
      		++i, ++table;
      
 975  		if (mod->nsyms == 0)
 976  			continue;
      
 978  		for (j = 0, msym = mod->syms; j < mod->nsyms; ++j, ++msym) {
      			ksym.value = msym->value;
      			strncpy(ksym.name, msym->name, sizeof(ksym.name));
      			ksym.name[sizeof(ksym.name)-1] = '\0';
      
 983  			if (copy_to_user(table, &ksym, sizeof(ksym)) != 0)
 984  				goto out;
      			++i, ++table;
      		}
      	}
      out:
 989  	unlock_kernel();
 990  	return i;
      }
      
      /*
       * Look for a module by name, ignoring modules marked for deletion.
       */
      
      struct module *
 998  find_module(const char *name)
      {
      	struct module *mod;
      
1002  	for (mod = module_list; mod ; mod = mod->next) {
1003  		if (mod->flags & MOD_DELETED)
1004  			continue;
1005  		if (!strcmp(mod->name, name))
1006  			break;
      	}
      
1009  	return mod;
      }
      
      /*
       * Free the given module.
       */
      
      void
1017  free_module(struct module *mod, int tag_freed)
      {
      	struct module_ref *dep;
      	unsigned i;
      
      	/* Let the module clean up.  */
      
1024  	if (mod->flags & MOD_RUNNING)
      	{
1026  		if(mod->cleanup)
      			mod->cleanup();
      		mod->flags &= ~MOD_RUNNING;
      	}
      
      	/* Remove the module from the dependency lists.  */
      
1033  	for (i = 0, dep = mod->deps; i < mod->ndeps; ++i, ++dep) {
      		struct module_ref **pp;
1035  		for (pp = &dep->dep->refs; *pp != dep; pp = &(*pp)->next_ref)
1036  			continue;
      		*pp = dep->next_ref;
1038  		if (tag_freed && dep->dep->refs == NULL)
      			dep->dep->flags |= MOD_JUST_FREED;
      	}
      
      	/* And from the main module list.  */
      
1044  	if (mod == module_list) {
      		module_list = mod->next;
1046  	} else {
      		struct module *p;
1048  		for (p = module_list; p->next != mod; p = p->next)
1049  			continue;
      		p->next = mod->next;
      	}
      
      	/* And free the memory.  */
      
      	module_unmap(mod);
      }
      
      /*
       * Called by the /proc file system to return a current list of modules.
       */
      
1062  int get_module_list(char *p)
      {
      	size_t left = PAGE_SIZE;
      	struct module *mod;
      	char tmpstr[64];
      	struct module_ref *ref;
      
1069  	for (mod = module_list; mod != &kernel_module; mod = mod->next) {
      		long len;
      		const char *q;
      
      #define safe_copy_str(str, len)						\
      		do {							\
      			if (left < len)					\
      				goto fini;				\
      			memcpy(p, str, len); p += len, left -= len;	\
      		} while (0)
      #define safe_copy_cstr(str)	safe_copy_str(str, sizeof(str)-1)
      
      		len = strlen(mod->name);
1082  		safe_copy_str(mod->name, len);
      
1084  		if ((len = 20 - len) > 0) {
1085  			if (left < len)
1086  				goto fini;
      			memset(p, ' ', len);
      			p += len;
      			left -= len;
      		}
      
      		len = sprintf(tmpstr, "%8lu", mod->size);
1093  		safe_copy_str(tmpstr, len);
      
1095  		if (mod->flags & MOD_RUNNING) {
      			len = sprintf(tmpstr, "%4ld",
      				      (mod_member_present(mod, can_unload)
      				       && mod->can_unload
      				       ? -1L : (long)atomic_read(&mod->uc.usecount)));
1100  			safe_copy_str(tmpstr, len);
      		}
      
1103  		if (mod->flags & MOD_DELETED)
1104  			safe_copy_cstr(" (deleted)");
1105  		else if (mod->flags & MOD_RUNNING) {
1106  			if (mod->flags & MOD_AUTOCLEAN)
1107  				safe_copy_cstr(" (autoclean)");
1108  			if (!(mod->flags & MOD_USED_ONCE))
1109  				safe_copy_cstr(" (unused)");
      		}
1111  		else if (mod->flags & MOD_INITIALIZING)
1112  			safe_copy_cstr(" (initializing)");
1113  		else
1114  			safe_copy_cstr(" (uninitialized)");
      
1116  		if ((ref = mod->refs) != NULL) {
1117  			safe_copy_cstr(" [");
1118  			while (1) {
      				q = ref->ref->name;
      				len = strlen(q);
1121  				safe_copy_str(q, len);
      
1123  				if ((ref = ref->next_ref) != NULL)
1124  					safe_copy_cstr(" ");
1125  				else
1126  					break;
      			}
1128  			safe_copy_cstr("]");
      		}
1130  		safe_copy_cstr("\n");
      
      #undef safe_copy_str
      #undef safe_copy_cstr
      	}
      
      fini:
1137  	return PAGE_SIZE - left;
      }
      
      /*
       * Called by the /proc file system to return a current list of ksyms.
       */
      
      int
1145  get_ksyms_list(char *buf, char **start, off_t offset, int length)
      {
      	struct module *mod;
      	char *p = buf;
      	int len     = 0;	/* code from  net/ipv4/proc.c */
      	off_t pos   = 0;
      	off_t begin = 0;
      
1153  	for (mod = module_list; mod; mod = mod->next) {
      		unsigned i;
      		struct module_symbol *sym;
      
1157  		if (!MOD_CAN_QUERY(mod))
1158  			continue;
      
1160  		for (i = mod->nsyms, sym = mod->syms; i > 0; --i, ++sym) {
      			p = buf + len;
1162  			if (*mod->name) {
      				len += sprintf(p, "%0*lx %s\t[%s]\n",
      					       (int)(2*sizeof(void*)),
      					       sym->value, sym->name,
      					       mod->name);
1167  			} else {
      				len += sprintf(p, "%0*lx %s\n",
      					       (int)(2*sizeof(void*)),
      					       sym->value, sym->name);
      			}
      			pos = begin + len;
1173  			if (pos < offset) {
      				len = 0;
      				begin = pos;
      			}
      			pos = begin + len;
1178  			if (pos > offset+length)
1179  				goto leave_the_loop;
      		}
      	}
      leave_the_loop:
      	*start = buf + (offset - begin);
      	len -= (offset - begin);
1185  	if (len > length)
      		len = length;
1187  	return len;
      }
      
      #else		/* CONFIG_MODULES */
      
      /* Dummy syscalls for people who don't want modules */
      
      asmlinkage unsigned long
      sys_create_module(const char *name_user, size_t size)
      {
      	return -ENOSYS;
      }
      
      asmlinkage long
      sys_init_module(const char *name_user, struct module *mod_user)
      {
      	return -ENOSYS;
      }
      
      asmlinkage long
      sys_delete_module(const char *name_user)
      {
      	return -ENOSYS;
      }
      
      asmlinkage long
      sys_query_module(const char *name_user, int which, char *buf, size_t bufsize,
      		 size_t *ret)
      {
      	/* Let the program know about the new interface.  Not that
      	   it'll do them much good.  */
      	if (which == 0)
      		return 0;
      
      	return -ENOSYS;
      }
      
      asmlinkage long
      sys_get_kernel_syms(struct kernel_sym *table)
      {
      	return -ENOSYS;
      }
      
      int try_inc_mod_count(struct module *mod)
      {
      	return 1;
      }
      
      #endif	/* CONFIG_MODULES */