The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kernel/kmod.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2         kmod, the new module loader (replaces kerneld)
    3         Kirk Petersen
    4 
    5         Reorganized not to be a daemon by Adam Richter, with guidance
    6         from Greg Zornetzer.
    7 
    8         Modified to avoid chroot and file sharing problems.
    9         Mikael Pettersson
   10 
   11         Limit the concurrent number of kmod modprobes to catch loops from
   12         "modprobe needs a service that is in a module".
   13         Keith Owens <kaos@ocs.com.au> December 1999
   14 
   15         Unblock all signals when we exec a usermode process.
   16         Shuu Yamaguchi <shuu@wondernetworkresources.com> December 2000
   17 */
   18 
   19 #define __KERNEL_SYSCALLS__
   20 
   21 #include <linux/config.h>
   22 #include <linux/module.h>
   23 #include <linux/sched.h>
   24 #include <linux/unistd.h>
   25 #include <linux/kmod.h>
   26 #include <linux/smp_lock.h>
   27 #include <linux/slab.h>
   28 #include <linux/namespace.h>
   29 #include <linux/completion.h>
   30 
   31 #include <asm/uaccess.h>
   32 
   33 extern int max_threads;
   34 
   35 static inline void
   36 use_init_fs_context(void)
   37 {
   38         struct fs_struct *our_fs, *init_fs;
   39         struct dentry *root, *pwd;
   40         struct vfsmount *rootmnt, *pwdmnt;
   41         struct namespace *our_ns, *init_ns;
   42 
   43         /*
   44          * Make modprobe's fs context be a copy of init's.
   45          *
   46          * We cannot use the user's fs context, because it
   47          * may have a different root than init.
   48          * Since init was created with CLONE_FS, we can grab
   49          * its fs context from "init_task".
   50          *
   51          * The fs context has to be a copy. If it is shared
   52          * with init, then any chdir() call in modprobe will
   53          * also affect init and the other threads sharing
   54          * init_task's fs context.
   55          *
   56          * We created the exec_modprobe thread without CLONE_FS,
   57          * so we can update the fields in our fs context freely.
   58          */
   59 
   60         init_fs = init_task.fs;
   61         init_ns = init_task.namespace;
   62         get_namespace(init_ns);
   63         our_ns = current->namespace;
   64         current->namespace = init_ns;
   65         put_namespace(our_ns);
   66         read_lock(&init_fs->lock);
   67         rootmnt = mntget(init_fs->rootmnt);
   68         root = dget(init_fs->root);
   69         pwdmnt = mntget(init_fs->pwdmnt);
   70         pwd = dget(init_fs->pwd);
   71         read_unlock(&init_fs->lock);
   72 
   73         /* FIXME - unsafe ->fs access */
   74         our_fs = current->fs;
   75         our_fs->umask = init_fs->umask;
   76         set_fs_root(our_fs, rootmnt, root);
   77         set_fs_pwd(our_fs, pwdmnt, pwd);
   78         write_lock(&our_fs->lock);
   79         if (our_fs->altroot) {
   80                 struct vfsmount *mnt = our_fs->altrootmnt;
   81                 struct dentry *dentry = our_fs->altroot;
   82                 our_fs->altrootmnt = NULL;
   83                 our_fs->altroot = NULL;
   84                 write_unlock(&our_fs->lock);
   85                 dput(dentry);
   86                 mntput(mnt);
   87         } else 
   88                 write_unlock(&our_fs->lock);
   89         dput(root);
   90         mntput(rootmnt);
   91         dput(pwd);
   92         mntput(pwdmnt);
   93 }
   94 
   95 int exec_usermodehelper(char *program_path, char *argv[], char *envp[])
   96 {
   97         int i;
   98         struct task_struct *curtask = current;
   99 
  100         curtask->session = 1;
  101         curtask->pgrp = 1;
  102 
  103         use_init_fs_context();
  104 
  105         /* Prevent parent user process from sending signals to child.
  106            Otherwise, if the modprobe program does not exist, it might
  107            be possible to get a user defined signal handler to execute
  108            as the super user right after the execve fails if you time
  109            the signal just right.
  110         */
  111         spin_lock_irq(&curtask->sigmask_lock);
  112         sigemptyset(&curtask->blocked);
  113         flush_signals(curtask);
  114         flush_signal_handlers(curtask);
  115         recalc_sigpending(curtask);
  116         spin_unlock_irq(&curtask->sigmask_lock);
  117 
  118         for (i = 0; i < curtask->files->max_fds; i++ ) {
  119                 if (curtask->files->fd[i]) close(i);
  120         }
  121 
  122         /* Drop the "current user" thing */
  123         {
  124                 struct user_struct *user = curtask->user;
  125                 curtask->user = INIT_USER;
  126                 atomic_inc(&INIT_USER->__count);
  127                 atomic_inc(&INIT_USER->processes);
  128                 atomic_dec(&user->processes);
  129                 free_uid(user);
  130         }
  131 
  132         /* Give kmod all effective privileges.. */
  133         curtask->euid = curtask->fsuid = 0;
  134         curtask->egid = curtask->fsgid = 0;
  135         cap_set_full(curtask->cap_effective);
  136 
  137         /* Allow execve args to be in kernel space. */
  138         set_fs(KERNEL_DS);
  139 
  140         /* Go, go, go... */
  141         if (execve(program_path, argv, envp) < 0)
  142                 return -errno;
  143         return 0;
  144 }
  145 
  146 #ifdef CONFIG_KMOD
  147 
  148 /*
  149         modprobe_path is set via /proc/sys.
  150 */
  151 char modprobe_path[256] = "/sbin/modprobe";
  152 
  153 static int exec_modprobe(void * module_name)
  154 {
  155         static char * envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
  156         char *argv[] = { modprobe_path, "-s", "-k", "--", (char*)module_name, NULL };
  157         int ret;
  158 
  159         ret = exec_usermodehelper(modprobe_path, argv, envp);
  160         if (ret) {
  161                 printk(KERN_ERR
  162                        "kmod: failed to exec %s -s -k %s, errno = %d\n",
  163                        modprobe_path, (char*) module_name, errno);
  164         }
  165         return ret;
  166 }
  167 
  168 /**
  169  * request_module - try to load a kernel module
  170  * @module_name: Name of module
  171  *
  172  * Load a module using the user mode module loader. The function returns
  173  * zero on success or a negative errno code on failure. Note that a
  174  * successful module load does not mean the module did not then unload
  175  * and exit on an error of its own. Callers must check that the service
  176  * they requested is now available not blindly invoke it.
  177  *
  178  * If module auto-loading support is disabled then this function
  179  * becomes a no-operation.
  180  */
  181 int request_module(const char * module_name)
  182 {
  183         pid_t pid;
  184         int waitpid_result;
  185         sigset_t tmpsig;
  186         int i;
  187         static atomic_t kmod_concurrent = ATOMIC_INIT(0);
  188 #define MAX_KMOD_CONCURRENT 50  /* Completely arbitrary value - KAO */
  189         static int kmod_loop_msg;
  190 
  191         /* Don't allow request_module() before the root fs is mounted!  */
  192         if ( ! current->fs->root ) {
  193                 printk(KERN_ERR "request_module[%s]: Root fs not mounted\n",
  194                         module_name);
  195                 return -EPERM;
  196         }
  197 
  198         /* If modprobe needs a service that is in a module, we get a recursive
  199          * loop.  Limit the number of running kmod threads to max_threads/2 or
  200          * MAX_KMOD_CONCURRENT, whichever is the smaller.  A cleaner method
  201          * would be to run the parents of this process, counting how many times
  202          * kmod was invoked.  That would mean accessing the internals of the
  203          * process tables to get the command line, proc_pid_cmdline is static
  204          * and it is not worth changing the proc code just to handle this case. 
  205          * KAO.
  206          */
  207         i = max_threads/2;
  208         if (i > MAX_KMOD_CONCURRENT)
  209                 i = MAX_KMOD_CONCURRENT;
  210         atomic_inc(&kmod_concurrent);
  211         if (atomic_read(&kmod_concurrent) > i) {
  212                 if (kmod_loop_msg++ < 5)
  213                         printk(KERN_ERR
  214                                "kmod: runaway modprobe loop assumed and stopped\n");
  215                 atomic_dec(&kmod_concurrent);
  216                 return -ENOMEM;
  217         }
  218 
  219         pid = kernel_thread(exec_modprobe, (void*) module_name, 0);
  220         if (pid < 0) {
  221                 printk(KERN_ERR "request_module[%s]: fork failed, errno %d\n", module_name, -pid);
  222                 atomic_dec(&kmod_concurrent);
  223                 return pid;
  224         }
  225 
  226         /* Block everything but SIGKILL/SIGSTOP */
  227         spin_lock_irq(&current->sigmask_lock);
  228         tmpsig = current->blocked;
  229         siginitsetinv(&current->blocked, sigmask(SIGKILL) | sigmask(SIGSTOP));
  230         recalc_sigpending(current);
  231         spin_unlock_irq(&current->sigmask_lock);
  232 
  233         waitpid_result = waitpid(pid, NULL, __WCLONE);
  234         atomic_dec(&kmod_concurrent);
  235 
  236         /* Allow signals again.. */
  237         spin_lock_irq(&current->sigmask_lock);
  238         current->blocked = tmpsig;
  239         recalc_sigpending(current);
  240         spin_unlock_irq(&current->sigmask_lock);
  241 
  242         if (waitpid_result != pid) {
  243                 printk(KERN_ERR "request_module[%s]: waitpid(%d,...) failed, errno %d\n",
  244                        module_name, pid, -waitpid_result);
  245         }
  246         return 0;
  247 }
  248 #endif /* CONFIG_KMOD */
  249 
  250 
  251 #ifdef CONFIG_HOTPLUG
  252 /*
  253         hotplug path is set via /proc/sys
  254         invoked by hotplug-aware bus drivers,
  255         with exec_usermodehelper and some thread-spawner
  256 
  257         argv [0] = hotplug_path;
  258         argv [1] = "usb", "scsi", "pci", "network", etc;
  259         ... plus optional type-specific parameters
  260         argv [n] = 0;
  261 
  262         envp [*] = HOME, PATH; optional type-specific parameters
  263 
  264         a hotplug bus should invoke this for device add/remove
  265         events.  the command is expected to load drivers when
  266         necessary, and may perform additional system setup.
  267 */
  268 char hotplug_path[256] = "/sbin/hotplug";
  269 
  270 EXPORT_SYMBOL(hotplug_path);
  271 
  272 #endif /* CONFIG_HOTPLUG */
  273 
  274 struct subprocess_info {
  275         struct completion *complete;
  276         char *path;
  277         char **argv;
  278         char **envp;
  279         pid_t retval;
  280 };
  281 
  282 /*
  283  * This is the task which runs the usermode application
  284  */
  285 static int ____call_usermodehelper(void *data)
  286 {
  287         struct subprocess_info *sub_info = data;
  288         int retval;
  289 
  290         retval = -EPERM;
  291         if (current->fs->root)
  292                 retval = exec_usermodehelper(sub_info->path, sub_info->argv, sub_info->envp);
  293 
  294         /* Exec failed? */
  295         sub_info->retval = (pid_t)retval;
  296         do_exit(0);
  297 }
  298 
  299 /*
  300  * This is run by keventd.
  301  */
  302 static void __call_usermodehelper(void *data)
  303 {
  304         struct subprocess_info *sub_info = data;
  305         pid_t pid;
  306 
  307         /*
  308          * CLONE_VFORK: wait until the usermode helper has execve'd successfully
  309          * We need the data structures to stay around until that is done.
  310          */
  311         pid = kernel_thread(____call_usermodehelper, sub_info, CLONE_VFORK | SIGCHLD);
  312         if (pid < 0)
  313                 sub_info->retval = pid;
  314         complete(sub_info->complete);
  315 }
  316 
  317 /**
  318  * call_usermodehelper - start a usermode application
  319  * @path: pathname for the application
  320  * @argv: null-terminated argument list
  321  * @envp: null-terminated environment list
  322  *
  323  * Runs a user-space application.  The application is started asynchronously.  It
  324  * runs as a child of keventd.  It runs with full root capabilities.  keventd silently
  325  * reaps the child when it exits.
  326  *
  327  * Must be called from process context.  Returns zero on success, else a negative
  328  * error code.
  329  */
  330 int call_usermodehelper(char *path, char **argv, char **envp)
  331 {
  332         DECLARE_COMPLETION(work);
  333         struct subprocess_info sub_info = {
  334                 complete:       &work,
  335                 path:           path,
  336                 argv:           argv,
  337                 envp:           envp,
  338                 retval:         0,
  339         };
  340         struct tq_struct tqs = {
  341                 routine:        __call_usermodehelper,
  342                 data:           &sub_info,
  343         };
  344 
  345         if (path[0] == '\0')
  346                 goto out;
  347 
  348         if (current_is_keventd()) {
  349                 /* We can't wait on keventd! */
  350                 __call_usermodehelper(&sub_info);
  351         } else {
  352                 schedule_task(&tqs);
  353                 wait_for_completion(&work);
  354         }
  355 out:
  356         return sub_info.retval;
  357 }
  358 
  359 /*
  360  * This is for the serialisation of device probe() functions
  361  * against device open() functions
  362  */
  363 static DECLARE_MUTEX(dev_probe_sem);
  364 
  365 void dev_probe_lock(void)
  366 {
  367         down(&dev_probe_sem);
  368 }
  369 
  370 void dev_probe_unlock(void)
  371 {
  372         up(&dev_probe_sem);
  373 }
  374 
  375 EXPORT_SYMBOL(exec_usermodehelper);
  376 EXPORT_SYMBOL(call_usermodehelper);
  377 
  378 #ifdef CONFIG_KMOD
  379 EXPORT_SYMBOL(request_module);
  380 #endif
  381 

Cache object: 8561d37d09f9bb22fe7354f0bf33b146


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.