~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/kernel/kmod.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.