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

kernel/kmod.c

24344 /*
24345   kmod, the new module loader (replaces kerneld)
24346   Kirk Petersen
24347 
24348   Reorganized not to be a daemon by Adam Richter, with
24349   guidance from Greg Zornetzer.
24350 
24351   Modified to avoid chroot and file sharing problems.
24352   Mikael Pettersson */
24353 
24354 #define __KERNEL_SYSCALLS__
24355 
24356 #include <linux/sched.h>
24357 #include <linux/unistd.h>
24358 #include <linux/smp_lock.h>
24359 
24360 #include <asm/uaccess.h>
24361 
24362 /* modprobe_path is set via /proc/sys.  */
24363 char modprobe_path[256] = "/sbin/modprobe";
24364 
24365 static inline void
24366 use_init_file_context(void)
24367 {
24368   struct fs_struct * fs;
24369 
24370   lock_kernel();
24371 
24372   /* Don't use the user's root, use init's root instead.
24373    * Note that we can use "init_task" (which is not
24374    * actually the same as the user-level "init" process)
24375    * because we started "init" with a CLONE_FS */
24376   exit_fs(current);       /* current->fs->count--; */
24377   fs = init_task.fs;
24378   current->fs = fs;
24379   atomic_inc(&fs->count);
24380 
24381   unlock_kernel();
24382 }
24383 
24384 static int exec_modprobe(void * module_name)
24385 {
24386   static char * envp[] = { "HOME=/", "TERM=linux",
24387     "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
24388   char *argv[] = { modprobe_path, "-s", "-k",
24389                    (char*)module_name, NULL };
24390   int i;
24391 
24392   use_init_file_context();
24393 
24394   /* Prevent parent user process from sending signals to
24395    * child.  Otherwise, if the modprobe program does not
24396    * exist, it might be possible to get a user defined
24397    * signal handler to execute as the super user right
24398    * after the execve fails if you time the signal just
24399    * right.  */
24400   spin_lock_irq(&current->sigmask_lock);
24401   flush_signals(current);
24402   flush_signal_handlers(current);
24403   spin_unlock_irq(&current->sigmask_lock);
24404 
24405   for (i = 0; i < current->files->max_fds; i++ ) {
24406     if (current->files->fd[i]) close(i);
24407   }
24408 
24409   /* Drop the "current user" thing */
24410   free_uid(current);
24411 
24412   /* Give kmod all privileges.. */
24413   current->uid = current->euid = current->fsuid = 0;
24414   cap_set_full(current->cap_inheritable);
24415   cap_set_full(current->cap_effective);
24416 
24417   /* Allow execve args to be in kernel space. */
24418   set_fs(KERNEL_DS);
24419 
24420   /* Go, go, go... */
24421   if (execve(modprobe_path, argv, envp) < 0) {
24422     printk(KERN_ERR
24423         "kmod: failed to exec %s -s -k %s, errno = %d\n",
24424         modprobe_path, (char*) module_name, errno);
24425     return -errno;
24426   }
24427   return 0;
24428 }
24429 
24430 /* request_module: the function that everyone calls when
24431  * they need a module.  */
 Комментарий
24432 int request_module(const char * module_name)
24433 {
24434   int pid;
24435   int waitpid_result;
24436   sigset_t tmpsig;
24437 
24438   /* Don't allow request_module() before the root fs is
24439    * mounted!  */
24440   if (!current->fs->root) {
24441     printk(KERN_ERR "request_module[%s]: Root fs "
24442            "not mounted\n", module_name);
24443     return -EPERM;
24444   }
24445 
24446   pid = kernel_thread(exec_modprobe,
24447                       (void*) module_name, CLONE_FS);
24448   if (pid < 0) {
24449     printk(KERN_ERR "request_module[%s]: fork failed, "
24450            "errno %d\n", module_name, -pid);
24451     return pid;
24452   }
24453 
24454   /* Block everything but SIGKILL/SIGSTOP */
24455   spin_lock_irq(&current->sigmask_lock);
24456   tmpsig = current->blocked;
24457   siginitsetinv(&current->blocked,
24458                 sigmask(SIGKILL) | sigmask(SIGSTOP));
24459   recalc_sigpending(current);
24460   spin_unlock_irq(&current->sigmask_lock);
24461 
24462   waitpid_result = waitpid(pid, NULL, __WCLONE);
24463 
24464   /* Allow signals again.. */
24465   spin_lock_irq(&current->sigmask_lock);
24466   current->blocked = tmpsig;
24467   recalc_sigpending(current);
24468   spin_unlock_irq(&current->sigmask_lock);
24469 
24470   if (waitpid_result != pid) {
24471     printk (KERN_ERR "kmod: waitpid(%d,NULL,0) failed, "
24472             "returning %d.\n", pid, waitpid_result);
24473   }
24474   return 0;
24475 }

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

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