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/libsa/kmod.cpp

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  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_LICENSE_HEADER_START@
    5  * 
    6  * The contents of this file constitute Original Code as defined in and
    7  * are subject to the Apple Public Source License Version 1.1 (the
    8  * "License").  You may not use this file except in compliance with the
    9  * License.  Please obtain a copy of the License at
   10  * http://www.apple.com/publicsource and read it before using this file.
   11  * 
   12  * This Original Code and all software distributed under the License are
   13  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   14  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   15  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   16  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
   17  * License for the specific language governing rights and limitations
   18  * under the License.
   19  * 
   20  * @APPLE_LICENSE_HEADER_END@
   21  */
   22 #include <libsa/kmod.h>
   23 #include <libkern/c++/OSContainers.h>
   24 #include <IOKit/IOCatalogue.h>
   25 #include <IOKit/IOLib.h>
   26 #include <libsa/kmod.h>
   27 #include <libsa/catalogue.h>
   28 
   29 extern "C" {
   30 #include <mach-o/kld.h>
   31 #include <libsa/vers_rsrc.h>
   32 #include <libsa/stdlib.h>
   33 #include <mach/kmod.h>
   34 #include <vm/vm_kern.h>
   35 #include <mach/kern_return.h>
   36 #include <mach-o/fat.h>
   37 #include <mach_loader.h>
   38 };
   39 
   40 #include "kld_patch.h"
   41 
   42 
   43 extern "C" {
   44 extern kern_return_t
   45 kmod_create_internal(
   46             kmod_info_t *info,
   47             kmod_t *id);
   48 
   49 extern kern_return_t
   50 kmod_destroy_internal(kmod_t id);
   51 
   52 extern kern_return_t
   53 kmod_start_or_stop(
   54     kmod_t id,
   55     int start,
   56     kmod_args_t *data,
   57     mach_msg_type_number_t *dataCount);
   58 
   59 extern kern_return_t kmod_retain(kmod_t id);
   60 extern kern_return_t kmod_release(kmod_t id);
   61 
   62 extern void flush_dcache64(addr64_t addr, unsigned cnt, int phys);
   63 extern void invalidate_icache64(addr64_t addr, unsigned cnt, int phys);
   64 };
   65 
   66 
   67 #define LOG_DELAY()
   68 
   69 #define VTYELLOW        "\033[33m"
   70 #define VTRESET         "\033[0m"
   71 
   72 
   73 
   74 
   75 /*********************************************************************
   76 *
   77 *********************************************************************/
   78 bool verifyCompatibility(OSString * extName, OSString * requiredVersion)
   79 {
   80     OSDictionary * extensionsDict;   // don't release
   81     OSDictionary * extDict;          // don't release
   82     OSDictionary * extPlist;         // don't release
   83     OSString     * extVersion;       // don't release
   84     OSString     * extCompatVersion; // don't release
   85     UInt32 ext_version;
   86     UInt32 ext_compat_version;
   87     UInt32 required_version;
   88 
   89    /* Get the dictionary of startup extensions.
   90     * This is keyed by module name.
   91     */
   92     extensionsDict = getStartupExtensions();
   93     if (!extensionsDict) {
   94         IOLog("verifyCompatibility(): No extensions dictionary.\n");
   95         return false;
   96     }
   97 
   98    /* Get the requested extension's dictionary entry and its property
   99     * list, containing module dependencies.
  100     */
  101     extDict = OSDynamicCast(OSDictionary,
  102         extensionsDict->getObject(extName));
  103 
  104     if (!extDict) {
  105         IOLog("verifyCompatibility(): "
  106            "Extension \"%s\" cannot be found.\n",
  107            extName->getCStringNoCopy());
  108         return false;
  109     }
  110 
  111     extPlist = OSDynamicCast(OSDictionary, extDict->getObject("plist"));
  112     if (!extPlist) {
  113         IOLog("verifyCompatibility(): "
  114             "Extension \"%s\" has no property list.\n",
  115             extName->getCStringNoCopy());
  116         return false;
  117     }
  118 
  119 
  120     extVersion = OSDynamicCast(OSString,
  121         extPlist->getObject("CFBundleVersion"));
  122     if (!extVersion) {
  123         IOLog("verifyCompatibility(): "
  124             "Extension \"%s\" has no \"CFBundleVersion\" property.\n",
  125             extName->getCStringNoCopy());
  126         return false;
  127     }
  128 
  129     extCompatVersion = OSDynamicCast(OSString,
  130         extPlist->getObject("OSBundleCompatibleVersion"));
  131     if (!extCompatVersion) {
  132         IOLog("verifyCompatibility(): "
  133             "Extension \"%s\" has no \"OSBundleCompatibleVersion\" property.\n",
  134             extName->getCStringNoCopy());
  135         return false;
  136     }
  137 
  138     if (!VERS_parse_string(requiredVersion->getCStringNoCopy(),
  139          &required_version)) {
  140         IOLog("verifyCompatibility(): "
  141             "Can't parse required version \"%s\" of dependency %s.\n",
  142             requiredVersion->getCStringNoCopy(),
  143             extName->getCStringNoCopy());
  144         return false;
  145     }
  146     if (!VERS_parse_string(extVersion->getCStringNoCopy(),
  147          &ext_version)) {
  148         IOLog("verifyCompatibility(): "
  149             "Can't parse version \"%s\" of dependency %s.\n",
  150             extVersion->getCStringNoCopy(),
  151             extName->getCStringNoCopy());
  152         return false;
  153     }
  154     if (!VERS_parse_string(extCompatVersion->getCStringNoCopy(),
  155          &ext_compat_version)) {
  156         IOLog("verifyCompatibility(): "
  157             "Can't parse compatible version \"%s\" of dependency %s.\n",
  158             extCompatVersion->getCStringNoCopy(),
  159             extName->getCStringNoCopy());
  160         return false;
  161     }
  162 
  163     if (required_version > ext_version || required_version < ext_compat_version) {
  164         return false;
  165     }
  166 
  167     return true;
  168 }
  169 
  170 /*********************************************************************
  171 *********************************************************************/
  172 static
  173 Boolean kextIsADependency(OSString * name) {
  174     Boolean result = true;
  175     OSDictionary * extensionsDict = 0;    // don't release
  176     OSDictionary * extDict = 0;           // don't release
  177     OSDictionary * extPlist = 0;          // don't release
  178     OSBoolean * isKernelResourceObj = 0;  // don't release
  179     OSData * driverCode = 0;              // don't release
  180     OSData * compressedCode = 0;          // don't release
  181 
  182     extensionsDict = getStartupExtensions();
  183     if (!extensionsDict) {
  184         IOLog("kextIsADependency(): No extensions dictionary.\n");
  185         LOG_DELAY();
  186         result = false;
  187         goto finish;
  188     }
  189     
  190 
  191     extDict = OSDynamicCast(OSDictionary,
  192         extensionsDict->getObject(name));
  193     if (!extDict) {
  194         IOLog("kextIsADependency(): "
  195            "Extension \"%s\" cannot be found.\n",
  196            name->getCStringNoCopy());
  197         LOG_DELAY();
  198         result = false;
  199         goto finish;
  200     }
  201 
  202     extPlist = OSDynamicCast(OSDictionary, extDict->getObject("plist"));
  203     if (!extPlist) {
  204         IOLog("getDependencyListForKmod(): "
  205             "Extension \"%s\" has no property list.\n",
  206             name->getCStringNoCopy());
  207         LOG_DELAY();
  208         result = false;
  209         goto finish;
  210     }
  211 
  212    /* A kext that is a kernel component is still a dependency, as there
  213     * are fake kmod entries for them.
  214     */
  215     isKernelResourceObj = OSDynamicCast(OSBoolean,
  216         extPlist->getObject("OSKernelResource"));
  217     if (isKernelResourceObj && isKernelResourceObj->isTrue()) {
  218         result = true;
  219         goto finish;
  220     }
  221 
  222     driverCode = OSDynamicCast(OSData, extDict->getObject("code"));
  223     compressedCode = OSDynamicCast(OSData,
  224         extDict->getObject("compressedCode"));
  225 
  226     if (!driverCode && !compressedCode) {
  227         result = false;
  228         goto finish;
  229     }
  230 
  231 finish:
  232 
  233     return result;
  234 }
  235 
  236 /*********************************************************************
  237 * This function builds a uniqued, in-order list of modules that need
  238 * to be loaded in order for kmod_name to be successfully loaded. This
  239 * list ends with kmod_name itself.
  240 *********************************************************************/
  241 static
  242 OSArray * getDependencyListForKmod(const char * kmod_name) {
  243 
  244     int error = 0;
  245 
  246     OSDictionary * extensionsDict; // don't release
  247     OSDictionary * extDict;        // don't release
  248     OSDictionary * extPlist;       // don't release
  249     OSString     * extName;        // don't release
  250     OSArray      * dependencyList = NULL; // return value, caller releases
  251     unsigned int   i;
  252 
  253    /* These are used to remove duplicates from the dependency list.
  254     */
  255     OSArray      * originalList = NULL;     // must be released
  256     OSDictionary * encounteredNames = NULL; // must be release
  257 
  258 
  259    /* Get the dictionary of startup extensions.
  260     * This is keyed by module name.
  261     */
  262     extensionsDict = getStartupExtensions();
  263     if (!extensionsDict) {
  264         IOLog("getDependencyListForKmod(): No extensions dictionary.\n");
  265         LOG_DELAY();
  266         error = 1;
  267         goto finish;
  268     }
  269     
  270 
  271    /* Get the requested extension's dictionary entry and its property
  272     * list, containing module dependencies.
  273     */
  274     extDict = OSDynamicCast(OSDictionary,
  275         extensionsDict->getObject(kmod_name));
  276 
  277     if (!extDict) {
  278         IOLog("getDependencyListForKmod(): "
  279            "Extension \"%s\" cannot be found.\n",
  280            kmod_name);
  281         LOG_DELAY();
  282         error = 1;
  283         goto finish;
  284     }
  285 
  286     extPlist = OSDynamicCast(OSDictionary, extDict->getObject("plist"));
  287     if (!extPlist) {
  288         IOLog("getDependencyListForKmod(): "
  289             "Extension \"%s\" has no property list.\n",
  290             kmod_name);
  291         LOG_DELAY();
  292         error = 1;
  293         goto finish;
  294     }
  295 
  296 
  297    /* Verify that the retrieved entry's "CFBundleIdentifier" property exists.
  298     * This will be added to the dependency list.
  299     */
  300     extName = OSDynamicCast(OSString,
  301         extPlist->getObject("CFBundleIdentifier"));
  302     if (!extName) {
  303         IOLog("getDependencyListForKmod(): "
  304             "Extension \"%s\" has no \"CFBundleIdentifier\" property.\n",
  305             kmod_name);
  306         LOG_DELAY();
  307         error = 1;
  308         goto finish;
  309     }
  310 
  311     dependencyList = OSArray::withCapacity(10);
  312     if (!dependencyList) {
  313         IOLog("getDependencyListForKmod(): "
  314             "Couldn't allocate dependency array for extension \"%s\".\n",
  315             kmod_name);
  316         LOG_DELAY();
  317         error = 1;
  318         goto finish;
  319     }
  320 
  321 
  322    /* Okay, let's get started.
  323     */
  324     dependencyList->setObject(extName);
  325 
  326 
  327    /* Here's a slightly tricky bit. This loop iterates through
  328     * the dependency list until it runs off the end. Each time
  329     * through, however, any number of dependencies can be added
  330     * to the end of the list. Eventually some extensions won't
  331     * have any more dependencies, no more names will be added
  332     * to the list, and this loop will terminate.
  333     */
  334     for (i = 0; i < dependencyList->getCount(); i++) {
  335 
  336         // None of these needs to be released, as they're all from plists.
  337         OSString     * curName;
  338         OSDictionary * curExtDict;
  339         OSDictionary * curExtDepDict;
  340         OSDictionary * curExtPlist;
  341         OSString     * curDepName;
  342 
  343 
  344        /* An arbitrary limit to prevent infinite loops.
  345         */
  346         if (i > 255) {
  347             IOLog("getDependencyListForKmod(): "
  348                 "max dependency list length exceeded for "
  349                 "extension \"%s\".\n",
  350                 kmod_name);
  351             LOG_DELAY();
  352             error = 1;
  353             goto finish;
  354         }
  355 
  356         curName = OSDynamicCast(OSString, dependencyList->getObject(i));
  357 
  358         curExtDict = OSDynamicCast(OSDictionary,
  359             extensionsDict->getObject(curName));
  360         if (!curExtDict) {
  361             IOLog("getDependencyListForKmod(): "
  362                 "Extension \"%s\", required for extension \"%s\", "
  363                 "is not available.\n",
  364                 curName->getCStringNoCopy(), kmod_name);
  365             LOG_DELAY();
  366             error = 1;
  367             goto finish;
  368         }
  369 
  370         curExtPlist = OSDynamicCast(OSDictionary,
  371             curExtDict->getObject("plist"));
  372         if (!curExtPlist) {
  373             IOLog("getDependencyListForKmod(): "
  374                 "Extension \"%s\", required for extension \"%s\", "
  375                 "has no property list.\n",
  376                 curName->getCStringNoCopy(), kmod_name);
  377             LOG_DELAY();
  378             error = 1;
  379             goto finish;
  380         }
  381 
  382         curExtDepDict = OSDynamicCast(OSDictionary,
  383               curExtPlist->getObject("OSBundleLibraries"));
  384         if (curExtDepDict) {
  385             OSCollectionIterator * keyIterator =
  386                 OSCollectionIterator::withCollection(curExtDepDict);
  387 
  388             if (!keyIterator) {
  389                 IOLog("getDependencyListForKmod(): "
  390                     "Couldn't allocate iterator for extension "
  391                     "\"%s\".\n", kmod_name);
  392                 LOG_DELAY();
  393                 error = 1;
  394                 goto finish;
  395             }
  396             while ( (curDepName =
  397                      OSDynamicCast(OSString,
  398                          keyIterator->getNextObject())) ) {
  399 
  400                 OSString * requiredVersion = OSDynamicCast(OSString,
  401                     curExtDepDict->getObject(curDepName));
  402 
  403                 if (!verifyCompatibility(curDepName, requiredVersion)) {
  404                     IOLog("getDependencyListForKmod(): "
  405                         "Dependency %s of %s is not compatible or is unavailable.\n",
  406                         curDepName->getCStringNoCopy(),
  407                         curName->getCStringNoCopy());
  408                     LOG_DELAY();
  409                     error = 1;
  410                     goto finish;
  411                 }
  412 
  413                 dependencyList->setObject(curDepName);
  414             }
  415 
  416             keyIterator->release();
  417         }
  418     }
  419 
  420 
  421    /*****
  422     * The dependency list now exists in the reverse order of required loads,
  423     * and may have duplicates. Now we turn the list around and remove
  424     * duplicates.
  425     */
  426     originalList = dependencyList;
  427     dependencyList = OSArray::withCapacity(originalList->getCount());
  428     if (!dependencyList) {
  429         IOLog("getDependenciesForKmod(): "
  430               "Couldn't allocate reversal dependency list for extension "
  431               "\"%s\".\n", kmod_name);
  432         LOG_DELAY();
  433         error = 1;
  434         goto finish;
  435     }
  436     encounteredNames = OSDictionary::withCapacity(originalList->getCount());
  437     if (!encounteredNames) {
  438         IOLog("getDependenciesForKmod(): "
  439               "Couldn't allocate list of encountered names for extension "
  440               "\"%s\".\n", kmod_name);
  441         LOG_DELAY();
  442         error = 1;
  443         goto finish;
  444     }
  445 
  446 
  447    /* Go backward through the original list, using the encounteredNames
  448     * dictionary to check for duplicates. We put originalList in as the
  449     * value because we need some non-NULL value. Here we also drop any
  450     * extensions that aren't proper dependencies (that is, any that are
  451     * nonkernel kexts without code).
  452     */
  453     i = originalList->getCount();
  454 
  455     if (i > 0) {
  456         do {
  457             i--;
  458 
  459             OSString * item = OSDynamicCast(OSString,
  460                 originalList->getObject(i));
  461 
  462             if ( (!encounteredNames->getObject(item)) &&
  463                  kextIsADependency(item)) {
  464 
  465                 encounteredNames->setObject(item, originalList);
  466                 dependencyList->setObject(item);
  467             }
  468         } while (i > 0);
  469     }
  470 
  471 
  472 finish:
  473 
  474     if (originalList) {
  475         originalList->release();
  476     }
  477     if (encounteredNames) {
  478         encounteredNames->release();
  479     }
  480     if (error) {
  481         if (dependencyList) {
  482             dependencyList->release();
  483             dependencyList = NULL;
  484         }
  485     }
  486 
  487     return dependencyList;
  488 }
  489 
  490 
  491 /*********************************************************************
  492 *********************************************************************/
  493 /* Used in address_for_loaded_kmod.
  494  */
  495 static kmod_info_t * g_current_kmod_info = NULL;
  496 static const char * g_current_kmod_name = NULL;
  497 
  498 /* Globals to pass link buffer info from
  499  * address_for_loaded_kmod() and alloc_for_kmod()
  500  * to load_kmod().
  501  *
  502  * link_load_address is the address used to lay
  503  * down the linked code. It gets adjusted by the
  504  * pad between the headers size and a full page
  505  * multiple. If an error occurs this gets set to
  506  * zero so that the kld client code can detect
  507  * an address or allocation error even if kld
  508  * returns success.
  509  *
  510  * link_load_size is the size of the image as
  511  * created by kld_load_from_memory(). link_buffer_size
  512  * is the size of the buffer allocated for the final
  513  * laid-down image, and is adjusted by rounding the
  514  * load size and header size up to full-page multiples.
  515  *
  516  * link_buffer_address is set only by alloc_for_kmod();
  517  * its value is used as a check if kld_load_from_memory()
  518  * fails so that the buffer can be deallocated. 
  519  */
  520 static unsigned long link_load_address = 0;
  521 static unsigned long link_load_size = 0;
  522 static unsigned long link_buffer_size = 0;
  523 static unsigned long link_header_size = 0;
  524 static unsigned long link_buffer_address = 0;
  525 
  526 
  527 /*********************************************************************
  528 * This function is registered before kmod_load_from_memory() is
  529 * invoked to build symbol table entries for an already-loaded
  530 * kmod. This function just checks the g_current_kmod_info variable
  531 * to gets its load address, and futzes it by the header offset (pad).
  532 * See lower comments for more info on load address futzing.
  533 *********************************************************************/
  534 static
  535 unsigned long address_for_loaded_kmod(
  536     unsigned long size,
  537     unsigned long headers_size) {
  538 
  539     unsigned long round_headers_size;
  540     unsigned long headers_pad;
  541 
  542     if (!g_current_kmod_info) {
  543         IOLog("address_for_loaded_kmod(): No current kmod.\n");
  544         LOG_DELAY();
  545         link_load_address = 0;  // error sentinel for kld client
  546         return 0;
  547     }
  548 
  549     round_headers_size = round_page_32(headers_size);
  550     headers_pad = round_headers_size - headers_size;
  551 
  552     link_load_address = (unsigned long)g_current_kmod_info->address +
  553         headers_pad;
  554 
  555     return link_load_address;
  556 }
  557 
  558 
  559 /*********************************************************************
  560 * This function is registered before kmod_load_from_memory() is
  561 * invoked to actually load a new kmod. It rounds up the header and
  562 * total sizes and vm_allocates a buffer for the kmod. Now, KLD doesn't
  563 * enforce any alignment of headers or segments, and we want to make
  564 * sure that the executable code of the kmod lies on a page boundary.
  565 * to do so, this function figures the pad between the actual header
  566 * size and the page-rounded header size, and returns that offset into
  567 * the allocated buffer. After kmod_load_from_memory() returns, its
  568 * caller will move the mach_header struct back to the beginning of the
  569 * allocated buffer so that the kmod_info_t structure contains the
  570 * correct address.
  571 *********************************************************************/
  572 static
  573 unsigned long alloc_for_kmod(
  574     unsigned long size,
  575     unsigned long headers_size) {
  576 
  577     vm_address_t  buffer = 0;
  578     kern_return_t k_result;
  579 
  580     unsigned long round_headers_size;
  581     unsigned long round_segments_size;
  582     unsigned long round_size;
  583     unsigned long headers_pad;
  584 
  585     round_headers_size  = round_page_32(headers_size);
  586     round_segments_size = round_page_32(size - headers_size);
  587     round_size  = round_headers_size + round_segments_size;
  588     headers_pad = round_headers_size - headers_size;
  589 
  590     k_result = vm_allocate(kernel_map, (vm_offset_t *)&buffer,
  591         round_size, VM_FLAGS_ANYWHERE);
  592     if (k_result != KERN_SUCCESS) {
  593         IOLog("alloc_for_kmod(): Can't allocate memory.\n");
  594         LOG_DELAY();
  595         link_buffer_address = 0;  // make sure it's clear
  596         link_load_address = 0;    // error sentinel for kld client
  597         return 0;
  598     }
  599 
  600     link_load_size = size;
  601 
  602     link_buffer_address = buffer;
  603     link_buffer_size = round_size;
  604     link_header_size = headers_size; // NOT rounded!
  605 
  606     link_load_address = link_buffer_address + headers_pad;
  607 
  608     return link_load_address;
  609 }
  610 
  611 /*********************************************************************
  612 * This function reads the startup extensions dictionary to get the
  613 * address and length of the executable data for the requested kmod.
  614 *********************************************************************/
  615 static
  616 int map_and_patch(const char * kmod_name) {
  617 
  618     char *address;
  619 
  620     // Does the kld system already know about this kmod?
  621     address = (char *) kld_file_getaddr(kmod_name, NULL);
  622     if (address)
  623         return 1;
  624 
  625     // None of these needs to be released.
  626     OSDictionary * extensionsDict;
  627     OSDictionary * kmodDict;
  628     OSData * compressedCode = 0;
  629 
  630     // Driver Code may need to be released
  631     OSData * driverCode;
  632 
  633    /* Get the requested kmod's info dictionary from the global
  634     * startup extensions dictionary.
  635     */
  636     extensionsDict = getStartupExtensions();
  637     if (!extensionsDict) {
  638         IOLog("map_and_patch(): No extensions dictionary.\n");
  639         LOG_DELAY();
  640         return 0;
  641     }
  642     
  643     kmodDict = OSDynamicCast(OSDictionary,
  644         extensionsDict->getObject(kmod_name));
  645     if (!kmodDict) {
  646         IOLog("map_and_patch(): "
  647             "Extension \"%s\" cannot be found.\n", kmod_name);
  648         LOG_DELAY();
  649         return 0;
  650     }
  651 
  652     Boolean ret = false;
  653 
  654     driverCode = OSDynamicCast(OSData, kmodDict->getObject("code"));
  655     if (driverCode) {
  656         ret =  kld_file_map(kmod_name,
  657                             (unsigned char *) driverCode->getBytesNoCopy(),
  658                             (size_t) driverCode->getLength(),
  659                             /* isKmem */ false);
  660     }
  661     else {      // May be an compressed extension
  662 
  663         // If we have a compressed segment the uncompressModule
  664         // will return a new OSData object that points to the kmem_alloced
  665         // memory.  Note we don't take a reference to driverCode so later
  666         // when we release it we will actually free this driver.  Ownership
  667         // of the kmem has been handed of to kld_file.
  668         compressedCode = OSDynamicCast(OSData,
  669             kmodDict->getObject("compressedCode"));
  670         if (!compressedCode) {
  671             IOLog("map_and_patch(): "
  672                  "Extension \"%s\" has no \"code\" property.\n", kmod_name);
  673             LOG_DELAY();
  674             return 0;
  675         }
  676         if (!uncompressModule(compressedCode, &driverCode)) {
  677             IOLog("map_and_patch(): "
  678                  "Extension \"%s\" Couldn't uncompress code.\n", kmod_name);
  679             LOG_DELAY();
  680             return 0;
  681         }
  682 
  683         unsigned char *driver = (unsigned char *) driverCode->getBytesNoCopy();
  684         size_t driverSize = driverCode->getLength();
  685 
  686         ret =  kld_file_map(kmod_name, driver, driverSize, /* isKmem */ true);
  687         driverCode->release();
  688         if (!ret)
  689             kmem_free(kernel_map, (vm_address_t) driver, driverSize);
  690     }
  691 
  692     if (!ret) {
  693         IOLog("map_and_patch(): "
  694               "Extension \"%s\" Didn't successfully load.\n", kmod_name);
  695         LOG_DELAY();
  696         return 0;
  697     }
  698 
  699     ret = TRUE;
  700     if (!kld_file_patch_OSObjects(kmod_name)) {
  701         IOLog("map_and_patch(): "
  702               "Extension \"%s\" Error binding OSObjects.\n", kmod_name);
  703         LOG_DELAY();
  704         
  705         // RY: Instead of returning here, set the return value.
  706         // We still need to call kld_file_prepare_for_link because
  707         // we might have patched files outside of the driver.  Don't
  708         // worry, it will know to ignore the damaged file
  709         ret = FALSE;
  710     }
  711 
  712     // Now repair any damage that the kld patcher may have done to the image
  713     kld_file_prepare_for_link();
  714 
  715     return ret;
  716 }
  717 
  718 /*********************************************************************
  719 *********************************************************************/
  720 bool stamp_kmod(const char * kmod_name, kmod_info_t * kmod_info) {
  721     bool result = false;
  722     OSDictionary * extensionsDict = NULL;  // don't release
  723     OSDictionary * kmodDict = NULL;        // don't release
  724     OSDictionary * plist = NULL;           // don't release
  725     OSString     * versionString = NULL;   // don't release
  726     const char   * plist_version = NULL;   // don't free
  727 
  728     if (strlen(kmod_name) + 1 > KMOD_MAX_NAME) {
  729         IOLog("stamp_kmod(): Kext identifier \"%s\" is too long.\n",
  730             kmod_name);
  731         LOG_DELAY();
  732         result = false;
  733         goto finish;
  734     }
  735 
  736     strcpy(kmod_info->name, kmod_name);
  737 
  738    /* Get the dictionary of startup extensions.
  739     * This is keyed by module name.
  740     */
  741     extensionsDict = getStartupExtensions();
  742     if (!extensionsDict) {
  743         IOLog("stamp_kmod(): No extensions dictionary.\n");
  744         LOG_DELAY();
  745         result = false;
  746         goto finish;
  747     }
  748 
  749     kmodDict = OSDynamicCast(OSDictionary,
  750         extensionsDict->getObject(kmod_name));
  751     if (!kmodDict) {
  752         IOLog("stamp_kmod(): Can't find record for kmod \"%s\".\n",
  753             kmod_name);
  754         LOG_DELAY();
  755         result = false;
  756         goto finish;
  757     }
  758 
  759     plist = OSDynamicCast(OSDictionary,
  760         kmodDict->getObject("plist"));
  761     if (!kmodDict) {
  762         IOLog("stamp_kmod(): Kmod \"%s\" has no property list.\n",
  763             kmod_name);
  764         LOG_DELAY();
  765         result = false;
  766         goto finish;
  767     }
  768 
  769    /*****
  770     * Get the kext's version and stuff it into the kmod. This used
  771     * to be a check that the kext & kmod had the same version, but
  772     * now we just overwrite the kmod's version.
  773     */
  774 
  775     versionString = OSDynamicCast(OSString,
  776         plist->getObject("CFBundleVersion"));
  777     if (!versionString) {
  778         IOLog("stamp_kmod(): Kmod \"%s\" has no \"CFBundleVersion\" "
  779             "property.\n",
  780             kmod_name);
  781         LOG_DELAY();
  782         result = false;
  783         goto finish;
  784     }
  785 
  786     plist_version = versionString->getCStringNoCopy();
  787     if (!plist_version) {
  788         IOLog("stamp_kmod(): Can't get C string for kext version.\n");
  789         LOG_DELAY();
  790         result = false;
  791         goto finish;
  792     }
  793 
  794     if (strlen(plist_version) + 1 > KMOD_MAX_NAME) {
  795         IOLog("stamp_kmod(): Version \"%s\" of kext \"%s\" is too long.\n",
  796             plist_version, kmod_name);
  797         LOG_DELAY();
  798         result = false;
  799         goto finish;
  800     }
  801 
  802     strcpy(kmod_info->version, plist_version);
  803 
  804     result = true;
  805 
  806 finish:
  807 
  808     return result;
  809 }
  810 
  811 
  812 /*********************************************************************
  813 * This function takes a dependency list containing a series of
  814 * already-loaded module names, followed by a single name for a module
  815 * that hasn't yet been loaded. It invokes kld_load_from_memory() to
  816 * build symbol info for the already-loaded modules, and then finally
  817 * loads the actually requested module.
  818 *********************************************************************/
  819 static
  820 kern_return_t load_kmod(OSArray * dependencyList) {
  821     kern_return_t result = KERN_SUCCESS;
  822 
  823     unsigned int  num_dependencies = 0;
  824     kmod_info_t ** kmod_dependencies = NULL;
  825     unsigned int  i;
  826     OSString    * requestedKmodName;   // don't release
  827     const char  * requested_kmod_name;
  828     OSString    * currentKmodName;     // don't release
  829     char        * kmod_address;
  830     unsigned long kmod_size;
  831     struct mach_header * kmod_header;
  832     unsigned long kld_result;
  833     int           do_kld_unload = 0;
  834     kmod_info_t * kmod_info_freeme = 0;
  835     kmod_info_t * kmod_info = 0;
  836     kmod_t        kmod_id;
  837 
  838 
  839    /* Separate the requested kmod from its dependencies.
  840     */
  841     i = dependencyList->getCount();
  842     if (i == 0) {
  843         IOLog("load_kmod(): Called with empty list.\n");
  844         LOG_DELAY();
  845         result = KERN_FAILURE;
  846         goto finish;
  847     } else {
  848         i--;  // make i be the index of the last entry
  849     }
  850 
  851     requestedKmodName = OSDynamicCast(OSString, dependencyList->getObject(i));
  852     if (!requestedKmodName) {
  853         IOLog("load_kmod(): Called with invalid list of kmod names.\n");
  854         LOG_DELAY();
  855         result = KERN_FAILURE;
  856         goto finish;
  857     }
  858     requested_kmod_name = requestedKmodName->getCStringNoCopy();
  859     dependencyList->removeObject(i);
  860 
  861    /* If the requested kmod is already loaded, there's no work to do.
  862     */
  863     kmod_info_freeme = kmod_lookupbyname_locked(requested_kmod_name);
  864     if (kmod_info_freeme) {
  865         // FIXME: Need to check for version mismatch if already loaded.
  866         result = KERN_SUCCESS;
  867         goto finish;
  868     }
  869 
  870 
  871    /* Do the KLD loads for the already-loaded modules in order to get
  872     * their symbols.
  873     */
  874     kld_address_func(&address_for_loaded_kmod);
  875 
  876     num_dependencies = dependencyList->getCount();
  877     kmod_dependencies = (kmod_info_t **)kalloc(num_dependencies *
  878         sizeof(kmod_info_t *));
  879     if (!kmod_dependencies) {
  880         IOLog("load_kmod(): Failed to allocate memory for dependency array "
  881             "during load of kmod \"%s\".\n", requested_kmod_name);
  882         LOG_DELAY();
  883         result = KERN_FAILURE;
  884         goto finish;
  885     }
  886 
  887     bzero(kmod_dependencies, num_dependencies *
  888         sizeof(kmod_info_t *));
  889 
  890     for (i = 0; i < num_dependencies; i++) {
  891 
  892         currentKmodName = OSDynamicCast(OSString,
  893             dependencyList->getObject(i));
  894 
  895         if (!currentKmodName) {
  896             IOLog("load_kmod(): Invalid dependency name at index %d for "
  897                 "kmod \"%s\".\n", i, requested_kmod_name);
  898             LOG_DELAY();
  899             result = KERN_FAILURE;
  900             goto finish;
  901         }
  902 
  903         const char * current_kmod_name = currentKmodName->getCStringNoCopy();
  904 
  905         // These globals are needed by the kld_address functions
  906         g_current_kmod_info = kmod_lookupbyname_locked(current_kmod_name);
  907         g_current_kmod_name = current_kmod_name;
  908 
  909         if (!g_current_kmod_info) {
  910             IOLog("load_kmod(): Missing dependency \"%s\".\n",
  911                 current_kmod_name);
  912             LOG_DELAY();
  913             result = KERN_FAILURE;
  914             goto finish;
  915         }
  916 
  917        /* Record the current kmod as a dependency of the requested
  918         * one. This will be used in building references after the
  919         * load is complete.
  920         */
  921         kmod_dependencies[i] = g_current_kmod_info;
  922 
  923         /* If the current kmod's size is zero it means that we have a
  924          * fake in-kernel dependency.  If so then don't have to arrange
  925          * for its symbol table to be reloaded as it is
  926          * part of the kernel's symbol table..
  927          */ 
  928         if (!g_current_kmod_info->size)
  929             continue;
  930 
  931         if (!kld_file_merge_OSObjects(current_kmod_name)) {
  932             IOLog("load_kmod(): Can't merge OSObjects \"%s\".\n",
  933                 current_kmod_name);
  934             LOG_DELAY();
  935             result = KERN_FAILURE;
  936             goto finish;
  937         }
  938 
  939         kmod_address = (char *)
  940             kld_file_getaddr(current_kmod_name, (long *) &kmod_size);
  941         if (!kmod_address) {
  942 
  943             IOLog("load_kmod() failed for dependency kmod "
  944                 "\"%s\".\n", current_kmod_name);
  945             LOG_DELAY();
  946             result = KERN_FAILURE;
  947             goto finish;
  948         }
  949 
  950         kld_result = kld_load_from_memory(&kmod_header,
  951             current_kmod_name, kmod_address, kmod_size);
  952 
  953         if (kld_result) {
  954             do_kld_unload = 1;
  955         }
  956 
  957         if (!kld_result || !link_load_address) {
  958             IOLog("kld_load_from_memory() failed for dependency kmod "
  959                 "\"%s\".\n", current_kmod_name);
  960             LOG_DELAY();
  961             result = KERN_FAILURE;
  962             goto finish;
  963         }
  964 
  965         kld_forget_symbol("_kmod_info");
  966     }
  967 
  968    /*****
  969     * Now that we've done all the dependencies, which should have already
  970     * been loaded, we do the last requested module, which should not have
  971     * already been loaded.
  972     */
  973     kld_address_func(&alloc_for_kmod);
  974 
  975     g_current_kmod_name = requested_kmod_name;
  976     g_current_kmod_info = 0;  // there is no kmod yet
  977 
  978     if (!map_and_patch(requested_kmod_name)) {
  979         IOLog("load_kmod: map_and_patch() failed for "
  980             "kmod \"%s\".\n", requested_kmod_name);
  981         LOG_DELAY();
  982         result = KERN_FAILURE;
  983         goto finish;
  984     }
  985 
  986     kmod_address = (char *)
  987         kld_file_getaddr(requested_kmod_name, (long *) &kmod_size);
  988     if (!kmod_address) {
  989         IOLog("load_kmod: kld_file_getaddr()  failed internal error "
  990             "on \"%s\".\n", requested_kmod_name);
  991         LOG_DELAY();
  992         result = KERN_FAILURE;
  993         goto finish;
  994     }
  995 
  996     kld_result = kld_load_from_memory(&kmod_header,
  997                             requested_kmod_name, kmod_address, kmod_size);
  998 
  999     if (kld_result) {
 1000         do_kld_unload = 1;
 1001     }
 1002 
 1003     if (!kld_result || !link_load_address) {
 1004         IOLog("load_kmod(): kld_load_from_memory() failed for "
 1005             "kmod \"%s\".\n", requested_kmod_name);
 1006         LOG_DELAY();
 1007         result = KERN_FAILURE;
 1008         goto finish;
 1009     }
 1010 
 1011 
 1012    /* Copy the linked header and image into the vm_allocated buffer.
 1013     * Move each onto the appropriate page-aligned boundary as given
 1014     * by the global link_... variables.
 1015     */
 1016     bzero((char *)link_buffer_address, link_buffer_size);
 1017     // bcopy() is (from, to, length)
 1018     bcopy((char *)kmod_header, (char *)link_buffer_address, link_header_size);
 1019     bcopy((char *)kmod_header + link_header_size,
 1020         (char *)link_buffer_address + round_page_32(link_header_size),
 1021         link_load_size - link_header_size);
 1022 
 1023 
 1024    /* Get the kmod_info struct for the newly-loaded kmod.
 1025     */
 1026     if (!kld_lookup("_kmod_info", (unsigned long *)&kmod_info)) {
 1027         IOLog("kld_lookup() of \"_kmod_info\" failed for "
 1028             "kmod \"%s\".\n", requested_kmod_name);
 1029         LOG_DELAY();
 1030         result = KERN_FAILURE;
 1031         goto finish;
 1032     }
 1033 
 1034 
 1035     if (!stamp_kmod(requested_kmod_name, kmod_info)) {
 1036         // stamp_kmod() logs a meaningful message
 1037         result = KERN_FAILURE;
 1038         goto finish;
 1039     }
 1040 
 1041 
 1042    /* kld_lookup of _kmod_info yielded the actual linked address,
 1043     * so now that we've copied the data into its real place,
 1044     * we can set this stuff.
 1045     */
 1046     kmod_info->address = link_buffer_address;
 1047     kmod_info->size = link_buffer_size;
 1048     kmod_info->hdr_size = round_page_32(link_header_size);
 1049 
 1050    /* We've written data and instructions, so *flush* the data cache
 1051     * and *invalidate* the instruction cache.
 1052     */
 1053     flush_dcache64((addr64_t)link_buffer_address, link_buffer_size, false);
 1054     invalidate_icache64((addr64_t)link_buffer_address, link_buffer_size, false);
 1055 
 1056 
 1057    /* Register the new kmod with the kernel proper.
 1058     */
 1059     if (kmod_create_internal(kmod_info, &kmod_id) != KERN_SUCCESS) {
 1060         IOLog("load_kmod(): kmod_create() failed for "
 1061             "kmod \"%s\".\n", requested_kmod_name);
 1062         LOG_DELAY();
 1063         result = KERN_FAILURE;
 1064         goto finish;
 1065     }
 1066 
 1067 #if DEBUG
 1068     IOLog("kmod id %d successfully created at 0x%lx, size %ld.\n",
 1069         (unsigned int)kmod_id, link_buffer_address, link_buffer_size);
 1070     LOG_DELAY();
 1071 #endif /* DEBUG */
 1072 
 1073    /* Record dependencies for the newly-loaded kmod.
 1074     */
 1075     for (i = 0; i < num_dependencies; i++) {
 1076         kmod_info_t * cur_dependency_info;
 1077         kmod_t packed_id;
 1078         cur_dependency_info = kmod_dependencies[i];
 1079         packed_id = KMOD_PACK_IDS(kmod_id, cur_dependency_info->id);
 1080         if (kmod_retain(packed_id) != KERN_SUCCESS) {
 1081             IOLog("load_kmod(): kmod_retain() failed for "
 1082                 "kmod \"%s\".\n", requested_kmod_name);
 1083             LOG_DELAY();
 1084             kmod_destroy_internal(kmod_id);
 1085             result = KERN_FAILURE;
 1086             goto finish;
 1087         }
 1088     }
 1089 
 1090    /* Start the kmod (which invokes constructors for I/O Kit
 1091     * drivers.
 1092     */
 1093     // kmod_start_or_stop(id, start?, user data, datalen)
 1094     if (kmod_start_or_stop(kmod_id, 1, 0, 0) != KERN_SUCCESS) {
 1095         IOLog("load_kmod(): kmod_start_or_stop() failed for "
 1096             "kmod \"%s\".\n", requested_kmod_name);
 1097         LOG_DELAY();
 1098         kmod_destroy_internal(kmod_id);
 1099         result = KERN_FAILURE;
 1100         goto finish;
 1101     }
 1102 
 1103 finish:
 1104 
 1105     if (kmod_info_freeme) {
 1106         kfree((unsigned int)kmod_info_freeme, sizeof(kmod_info_t));
 1107     }
 1108 
 1109    /* Only do a kld_unload_all() if at least one load happened.
 1110     */
 1111     if (do_kld_unload) {
 1112         kld_unload_all(/* deallocate sets */ 1);
 1113     }
 1114 
 1115    /* If the link failed, blow away the allocated link buffer.
 1116     */
 1117     if (result != KERN_SUCCESS && link_buffer_address) {
 1118         vm_deallocate(kernel_map, link_buffer_address, link_buffer_size);
 1119     }
 1120 
 1121     if (kmod_dependencies) {
 1122         for (i = 0; i < num_dependencies; i++) {
 1123             if (kmod_dependencies[i]) {
 1124                 kfree((unsigned int)kmod_dependencies[i], sizeof(kmod_info_t));
 1125             }
 1126         }
 1127         kfree((unsigned int)kmod_dependencies,
 1128             num_dependencies * sizeof(kmod_info_t *));
 1129     }
 1130 
 1131    /* Reset these static global variables for the next call.
 1132     */
 1133     g_current_kmod_name = NULL;
 1134     g_current_kmod_info = NULL;
 1135     link_buffer_address = 0;
 1136     link_load_address = 0;
 1137     link_load_size = 0;
 1138     link_buffer_size = 0;
 1139     link_header_size = 0;
 1140 
 1141     return result;
 1142 }
 1143 
 1144 
 1145 /*********************************************************************
 1146 * This is the function that IOCatalogue calls in order to load a kmod.
 1147 * It first checks whether the kmod is already loaded. If the kmod
 1148 * isn't loaded, this function builds a dependency list and calls
 1149 * load_kmod() repeatedly to guarantee that each dependency is in fact
 1150 * loaded.
 1151 *********************************************************************/
 1152 __private_extern__
 1153 kern_return_t load_kernel_extension(char * kmod_name) {
 1154     kern_return_t result = KERN_SUCCESS;
 1155     kmod_info_t * kmod_info = 0;  // must free
 1156     OSArray * dependencyList = NULL;     // must release
 1157     OSArray * curDependencyList = NULL;  // must release
 1158 
 1159    /* See if the kmod is already loaded.
 1160     */
 1161     kmod_info = kmod_lookupbyname_locked(kmod_name);
 1162     if (kmod_info) {  // NOT checked
 1163         result = KERN_SUCCESS;
 1164         goto finish;
 1165     }
 1166 
 1167    /* It isn't loaded; build a dependency list and
 1168     * load those.
 1169     */
 1170     unsigned int count;
 1171     unsigned int i;
 1172     dependencyList = getDependencyListForKmod(kmod_name);
 1173     if (!dependencyList) {
 1174         IOLog("load_kernel_extension(): "
 1175             "Can't get dependencies for kernel extension \"%s\".\n",
 1176             kmod_name);
 1177         LOG_DELAY();
 1178         result = KERN_FAILURE;
 1179         goto finish;
 1180     }
 1181 
 1182     count = dependencyList->getCount();
 1183     for (i = 0; i < count; i++) {
 1184         kern_return_t load_result;
 1185         OSString * curKmodName;  // don't release
 1186         const char * cur_kmod_name;
 1187 
 1188         curKmodName = OSDynamicCast(OSString,
 1189             dependencyList->getObject(i));
 1190         cur_kmod_name = curKmodName->getCStringNoCopy();
 1191         curDependencyList = getDependencyListForKmod(cur_kmod_name);
 1192         if (!curDependencyList) {
 1193             IOLog("load_kernel_extension(): "
 1194                 "Can't get dependencies for kernel extension \"%s\".\n",
 1195                 cur_kmod_name);
 1196             LOG_DELAY();
 1197             result = KERN_FAILURE;
 1198             goto finish;
 1199         } else {
 1200             load_result = load_kmod(curDependencyList);
 1201             if (load_result != KERN_SUCCESS) {
 1202                 IOLog("load_kernel_extension(): "
 1203                     "load_kmod() failed for kmod \"%s\".\n",
 1204                     cur_kmod_name);
 1205                 LOG_DELAY();
 1206                 result = load_result;
 1207                 goto finish;
 1208             }
 1209             curDependencyList->release();
 1210             curDependencyList = NULL;
 1211         }
 1212     }
 1213 
 1214 
 1215 finish:
 1216 
 1217     if (kmod_info) {
 1218         kfree((unsigned int)kmod_info, sizeof(kmod_info_t));
 1219     }
 1220 
 1221     if (dependencyList) {
 1222         dependencyList->release();
 1223         dependencyList = NULL;
 1224     }
 1225     if (curDependencyList) {
 1226         curDependencyList->release();
 1227         curDependencyList = NULL;
 1228     }
 1229 
 1230     return result;
 1231 }

Cache object: 1a189f4b7a0c71f1e3cc28ff9fb51a6d


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