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/kern/kern_module_vfs.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 /*      $NetBSD: kern_module_vfs.c,v 1.18 2021/06/29 22:40:53 dholland Exp $    */
    2 
    3 /*-
    4  * Copyright (c) 2008 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software developed for The NetBSD Foundation
    8  * by Andrew Doran.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   29  * POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 
   32 /*
   33  * Kernel module file system interaction.
   34  */
   35 
   36 #include <sys/cdefs.h>
   37 __KERNEL_RCSID(0, "$NetBSD: kern_module_vfs.c,v 1.18 2021/06/29 22:40:53 dholland Exp $");
   38 
   39 #define _MODULE_INTERNAL
   40 #include <sys/param.h>
   41 #include <sys/fcntl.h>
   42 #include <sys/kmem.h>
   43 #include <sys/kobj.h>
   44 #include <sys/module.h>
   45 #include <sys/namei.h>
   46 #include <sys/pool.h>
   47 #include <sys/stat.h>
   48 #include <sys/vnode.h>
   49 
   50 #include <prop/proplib.h>
   51 
   52 static int      module_load_plist_vfs(const char *, const bool,
   53                                       prop_dictionary_t *);
   54 
   55 void
   56 module_load_vfs_init(void)
   57 {
   58         module_load_vfs_vec = module_load_vfs;
   59         aprint_normal("kern.module.path=%s\n", module_base);
   60 }
   61 
   62 int
   63 module_load_vfs(const char *name, int flags, bool autoload,
   64         module_t *mod, prop_dictionary_t *filedictp)
   65 {
   66         char *path;
   67         bool nochroot;
   68         int error;
   69         prop_bool_t noload;
   70         prop_dictionary_t moduledict;
   71 
   72         nochroot = false;
   73         error = 0;
   74         path = NULL;
   75         moduledict = NULL;
   76         if (filedictp)
   77                 *filedictp = NULL;
   78         path = PNBUF_GET();
   79 
   80         if (!autoload) {
   81                 if (strchr(name,  '/') != NULL) {
   82                         nochroot = false;
   83                         snprintf(path, MAXPATHLEN, "%s", name);
   84                         module_print("Loading module from %s", path);
   85                         error = kobj_load_vfs(&mod->mod_kobj, path, nochroot);
   86                 } else
   87                         error = ENOENT;
   88         }
   89         if (autoload || (error == ENOENT)) {
   90                 if (strchr(name, '/') == NULL) {
   91                         nochroot = true;
   92                         snprintf(path, MAXPATHLEN, "%s/%s/%s.kmod",
   93                             module_base, name, name);
   94                         module_print("Loading module from %s", path);
   95                         error = kobj_load_vfs(&mod->mod_kobj, path, nochroot);
   96                 } else
   97                         error = ENOENT;
   98         }
   99         if (error != 0) {
  100                 PNBUF_PUT(path);
  101                 module_print("Cannot %sload kernel object `%s'"
  102                     " error=%d", autoload ? "auto" : "", name, error);
  103                 return error;
  104         }
  105 
  106         /*
  107          * Load and process <module>.plist if it exists.
  108          */
  109         if ((!ISSET(flags, MODCTL_NO_PROP) && filedictp) || autoload) {
  110                 error = module_load_plist_vfs(path, nochroot, &moduledict);
  111                 if (error != 0) {
  112                         module_print("plist load returned error %d for `%s'",
  113                             error, path);
  114                         if (error != ENOENT)
  115                                 goto fail;
  116                 } else if (autoload) {
  117                         noload = prop_dictionary_get(moduledict, "noautoload");
  118                         if (noload != NULL && prop_bool_true(noload)) {
  119                                 module_error("autoloading is disallowed for %s",
  120                                     path);
  121                                 prop_object_release(moduledict);
  122                                 error = EPERM;
  123                                 goto fail;
  124                         }
  125                 }
  126                 if (error == 0) {       /* can get here if error == ENOENT */
  127                         if (!ISSET(flags, MODCTL_NO_PROP) && filedictp)
  128                                 *filedictp = moduledict;
  129                         else 
  130                                 prop_object_release(moduledict);
  131                 }
  132         }
  133 
  134         PNBUF_PUT(path);
  135         return 0;
  136 
  137  fail:
  138         kobj_unload(mod->mod_kobj);
  139         PNBUF_PUT(path);
  140         return error;
  141 }
  142 
  143 /*
  144  * module_load_plist_vfs:
  145  *
  146  *      Load a plist located in the file system into memory.
  147  */
  148 static int
  149 module_load_plist_vfs(const char *modpath, const bool nochroot,
  150     prop_dictionary_t *filedictp)
  151 {
  152         struct pathbuf *pb;
  153         struct vnode *vp;
  154         struct stat sb;
  155         void *base;
  156         char *proppath;
  157         const size_t plistsize = 8192;
  158         size_t resid;
  159         int error, pathlen;
  160 
  161         KASSERT(filedictp != NULL);
  162         base = NULL;
  163 
  164         proppath = PNBUF_GET();
  165         strlcpy(proppath, modpath, MAXPATHLEN);
  166         pathlen = strlen(proppath);
  167         if ((pathlen >= 6) && (strcmp(&proppath[pathlen - 5], ".kmod") == 0)) {
  168                 strcpy(&proppath[pathlen - 5], ".plist");
  169         } else if (pathlen < MAXPATHLEN - 6) {
  170                         strcat(proppath, ".plist");
  171         } else {
  172                 error = ENOENT;
  173                 goto out1;
  174         }
  175 
  176         /* XXX this makes an unnecessary extra copy of the path */
  177         pb = pathbuf_create(proppath);
  178         if (pb == NULL) {
  179                 error = ENOMEM;
  180                 goto out1;
  181         }
  182         module_print("Loading plist from %s", proppath);
  183         
  184         error = vn_open(NULL, pb, (nochroot ? NOCHROOT : 0), FREAD, 0,
  185             &vp, NULL, NULL);
  186         if (error != 0) {
  187                 goto out2;
  188         }
  189 
  190         error = vn_stat(vp, &sb);
  191         if (error != 0) {
  192                 goto out3;
  193         }
  194         if (sb.st_size >= (plistsize - 1)) {    /* leave space for term \0 */
  195                 error = EFBIG;
  196                 goto out3;
  197         }
  198 
  199         base = kmem_alloc(plistsize, KM_SLEEP);
  200         error = vn_rdwr(UIO_READ, vp, base, sb.st_size, 0,
  201             UIO_SYSSPACE, IO_NODELOCKED, curlwp->l_cred, &resid, curlwp);
  202         *((uint8_t *)base + sb.st_size) = '\0';
  203         if (error == 0 && resid != 0) {
  204                 error = EFBIG;
  205         }
  206         if (error != 0) {
  207                 kmem_free(base, plistsize);
  208                 base = NULL;
  209                 goto out3;
  210         }
  211 
  212         *filedictp = prop_dictionary_internalize(base);
  213         if (*filedictp == NULL) {
  214                 error = EINVAL;
  215         }
  216         kmem_free(base, plistsize);
  217         base = NULL;
  218         KASSERT(error == 0);
  219 
  220 out3:
  221         VOP_UNLOCK(vp);
  222         vn_close(vp, FREAD, kauth_cred_get());
  223 
  224 out2:
  225         pathbuf_destroy(pb);
  226 
  227 out1:
  228         PNBUF_PUT(proppath);
  229         return error;
  230 }

Cache object: c7ad211e955ea1f58f0f0eb816dc0409


[ 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.