1/*
2 * Copyright (c) 2008-2012 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29#ifndef _LIBKERN_OSKEXT_H
30#define _LIBKERN_OSKEXT_H
31
32extern "C" {
33#include <kern/thread_call.h>
34#include <libkern/OSKextLibPrivate.h>
35#include <libkern/kernel_mach_header.h>
36#include <libkern/kxld.h>
37#include <mach/kmod.h>
38
39#ifdef XNU_KERNEL_PRIVATE
40#include <kern/thread_call.h>
41#endif /* XNU_KERNEL_PRIVATE */
42}
43
44#include <libkern/OSKextLib.h>
45#include <libkern/OSKextLibPrivate.h>
46#include <libkern/c++/OSObject.h>
47#include <libkern/c++/OSContainers.h>
48#include <IOKit/IOLocks.h>
49
50/*********************************************************************
51* C functions used for callbacks.
52*********************************************************************/
53#ifdef XNU_KERNEL_PRIVATE
54extern "C" {
55void osdata_kmem_free(void * ptr, unsigned int length);
56void osdata_phys_free(void * ptr, unsigned int length);
57void osdata_vm_deallocate(void * ptr, unsigned int length);
58};
59#endif /* XNU_KERNEL_PRIVATE */
60
61/*********************************************************************
62* C Function Prototypes for Friend Declarations.
63*********************************************************************/
64class OSKext;
65
66extern "C" {
67
68void OSKextLog(
69    OSKext         * aKext,
70    OSKextLogSpec    msgLogSpec,
71    const char     * format, ...)
72        __attribute__((format(printf, 3, 4)));
73
74void OSKextVLog(
75    OSKext         * aKext,
76    OSKextLogSpec    msgLogSpec,
77    const char     * format,
78    va_list          srcArgList);
79
80#ifdef XNU_KERNEL_PRIVATE
81void OSKextRemoveKextBootstrap(void);
82void IOSystemShutdownNotification(void);
83
84kern_return_t OSRuntimeInitializeCPP(
85    kmod_info_t * kmodInfo,
86    void *        data);
87kern_return_t OSRuntimeFinalizeCPP(
88    kmod_info_t * kmodInfo,
89    void        * data);
90
91kern_return_t is_io_catalog_send_data(
92    mach_port_t              masterPort,
93    uint32_t                 flag,
94    io_buf_ptr_t             inData,
95    mach_msg_type_number_t   inDataCount,
96    kern_return_t          * result);
97
98void kmod_dump_log(vm_offset_t*, unsigned int);
99
100
101#endif /* XNU_KERNEL_PRIVATE */
102};
103
104/********************************************************************/
105#if PRAGMA_MARK
106#pragma mark -
107#endif
108/*
109 * @class OSKext
110 */
111/********************************************************************/
112class OSKext : public OSObject
113{
114    OSDeclareDefaultStructors(OSKext)
115
116#if PRAGMA_MARK
117/**************************************/
118#pragma mark Friend Declarations
119/**************************************/
120#endif
121    friend class IOCatalogue;
122    friend class KLDBootstrap;
123    friend class OSMetaClass;
124
125#ifdef XNU_KERNEL_PRIVATE
126    friend void OSKextVLog(
127        OSKext         * aKext,
128        OSKextLogSpec    msgLogSpec,
129        const char     * format,
130        va_list          srcArgList);
131
132    friend void OSKextRemoveKextBootstrap(void);
133    friend void IOSystemShutdownNotification(void);
134    friend OSReturn OSKextUnloadKextWithLoadTag(uint32_t);
135
136    friend kern_return_t kext_request(
137        host_priv_t                             hostPriv,
138        /* in only */  uint32_t                 clientLogSpec,
139        /* in only */  vm_offset_t              requestIn,
140        /* in only */  mach_msg_type_number_t   requestLengthIn,
141        /* out only */ vm_offset_t            * responseOut,
142        /* out only */ mach_msg_type_number_t * responseLengthOut,
143        /* out only */ vm_offset_t            * logDataOut,
144        /* out only */ mach_msg_type_number_t * logDataLengthOut,
145        /* out only */ kern_return_t          * op_result);
146
147    friend kxld_addr_t kern_allocate(
148        u_long              size,
149        KXLDAllocateFlags * flags,
150        void              * user_data);
151
152    friend void kxld_log_shim(
153        KXLDLogSubsystem    subsystem,
154        KXLDLogLevel        level,
155        const char        * format,
156        va_list             argList,
157        void              * user_data);
158
159    friend void _OSKextConsiderUnloads(
160        __unused thread_call_param_t p0,
161        __unused thread_call_param_t p1);
162
163    friend kern_return_t OSRuntimeInitializeCPP(
164        kmod_info_t * kmodInfo,
165        void *        data);
166    friend kern_return_t OSRuntimeFinalizeCPP(
167        kmod_info_t * kmodInfo,
168        void        * data);
169
170    friend kern_return_t is_io_catalog_send_data(
171            mach_port_t              masterPort,
172            uint32_t                 flag,
173            io_buf_ptr_t             inData,
174            mach_msg_type_number_t   inDataCount,
175            kern_return_t          * result);
176
177    friend void kmod_panic_dump(vm_offset_t*, unsigned int);
178    friend void kmod_dump_log(vm_offset_t*, unsigned int);
179    friend void kext_dump_panic_lists(int (*printf_func)(const char * fmt, ...));
180
181
182#endif /* XNU_KERNEL_PRIVATE */
183
184private:
185
186   /*************************
187    * Instance variables
188    *************************/
189    OSDictionary   * infoDict;
190
191    const OSSymbol * bundleID;
192    OSString       * path;               // not necessarily correct :-/
193    OSString       * executableRelPath;  // relative to bundle
194
195    OSKextVersion    version;            // parsed
196    OSKextVersion    compatibleVersion;  // parsed
197
198   /* These fields are required for tracking loaded kexts and
199    * will always have values for a loaded kext.
200    */
201    OSKextLoadTag    loadTag;            // 'id' from old kmod_info;
202                                         // kOSKextInvalidLoadTag invalid
203    kmod_info_t    * kmod_info;          // address into linkedExec./alloced for interface
204
205    OSArray        * dependencies;       // kernel resource does not have any;
206                                         // links directly to kernel
207
208   /* Only real kexts have these; interface kexts do not.
209    */
210    OSData         * linkedExecutable;
211    OSSet          * metaClasses;           // for C++/OSMetaClass kexts
212
213   /* Only interface kexts have these; non-interface kexts can get at them
214    * in the linked Executable.
215    */
216    OSData         * interfaceUUID;
217
218    struct {
219        unsigned int loggingEnabled:1;
220
221        unsigned int hasAllDependencies:1;
222        unsigned int hasBleedthrough:1;
223
224        unsigned int interface:1;
225        unsigned int kernelComponent:1;
226        unsigned int prelinked:1;
227        unsigned int loaded:1;
228        unsigned int dtraceInitialized:1;
229        unsigned int starting:1;
230        unsigned int started:1;
231        unsigned int stopping:1;
232        unsigned int unloading:1;
233
234        unsigned int autounloadEnabled:1;
235        unsigned int delayAutounload:1;    // for development
236
237        unsigned int CPPInitialized:1;
238        unsigned int jettisonLinkeditSeg:1;
239    } flags;
240
241#if PRAGMA_MARK
242/**************************************/
243#pragma mark Private Functions
244/**************************************/
245#endif
246
247#ifdef XNU_KERNEL_PRIVATE
248   /* Startup/shutdown phases.
249    */
250public:
251    static void           initialize(void);
252    static OSDictionary * copyKexts(void);
253    static OSReturn       removeKextBootstrap(void);
254    static void           willShutdown(void);  // called by IOPMrootDomain on shutdown
255#endif /* XNU_KERNEL_PRIVATE */
256
257private:
258   /* Called by power management at sleep/shutdown.
259    */
260    static bool setLoadEnabled(bool flag);
261    static bool setUnloadEnabled(bool flag);
262    static bool setAutounloadsEnabled(bool flag);
263    static bool setKernelRequestsEnabled(bool flag);
264
265    // all getters subject to race condition, caller beware
266    static bool getLoadEnabled(void);
267    static bool getUnloadEnabled(void);
268    static bool getAutounloadEnabled(void);
269    static bool getKernelRequestsEnabled(void);
270
271   /* Instance life cycle.
272    */
273    static OSKext * withBooterData(
274        OSString * deviceTreeName,
275        OSData   * booterData);
276    virtual bool initWithBooterData(
277        OSString * deviceTreeName,
278        OSData   * booterData);
279
280    static OSKext * withPrelinkedInfoDict(
281        OSDictionary * infoDict);
282    virtual bool initWithPrelinkedInfoDict(
283        OSDictionary * infoDict);
284
285    static OSKext * withMkext2Info(
286        OSDictionary * anInfoDict,
287        OSData       * mkextData);
288    virtual bool initWithMkext2Info(
289        OSDictionary * anInfoDict,
290        OSData       * mkextData);
291
292    virtual bool setInfoDictionaryAndPath(
293        OSDictionary * aDictionary,
294        OSString     * aPath);
295    virtual bool setExecutable(
296        OSData       * anExecutable,
297        OSData       * externalData        = NULL,
298        bool           externalDataIsMkext = false);
299    virtual bool registerIdentifier(void);
300
301    virtual void free(void);
302
303    static OSReturn removeKext(
304        OSKext * aKext,
305        bool     terminateServicesAndRemovePersonalitiesFlag = false);
306
307    virtual bool isInExcludeList(void);
308
309   /* Mkexts.
310    */
311    static OSReturn readMkextArchive(
312        OSData   * mkextData,
313        uint32_t * checksumPtr = NULL);
314    static OSReturn readMkext2Archive(
315        OSData * mkextData,
316        OSDictionary ** mkextPlistOut,
317        uint32_t * checksumPtr = NULL);
318    virtual OSData * createMkext2FileEntry(
319        OSData * mkextData,
320        OSNumber * offsetNum,
321        const char * entryName);
322    virtual OSData * extractMkext2FileData(
323        UInt8      * data,
324        const char * name,
325        uint32_t     compressedSize,
326        uint32_t     fullSize);
327
328    static OSReturn readMkext1Archive(
329        OSData   * mkextData,
330        uint32_t * checksumPtr);
331    bool initWithMkext1Info(
332        OSDictionary * anInfoDict,
333        OSData       * executableWrapper,
334        OSData       * mkextData);
335    static OSData * extractMkext1Entry(
336        const void * mkextFileBase,
337        const void * entry);
338
339   /* Dependencies.
340    */
341    virtual bool resolveDependencies(
342        OSArray * loopStack = NULL); // priv/prot
343    virtual bool addBleedthroughDependencies(OSArray * anArray);
344    virtual bool flushDependencies(bool forceFlag = false); // priv/prot
345    virtual uint32_t  getNumDependencies(void);
346    virtual OSArray * getDependencies(void);
347
348   /* User-space requests (load/generic).
349    */
350    static OSReturn loadFromMkext(
351        OSKextLogSpec   clientLogSpec,
352        char          * mkextBuffer,
353        uint32_t        mkextBufferLength,
354        char         ** logInfoOut,
355        uint32_t      * logInfoLengthOut);
356    static OSReturn handleRequest(
357        host_priv_t     hostPriv,
358        OSKextLogSpec   clientLogSpec,
359        char          * requestBuffer,
360        uint32_t        requestLength,
361        char         ** responseOut,
362        uint32_t      * responseLengthOut,
363        char         ** logInfoOut,
364        uint32_t      * logInfoLengthOut);
365    static OSReturn serializeLogInfo(
366        OSArray   * logInfoArray,
367        char     ** logInfoOut,
368        uint32_t  * logInfoLengthOut);
369
370   /* Loading.
371    */
372    virtual OSReturn load(
373        OSKextExcludeLevel   startOpt         = kOSKextExcludeNone,
374        OSKextExcludeLevel   startMatchingOpt = kOSKextExcludeAll,
375        OSArray            * personalityNames = NULL); // priv/prot
376    virtual OSReturn unload(void);
377    virtual OSReturn queueKextNotification(
378        const char * notificationName,
379        OSString   * kextIdentifier);
380
381    static void recordIdentifierRequest(
382        OSString * kextIdentifier);
383
384    virtual OSReturn slidePrelinkedExecutable(void);
385    virtual OSReturn loadExecutable(void);
386    virtual void     jettisonLinkeditSegment(void);
387    static  void     considerDestroyingLinkContext(void);
388    virtual OSData * getExecutable(void);
389    virtual void     setLinkedExecutable(OSData * anExecutable);
390
391#if CONFIG_DTRACE
392    friend  void OSKextRegisterKextsWithDTrace(void);
393    static  void registerKextsWithDTrace(void);
394    virtual void registerWithDTrace(void);
395    virtual void unregisterWithDTrace(void);
396#endif /* CONFIG_DTRACE */
397
398    virtual OSReturn start(bool startDependenciesFlag = true);
399    virtual OSReturn stop(void);
400    virtual OSReturn setVMProtections(void);
401    virtual boolean_t segmentShouldBeWired(kernel_segment_command_t *seg);
402    virtual OSReturn validateKextMapping(bool startFlag);
403    virtual boolean_t verifySegmentMapping(kernel_segment_command_t *seg);
404
405    static OSArray * copyAllKextPersonalities(
406        bool filterSafeBootFlag = false);
407
408    static  void  setPrelinkedPersonalities(OSArray * personalitiesArray);
409
410    static  void  sendAllKextPersonalitiesToCatalog(
411        bool startMatching = false);
412    virtual OSReturn  sendPersonalitiesToCatalog(
413        bool      startMatching    = false,
414        OSArray * personalityNames = NULL);
415
416    static bool canUnloadKextWithIdentifier(
417        OSString * kextIdentifier,
418        bool       checkClassesFlag = true);
419
420    static OSReturn autounloadKext(OSKext * aKext);
421
422   /* Sync with user space.
423    */
424    static OSReturn pingKextd(void);
425
426   /* Getting info about loaded kexts (kextstat).
427    */
428    static  OSDictionary * copyLoadedKextInfo(
429        OSArray * kextIdentifiers = NULL,
430        OSArray * keys = NULL);
431    virtual OSDictionary * copyInfo(OSArray * keys = NULL);
432
433   /* Logging to user space.
434    */
435    static OSKextLogSpec setUserSpaceLogFilter(
436        OSKextLogSpec  userLogSpec,
437        bool           captureFlag = false);
438    static OSArray * clearUserSpaceLogFilter(void);
439    static OSKextLogSpec getUserSpaceLogFilter(void);
440
441   /* OSMetaClasses defined by kext.
442    */
443    virtual OSReturn addClass(
444        OSMetaClass * aClass,
445        uint32_t     numClasses);
446    virtual OSReturn removeClass(
447        OSMetaClass * aClass);
448    virtual bool    hasOSMetaClassInstances(void);
449    virtual OSSet * getMetaClasses(void);
450    static  void reportOSMetaClassInstances(
451        const char     * kextIdentifier,
452        OSKextLogSpec    msgLogSpec);
453    virtual void reportOSMetaClassInstances(
454        OSKextLogSpec msgLogSpec);
455
456   /* Resource requests and other callback stuff.
457    */
458    static OSReturn dispatchResource(OSDictionary * requestDict);
459
460    static OSReturn dequeueCallbackForRequestTag(
461        OSKextRequestTag    requestTag,
462        OSDictionary     ** callbackRecordOut);
463    static OSReturn dequeueCallbackForRequestTag(
464        OSNumber     *    requestTagNum,
465        OSDictionary ** callbackRecordOut);
466    static void invokeRequestCallback(
467        OSDictionary * callbackRecord,
468        OSReturn         requestResult);
469    virtual void invokeOrCancelRequestCallbacks(
470        OSReturn callbackResult,
471        bool     invokeFlag = true);
472    virtual uint32_t countRequestCallbacks(void);
473
474   /* panic() support.
475    */
476    static void printKextsInBacktrace(
477        vm_offset_t   * addr,
478        unsigned int    cnt,
479        int          (* printf_func)(const char *fmt, ...),
480        bool            lockFlag);
481    static boolean_t summaryIsInBacktrace(
482        OSKextLoadedKextSummary * summary,
483        vm_offset_t             * addr,
484        unsigned int              cnt);
485    static void printSummary(
486        OSKextLoadedKextSummary * summary,
487        int                    (* printf_func)(const char *fmt, ...));
488
489    static uint32_t saveLoadedKextPanicListTyped(
490        const char * prefix,
491        int          invertFlag,
492        int          libsFlag,
493        char       * paniclist,
494        uint32_t     list_size,
495        uint32_t   * list_length_ptr);
496    static void saveLoadedKextPanicList(void);
497    void savePanicString(bool isLoading);
498    static void printKextPanicLists(int (*printf_func)(const char *fmt, ...));
499
500   /* Kext summary support.
501    */
502    static void updateLoadedKextSummaries(void);
503    void updateLoadedKextSummary(OSKextLoadedKextSummary *summary);
504
505    /* C++ Initialization.
506     */
507    virtual void               setCPPInitialized(bool initialized=true);
508
509
510
511#if PRAGMA_MARK
512/**************************************/
513#pragma mark Public Functions
514/**************************************/
515#endif
516public:
517    // caller must release
518    static OSKext * lookupKextWithIdentifier(const char * kextIdentifier);
519    static OSKext * lookupKextWithIdentifier(OSString * kextIdentifier);
520    static OSKext * lookupKextWithLoadTag(OSKextLoadTag aTag);
521    static OSKext * lookupKextWithAddress(vm_address_t address);
522
523    static bool isKextWithIdentifierLoaded(const char * kextIdentifier);
524
525    static OSReturn loadKextWithIdentifier(
526        const char       * kextIdentifier,
527        Boolean            allowDeferFlag      = true,
528        Boolean            delayAutounloadFlag = false,
529        OSKextExcludeLevel startOpt            = kOSKextExcludeNone,
530        OSKextExcludeLevel startMatchingOpt    = kOSKextExcludeAll,
531        OSArray          * personalityNames    = NULL);
532    static OSReturn loadKextWithIdentifier(
533        OSString         * kextIdentifier,
534        Boolean            allowDeferFlag      = true,
535        Boolean            delayAutounloadFlag = false,
536        OSKextExcludeLevel startOpt            = kOSKextExcludeNone,
537        OSKextExcludeLevel startMatchingOpt    = kOSKextExcludeAll,
538        OSArray          * personalityNames    = NULL);
539    static OSReturn removeKextWithIdentifier(
540        const char * kextIdentifier,
541        bool         terminateServicesAndRemovePersonalitiesFlag = false);
542    static OSReturn removeKextWithLoadTag(
543        OSKextLoadTag loadTag,
544        bool          terminateServicesAndRemovePersonalitiesFlag = false);
545
546    static OSReturn requestResource(
547        const char                    * kextIdentifier,
548        const char                    * resourceName,
549        OSKextRequestResourceCallback   callback,
550        void                          * context,
551        OSKextRequestTag              * requestTagOut);
552    static OSReturn cancelRequest(
553        OSKextRequestTag    requestTag,
554        void             ** contextOut);
555
556    static void     considerUnloads(Boolean rescheduleOnlyFlag = false);
557    static void     flushNonloadedKexts(Boolean flushPrelinkedKexts);
558    static void     setKextdActive(Boolean active = true);
559    static void     setDeferredLoadSucceeded(Boolean succeeded = true);
560    static void     considerRebuildOfPrelinkedKernel(void);
561    static void     createExcludeListFromBooterData(
562                                            OSDictionary * theDictionary,
563                                            OSCollectionIterator * theIterator);
564    static void     createExcludeListFromPrelinkInfo(OSArray * theInfoArray);
565
566    virtual bool    setAutounloadEnabled(bool flag);
567
568    virtual const OSSymbol   * getIdentifier(void);
569    virtual const char       * getIdentifierCString(void);
570    virtual OSKextVersion      getVersion(void);
571    virtual OSKextVersion      getCompatibleVersion(void);
572    virtual bool               isLibrary(void);
573    virtual bool               isCompatibleWithVersion(OSKextVersion aVersion);
574    virtual OSObject         * getPropertyForHostArch(const char * key);
575
576    virtual OSKextLoadTag      getLoadTag(void);
577    virtual void               getSizeInfo(uint32_t *loadSize, uint32_t *wiredSize);
578    virtual OSData           * copyUUID(void);
579    virtual OSArray          * copyPersonalitiesArray(void);
580
581   /* This removes personalities naming the kext (by CFBundleIdentifier),
582    * not all personalities defined by the kext (IOPersonalityPublisher or CFBundleIdentifier).
583    */
584    virtual void               removePersonalitiesFromCatalog(void);
585
586   /* Converts common string-valued properties to OSSymbols for lower memory consumption.
587    */
588    static void uniquePersonalityProperties(OSDictionary * personalityDict);
589
590    virtual bool               declaresExecutable(void);     // might be missing
591    virtual bool               isInterface(void);
592    virtual bool               isKernel(void);
593    virtual bool               isKernelComponent(void);
594    virtual bool               isExecutable(void);
595    virtual bool               isLoadableInSafeBoot(void);
596    virtual bool               isPrelinked(void);
597    virtual bool               isLoaded(void);
598    virtual bool               isStarted(void);
599    virtual bool               isCPPInitialized(void);
600};
601
602
603#endif /* !_LIBKERN_OSKEXT_H */
604