├── APPLE_LICENSE ├── QEQuery.c ├── QEQuery.h ├── TESTME ├── bootcaches.c ├── bootcaches.h ├── bootcaches.plist ├── bootroot.h ├── bootroot_internal.h ├── brtest.c ├── com.apple.kextd.plist ├── compression.c ├── compression.h ├── fork_program.c ├── fork_program.h ├── kcgen_main.c ├── kcgen_main.h ├── kclist_main.c ├── kclist_main.h ├── kctool_main.c ├── kctool_main.h ├── kernelcache.c ├── kernelcache.h ├── kext_logging.8 ├── kext_tools.xcodeproj └── project.pbxproj ├── kext_tools_util.c ├── kext_tools_util.h ├── kextcache-entitlements.plist ├── kextcache.8 ├── kextcache_main.c ├── kextcache_main.h ├── kextd-entitlements.plist ├── kextd.8 ├── kextd_globals.h ├── kextd_mach.defs ├── kextd_main.c ├── kextd_main.h ├── kextd_mig_server.c ├── kextd_mig_server.h ├── kextd_personalities.c ├── kextd_personalities.h ├── kextd_request.c ├── kextd_request.h ├── kextd_serialize_kextload.c ├── kextd_usernotification.c ├── kextd_usernotification.h ├── kextd_watchvol.c ├── kextd_watchvol.h ├── kextfind.8 ├── kextfind_commands.c ├── kextfind_commands.h ├── kextfind_main.c ├── kextfind_main.h ├── kextfind_query.c ├── kextfind_query.h ├── kextfind_report.c ├── kextfind_report.h ├── kextfind_tables.c ├── kextfind_tables.h ├── kextlibs.8 ├── kextlibs_main.c ├── kextlibs_main.h ├── kextload-entitlements.plist ├── kextload.8 ├── kextload_main.c ├── kextload_main.h ├── kextmanager.defs ├── kextmanager_async.defs ├── kextstat-entitlements.plist ├── kextstat.8 ├── kextstat_main.c ├── kextstat_main.h ├── kextunload.8 ├── kextunload_main.c ├── kextunload_main.h ├── kextutil-entitlements.plist ├── kextutil.8 ├── kextutil_main.c ├── kextutil_main.h ├── mkext.c ├── mkext1_file.c ├── mkext1_file.h ├── mkextunpack.8 ├── mkextunpack_main.c ├── pgo.c ├── pgo.h ├── safecalls.c ├── safecalls.h ├── security.c ├── security.h └── update_boot.c /TESTME: -------------------------------------------------------------------------------- 1 | #/bin/sh -e 2 | 3 | # Currently, this TESTME script is capable of generating command lines 4 | # that can be copied and pasted. 5 | 6 | # re-launch a copy from /tmp 7 | tmprun="${TMP:-/tmp}/kt.TESTME" 8 | if [ "$0" != "$tmprun" ]; then 9 | cp "$0" "$tmprun" 10 | exec "$tmprun" 11 | fi 12 | 13 | usage() { 14 | echo "Usage: TESTME [-h]" 15 | exit "$1" 16 | } 17 | 18 | [ "$1" = "-h" ] && usage 0 19 | 20 | die() { 21 | echo `basename "$0"`: "$@" 22 | exit 1 23 | } 24 | 25 | unset raiddisk raidvol 26 | unset csdisk csvol 27 | unset fdedisk fdevol 28 | MOUNTPOINTAWKBITS="{ 29 | if (index(\$0, \"/Volumes\")) { 30 | print substr(\$0, index(\$0,\"/Volumes\"), length(\$0)) 31 | } else { 32 | print \$NF 33 | } 34 | }" 35 | 36 | isOSvol() { 37 | [ -s "$1"/System/Library/CoreServices/Finder.app ] 38 | } 39 | 40 | # only looks at first one 41 | findRAIDos() { 42 | raiddisk=$(diskutil ar list | awk '/^Device Node:/ { print $NF; exit 0 }') 43 | [ -z "$raiddisk" ] && return 1 44 | 45 | raidvol=$(df -lh | awk "/$raiddisk / $MOUNTPOINTAWKBITS") 46 | isOSvol "$raidvol" && echo "$raidvol" 47 | } 48 | 49 | findCSos() { 50 | searchstr="Logical Volume [0-9A-F]" 51 | [ "$1" ] && searchstr="$1" 52 | csdisks=$(diskutil cs list | sed -n "/$searchstr/,/Disk:/ { 53 | /Disk:.*disk/ { 54 | s/^[^D]*Disk:[^d]*// 55 | p 56 | } 57 | }") 58 | [ -z "$csdisks" ] && return 1 59 | 60 | for csdisk in $csdisks; do 61 | csvol=$(df -lh | awk "/$csdisk/ $MOUNTPOINTAWKBITS") 62 | isOSvol "$csvol" && echo "$csvol" && return 63 | done 64 | } 65 | 66 | findFDEos() { 67 | findCSos "Encryption Type:.*AES-XTS" 68 | } 69 | 70 | getHelper() { 71 | bless -verbose -info "$1" 2>&1 >/dev/null | awk '/Aux.*Part/ { getline; print $1 }' 72 | } 73 | 74 | [ "$kextcache" ] || kextcache=/usr/sbin/kextcache 75 | brtest=/usr/local/bin/brtest 76 | [ -x "$brtest" ] || brtest=./brtest 77 | [ -d "$bros" ] || bros=$(findRAIDos) 78 | [ -d "$csos" ] || csos=$(findCSos); 79 | if ! [ -d "$bros" ]; then 80 | if [ -d "$csos" ]; then 81 | echo "WARNING: no RAID OS found; substituting CoreStorage volume $csos" >&2 82 | sleep 2 83 | bros=$csos 84 | else 85 | echo "WARNING: no Boot!=Root OS volumes found..." >&2 86 | sleep 5 87 | bros="[unknown!]" 88 | fi 89 | fi 90 | [ -d "$fdeos" ] || fdeos=$(findFDEos) 91 | if ! [ -d "$fdeos" ]; then 92 | echo "WARNING: no FDE OS volumes found..." >&2 93 | diskutil cs list | grep -q -- "Encryptions Status:.*Locked" && \ 94 | echo "(there appears to be one offline)" >&2 95 | sleep 5 96 | fi 97 | 98 | unset brhelper cshelper fdehelper 99 | brhelper=$(getHelper "$bros") 100 | cshelper=$(getHelper "$csos") 101 | fdehelper=$(getHelper "$fdeos") 102 | 103 | 104 | # dump commands (yes, the next round will start executing some of them :) 105 | ${PAGER:-less} < reboot if needed (later tests use this for reporting) 120 | sudo "$kextcache" -U "$bros"; echo \$? # should be 0 121 | sudo touch "$bros"/Library/Preferences/SystemConfiguration/com.apple.Boot.plist \ 122 | && sudo "$kextcache" -U "$bros"; echo \$? # should be EX_OSFILE (72) 123 | 124 | # installer test (mid-way, non-FDE: should not rebuild EFILoginLocalizations) 125 | sudo rm -rf "$bros"/System/Library/Caches/com.apple.kext.caches/Startup/kernelcache \ 126 | "$bros"/System/Library/Caches/com.apple.corestorage/EFILoginLocalizations \ 127 | "$bros"/System/Library/Caches/com.apple.corestorage/EncryptedRoot.plist.wipekey \ 128 | "$bros"/System/Library/CoreServices/boot.efi \ 129 | && sudo "$kextcache" -v -Installer -u "$bros"; echo \$? 130 | sudo bless -folder "$bros"/System/Library/CoreServices -bootefi # restore boot.efi 131 | 132 | # and at the end 133 | # background kextcache -vU success w/9567748 fixed 134 | (sleep 2 && sudo kextcache -vU "$bros"; echo \$?) & \ 135 | sudo rm -rf "$bros"/System/Library/Caches/com.apple.kext.caches/Startup/kernelcache \ 136 | "$bros"/System/Library/Caches/com.apple.corestorage/EFILoginLocalizations \ 137 | && sudo "$kextcache" -v -Installer -u "$bros"; echo \$? 138 | 139 | # now targetting an FDE volume (should rebuild EFILoginLocalizations) 140 | sudo rm -rf "$fdeos"/System/Library/Caches/com.apple.corestorage/EFILoginLocalizations \ 141 | "$fdeos"/System/Library/Caches/com.apple.corestorage/EncryptedRoot.plist.wipekey \ 142 | && sudo "$kextcache" -v -Installer -u "$fdeos"; echo \$? 143 | 144 | # -caches-only 145 | # background kextcache -vU should only update the helpers 146 | (sleep 2 && sudo kextcache -vU "$bros"; echo \$?) & \ 147 | sudo rm -rf "$bros"/System/Library/Caches/com.apple.kext.caches/Startup/kernelcache \ 148 | "$bros"/System/Library/Caches/com.apple.corestorage/EFILoginLocalizations \ 149 | && sudo "$kextcache" -v -caches-only -u "$bros"; echo \$? 150 | 151 | # enable FDE on root volume (or use GUI) 152 | [ "$bros" = / ] && echo "/ appears to already be using Boot!=Root" 153 | [ "$fdeos" = / ] && echo "/ is already running FDE" 154 | [ "$csos" = / ] && echo "/ appears may be unencrypted CoreStorage (use 'diskutil cs encryptVolume')" 155 | sudo diskutil cs convert / -passphrase test && sudo reboot 156 | echo EFI Login should come up on reboot. 157 | echo "----- AFTER REBOOT -----" 158 | diskutil mount $fdehelper 159 | ls -l /Volumes/Rec* # should have com.apple.boot.[RPS] 160 | bless -info /Volumes/Rec* # finderinfo[0] -> /S/L/CoreServices 161 | # finderinfo[1] -> /S/L/CoreServices/boot.efi 162 | # finderinfo[3] -> com.apple.recovery.boot 163 | echo feel free to turn off FDE, either w/SecPref or diskutil cs decrypt 164 | 165 | # kextcache -u -f tested below w/brtest 166 | 167 | [...need to fill in lots more...] 168 | -- end TEST -- 169 | 170 | kextd 171 | kextfind 172 | kextlibs 173 | kextload 174 | kextstat 175 | kextunload 176 | kextutil 177 | kextsymboltool - /usr/local/bin 178 | mkextunpack 179 | 180 | libBootRoot 181 | brtest 182 | -- To TEST -- 183 | # run through the verbs 184 | "$brtest" listboots "$bros" 185 | 186 | sudo "$brtest" erasefiles "$fdeos" $fdehelper -f # temporarily make unbootable 187 | diskutil mount "$fdehelper" # check disable FDE case 188 | bless -info /Volumes/Recovery* # Recovery should be blessed 189 | ls -la /Volumes/Recovery* # no cruft 190 | 191 | sudo "$kextcache" -vu "$fdeos" # '/' should look clean 192 | sudo $brtest update "$fdeos" # shouldn't update 193 | diskutil mount "$fdehelper" 194 | ls -la /Volumes/Recovery* # check still empty 195 | 196 | sudo "$brtest" copyfiles "$fdeos" $fdehelper # update one of them 197 | diskutil mount "$fdehelper" # check copied 198 | bless -info /Volumes/Recovery* # Boot!=Root should be blessed 199 | ls -la /Volumes/Recovery* # Boot!=Root back 200 | 201 | sudo "$brtest" erasefiles "$fdeos" $fdehelper -f # nuke $brhelper again 202 | sudo "$brtest" update "$fdeos" -f # should update all 203 | diskutil mount "$fdehelper" # check everything is back 204 | bless -info /Volumes/Recovery* 205 | ls -la /Volumes/Recovery* 206 | 207 | # try w/multi-PV FDE, try w/unencrypted CoreStorage 208 | sudo "$brtest" erasefiles "$csos" $cshelper -f # temporarily make unbootable :) 209 | sudo "$kextcache" -vu "$csos" -f # should update everything 210 | 211 | # set up non-functional dmg-booting inputs 212 | diskutil mount "$fdehelper" 213 | sudo ln -fs /Volumes/Rec*/com.apple.recovery.boot/BaseSystem.dmg "$fdeos" 214 | hdid "$fdeos"/BaseSystem.dmg 215 | 216 | # InstallAssistant[.app] on an encrypted volume 217 | sudo "$brtest" copyfiles "/Volumes/Mac OS X Internal Base System" "$fdeos" /BaseSystem.dmg "$fdehelper" 218 | sudo cat /Volumes/Recovery*/com.apple.boot.?/Library/Preferences/SystemConfiguration/com.apple.Boot.plist 219 | # should have root-dmg referring to BaseSystem.dmg (.dmg keeps A_B mounted :) 220 | 221 | # Time Machine making an encrypted backup bootable 222 | sudo mkdir /Volumes/Recovery\ HD/testdir 223 | sudo "$brtest" copyfiles "/Volumes/Mac OS X Internal Base System" "$fdeos" /BaseSystem.dmg "$fdehelper"/testdir 224 | cat /Volumes/Recovery*/testdir/com.apple.Boot.plist 225 | # confirm root-dmg + Kernel Cache 226 | 227 | # clean up 228 | df -lh 229 | # eject Internal System 230 | diskutil unmount "$fdehelper" 231 | 232 | 233 | -- end TEST -- 234 | 235 | setsegname - /usr/local/bin 236 | Create system cache folders - script 237 | 238 | embedded - built for the device (no tools ship)? 239 | Create system cache folders - script 240 | kextunload 241 | kextstat 242 | 243 | embedded-host - for internal SDK (to build kernel caches) 244 | kextcache-embedded-host 245 | kextsymboltool-embedded-host 246 | setsegname 247 | -- To TEST -- 248 | # mountebuild.sh 249 | sudo ditto -v ~rc/Software/$IOSTRAIN/Updates/Current$IOSTRAIN/Roots/MacOSXSDKInternal10_7/ / 250 | if [ "$kxld_changed" ]; then 251 | sudo ~rc/bin/buildit xnu -release "$IOSTRAIN" -project libkxld_host -arch i386 -arch x86_64 -noinstallsrc -noverify -merge / 252 | fi 253 | if [ "$kxldAPI_changed" -o "$IOKit_Kext_changed" ]; then 254 | sudo ~rc/bin/buildit IOKitUser -release "$IOSTRAIN" -project IOKitUser_host -arch i386 -arch x86_64 -target libkext -noinstallsrc -noverify -merge / 255 | fi 256 | # libkxld_host and IOKitUser_host both build static libs that end up in /Developer/SDKs/iPhoneHostSideTools.sparse.sdk/ 257 | sudo ~rc/bin/buildit kext_tools -release "$IOSTRAIN" -project kext_tools_host -arch i386 -arch x86_64 -target embedded-host -noinstallsrc -noverify # -merge / 258 | # kext_tools_host builds the tools used during development (e.g. kcgen) 259 | -- end TEST -- 260 | 261 | 262 | 263 | KextUserAgent - inactive? 264 | 265 | Build Configurations: 266 | Development - maximal debugging; only build current arch 267 | Deployment - optimized code; will build multiple archs 268 | (If no build configuration is specified "Deployment" is used by desktop B&I.) 269 | Analyze - run analyzer on optimized code 270 | 271 | A number of Build settings are mirrored amongst these configurations 272 | (-D__MigTypeCheck=1 anyone?) and should be moved to the top level. 273 | TESTME_TEXT 274 | -------------------------------------------------------------------------------- /bootcaches.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2012 Apple Inc. All rights reserved. 3 | * 4 | * @APPLE_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. Please obtain a copy of the License at 10 | * http://www.opensource.apple.com/apsl/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | * 21 | * @APPLE_LICENSE_HEADER_END@ 22 | */ 23 | /* 24 | * FILE: bootcaches.h 25 | * AUTH: Soren Spies (sspies) 26 | * DATE: "spring" 2006 27 | * DESC: routines for dealing with bootcaches.plist data, bootstamps, etc 28 | * shared between kextcache and kextd 29 | * 30 | */ 31 | 32 | #ifndef __BOOTCACHES_H__ 33 | #define __BOOTCACHES_H__ 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include // uuid_string_t 40 | #include 41 | 42 | #include "bootroot_internal.h" // includes bootroot.h 43 | 44 | // cache directories that we create (we also create kCSFDEPropertyCacheDir) 45 | #define kTSCacheDir "/System/Library/Caches/com.apple.bootstamps" 46 | #define kCacheDirMode 0755 // Sec reviewed 47 | #define kCacheFileMode 0644 48 | 49 | // bootcaches.plist and keys 50 | 51 | #define kBootCachesPath "/usr/standalone/bootcaches.plist" 52 | #define kBCPreBootKey CFSTR("PreBootPaths") // dict 53 | #define kBCLabelKey CFSTR("DiskLabel") // ".disk_label" 54 | #define kBCBootersKey CFSTR("BooterPaths") // dict 55 | #define kBCEFIBooterKey CFSTR("EFIBooter") // "boot.efi" 56 | #define kBCOFBooterKey CFSTR("OFBooter") // "BootX" 57 | #define kBCPostBootKey CFSTR("PostBootPaths") // dict 58 | #define kBCMKextKey CFSTR("MKext") // dict 59 | #define kBCMKext2Key CFSTR("MKext2") // dict 60 | #define kBCKernelcacheV1Key CFSTR("Kernelcache v1.1")// dict 61 | #define kBCKernelcacheV2Key CFSTR("Kernelcache v1.2")// dict 62 | #define kBCKernelcacheV3Key CFSTR("Kernelcache v1.3")// dict 63 | #define kBCKernelPathKey CFSTR("KernelPath") // m_k | kernel 64 | #define kBCPreferredCompressionKey CFSTR("Preferred Compression") // "lzvn" 65 | #if DEV_KERNEL_SUPPORT 66 | #define kBCKernelsDirKey CFSTR("KernelsDir") // S/L/Kernels 67 | #endif 68 | #define kBCArchsKey CFSTR("Archs") // ... i386 69 | #define kBCExtensionsDirKey CFSTR("ExtensionsDir") // /S/L/E, /L/E 70 | #define kBCPathKey CFSTR("Path") // ...prelinkedkernel 71 | // AdditionalPaths are optional w/PreBootPaths, required w/PostBootPaths 72 | #define kBCAdditionalPathsKey CFSTR("AdditionalPaths") // array 73 | #define kBCBootConfigKey CFSTR("BootConfig") // bc.plist 74 | #define kBCEncryptedRootKey CFSTR("EncryptedRoot") // dict 75 | #define kBCCSFDEPropertyCacheKey CFSTR("EncryptedPropertyCache") // .wipekey 76 | #define kBCCSFDERootVolPropCacheKey CFSTR("RootVolumePropertyCache")//A_B only? 77 | #define kBCCSFDEDefResourcesDirKey CFSTR("DefaultResourcesDir") // EfiLoginUI 78 | #define kBCCSFDELocalizationSrcKey CFSTR("LocalizationSource") // EFI.fr/Res 79 | #define kBCCSFDELanguagesPrefKey CFSTR("LanguagesPref") // .GlobalPrefs 80 | #define kBCCSFDEBackgroundImageKey CFSTR("BackgroundImage") // desktop..png 81 | #define kBCCSFDELocRsrcsCacheKey CFSTR("LocalizedResourcesCache") // EFILocs 82 | 83 | typedef enum { 84 | kMkextCRCError = -1, 85 | kMkextCRCFound = 0, 86 | kMkextCRCNotFound = 1, 87 | } MkextCRCResult; 88 | 89 | // 6486172 points out that kextd ends up with a lot of these buffers 90 | // (especially w/multiple OS vols). BCPATH_MAX (8163405) reduces the impact. 91 | #define NCHARSUUID (2*sizeof(uuid_t) + 5) // hex with 4 -'s and one NUL 92 | #define BCPATH_MAX 128 93 | #define TSPATH_MAX (BCPATH_MAX + 1 + NCHARSUUID + 1 + BCPATH_MAX) 94 | #define DEVMAXPATHSIZE 128 // xnu/devfs/devfsdefs.h: 95 | #define ROOTPATH_MAX (sizeof("/Volumes/") + NAME_MAX) 96 | 97 | typedef struct { 98 | char rpath[BCPATH_MAX]; // (relative) source path in root filesystem 99 | char tspath[TSPATH_MAX]; // shadow timestamp path tracking Apple_Boot[s] 100 | struct timeval tstamps[2]; // rpath's initial timestamp(s) 101 | } cachedPath; 102 | 103 | struct bootCaches { 104 | int cachefd; // Sec: file descriptor to validate data 105 | char bsdname[DEVMAXPATHSIZE]; // for passing to bless to get helpers 106 | uuid_string_t fsys_uuid; // optimized for cachedPaths (cf. 5114411, XX?) 107 | CFStringRef csfde_uuid; // encrypted volumes's LVF UUID 108 | char defLabel[NAME_MAX]; // defaults to volume name 109 | char root[ROOTPATH_MAX]; // struct's paths relative to this root 110 | CFDictionaryRef cacheinfo; // raw BootCaches.plist data (for archs, etc) 111 | struct timespec bcTime; // cache the timestamp of bootcaches.plist 112 | 113 | char kernelpath[BCPATH_MAX]; // path to kernel file (watch only) 114 | // <= 10.9 - /Volumes/foo/mach_kernel 115 | // > 10.9 - /Volumes/foo/System/Library/Kernels/kernel 116 | int nexts; // number of extensions directory paths 117 | char *exts; // null terminated extensions dir paths 118 | char locSource[BCPATH_MAX]; // only EFILogin.framework/Resources for now 119 | char locPref[BCPATH_MAX]; // /L/P/.GlobalPreferences 120 | char bgImage[BCPATH_MAX]; // /L/Caches/com.apple.desktop.admin.png 121 | unsigned nrps; // number of RPS paths in Apple_Boot 122 | cachedPath *rpspaths; // e.g. mkext, kernel, Boot.plist 123 | unsigned nmisc; // "other" files (non-critical) 124 | cachedPath *miscpaths; // e.g. icons, labels, etc 125 | cachedPath efibooter; // booters get their own paths 126 | cachedPath ofbooter; // (we have to bless them, etc) 127 | 128 | // pointers to special watched paths (stored in arrays above) 129 | cachedPath *kext_boot_cache_file; // -> kernelcache 130 | cachedPath *bootconfig; // -> .../L/Prefs/SC/com.apple.Boot.plist 131 | cachedPath *efidefrsrcs; // -> usr/standalone/i386/EfiLoginUI 132 | cachedPath *efiloccache; // -> ...Caches/../EFILoginLocalizations 133 | cachedPath *label; // -> .../S/L/CS/.disk_label (in miscPaths) 134 | cachedPath *erpropcache; // crypto metadata gets special treatment 135 | Boolean erpropTSOnly; // whether props expected in root fsys 136 | #if DEV_KERNEL_SUPPORT 137 | int kernelsCount; // count of valid kernels in /System/Library/Kernels 138 | // This will be 0 for volumes that do not support 139 | // /System/Library/Kernels/. 140 | int nekcp; // number of extraKernelCachePaths 141 | cachedPath *extraKernelCachePaths; // kernelcache files with suffix, may be NULL 142 | #endif 143 | }; 144 | /* use sizeof() to get it the right bounds */ 145 | #undef TSPATH_MAX 146 | #undef BCPATH_MAX 147 | #undef ROOTPATH_MAX 148 | 149 | // check and tweak Boot!=Root status 150 | Boolean hasBootRootBoots(struct bootCaches *caches, CFArrayRef *auxPartsCopy, 151 | CFArrayRef *dataPartsCopy, Boolean *isAPM); 152 | Boolean notBRDefault(const char *mount, const char *subdir); 153 | int markNotBRDefault(int scopefd, const char *mount, const char* subdir, 154 | Boolean marking); 155 | 156 | // Everything except vol_path is optional. 157 | // If specified, vol_bsd must point to at least DEVMAXPATHSIZE bytes. 158 | // If specified, vol_name must point to at least NAME_MAX bytes. 159 | // If no CoreStorage is detected and cslvf_uuid is non-NULL, 160 | // *cslvf_uuid will be set to NULL. 161 | int copyVolumeInfo(const char *vol_path, uuid_t *vol_uuid, 162 | CFStringRef *cslvf_uuid, char vol_bsd[DEVMAXPATHSIZE], 163 | char vol_name[NAME_MAX]); 164 | 165 | // no CSFDE data => encContext = NULL, timeStamp = 0LL; 166 | int copyCSFDEInfo(CFStringRef uuidStr, CFDictionaryRef *encContext, 167 | time_t *timeStamp); 168 | 169 | /* ctors / dtors */ 170 | // for kextcache 171 | struct bootCaches* readBootCaches(char *volRoot, BRUpdateOpts_t opts); 172 | // and kextd 173 | struct bootCaches* readBootCachesForDADisk(DADiskRef dadisk); // kextd 174 | // (Warning: these will create S/L/Caches/bootstamps if missing.) 175 | 176 | void destroyCaches(struct bootCaches *caches); 177 | DADiskRef createDiskForMount(DASessionRef session, const char *mount); 178 | 179 | // Check all cached paths vs. bootstamps 180 | Boolean needUpdates(struct bootCaches *caches, BRUpdateOpts_t opts, 181 | Boolean *rps, Boolean *booters, Boolean *misc, 182 | OSKextLogSpec oodLogSpec); 183 | 184 | /* When copying non-default content to a helper partition, 185 | taintDefaultStamps() finds and taints any online volumes that own the 186 | helper. Once tainted, kextcache -u (called through Disk Management 187 | by Startup Disk and the Installer) will notice that the helper contents 188 | need to be replaced and will restore the volume and helper back to the 189 | default configuration. kextd ignores the taint in its checks, but if 190 | something else changes, the kextcache -u launched by kextd *will* 191 | notice the taint and copy everything instead of only what changed. */ 192 | int taintDefaultStamps(CFStringRef targetBSD); 193 | 194 | // update the bootstamp files from the tstamps stored in the bootCaches struct 195 | #define kBCStampsUnlinkOnly 0 // updateStamps always unlinks 196 | #define kBCStampsApplyTimes 1 // apply stored timestamps 197 | int updateStamps(struct bootCaches *caches, int command); 198 | 199 | // check / rebuild kext caches needs rebuilding 200 | Boolean plistCachesNeedRebuild(const NXArchInfo * kernelArchInfo); 201 | Boolean check_kext_boot_cache_file( 202 | struct bootCaches * caches, 203 | const char * cache_path, 204 | const char * kernel_path); 205 | // build the mkext; waiting for the kextcache child if instructed 206 | int rebuild_kext_boot_cache_file( 207 | struct bootCaches *caches, 208 | Boolean wait, 209 | const char * cache_path, 210 | const char * kernel_file); 211 | 212 | // check/rebuild CSFDE caches 213 | Boolean check_csfde(struct bootCaches *caches); 214 | int rebuild_csfde_cache(struct bootCaches *caches); 215 | int writeCSFDEProps(int scopefd, CFDictionaryRef ectx, 216 | char *cspvbsd, char *dstpath); 217 | Boolean check_loccache(struct bootCaches *caches); 218 | int rebuild_loccache(struct bootCaches *caches); 219 | 220 | // diskarb helpers 221 | void _daDone(DADiskRef disk, DADissenterRef dissenter, void *ctx); 222 | int updateMount(mountpoint_t mount, uint32_t mntgoal); 223 | 224 | pid_t launch_rebuild_all(char * rootPath, Boolean force, Boolean wait); 225 | 226 | #endif /* __BOOTCACHES_H__ */ 227 | 228 | -------------------------------------------------------------------------------- /bootcaches.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreBootPaths 6 | 7 | DiskLabel 8 | /System/Library/CoreServices/.disk_label 9 | 10 | AdditionalPaths 11 | 12 | /.VolumeIcon.icns 13 | /System/Library/CoreServices/SystemVersion.plist 14 | /System/Library/CoreServices/PlatformSupport.plist 15 | 16 | 17 | 18 | BooterPaths 19 | 20 | EFIBooter 21 | /System/Library/CoreServices/boot.efi 22 | 23 | 24 | PostBootPaths 25 | 26 | BootConfig 27 | /Library/Preferences/SystemConfiguration/com.apple.Boot.plist 28 | EncryptedRoot 29 | 30 | EncryptedPropertyCache 31 | /System/Library/Caches/com.apple.corestorage/EncryptedRoot.plist.wipekey 32 | 33 | RootVolumePropertyCache 34 | 35 | DefaultResourcesDir 36 | /usr/standalone/i386/EfiLoginUI/ 37 | 38 | LocalizationSource 39 | /System/Library/PrivateFrameworks/EFILogin.framework/Resources/EFIResourceBuilder.bundle/Contents/Resources 40 | LanguagesPref 41 | /Library/Preferences/.GlobalPreferences.plist 42 | BackgroundImage 43 | /Library/Caches/com.apple.desktop.admin.png 44 | LocalizedResourcesCache 45 | /System/Library/Caches/com.apple.corestorage/EFILoginLocalizations 46 | 47 | Kernelcache v1.3 48 | 49 | ExtensionsDir 50 | 51 | /System/Library/Extensions 52 | /Library/Extensions 53 | 54 | Path 55 | /System/Library/PrelinkedKernels/prelinkedkernel 56 | KernelPath 57 | /System/Library/Kernels/kernel 58 | KernelsDir 59 | /System/Library/Kernels 60 | Archs 61 | 62 | x86_64 63 | 64 | Preferred Compression 65 | lzvn 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /bootroot_internal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007 Apple Inc. All rights reserved. 3 | * 4 | * @APPLE_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. Please obtain a copy of the License at 10 | * http://www.opensource.apple.com/apsl/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | * 21 | * @APPLE_LICENSE_HEADER_END@ 22 | */ 23 | /* 24 | * FILE: bootroot_internal.h 25 | * AUTH: Soren Spies (sspies) 26 | * DATE: 8 June 2006 (as update_boot.h) 27 | * DESC: routines for implementing 'kextcache -u' functionality (4252674) 28 | * in which bootcaches.plist files get copied to any Apple_Boots 29 | */ 30 | 31 | #ifndef _BOOTROOT_INTERNAL_H_ 32 | #define _BOOTROOT_INTERNAL_H_ 33 | 34 | #include 35 | 36 | #include "bootroot.h" 37 | 38 | // internal options for "update" operations 39 | typedef enum { 40 | // BROptsNone = 0x0, // in bootroot.h 41 | 42 | // command-line options 43 | kBRUForceUpdateHelpers = 1 << 0, // -f: ignore bootstamps, update helpers 44 | 45 | kBRUCachesOnly = 1 << 1, // -caches-only: don't update helpers 46 | kBRUHelpersOptional = 1 << 2, // -Installer: helper updates !req'd 47 | kBRUExpectUpToDate = 1 << 3, // -U: successful updates -> EX_OSFILE 48 | kBRUEarlyBoot = 1 << 4, // -Boot: launch* calling us 49 | 50 | kBRUInvalidateKextcache = 1 << 5, // -i: mimic sudo touch /S/L/Extensions 51 | 52 | // needUpdates() opt (default is all caches, default-bootable) 53 | kBRUCachesAnyRoot = 1 << 6, // non-default B!=R configs okay 54 | 55 | // copy files opts 56 | // kBRAnyBootStamps = 0x10000 (1<<16) // in bootroot.h 57 | } BRUpdateOpts_t; 58 | 59 | // in update_boot.c 60 | 61 | /* 62 | * Update all caches and any helper partitions (kextcache -u). 63 | * Except when kForceUpdateHelpers is specified, unrecognized 64 | * bootcaches.plist causes immediate success. 65 | */ 66 | int checkUpdateCachesAndBoots(CFURLRef volumeURL, BRUpdateOpts_t flags); 67 | 68 | // "put" and "take" let routines decide if a lock is needed (e.g. if no kextd) 69 | // Only used by volume lockers (kextcache, libBootRoot clients, !kextd) 70 | int takeVolumeForPath(const char *volPath); 71 | int putVolumeForPath(const char *path, int status); 72 | 73 | #endif // _BOOTROOT_INTERNAL_H_ 74 | -------------------------------------------------------------------------------- /com.apple.kextd.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | POSIXSpawnType 6 | Interactive 7 | Label 8 | com.apple.kextd 9 | ProgramArguments 10 | 11 | /usr/libexec/kextd 12 | 13 | KeepAlive 14 | 15 | SuccessfulExit 16 | 17 | 18 | MachServices 19 | 20 | com.apple.KernelExtensionServer 21 | 22 | 23 | HostSpecialPort 24 | 15 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /compression.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_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. Please obtain a copy of the License at 10 | * http://www.opensource.apple.com/apsl/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | * 21 | * @APPLE_LICENSE_HEADER_END@ 22 | */ 23 | 24 | #ifndef __COMPRESSION_H__ 25 | #define __COMPRESSION_H__ 26 | 27 | #include 28 | 29 | u_int32_t local_adler32( 30 | u_int8_t * buffer, 31 | int32_t length); 32 | 33 | int decompress_lzss( 34 | u_int8_t * dst, 35 | u_int32_t dstlen, 36 | u_int8_t * src, 37 | u_int32_t srclen); 38 | 39 | u_int8_t * compress_lzss( 40 | u_int8_t * dst, 41 | u_int32_t dstlen, 42 | u_int8_t * src, 43 | u_int32_t srclen); 44 | 45 | #endif /* __COMPRESSION_H__ */ 46 | -------------------------------------------------------------------------------- /fork_program.c: -------------------------------------------------------------------------------- 1 | /* 2 | * fork_program.c 3 | * kext_tools 4 | * 5 | * Created by nik on 5/11/08. 6 | * Copyright 2008 __MyCompanyName__. All rights reserved. 7 | * 8 | */ 9 | 10 | #include "fork_program.h" 11 | #include "kext_tools_util.h" 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | /******************************************************************************* 18 | * Fork a process after a specified delay, and either wait on it to exit or 19 | * leave it to run in the background. 20 | * 21 | * Returns -2 on spawn() failure, -1 on other failure, and depending on wait: 22 | * wait: true - exit status of forked program 23 | * wait: false - pid of background process 24 | *******************************************************************************/ 25 | int fork_program(const char * argv0, char * const argv[], Boolean wait) 26 | { 27 | int result; 28 | int spawn_result; 29 | pid_t child_pid; 30 | int child_status; 31 | int normal_iopolicy = getiopolicy_np(IOPOL_TYPE_DISK, 32 | 33 | 34 | IOPOL_SCOPE_PROCESS); 35 | char ** environ = *(_NSGetEnviron()); 36 | 37 | #if 0 // spew program and arguments we are forking... 38 | if (argv0) { 39 | int i; 40 | int commandLen = 0; 41 | 42 | OSKextLog(NULL, 43 | kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 44 | "Forking: %s", 45 | argv0); 46 | for (i = 0; argv[i] != NULL; i++) { 47 | commandLen += strlen(argv[i]); 48 | commandLen++; 49 | } 50 | if (commandLen > 0) { 51 | char * myCmd = NULL; 52 | myCmd = (char *) malloc(commandLen); 53 | if (myCmd) { 54 | for (i = 0; argv[i] != NULL; i++) { 55 | strcat(myCmd, argv[i]); 56 | strcat(myCmd, " "); 57 | } 58 | OSKextLog(NULL, 59 | kOSKextLogErrorLevel | kOSKextLogGeneralFlag, 60 | "%s ", 61 | myCmd); 62 | free(myCmd); 63 | } 64 | } 65 | } 66 | #endif 67 | 68 | if (!wait) { 69 | setiopolicy_np(IOPOL_TYPE_DISK, IOPOL_SCOPE_PROCESS, IOPOL_THROTTLE); 70 | } 71 | 72 | spawn_result = posix_spawn(&child_pid, argv0, /* file_actions */ NULL, 73 | /* spawnattrs */ NULL, argv, environ); 74 | 75 | // If we couldn't spawn the process, return -2 with errno for detail 76 | if (spawn_result != 0) { 77 | OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel, 78 | "posix_spawn failed for %s.", argv0); 79 | errno = spawn_result; 80 | result = -2; 81 | goto finish; 82 | } 83 | 84 | OSKextLog(/* kext */ NULL, kOSKextLogDetailLevel, 85 | "started child process %s[%d] (%ssynchronous).", 86 | argv0, child_pid, wait ? "" : "a"); 87 | 88 | if (wait) { 89 | OSKextLogSpec logSpec = kOSKextLogDetailLevel; 90 | if (waitpid(child_pid, &child_status, 0) == -1) { 91 | result = -1; 92 | goto finish; 93 | } 94 | if (WIFEXITED(child_status)) { 95 | result = WEXITSTATUS(child_status); 96 | if (result) { 97 | logSpec = kOSKextLogErrorLevel; 98 | } 99 | OSKextLog(/* kext */ NULL, logSpec, 100 | "Child process %s[%d] exited with status %d.", 101 | argv0, child_pid, result); 102 | } else if (WIFSIGNALED(child_status)) { 103 | result = WTERMSIG(child_status); 104 | logSpec = kOSKextLogErrorLevel; 105 | OSKextLog(/* kext */ NULL, logSpec, 106 | "Child process %s[%d] exited due to signal %d.", 107 | argv0, child_pid, result); 108 | } else { 109 | // shouldn't be any other types of exit 110 | result = -1; 111 | } 112 | } else { 113 | result = child_pid; 114 | } 115 | 116 | finish: 117 | setiopolicy_np(IOPOL_TYPE_DISK, IOPOL_SCOPE_PROCESS, normal_iopolicy); 118 | 119 | return result; 120 | } 121 | -------------------------------------------------------------------------------- /fork_program.h: -------------------------------------------------------------------------------- 1 | /* 2 | * fork_program.h 3 | * kext_tools 4 | * 5 | * Created by nik on 5/11/08. 6 | * Copyright 2008 Apple Inc. All rights reserved. 7 | * 8 | */ 9 | #ifndef _FORK_PROGRAM 10 | #define _FORK_PROGRAM 11 | 12 | #include 13 | #include 14 | int fork_program( 15 | const char * argv0, 16 | char * const argv[], 17 | Boolean wait); 18 | 19 | #endif /* _FORK_PROGRAM */ 20 | -------------------------------------------------------------------------------- /kcgen_main.h: -------------------------------------------------------------------------------- 1 | /* 2 | * kcgen_main.h 3 | * kext_tools 4 | * 5 | * Created by nik on 5/20/08. 6 | * Copyright 2008 __MyCompanyName__. All rights reserved. 7 | * 8 | */ 9 | #ifndef _KCGEN_MAIN_H 10 | #define _KCGEN_MAIN_H 11 | 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | 18 | #include 19 | 20 | #include "kext_tools_util.h" 21 | #include "kernelcache.h" 22 | 23 | #pragma mark Basic Types & Constants 24 | /******************************************************************************* 25 | * Constants 26 | *******************************************************************************/ 27 | 28 | enum { 29 | kKcgenExitOK = EX_OK, 30 | kKcgenExitNotFound, 31 | kKcgenExitArchNotFound, 32 | kKcgenExitKextBad, 33 | kKcgenExitStale, 34 | 35 | // don't think we use it 36 | kKcgenExitUnspecified = 11, 37 | 38 | // don't actually exit with this, it's just a sentinel value 39 | kKcgenExitHelp = 33, 40 | kKcgenExitNoStart 41 | }; 42 | 43 | #pragma mark Command-line Option Definitions 44 | /******************************************************************************* 45 | * Command-line options. This data is used by getopt_long_only(). 46 | * 47 | * Options common to all kext tools are in kext_tools_util.h. 48 | *******************************************************************************/ 49 | 50 | // kOptNameBundleIdentifier in kext_tools_util.h 51 | // kOptNameSystemExtensions in kext_tools_util.h 52 | 53 | #define kOptNameOptionalBundleIdentifier "optional-bundle-id" 54 | 55 | /* Prelinked-kernel-generation flags. 56 | */ 57 | #define kOptNamePrelinkedKernel "prelinked-kernel" 58 | #define kOptNameSystemPrelinkedKernel "system-prelinked-kernel" 59 | #define kOptNameKernel "kernel" 60 | #define kOptNameAllLoaded "all-loaded" 61 | #define kOptNameSymbols "symbols" 62 | #define kOptNameVolumeRoot "volume-root" 63 | 64 | /* Embedded prelinked-kernel-generation flags. 65 | */ 66 | #define kOptNameAllPersonalities "all-personalities" 67 | #define kOptNameNoLinkFailures "no-link-failures" 68 | #define kOptNameStripSymbols "strip-symbols" 69 | 70 | #define kOptNameMaxSliceSize "max-slice-size" 71 | 72 | /* Misc flags. 73 | */ 74 | #define kOptNameNoAuthentication "no-authentication" 75 | #define kOptNameTests "print-diagnostics" 76 | #define kOptNameCompressed "compressed" 77 | #define kOptNameUncompressed "uncompressed" 78 | 79 | #define kOptArch 'a' 80 | // 'b' in kext_tools_util.h 81 | #define kOptPrelinkedKernel 'c' 82 | // 'h' in kext_tools_util.h 83 | #define kOptKernel 'K' 84 | // 'q' in kext_tools_util.h 85 | #define kOptTests 't' 86 | // 'v' in kext_tools_util.h 87 | #define kOptNoAuthentication 'z' 88 | 89 | /* Options with no single-letter variant. */ 90 | // Do not use -1, that's getopt() end-of-args return value 91 | // and can cause confusion 92 | #define kLongOptLongindexHack (-2) 93 | #define kLongOptOptionalBundleIdentifier (-3) 94 | #define kLongOptCompressed (-5) 95 | #define kLongOptUncompressed (-6) 96 | #define kLongOptSymbols (-7) 97 | #define kLongOptVolumeRoot (-10) 98 | #define kLongOptAllPersonalities (-11) 99 | #define kLongOptNoLinkFailures (-12) 100 | #define kLongOptStripSymbols (-13) 101 | #define kLongOptMaxSliceSize (-14) 102 | 103 | #define kOptChars ":a:b:c:ehK:lLnNqsStvz" 104 | 105 | int longopt = 0; 106 | 107 | struct option sOptInfo[] = { 108 | { kOptNameLongindexHack, no_argument, &longopt, kLongOptLongindexHack }, 109 | 110 | { kOptNameHelp, no_argument, NULL, kOptHelp }, 111 | { kOptNameQuiet, no_argument, NULL, kOptQuiet }, 112 | { kOptNameVerbose, optional_argument, NULL, kOptVerbose }, 113 | { kOptNameCompressed, optional_argument, &longopt, kLongOptCompressed }, 114 | { kOptNameUncompressed, no_argument, &longopt, kLongOptUncompressed }, 115 | 116 | { kOptNameArch, required_argument, NULL, kOptArch }, 117 | { kOptNameVolumeRoot, required_argument, &longopt, kLongOptVolumeRoot }, 118 | 119 | { kOptNameBundleIdentifier, required_argument, NULL, kOptBundleIdentifier }, 120 | { kOptNameOptionalBundleIdentifier, required_argument, &longopt, kLongOptOptionalBundleIdentifier }, 121 | 122 | { kOptNamePrelinkedKernel, optional_argument, NULL, kOptPrelinkedKernel }, 123 | { kOptNameKernel, required_argument, NULL, kOptKernel }, 124 | { kOptNameSymbols, required_argument, &longopt, kLongOptSymbols }, 125 | 126 | { kOptNameTests, no_argument, NULL, kOptTests }, 127 | 128 | { kOptNameMaxSliceSize, required_argument, &longopt, kLongOptMaxSliceSize }, 129 | 130 | /* Always on for kcgen; can be removed at some point. */ 131 | { kOptNameAllPersonalities, no_argument, &longopt, kLongOptAllPersonalities }, 132 | { kOptNameNoLinkFailures, no_argument, &longopt, kLongOptNoLinkFailures }, 133 | { kOptNameStripSymbols, no_argument, &longopt, kLongOptStripSymbols }, 134 | { kOptNameNoAuthentication, no_argument, NULL, kOptNoAuthentication }, 135 | 136 | { NULL, 0, NULL, 0 } // sentinel to terminate list 137 | }; 138 | 139 | typedef struct { 140 | Boolean printTestResults; // -t 141 | 142 | char * prelinkedKernelPath; // -c option 143 | Boolean generatePrelinkedSymbols; // -symbols option 144 | Boolean stripSymbols; // -strip-symbols option 145 | CFIndex maxSliceSize; 146 | 147 | CFURLRef compressedPrelinkedKernelURL; // -uncompress option 148 | 149 | char * kernelPath; // overriden by -K option 150 | CFDataRef kernelFile; // contents of kernelURL 151 | CFURLRef symbolDirURL; // -s option; 152 | CFURLRef volumeRootURL; 153 | 154 | CFMutableSetRef kextIDs; // -b; must release 155 | CFMutableSetRef optionalKextIDs; // -optional-bundle-id; must release 156 | CFMutableArrayRef argURLs; // directories & kexts in order 157 | CFMutableArrayRef repositoryURLs; // just non-kext directories 158 | CFMutableArrayRef namedKextURLs; 159 | CFMutableArrayRef targetArchs; 160 | 161 | CFArrayRef allKexts; // directories + named 162 | CFArrayRef repositoryKexts; // all from directories (may include named) 163 | CFArrayRef namedKexts; 164 | 165 | Boolean compress; 166 | uint32_t compressionType; 167 | Boolean uncompress; 168 | } KcgenArgs; 169 | 170 | #pragma mark Function Prototypes 171 | /******************************************************************************* 172 | * Function Prototypes 173 | *******************************************************************************/ 174 | ExitStatus readArgs( 175 | int * argc, 176 | char * const ** argv, 177 | KcgenArgs * toolArgs); 178 | const NXArchInfo * addArchForName( 179 | KcgenArgs * toolArgs, 180 | const char * archname); 181 | ExitStatus readPrelinkedKernelArgs( 182 | KcgenArgs * toolArgs, 183 | int argc, 184 | char * const * argv, 185 | Boolean isLongopt); 186 | ExitStatus setPrelinkedKernelArgs( 187 | KcgenArgs * toolArgs, 188 | char * filename); 189 | 190 | ExitStatus checkArgs(KcgenArgs * toolArgs); 191 | 192 | ExitStatus writeFatFile( 193 | const char * filePath, 194 | CFArrayRef fileSlices, 195 | CFArrayRef fileArchs, 196 | mode_t fileMode, 197 | const struct timeval fileTimes[2]); 198 | ExitStatus checkKextForProblems( 199 | KcgenArgs * toolArgs, 200 | OSKextRef theKext, 201 | const NXArchInfo * arch); 202 | ExitStatus filterKextsForCache( 203 | KcgenArgs * toolArgs, 204 | CFMutableArrayRef kextArray, 205 | const NXArchInfo * arch, 206 | Boolean * fatalOut); 207 | ExitStatus createPrelinkedKernelArchs( 208 | KcgenArgs * toolArgs, 209 | CFMutableArrayRef * prelinkArchsOut); 210 | ExitStatus createExistingPrelinkedSlices( 211 | KcgenArgs * toolArgs, 212 | CFMutableArrayRef * prelinkedSlicesOut, 213 | CFMutableArrayRef * prelinkedArchsOut); 214 | ExitStatus createPrelinkedKernel( 215 | KcgenArgs * toolArgs); 216 | CFArrayRef mergeArchs( 217 | CFArrayRef archSet1, 218 | CFArrayRef archSet2); 219 | ExitStatus createPrelinkedKernelForArch( 220 | KcgenArgs * toolArgs, 221 | CFDataRef * prelinkedKernelOut, 222 | CFDictionaryRef * prelinkedSymbolsOut, 223 | const NXArchInfo * archInfo); 224 | ExitStatus compressPrelinkedKernel( 225 | const char * prelinkedKernelPath, 226 | Boolean compress, 227 | uint32_t compressionType); 228 | void logUsedKexts( 229 | KcgenArgs * toolArgs, 230 | CFArrayRef prelinkKexts); 231 | 232 | void usage(UsageLevel usageLevel); 233 | 234 | #endif /* _KCGEN_MAIN_H */ 235 | -------------------------------------------------------------------------------- /kclist_main.h: -------------------------------------------------------------------------------- 1 | #ifndef _KCLIST_MAIN_H 2 | #define _KCLIST_MAIN_H 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #include "kext_tools_util.h" 13 | #include "kernelcache.h" 14 | 15 | #pragma mark Basic Types & Constants 16 | /******************************************************************************* 17 | * Constants 18 | *******************************************************************************/ 19 | 20 | enum { 21 | kKclistExitOK = EX_OK, 22 | 23 | // don't think we use it 24 | kKclistExitUnspecified = 11, 25 | 26 | // don't actually exit with this, it's just a sentinel value 27 | kKclistExitHelp = 33, 28 | }; 29 | 30 | #pragma mark Command-line Option Definitions 31 | /******************************************************************************* 32 | * Command-line options. This data is used by getopt_long_only(). 33 | * 34 | * Options common to all kext tools are in kext_tools_util.h. 35 | *******************************************************************************/ 36 | 37 | #define kOptArch 'a' 38 | 39 | #define kOptUUID 'u' 40 | #define kOptNameUUID "uuid" 41 | 42 | #define kOptChars "a:hvu" 43 | 44 | int longopt = 0; 45 | 46 | struct option sOptInfo[] = { 47 | { kOptNameHelp, no_argument, NULL, kOptHelp }, 48 | { kOptNameArch, required_argument, NULL, kOptArch }, 49 | { kOptNameUUID, no_argument, NULL, kOptUUID }, 50 | { kOptNameVerbose, no_argument, NULL, kOptVerbose }, 51 | 52 | { NULL, 0, NULL, 0 } // sentinel to terminate list 53 | }; 54 | 55 | typedef struct { 56 | char * kernelcachePath; 57 | CFMutableSetRef kextIDs; 58 | const NXArchInfo * archInfo; 59 | Boolean verbose; 60 | Boolean printUUIDs; 61 | } KclistArgs; 62 | 63 | #pragma mark Function Prototypes 64 | /******************************************************************************* 65 | * Function Prototypes 66 | *******************************************************************************/ 67 | ExitStatus readArgs( 68 | int * argc, 69 | char * const ** argv, 70 | KclistArgs * toolArgs); 71 | ExitStatus checkArgs(KclistArgs * toolArgs); 72 | void listPrelinkedKexts(KclistArgs * toolArgs, 73 | CFPropertyListRef kcInfoPlist, 74 | const char *prelinkTextBytes, 75 | uint64_t prelinkTextSourceAddress, 76 | uint64_t prelinkTextSourceSize, 77 | const NXArchInfo * archInfo); 78 | void printKextInfo(CFDictionaryRef kextPlist, 79 | Boolean beVerbose, 80 | Boolean printUUIDs, 81 | const char *kextTextBytes); 82 | 83 | void usage(UsageLevel usageLevel); 84 | 85 | #endif /* _KCLIST_MAIN_H */ 86 | -------------------------------------------------------------------------------- /kctool_main.h: -------------------------------------------------------------------------------- 1 | #ifndef _KCTOOL_MAIN_H 2 | #define _KCTOOL_MAIN_H 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #include "kext_tools_util.h" 13 | #include "kernelcache.h" 14 | 15 | #pragma mark Basic Types & Constants 16 | /******************************************************************************* 17 | * Constants 18 | *******************************************************************************/ 19 | 20 | enum { 21 | kKctoolExitOK = EX_OK, 22 | 23 | // don't think we use it 24 | kKctoolExitUnspecified = 11, 25 | 26 | // don't actually exit with this, it's just a sentinel value 27 | kKctoolExitHelp = 33, 28 | }; 29 | 30 | #pragma mark Command-line Option Definitions 31 | /******************************************************************************* 32 | * Command-line options. This data is used by getopt_long_only(). 33 | * 34 | * Options common to all kext tools are in kext_tools_util.h. 35 | *******************************************************************************/ 36 | 37 | #define kOptArch 'a' 38 | 39 | #define kOptChars "a:h" 40 | 41 | int longopt = 0; 42 | 43 | struct option sOptInfo[] = { 44 | { kOptNameHelp, no_argument, NULL, kOptHelp }, 45 | { kOptNameArch, required_argument, NULL, kOptArch }, 46 | 47 | { NULL, 0, NULL, 0 } // sentinel to terminate list 48 | }; 49 | 50 | typedef struct { 51 | const NXArchInfo * archInfo; 52 | 53 | char * kernelcachePath; 54 | CFStringRef kextID; 55 | const char * segmentName; 56 | const char * sectionName; 57 | 58 | const UInt8 * kernelcacheImageBytes; 59 | CFPropertyListRef kernelcacheInfoPlist; 60 | 61 | } KctoolArgs; 62 | 63 | #pragma mark Function Prototypes 64 | /******************************************************************************* 65 | * Function Prototypes 66 | *******************************************************************************/ 67 | ExitStatus readArgs( 68 | int * argc, 69 | char * const ** argv, 70 | KctoolArgs * toolArgs); 71 | ExitStatus printKextInfo(KctoolArgs * toolArgs); 72 | Boolean getKextAddressAndSize(CFDictionaryRef infoDict, uint64_t *addr, uint64_t *size); 73 | 74 | void usage(UsageLevel usageLevel); 75 | 76 | #endif /* _KCTOOL_MAIN_H */ 77 | -------------------------------------------------------------------------------- /kernelcache.h: -------------------------------------------------------------------------------- 1 | /* 2 | * kernelcache.h 3 | * kext_tools 4 | * 5 | * Created by Nik Gervae on 2010 10 04. 6 | * Copyright 2010, 2012 Apple Computer, Inc. All rights reserved. 7 | * 8 | */ 9 | #ifndef _KERNELCACHE_H_ 10 | #define _KERNELCACHE_H_ 11 | 12 | #include 13 | #include "kext_tools_util.h" 14 | 15 | #define PLATFORM_NAME_LEN (64) 16 | #define ROOT_PATH_LEN (256) 17 | 18 | #define COMP_TYPE_LZSS 'lzss' 19 | #define COMP_TYPE_FASTLIB 'lzvn' 20 | 21 | 22 | // prelinkVersion value >= 1 means KASLR supported 23 | typedef struct prelinked_kernel_header { 24 | uint32_t signature; 25 | uint32_t compressType; 26 | uint32_t adler32; 27 | uint32_t uncompressedSize; 28 | uint32_t compressedSize; 29 | uint32_t prelinkVersion; 30 | uint32_t reserved[10]; 31 | char platformName[PLATFORM_NAME_LEN]; // unused 32 | char rootPath[ROOT_PATH_LEN]; // unused 33 | char data[0]; 34 | } PrelinkedKernelHeader; 35 | 36 | typedef struct platform_info { 37 | char platformName[PLATFORM_NAME_LEN]; 38 | char rootPath[ROOT_PATH_LEN]; 39 | } PlatformInfo; 40 | 41 | /******************************************************************************* 42 | *******************************************************************************/ 43 | 44 | ExitStatus 45 | writeFatFileWithValidation( 46 | const char * filePath, 47 | boolean_t doValidation, 48 | dev_t file_dev_t, 49 | ino_t file_ino_t, 50 | CFArrayRef fileSlices, 51 | CFArrayRef fileArchs, 52 | mode_t fileMode, 53 | const struct timeval fileTimes[2]); 54 | 55 | ExitStatus 56 | writeFatFile( 57 | const char * filePath, 58 | CFArrayRef fileSlices, 59 | CFArrayRef fileArchs, 60 | mode_t fileMode, 61 | const struct timeval fileTimes[2]); 62 | void * mapAndSwapFatHeaderPage( 63 | int fileDescriptor); 64 | void unmapFatHeaderPage( 65 | void *headerPage); 66 | struct fat_arch * getFirstFatArch( 67 | u_char *headerPage); 68 | struct fat_arch * getNextFatArch( 69 | u_char *headerPage, 70 | struct fat_arch *lastArch); 71 | struct fat_arch * getFatArchForArchInfo( 72 | u_char *headerPage, 73 | const NXArchInfo *archInfo); 74 | const NXArchInfo * 75 | getThinHeaderPageArch( 76 | const void *headerPage); 77 | ExitStatus readFatFileArchsWithPath( 78 | const char * filePath, 79 | CFMutableArrayRef * archsOut); 80 | ExitStatus readFatFileArchsWithHeader( 81 | u_char * headerPage, 82 | CFMutableArrayRef * archsOut); 83 | ExitStatus readMachOSlices( 84 | const char * filePath, 85 | CFMutableArrayRef * slicesOut, 86 | CFMutableArrayRef * archsOut, 87 | mode_t * modeOut, 88 | struct timeval machOTimesOut[2]); 89 | 90 | CF_RETURNS_RETAINED 91 | CFDataRef readMachOSliceForArch( 92 | const char * filePath, 93 | const NXArchInfo * archInfo, 94 | Boolean checkArch); 95 | 96 | CF_RETURNS_RETAINED 97 | CFDataRef readMachOSlice( 98 | int fileDescriptor, 99 | off_t fileOffset, 100 | size_t fileSliceSize); 101 | int readFileAtOffset( 102 | int fileDescriptor, 103 | off_t fileOffset, 104 | size_t fileSize, 105 | u_char * buf); 106 | int verifyMachOIsArch( 107 | const UInt8 * fileBuf, 108 | size_t size, 109 | const NXArchInfo * archInfo); 110 | Boolean supportsFastLibCompression( 111 | void); 112 | CF_RETURNS_RETAINED 113 | CFDataRef uncompressPrelinkedSlice( 114 | CFDataRef prelinkImage); 115 | CF_RETURNS_RETAINED 116 | CFDataRef compressPrelinkedSlice( 117 | uint32_t compressionType, 118 | CFDataRef prelinkImage, 119 | Boolean hasRelocs); 120 | ExitStatus writePrelinkedSymbols( 121 | CFURLRef symbolDirURL, 122 | CFArrayRef prelinkSymbols, 123 | CFArrayRef prelinkArchs); 124 | ExitStatus makeDirectoryWithURL( 125 | CFURLRef dirURL); 126 | 127 | #endif /* _KERNELCACHE_H_ */ 128 | -------------------------------------------------------------------------------- /kext_logging.8: -------------------------------------------------------------------------------- 1 | .Dd March 6, 2009 2 | .Os Darwin 3 | .Dt KEXT_LOGGING 8 4 | .Sh NAME 5 | .Nm kext logging 6 | .Nd verbose/logging flags for kernel extensions (kexts) in the kernel and command-line utilities 7 | .Sh DESCRIPTION 8 | The kext management facilities of Mac OS X 9 | allow for logging of kext activity at all system levels, 10 | from the kernel to the user-space kext daemon and most command-line kext tools. 11 | The 12 | .Fl verbose 13 | .Li ( Ns Fl v Ns Li ) 14 | flag of the tools provides a simple system of levels that apply a set 15 | of lower level binary logging flags appropriate to each tool, 16 | for maximally useful verbose output. 17 | The binary log specification is used for kernel logging 18 | and is also available for use with the 19 | .Fl verbose 20 | option when you need precise control over logging. 21 | .Sh ENABLING LOGGING 22 | For command-line tools the 23 | .Fl verbose 24 | .Li ( Ns Fl v Ns Li ) 25 | and 26 | .Fl quiet 27 | .Li ( Ns Fl q Ns Li ) 28 | flags control verbose output. 29 | The 30 | .Fl verbose 31 | flag accepts a decimal level from 0-6 or a hexadecimal log specification, 32 | both described below. 33 | The 34 | .Fl verbose 35 | flag temporarily sets the log spec within the kernel, 36 | and captures any log messages from the kernel to print along with the tool's own log messages. 37 | .Pp 38 | If you wish to alter the logging behavior of 39 | .Xr kextd 8 , 40 | you will need to edit its 41 | .Xr launchd.plist 5 42 | file in 43 | .Pa /System/Library/LaunchDaemons/com.apple.kextd.plist . 44 | .Pp 45 | To enable kernel kext logging (in 46 | .Pa /var/log/kernel.log ) 47 | on a long-term basis, 48 | use the 49 | .Sy kextlog 50 | boot arg or 51 | .Xr sysctl 8 52 | parameter. 53 | You can set it as root using 54 | .Xr nvram 8 55 | like so: 56 | .Bd -literal -offset indent 57 | .Li "nvram boot-args=" Ns Qo kextlog=0x Ns Ar logspec Ar other_boot_args Ns Qc 58 | .Ed 59 | .Pp 60 | where 61 | .Ar logspec 62 | is a hexadecimal log specification, 63 | as described below under 64 | .Dq BINARY LOG SPECIFICATION . 65 | .Pp 66 | .Em Caution: 67 | Enabling logging at a high level via boot arg can greatly slow down system startup time. 68 | .Pp 69 | To change the 70 | .Sy kextlog 71 | setting at any time use 72 | .Xr sysctl 8 : 73 | .Bd -literal -offset indent 74 | .Li "sysctl -w debug.kextlog=0x" Ns Ar logspec 75 | .Ed 76 | .Sh VERBOSE LEVELS 77 | As mentioned, for the command-line kext tools you use the 78 | .Fl verbose 79 | .Li ( Ns Fl v Ns Li ) 80 | flag, 81 | which takes an optional argument that is either a decimal level from 0-6, 82 | or a hexadecimal log specification (described under 83 | .Do BINARY LOG SPECIFICATION Dc Ns ). 84 | The details of each level vary by tool, but in general they are: 85 | .Bl -tag -width "1 (or none)" 86 | .It 0 87 | Errors only (that is, suppress warnings). 88 | Tools with a 89 | .Fl verbose 90 | flag also support a 91 | .Fl quiet 92 | flag to suppress all output. 93 | .It 1 (or none) 94 | Basic information about program operation. 95 | .It 2 96 | Basic information about program progress, including files created. 97 | .It 3 98 | Information about individual kexts, link/load operation, 99 | and processing of I/O Kit personalities. 100 | .It 4 101 | Detailed information about kext operations, 102 | including C++ class construction/destruction, 103 | and for archives, 104 | about compression and architectures processed. 105 | .It 5 106 | Debug-level information about internal operations. 107 | .It 6 108 | Identical to level 5 but with bit 0x8 turned on 109 | (see the hecadecimal log specification for details). 110 | .El 111 | .Sh BINARY LOG SPECIFICATION 112 | The binary log specification is a 32-bit value comprising a log level with a bitmask 113 | divided into several regions from the least-significant nibble 114 | (corresponding to digits from right to left in a hexadecimal representation). 115 | This table describes the regions and bits used; 116 | unlisted regions and bits are reserved for future use: 117 | .Bl -tag -width "Nibbles 1-2" 118 | .It Nibble 0 119 | The log level, from 0-7. 120 | Each level includes all levels below it. 121 | This is generally two higher than the decimal level specified with 122 | .Fl verbose . 123 | .Bl -inset 124 | .It Em "Log level 0" - 125 | Silent. 126 | .It Em "Log level 1" - 127 | Errors. 128 | .It Em "Log level 2" - 129 | Warnings. 130 | .It Em "Log level 3" - 131 | Basic outcome/result. 132 | .It Em "Log level 4" - 133 | Operation progress. 134 | .It Em "Log level 5" - 135 | Steps in a given operation. 136 | .It Em "Log level 6" - 137 | Detailed logging. 138 | .It Em "Log level 7" - 139 | Debug level logging. 140 | .El 141 | .Pp 142 | In addition, bit 0x8 of this nibble controls 143 | whether kext-specific log messages are always printed. 144 | .Xr kextcache 8 145 | and 146 | .Xr kextunload 8 147 | turn this bit on with their 148 | .Fl verbose 149 | flag. 150 | See 151 | .Dq PER-KEXT LOGGING 152 | for more information. 153 | .It Nibbles 1-2 154 | Activity flags relevant to general tool use, as in development scenarios. 155 | The 156 | .Fl verbose 157 | flag always includes these. 158 | 8 bits total. 159 | .Bl -inset 160 | .It Em "Nibble 1, Bit 0 (0x10)" - 161 | General activity. 162 | .It Em "Nibble 1, Bit 1 (0x20)" - 163 | Load activity. 164 | .It Em "Nibble 1, Bit 2 (0x40)" - 165 | IPC and load settings. 166 | .It Em "Nibble 1, Bit 3 (0x80)" - 167 | Archive processing. 168 | .It Em "Nibble 2" - 169 | Reserved. 170 | .El 171 | .It Nibbles 3-7 172 | Activity flags for internal operations, 173 | for debugging the kext management system itself. 174 | These are available only when using a hexadecimal log specification; 175 | the 176 | .Fl verbose 177 | flag never includes these. 178 | 20 bits total. 179 | .Bl -inset 180 | .It Em "Nibble 3, Bit 0 (0x1000)" - 181 | Kext validation. 182 | .It Em "Nibble 3, Bit 1 (0x2000)" - 183 | Kext authentication. 184 | .It Em "Nibble 3, Bit 2 (0x4000)" - 185 | Kext dependency resolution. 186 | .It Em "Nibble 4, Bit 0 (0x10000)" - 187 | Directory scan (booter data scan in the kernel). 188 | .It Em "Nibble 4, Bit 1 (0x20000)" - 189 | File I/O. 190 | .It Em "Nibble 4, Bit 2 (0x40000)" - 191 | Kext bookkeeping. 192 | .It Em "Nibble 5, Bit 0 (0x100000)" - 193 | Link activity. 194 | .It Em "Nibble 5, Bit 1 (0x200000)" - 195 | C++ patching activity. 196 | .It Em "Nibbles 6-7" - 197 | Reserved. 198 | .El 199 | .El 200 | .Sh PER-KEXT LOGGING 201 | Many log messages apply to the kext being processed. 202 | The kernel and most of the command-line kext tools do not log 203 | these messages by default. 204 | You can enable these messages for an individual kext 205 | by specifying an OSBundleEnableKextLogging 206 | property in its 207 | .Pa Info.plist 208 | file with a boolean value of true. 209 | For convenience, 210 | .Xr kextutil 8 211 | automatically sets this property for the kexts it is loading. 212 | .Pp 213 | You can activate all per-kext log messages using 214 | level 6 with the 215 | .Fl verbose 216 | flag or by turning on bit 0x8 in a hexadecimal log specification. 217 | For convenience, 218 | .Xr kextcache 8 219 | and 220 | .Xr kextunload 8 221 | do this for all verbose levels of their 222 | .Fl verbose 223 | flag. 224 | .Sh MAPPING VERBOSE LEVELS TO LOG SPECIFICATIONS 225 | Here is a list of the exact hecadecimal log specifications 226 | applied by each of the 227 | .Fl verbose 228 | levels: 229 | .Bl -tag -width "1 (or none)" 230 | .It 0 231 | equivalent to 0x0 for all tools. 232 | .It (default level) 233 | equivalent to 0xff2, 234 | 0xff9 for 235 | .Xr kextcache 8 236 | and 237 | .Xr kextunload 8 , 238 | 0xff3 for 239 | .Xr kextd 8 240 | and for 241 | .Xr kextcache 8 242 | spawned by 243 | .Xr kextd 8 . 244 | .It 1 (or none) 245 | equivalent to 0xff3, or 0xffa for 246 | .Xr kextcache 8 247 | and 248 | .Xr kextunload 8 . 249 | .It 2 250 | equivalent to 0xff4, or 0xffb for 251 | .Xr kextcache 8 252 | and 253 | .Xr kextunload 8 . 254 | .It 3 255 | equivalent to 0xff5, or 0xffc for 256 | .Xr kextcache 8 257 | and 258 | .Xr kextunload 8 . 259 | .It 4 260 | equivalent to 0xff6, or 0xffd for 261 | .Xr kextcache 8 262 | and 263 | .Xr kextunload 8 . 264 | .It 5 265 | equivalent to 0xff7, or 0xffe for 266 | .Xr kextcache 8 267 | and 268 | .Xr kextunload 8 . 269 | .It 6 270 | equivalent to 0xfff for all tools. 271 | .El 272 | .Sh FILES 273 | .Bl -tag -width "/var/log/kernel.log" 274 | .It Pa /var/log/kernel.log 275 | The kernel log file, where kernel kext activity is logged. 276 | .It Pa /var/log/system.log 277 | The system log file, where 278 | .Xr kextd 8 279 | activity is logged. 280 | .It Pa /System/Library/LaunchDaemons/com.apple.kextd.plist 281 | Edit this 282 | .Xr launchd.plist 5 283 | file to specify verbose logging for 284 | .Xr kextd 8 . 285 | .El 286 | .Sh SEE ALSO 287 | .Xr syslog 1 , 288 | .Xr kextcache 8 , 289 | .Xr kextd 8 , 290 | .Xr kextlibs 8 , 291 | .Xr kextload 8 , 292 | .Xr kextunload 8 , 293 | .Xr kextutil 8 -------------------------------------------------------------------------------- /kext_tools_util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * kext_tools_util.h 3 | * kext_tools 4 | * 5 | * Created by Nik Gervae on 4/25/08. 6 | * Copyright 2008 Apple Inc. All rights reserved. 7 | * 8 | */ 9 | #ifndef _KEXT_TOOLS_UTIL_H 10 | #define _KEXT_TOOLS_UTIL_H 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #pragma mark Types 23 | /******************************************************************************* 24 | * Types 25 | *******************************************************************************/ 26 | typedef int ExitStatus; 27 | 28 | typedef enum { 29 | kUsageLevelBrief = 0, 30 | kUsageLevelFull = 1 31 | } UsageLevel; 32 | 33 | typedef struct { 34 | CFURLRef saveDirURL; 35 | Boolean overwrite; 36 | Boolean fatal; 37 | } SaveFileContext; 38 | 39 | #pragma mark Constants 40 | /******************************************************************************* 41 | * Constants 42 | *******************************************************************************/ 43 | #define _kKextPropertyValuesCacheBasename "KextPropertyValues_" 44 | #define __kOSKextApplePrefix CFSTR("com.apple.") 45 | 46 | #define kAppleInternalPath "/AppleInternal" 47 | #define kDefaultDevKernelPath "/System/Library/Kernels/kernel.development" 48 | #define kDefaultDevKernelSuffix ".development" 49 | 50 | #pragma mark Macros 51 | /********************************************************************* 52 | * Macros 53 | *********************************************************************/ 54 | 55 | #define SAFE_FREE(ptr) do { \ 56 | if (ptr) free(ptr); \ 57 | } while (0) 58 | #define SAFE_FREE_NULL(ptr) do { \ 59 | if (ptr) free(ptr); \ 60 | (ptr) = NULL; \ 61 | } while (0) 62 | #define SAFE_RELEASE(ptr) do { \ 63 | if (ptr) CFRelease(ptr); \ 64 | } while (0) 65 | #define SAFE_RELEASE_NULL(ptr) do { \ 66 | if (ptr) CFRelease(ptr); \ 67 | (ptr) = NULL; \ 68 | } while (0) 69 | 70 | #define RANGE_ALL(a) CFRangeMake(0, CFArrayGetCount(a)) 71 | 72 | #define COMPILE_TIME_ASSERT(pred) switch(0){case 0:case pred:;} 73 | 74 | /********************************************************************* 75 | *********************************************************************/ 76 | 77 | /* Library default is not to log Basic, but kextd & kextcache spawned 78 | * by kextd want to do that. 79 | */ 80 | #define kDefaultServiceLogFilter ((OSKextLogSpec) kOSKextLogBasicLevel | \ 81 | kOSKextLogVerboseFlagsMask) 82 | 83 | #pragma mark Shared Command-line Option Definitions 84 | /******************************************************************************* 85 | * Command-line options. This data is used by getopt_long_only(). 86 | *******************************************************************************/ 87 | #define kOptNameArch "arch" 88 | #define kOptNameBundleIdentifier "bundle-id" 89 | #define kOptNameRepository "repository" 90 | 91 | #define kOptNameSafeBoot "safe-boot" 92 | #define kOptNameSystemExtensions "system-extensions" 93 | #define kOptNameKernel "kernel" 94 | #define kOptNameNoAuthentication "no-authentication" 95 | 96 | #define kOptNameHelp "help" 97 | #define kOptNameQuiet "quiet" 98 | #define kOptNameVerbose "verbose" 99 | 100 | #define kOptNameLongindexHack "________" 101 | 102 | // Can't use -a globally for -arch because of kextutil...? 103 | #define kOptBundleIdentifier 'b' 104 | // Can't use -r globally for -repository because of kextcache...? 105 | 106 | // Can't use -x globally for -safe-boot because of kextcache's -s...? 107 | // Can't use -e globally for -system-extensions because of kextutil...? 108 | // Can't use -k globally for -kernel because of kextcache...? 109 | #define kOptNoAuthentication 'z' 110 | 111 | #define kOptHelp 'h' 112 | #define kOptQuiet 'q' 113 | #define kOptVerbose 'v' 114 | 115 | // Long opts always defined in each program to avoid # collisions 116 | 117 | #pragma mark Function Protos 118 | /********************************************************************* 119 | * Function Protos 120 | *********************************************************************/ 121 | 122 | Boolean createCFMutableArray(CFMutableArrayRef * arrayOut, 123 | const CFArrayCallBacks * callbacks); 124 | Boolean createCFMutableDictionary(CFMutableDictionaryRef * dictionaryOut); 125 | Boolean createCFMutableSet(CFMutableSetRef * setOut, 126 | const CFSetCallBacks * callbacks); 127 | Boolean createCFDataFromFile(CFDataRef *dataRefOut, 128 | const char *filePath); 129 | 130 | void addToArrayIfAbsent(CFMutableArrayRef array, const void * value); 131 | 132 | ExitStatus checkPath( 133 | const char * path, 134 | const char * suffix, // w/o the dot 135 | Boolean directoryRequired, 136 | Boolean writableRequired); 137 | 138 | ExitStatus setLogFilterForOpt( 139 | int argc, 140 | char * const * argv, 141 | OSKextLogSpec forceOnFlags); 142 | 143 | void beQuiet(void); 144 | 145 | FILE * g_log_stream; 146 | // tool_openlog(), tool_log() copied to bootroot.h for libBootRoot clients 147 | void tool_openlog(const char * name); 148 | void tool_log( 149 | OSKextRef aKext, 150 | OSKextLogSpec logSpec, 151 | const char * format, 152 | ...); 153 | void log_CFError( 154 | OSKextRef aKext __unused, 155 | OSKextLogSpec msgLogSpec, 156 | CFErrorRef error); 157 | 158 | const char * safe_mach_error_string(mach_error_t error_code); 159 | 160 | #define REPLY_ERROR (-1) 161 | #define REPLY_NO (0) 162 | #define REPLY_YES (1) 163 | #define REPLY_ALL (2) 164 | 165 | int user_approve(Boolean ask_all, int default_answer, const char * format, ...); 166 | 167 | const char * user_input(Boolean * eof, const char * format, ...); 168 | void saveFile(const void * vKey, const void * vValue, void * vContext); 169 | 170 | CFStringRef copyKextPath(OSKextRef aKext); 171 | Boolean readSystemKextPropertyValues( 172 | CFStringRef propertyKey, 173 | const NXArchInfo * arch, 174 | Boolean forceUpdateFlag, 175 | CFArrayRef * valuesOut); 176 | 177 | ExitStatus writeToFile( 178 | int fileDescriptor, 179 | const UInt8 * data, 180 | CFIndex length); 181 | 182 | ExitStatus statURL(CFURLRef anURL, struct stat * statBuffer); 183 | ExitStatus statPath(const char *path, struct stat *statBuffer); 184 | ExitStatus statParentPath(const char *thePath, struct stat *statBuffer); 185 | ExitStatus getLatestTimesFromCFURLArray( 186 | CFArrayRef fileURLArray, 187 | struct timeval fileTimes[2]); 188 | ExitStatus getLatestTimesFromDirURL( 189 | CFURLRef dirURL, 190 | struct timeval dirTimeVals[2]); 191 | 192 | ExitStatus getLatestTimesFromDirPath( 193 | const char * dirPath, 194 | struct timeval dirTimeVals[2]); 195 | 196 | ExitStatus getFilePathTimes( 197 | const char * filePath, 198 | struct timeval cacheFileTimes[2]); 199 | 200 | ExitStatus getParentPathTimes( 201 | const char * thePath, 202 | struct timeval cacheFileTimes[2] ); 203 | 204 | void postNoteAboutKexts( 205 | CFStringRef theNotificationCenterName, 206 | CFMutableDictionaryRef theDict ); 207 | 208 | void postNoteAboutKextLoadsMT( 209 | CFStringRef theNotificationCenterName, 210 | CFMutableArrayRef theKextPathArray ); 211 | 212 | void addKextToAlertDict( 213 | CFMutableDictionaryRef *theDictPtr, 214 | OSKextRef theKext ); 215 | 216 | char * getPathExtension(const char * pathPtr); 217 | 218 | int getFileDevAndIno(const char * thePath, dev_t * the_dev_t, ino_t * the_ino_t); 219 | Boolean isSameFileDevAndIno(int the_fd, 220 | const char * thePath, 221 | dev_t the_dev_t, 222 | ino_t the_ino_t); 223 | 224 | // bootcaches.plist helpers 225 | CFDictionaryRef copyBootCachesDictForURL(CFURLRef theVolRootURL); 226 | Boolean getKernelPathForURL( 227 | CFURLRef theVolRootURL, 228 | char * theBuffer, 229 | int theBufferSize ); 230 | 231 | // Development kernel support 232 | Boolean useDevelopmentKernel(const char * theKernelPath); 233 | Boolean isDebugSetInBootargs(void); 234 | 235 | 236 | /********************************************************************* 237 | * From IOKitUser/kext.subproj/OSKext.c. 238 | *********************************************************************/ 239 | 240 | extern char * createUTF8CStringForCFString(CFStringRef aString); 241 | 242 | #endif /* _KEXT_TOOLS_UTIL_H */ 243 | -------------------------------------------------------------------------------- /kextcache-entitlements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.private.kernel.get-kext-info 6 | 7 | com.apple.rootless.install 8 | 9 | com.apple.rootless.kext-management 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /kextd-entitlements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.private.kernel.get-kext-info 6 | 7 | com.apple.rootless.kext-management 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /kextd.8: -------------------------------------------------------------------------------- 1 | .Dd March 6, 2009 2 | .Os Darwin 3 | .Dt KEXTD 8 4 | .Sh NAME 5 | .Nm kextd 6 | .Nd kernel extension server 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Ar options 10 | .Sh DESCRIPTION 11 | .Nm 12 | is the kernel extension server. 13 | It runs as a standalone 14 | .Xr launchd 8 daemon to handle requests from the kernel 15 | and from other user-space processes 16 | to load kernel extensions (kexts) or provide information about them. 17 | .Sh OPTIONS 18 | These options are available: 19 | .Bl -tag -width -indent 20 | .It Fl c , Fl no-caches 21 | Ignore any repository cache files and scan all kext bundles 22 | to gather information. 23 | If this option is not given, 24 | .Nm 25 | attempts to use cache files and to create them 26 | if they are out of date or don't exist. 27 | .It Fl d , Fl debug 28 | Debug mode; print messages to stdout/stderr rather than 29 | the sysem log. 30 | .It Fl h , Fl help 31 | Print a help message describing each option flag and exit with a success result, 32 | regardless of any other options on the command line. 33 | .It Fl q , Fl quiet 34 | Quiet mode; log no informational or error messages. 35 | .It Fl v Li [ 0-6 | 0x#### Ns Li ] , Fl verbose Li [ 0-6 | 0x#### Ns Li ] 36 | Verbose mode; print information about program operation. 37 | Higher levels of verbosity include all lower levels. 38 | By default 39 | .Nm 40 | logs at verbose level 1. 41 | You can specify a level from 0-6, 42 | or a hexadecimal log specification 43 | (as described in 44 | .Xr kext_logging 8 Ns No ). 45 | The levels of verbose output are: 46 | .Bl -tag -width "1 (or none)" 47 | .It 0 48 | Print only errors (that is, suppress warnings); see also 49 | .Fl quiet . 50 | .It 1 (or none) 51 | Print basic information about program operation. 52 | .It 2 53 | Print information about program operation progress, client requests, and files created. 54 | .It 3 55 | Print information about individual kexts with an 56 | OSBundleEnableKextLogging property set to true. 57 | .It 4 58 | Print information about spawned child processes. 59 | .It 5 60 | Print debug-level information. 61 | .It 6 62 | Identical to level 5 but for all kexts read by the program. 63 | .El 64 | .Pp 65 | See 66 | .Xr kext_logging 8 67 | for more information on verbose logging. 68 | .It Fl x , Fl safe-boot 69 | Run 70 | .Nm 71 | in safe boot mode (indicating startup with the Shift key held down). 72 | Kexts that don't specify a proper value for the OSBundleRequired 73 | info dictionary property will not be loaded. 74 | As of Mac OS X 10.5 (Leopard), 75 | .Nm 76 | determines from the kernel 77 | whether the system has started in safe boot mode, 78 | so this flag is no longer necessary (but may be used for testing). 79 | In safe boot mode, 80 | .Nm 81 | does not use caches 82 | (that is, this option implies the use of the 83 | .Fl no-caches 84 | option). 85 | .El 86 | .Sh RESETTING KEXTD 87 | On Mac OS X 10.3 and later, it is possible to reset 88 | .Nm 89 | without terminating and restarting it, by sending it a HUP signal. This 90 | causes 91 | .Nm 92 | to rescan the Extensions folder, rebuild all its caches, 93 | and send all I/O Kit drivers' personalities to the kernel 94 | for a new round of driver matching. 95 | As of Mac OS X 10.5 (Leopard), 96 | .Nm 97 | watches 98 | .Pa /System/Library/Extensions/ 99 | and automatically invokes 100 | .Xr kextcache 8 101 | to rebuild kext caches when its modification time changes. 102 | It also sends new drivers' 103 | personalities to the kernel at this time. 104 | .Pp 105 | Installers that add new drivers can signal 106 | .Nm 107 | in these ways instead of requiring the computer to be restarted. 108 | Note that if a hardware device has a driver attached when this is done, 109 | a newly-installed driver will not match on it. 110 | For more information, see 111 | .Dq "Apple Developer Technical Q&A QA1319: Installing an I/O Kit Kext Without Rebooting" . 112 | .Sh FILES 113 | .Bl -tag -width "/System/Library/Extensions/" 114 | .It Pa /System/Library/Extensions/ 115 | The standard system repository of kernel extensions. 116 | .It Pa /System/Library/Caches/com.apple.kext.caches/ 117 | Contains all kext caches for a Mac OS X 10.6 (Snow Leopard) system: prelinked kernel, 118 | mkext, and system kext info caches. 119 | .It Pa /usr/standalone/bootcaches.plist 120 | Describes specific kext cache files for a Mac OS X volume. 121 | .It Pa /System/Library/LaunchDaemons/com.apple.kextd.plist 122 | The 123 | .Xr launchd.plist 5 124 | controlling the 125 | .Nm 126 | job. 127 | .El 128 | .Sh DIAGNOSTICS 129 | .Nm 130 | normally never exits. 131 | If an error occurs it exits with a nonzero status. 132 | .Pp 133 | .Nm 134 | logs all error and verbose messages to the system log, 135 | or to the console if the system log facility isn't available. 136 | When running in debug mode all output is printed 137 | to the standard output and error streams. 138 | .Sh SEE ALSO 139 | .Xr kextcache 8 , 140 | .Xr kextload 8 , 141 | .Xr kextutil 8 , 142 | .Xr kextstat 8 , 143 | .Xr kextunload 8 , 144 | .Xr kextfind 8 , 145 | .Xr syslogd 8 , 146 | .Xr launchd.plist 5 147 | -------------------------------------------------------------------------------- /kextd_globals.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2008 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 | #ifndef _KEXTD_GLOBALS_H 29 | #define _KEXTD_GLOBALS_H 30 | 31 | // currently not suitable for sharing with other tools 32 | // xxx - NOT SUPPOSED TO BE SHARED WITH OTHER TOOLS! 33 | 34 | #include 35 | #include 36 | #include 37 | 38 | // kextd_main.c 39 | extern const NXArchInfo * gKernelArchInfo; 40 | 41 | // kextd_mig_server.c 42 | extern uid_t gClientUID; // set & cleared by kextd_demux() 43 | 44 | // serialize_kextload.c 45 | extern dispatch_source_t _gKextutilLock; 46 | extern Boolean gKernelRequestsPending; 47 | 48 | #endif /* _KEXTD_GLOBALS_H */ 49 | -------------------------------------------------------------------------------- /kextd_mach.defs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008 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 | #include 29 | -------------------------------------------------------------------------------- /kextd_main.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008 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 | #ifndef _KEXTD_MAIN_H 29 | #define _KEXTD_MAIN_H 30 | 31 | #include 32 | #include 33 | 34 | #include 35 | #include 36 | 37 | #include "kext_tools_util.h" 38 | 39 | 40 | #pragma mark Basic Types & Constants 41 | /******************************************************************************* 42 | * Basic Types & Constants 43 | *******************************************************************************/ 44 | enum { 45 | kKextdExitOK = EX_OK, 46 | kKextdExitError, 47 | kKextdExitSigterm, 48 | 49 | // don't actually exit with this, it's just a sentinel value 50 | kKextdExitHelp = 33 51 | }; 52 | 53 | typedef struct { 54 | mach_msg_header_t header; 55 | int signum; 56 | } kextd_mach_msg_signal_t; 57 | 58 | 59 | #define kAppleSetupDonePath "/var/db/.AppleSetupDone" 60 | #define kKextcacheDelayStandard (60) 61 | #define kKextcacheDelayFirstBoot (60 * 5) 62 | 63 | #define kReleaseKextsDelay (30) 64 | 65 | #pragma mark Command-line Option Definitions 66 | /******************************************************************************* 67 | * Command-line options. This data is used by getopt_long_only(). 68 | * 69 | * Options common to all kext tools are in kext_tools_util.h. 70 | *******************************************************************************/ 71 | 72 | #define kOptNameNoCaches "no-caches" 73 | #define kOptNameDebug "debug" 74 | #define kOptNameNoJettison "no-jettison" 75 | 76 | #define kOptNoCaches 'c' 77 | #define kOptDebug 'd' 78 | #define kOptSafeBoot 'x' 79 | 80 | #define kOptChars "cdhqvx" 81 | 82 | /* Options with no single-letter variant. */ 83 | // Do not use -1, that's getopt() end-of-args return value 84 | // and can cause confusion 85 | #define kLongOptLongindexHack (-2) 86 | 87 | #pragma mark Tool Args Structure 88 | /******************************************************************************* 89 | * Tool Args Structure 90 | *******************************************************************************/ 91 | typedef struct { 92 | Boolean useRepositoryCaches; 93 | Boolean debugMode; 94 | Boolean safeBootMode; // actual or simulated 95 | 96 | Boolean firstBoot; 97 | } KextdArgs; 98 | 99 | extern CFArrayRef gRepositoryURLs; 100 | 101 | #pragma mark Function Prototypes 102 | /******************************************************************************* 103 | * Function Prototypes 104 | *******************************************************************************/ 105 | ExitStatus readArgs(int argc, char * const * argv, KextdArgs * toolArgs); 106 | 107 | void checkStartupMkext(KextdArgs * toolArgs); 108 | Boolean isNetboot(void); 109 | void sendActiveToKernel(void); 110 | void sendFinishedToKernel(void); 111 | ExitStatus setUpServer(KextdArgs * toolArgs); 112 | 113 | bool isBootRootActive(void); 114 | 115 | void handleSignal(int signum); 116 | void handleSignalInRunloop( 117 | CFMachPortRef port, 118 | void * msg, 119 | CFIndex size, 120 | void * info); 121 | 122 | void readExtensions(void); 123 | void scheduleReleaseExtensions(void); 124 | void releaseExtensions(CFRunLoopTimerRef timer, void * context); 125 | void rescanExtensions(void); 126 | 127 | void usage(UsageLevel usageLevel); 128 | 129 | #endif /* _KEXTD_MAIN_H */ 130 | -------------------------------------------------------------------------------- /kextd_mig_server.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2008 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 | #include 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include 36 | #include "kext_tools_util.h" 37 | #include "kextd_globals.h" 38 | #include "kextd_mig_server.h" 39 | 40 | /* mig-generated externals and functions */ 41 | extern struct mig_subsystem _kextmanager_subsystem; 42 | extern boolean_t kextmanager_server(mach_msg_header_t *, mach_msg_header_t *); 43 | 44 | extern struct mig_subsystem svc_kextd_kernel_request_subsystem; 45 | extern boolean_t kextd_kernel_request_server( 46 | mach_msg_header_t *InHeadP, 47 | mach_msg_header_t *OutHeadP); 48 | 49 | uid_t gClientUID = -1; 50 | 51 | /******************************************************************************* 52 | *******************************************************************************/ 53 | boolean_t kextd_demux( 54 | mach_msg_header_t * request, 55 | mach_msg_header_t * reply) 56 | { 57 | boolean_t processed = FALSE; 58 | 59 | mach_msg_format_0_trailer_t * trailer; 60 | 61 | /* Feed the request into the ("MiG" generated) server. We have two 62 | * subsystems, one for user-space clients, one for the kernel. 63 | */ 64 | if (!processed) { 65 | if (request->msgh_id >= _kextmanager_subsystem.start && 66 | request->msgh_id < _kextmanager_subsystem.end) { 67 | 68 | /* 69 | * Get the caller's credentials (eUID/eGID) from the message trailer. 70 | */ 71 | trailer = (mach_msg_security_trailer_t *)((vm_offset_t)request + 72 | round_msg(request->msgh_size)); 73 | 74 | if ((trailer->msgh_trailer_type == MACH_MSG_TRAILER_FORMAT_0) && 75 | (trailer->msgh_trailer_size >= MACH_MSG_TRAILER_FORMAT_0_SIZE)) { 76 | 77 | gClientUID = trailer->msgh_sender.val[0]; 78 | 79 | OSKextLog(/* kext */ NULL, 80 | kOSKextLogDebugLevel | kOSKextLogIPCFlag, 81 | "MIG message received: caller has eUID = %d, eGID = %d.", 82 | trailer->msgh_sender.val[0], 83 | trailer->msgh_sender.val[1]); 84 | 85 | } else { 86 | OSKextLog(/* kext */ NULL, 87 | kOSKextLogWarningLevel | kOSKextLogIPCFlag, 88 | "Caller's credentials not available."); 89 | gClientUID = -1; 90 | 91 | } 92 | 93 | /* Process user task requests. 94 | */ 95 | processed = kextmanager_server(request, reply); 96 | 97 | } else if (request->msgh_id >= svc_kextd_kernel_request_subsystem.start && 98 | request->msgh_id < svc_kextd_kernel_request_subsystem.end) { 99 | 100 | /* Process kernel requests. 101 | */ 102 | processed = kextd_kernel_request_server(request, reply); 103 | } 104 | } 105 | 106 | if (!processed) { 107 | if (request->msgh_id >= MACH_NOTIFY_FIRST && 108 | request->msgh_id < MACH_NOTIFY_LAST) { 109 | 110 | OSKextLog(/* kext */ NULL, 111 | kOSKextLogErrorLevel | kOSKextLogIPCFlag, 112 | "Failed to process MIG message."); 113 | } else { 114 | OSKextLog(/* kext */ NULL, 115 | kOSKextLogErrorLevel | kOSKextLogIPCFlag, 116 | "Unknown MIG message received."); 117 | } 118 | } 119 | 120 | gClientUID = (uid_t)-1; 121 | 122 | return processed; 123 | } 124 | 125 | /******************************************************************************* 126 | *******************************************************************************/ 127 | void kextd_mach_port_callback( 128 | CFMachPortRef port, 129 | void *msg, 130 | CFIndex size, 131 | void *info) 132 | { 133 | mig_reply_error_t * bufRequest = msg; 134 | mig_reply_error_t * bufReply = CFAllocatorAllocate( 135 | NULL, _kextmanager_subsystem.maxsize, 0); 136 | mach_msg_return_t mr; 137 | int options; 138 | 139 | /* we have a request message */ 140 | (void) kextd_demux(&bufRequest->Head, &bufReply->Head); 141 | 142 | if (!(bufReply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) && 143 | (bufReply->RetCode != KERN_SUCCESS)) { 144 | 145 | if (bufReply->RetCode == MIG_NO_REPLY) { 146 | /* 147 | * This return code is a little tricky -- it appears that the 148 | * demux routine found an error of some sort, but since that 149 | * error would not normally get returned either to the local 150 | * user or the remote one, we pretend it's ok. 151 | */ 152 | CFAllocatorDeallocate(NULL, bufReply); 153 | return; 154 | } 155 | 156 | /* 157 | * destroy any out-of-line data in the request buffer but don't destroy 158 | * the reply port right (since we need that to send an error message). 159 | */ 160 | bufRequest->Head.msgh_remote_port = MACH_PORT_NULL; 161 | mach_msg_destroy(&bufRequest->Head); 162 | } 163 | 164 | if (bufReply->Head.msgh_remote_port == MACH_PORT_NULL) { 165 | /* no reply port, so destroy the reply */ 166 | if (bufReply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) { 167 | mach_msg_destroy(&bufReply->Head); 168 | } 169 | CFAllocatorDeallocate(NULL, bufReply); 170 | return; 171 | } 172 | 173 | /* 174 | * send reply. 175 | * 176 | * We don't want to block indefinitely because the client 177 | * isn't receiving messages from the reply port. 178 | * If we have a send-once right for the reply port, then 179 | * this isn't a concern because the send won't block. 180 | * If we have a send right, we need to use MACH_SEND_TIMEOUT. 181 | * To avoid falling off the kernel's fast RPC path unnecessarily, 182 | * we only supply MACH_SEND_TIMEOUT when absolutely necessary. 183 | */ 184 | 185 | options = MACH_SEND_MSG; 186 | if (MACH_MSGH_BITS_REMOTE(bufReply->Head.msgh_bits) == MACH_MSG_TYPE_MOVE_SEND_ONCE) { 187 | options |= MACH_SEND_TIMEOUT; 188 | } 189 | mr = mach_msg(&bufReply->Head, /* msg */ 190 | options, /* option */ 191 | bufReply->Head.msgh_size, /* send_size */ 192 | 0, /* rcv_size */ 193 | MACH_PORT_NULL, /* rcv_name */ 194 | MACH_MSG_TIMEOUT_NONE, /* timeout */ 195 | MACH_PORT_NULL); /* notify */ 196 | 197 | 198 | /* Has a message error occurred? */ 199 | switch (mr) { 200 | case MACH_SEND_INVALID_DEST: 201 | case MACH_SEND_TIMED_OUT: 202 | /* the reply can't be delivered, so destroy it */ 203 | mach_msg_destroy(&bufReply->Head); 204 | break; 205 | 206 | default : 207 | /* Includes success case. */ 208 | break; 209 | } 210 | 211 | CFAllocatorDeallocate(NULL, bufReply); 212 | } 213 | -------------------------------------------------------------------------------- /kextd_mig_server.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008 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 | void kextd_mach_port_callback( 29 | CFMachPortRef port, 30 | void * msg, 31 | CFIndex size, 32 | void * info); 33 | -------------------------------------------------------------------------------- /kextd_personalities.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008 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 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | #include "kextd_main.h" 39 | #include "kextd_personalities.h" 40 | #include "kextd_usernotification.h" 41 | #include "kextd_globals.h" 42 | 43 | static OSReturn sendCachedPersonalitiesToKernel(Boolean resetFlag); 44 | 45 | /******************************************************************************* 46 | *******************************************************************************/ 47 | OSReturn sendSystemKextPersonalitiesToKernel( 48 | CFArrayRef kexts, 49 | Boolean resetFlag) 50 | { 51 | OSReturn result = kOSReturnSuccess; // optimistic 52 | CFArrayRef personalities = NULL; // must release 53 | CFMutableArrayRef authenticKexts = NULL; // must release 54 | CFIndex count, i; 55 | 56 | /* Note that we are going to finish on success here! 57 | * If we sent personalities we are done. 58 | * sendCachedPersonalitiesToKernel() logs a msg on failure. 59 | */ 60 | result = sendCachedPersonalitiesToKernel(resetFlag); 61 | if (result == kOSReturnSuccess) { 62 | goto finish; 63 | } 64 | 65 | /* If we didn't send from cache, send from the kexts. This will cause 66 | * lots of I/O. 67 | */ 68 | if (!createCFMutableArray(&authenticKexts, &kCFTypeArrayCallBacks)) { 69 | OSKextLogMemError(); 70 | goto finish; 71 | } 72 | 73 | /* Check all the kexts to see if we need to raise alerts 74 | * about improperly-installed extensions. 75 | */ 76 | recordNonsecureKexts(kexts); 77 | 78 | count = CFArrayGetCount(kexts); 79 | for (i = 0; i < count; i++) { 80 | OSKextRef aKext = (OSKextRef)CFArrayGetValueAtIndex(kexts, i); 81 | if (OSKextIsAuthentic(aKext)) { 82 | CFArrayAppendValue(authenticKexts, aKext); 83 | } 84 | } 85 | 86 | result = OSKextSendPersonalitiesOfKextsToKernel(authenticKexts, 87 | resetFlag); 88 | if (result != kOSReturnSuccess) { 89 | goto finish; 90 | } 91 | 92 | personalities = OSKextCopyPersonalitiesOfKexts(authenticKexts); 93 | 94 | /* Now try to write the cache file. Don't save the return value 95 | * of that function, we're more concerned with whether personalities 96 | * have actually gone to the kernel. 97 | */ 98 | _OSKextWriteCache(OSKextGetSystemExtensionsFolderURLs(), 99 | CFSTR(kIOKitPersonalitiesKey), gKernelArchInfo, 100 | _kOSKextCacheFormatIOXML, personalities); 101 | 102 | finish: 103 | if (result != kOSReturnSuccess) { 104 | OSKextLog(/* kext */ NULL, 105 | kOSKextLogErrorLevel | kOSKextLogIPCFlag, 106 | "Error: Couldn't send kext personalities to the IOCatalogue."); 107 | } else if (personalities) { 108 | OSKextLog(/* kext */ NULL, 109 | kOSKextLogProgressLevel | kOSKextLogIPCFlag | 110 | kOSKextLogKextBookkeepingFlag, 111 | "Sent %ld kext personalities to the IOCatalogue.", 112 | CFArrayGetCount(personalities)); 113 | } 114 | SAFE_RELEASE(personalities); 115 | SAFE_RELEASE(authenticKexts); 116 | return result; 117 | } 118 | 119 | /******************************************************************************* 120 | *******************************************************************************/ 121 | static OSReturn sendCachedPersonalitiesToKernel(Boolean resetFlag) 122 | { 123 | OSReturn result = kOSReturnError; 124 | CFDataRef cacheData = NULL; // must release 125 | 126 | if (!_OSKextReadCache(gRepositoryURLs, CFSTR(kIOKitPersonalitiesKey), 127 | gKernelArchInfo, _kOSKextCacheFormatIOXML, 128 | /* parseXML? */ false, (CFPropertyListRef *)&cacheData)) { 129 | 130 | goto finish; 131 | } 132 | 133 | OSKextLogCFString(/* kext */ NULL, 134 | kOSKextLogProgressLevel | kOSKextLogIPCFlag | 135 | kOSKextLogKextBookkeepingFlag, 136 | CFSTR("%@"), CFSTR("Sending cached kext personalities to IOCatalogue.")); 137 | 138 | result = IOCatalogueSendData(kIOMasterPortDefault, 139 | resetFlag ? kIOCatalogResetDrivers : kIOCatalogAddDrivers, 140 | (char *)CFDataGetBytePtr(cacheData), (unsigned int)CFDataGetLength(cacheData)); 141 | if (result != kOSReturnSuccess) { 142 | OSKextLog(/* kext */ NULL, 143 | kOSKextLogErrorLevel | kOSKextLogIPCFlag, 144 | "error: couldn't send personalities to the kernel."); 145 | goto finish; 146 | } 147 | 148 | OSKextLogCFString(/* kext */ NULL, 149 | kOSKextLogProgressLevel | kOSKextLogIPCFlag | 150 | kOSKextLogKextBookkeepingFlag, 151 | CFSTR("%@"), CFSTR("Sent cached kext personalities to the IOCatalogue.")); 152 | 153 | result = kOSReturnSuccess; 154 | 155 | finish: 156 | SAFE_RELEASE(cacheData); 157 | return result; 158 | } 159 | 160 | -------------------------------------------------------------------------------- /kextd_personalities.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008 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 | #ifndef __KEXTD_PERSONALITIES__ 29 | #define __KEXTD_PERSONALITIES__ 30 | 31 | #include "kext_tools_util.h" 32 | 33 | /* This function must be given the array of all kexts opened by 34 | * kextd from the system extensions folders. kextd tries to use 35 | * cache files for the system extension folders' personalities, 36 | * but if it can't use them all, it sends the personalities from 37 | * all kexts opened. 38 | */ 39 | OSReturn sendSystemKextPersonalitiesToKernel(CFArrayRef kexts, Boolean resetFlag); 40 | 41 | #endif /* __KEXTD_PERSONALITIES__ */ 42 | -------------------------------------------------------------------------------- /kextd_request.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008 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 | #ifndef __REQUEST_H__ 29 | #define __REQUEST_H__ 30 | 31 | #include 32 | #include 33 | 34 | #include 35 | 36 | #include "kext_tools_util.h" 37 | 38 | bool kextd_process_kernel_requests(void); 39 | 40 | #endif /* __REQUEST_H__ */ 41 | -------------------------------------------------------------------------------- /kextd_serialize_kextload.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008 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 | #include 29 | 30 | #include 31 | #include "kext_tools_util.h" 32 | #include "kextd_globals.h" 33 | #include 34 | 35 | dispatch_source_t _gKextutilLock = NULL; 36 | 37 | void kextd_process_kernel_requests(void); 38 | 39 | /****************************************************************************** 40 | * _kextmanager_lock_volume tries to lock volumes for clients (kextutil) 41 | *****************************************************************************/ 42 | static void removeKextutilLock(void) 43 | { 44 | if (_gKextutilLock) { 45 | dispatch_source_cancel(_gKextutilLock); 46 | } 47 | 48 | if (gKernelRequestsPending) { 49 | kextd_process_kernel_requests(); 50 | } 51 | 52 | CFRunLoopWakeUp(CFRunLoopGetCurrent()); 53 | return; 54 | } 55 | 56 | /****************************************************************************** 57 | * _kextmanager_lock_volume tries to lock volumes for clients (kextutil) 58 | *****************************************************************************/ 59 | kern_return_t _kextmanager_lock_kextload( 60 | mach_port_t server, 61 | mach_port_t client, 62 | int * lockstatus) 63 | { 64 | kern_return_t mig_result = KERN_FAILURE; 65 | int result; 66 | 67 | if (!lockstatus) { 68 | OSKextLog(/* kext */ NULL, 69 | kOSKextLogErrorLevel | kOSKextLogIPCFlag, 70 | "kextmanager_lock_kextload requires non-NULL lockstatus."); 71 | mig_result = KERN_SUCCESS; 72 | result = EINVAL; 73 | goto finish; 74 | } 75 | 76 | if (gClientUID != 0) { 77 | OSKextLog(/* kext */ NULL, 78 | kOSKextLogErrorLevel, 79 | "Non-root process doesn't need to lock as it will fail to load."); 80 | mig_result = KERN_SUCCESS; 81 | result = EPERM; 82 | goto finish; 83 | } 84 | 85 | if (_gKextutilLock) { 86 | mig_result = KERN_SUCCESS; 87 | result = EBUSY; 88 | goto finish; 89 | } 90 | 91 | result = ENOMEM; 92 | 93 | _gKextutilLock = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_SEND, client, 94 | DISPATCH_MACH_SEND_DEAD, dispatch_get_main_queue()); 95 | 96 | if (_gKextutilLock) { 97 | 98 | dispatch_source_set_event_handler(_gKextutilLock, ^{ 99 | OSKextLog(/* kext */ NULL, 100 | kOSKextLogErrorLevel | kOSKextLogIPCFlag, 101 | "Client exited without releasing kextutil lock."); 102 | removeKextutilLock(); 103 | }); 104 | 105 | dispatch_source_set_cancel_handler(_gKextutilLock, ^{ 106 | dispatch_release(_gKextutilLock); 107 | mach_port_deallocate(mach_task_self(), client); 108 | _gKextutilLock = NULL; 109 | }); 110 | 111 | dispatch_resume(_gKextutilLock); 112 | 113 | mig_result = KERN_SUCCESS; 114 | result = 0; 115 | } 116 | 117 | finish: 118 | if (mig_result != KERN_SUCCESS) { 119 | if (gClientUID == 0) { 120 | OSKextLog(/* kext */ NULL, 121 | kOSKextLogErrorLevel | kOSKextLogIPCFlag, 122 | "Trouble while locking for kextutil - %s.", 123 | safe_mach_error_string(mig_result)); 124 | } 125 | removeKextutilLock(); 126 | } else if (lockstatus) { 127 | *lockstatus = result; // only meaningful if mig_result == KERN_SUCCESS 128 | } 129 | 130 | return mig_result; 131 | } 132 | 133 | /****************************************************************************** 134 | * _kextmanager_unlock_kextload unlocks for clients (kextutil) 135 | *****************************************************************************/ 136 | kern_return_t _kextmanager_unlock_kextload( 137 | mach_port_t server, 138 | mach_port_t client) 139 | { 140 | kern_return_t mig_result = KERN_FAILURE; 141 | 142 | if (gClientUID != 0) { 143 | OSKextLog(/* kext */ NULL, 144 | kOSKextLogErrorLevel | kOSKextLogIPCFlag, 145 | "Non-root kextutil doesn't need to lock/unlock."); 146 | mig_result = KERN_SUCCESS; 147 | goto finish; 148 | } 149 | 150 | if (client != (mach_port_t)dispatch_source_get_handle(_gKextutilLock)) { 151 | OSKextLog(/* kext */ NULL, 152 | kOSKextLogErrorLevel | kOSKextLogIPCFlag, 153 | "%d not used to lock for kextutil.", client); 154 | goto finish; 155 | } 156 | 157 | removeKextutilLock(); 158 | 159 | mig_result = KERN_SUCCESS; 160 | 161 | finish: 162 | // we don't need the extra send right added by MiG 163 | mach_port_deallocate(mach_task_self(), client); 164 | 165 | return mig_result; 166 | } 167 | 168 | -------------------------------------------------------------------------------- /kextd_usernotification.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008 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 | #ifndef __KEXTD_USERNOTIFICATION_H__ 29 | #define __KEXTD_USERNOTIFICATION_H__ 30 | 31 | #include 32 | #include 33 | #include "kextd_main.h" 34 | 35 | #ifndef NO_CFUserNotification 36 | ExitStatus startMonitoringConsoleUser( 37 | KextdArgs * toolArgs, 38 | unsigned int * sourcePriority); 39 | void stopMonitoringConsoleUser(void); 40 | 41 | #define INVALID_SIGNATURE_KEXT_ALERT 1 42 | #define NO_LOAD_KEXT_ALERT 2 43 | #define REVOKED_SIG_KEXT_ALERT 3 44 | #define EXCLUDED_KEXT_ALERT 4 45 | //#define UNSIGNED_KEXT_ALERT 5 46 | 47 | Boolean recordNonsecureKexts(CFArrayRef kextList); 48 | Boolean recordNonSignedKextPath(CFStringRef theKextPath); 49 | void resetUserNotifications(Boolean dismissAlert); 50 | void sendNonsignedKextNotification(void); 51 | 52 | void writeKextAlertPlist(CFDictionaryRef theDict, int theAlertType); 53 | void writeKextLoadPlist(CFArrayRef theArray); 54 | void sendRevokedCertAlert(CFDictionaryRef theDict); 55 | 56 | void kextd_raise_notification( 57 | CFStringRef alertHeader, 58 | CFArrayRef messageArray); 59 | 60 | #endif /* ifndef NO_CFUserNotification */ 61 | 62 | #endif /* __KEXTD_USERNOTIFICATION_H__ */ 63 | -------------------------------------------------------------------------------- /kextd_watchvol.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007 Apple Inc. All rights reserved. 3 | * 4 | * @APPLE_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. Please obtain a copy of the License at 10 | * http://www.opensource.apple.com/apsl/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | * 21 | * @APPLE_LICENSE_HEADER_END@ 22 | */ 23 | /* 24 | * 25 | * FILE: watchvol.h 26 | * AUTH: Soren Spies (sspies) 27 | * DATE: 6 March 2006 28 | * DESC: header for volume watching routines 29 | * 30 | */ 31 | 32 | // for kextd_main 33 | int kextd_watch_volumes(int sourcePriority/*, CFRunLoopRef runloop*/); 34 | int kextd_giveup_volwatch(); 35 | void kextd_stop_volwatch(); 36 | 37 | void updateRAIDSet( 38 | CFNotificationCenterRef center, 39 | void * observer, 40 | CFStringRef name, 41 | const void * object, 42 | CFDictionaryRef userInfo); 43 | 44 | void updateCoreStorageVolume( 45 | CFNotificationCenterRef center, 46 | void * observer, 47 | CFStringRef name, 48 | const void * object, 49 | CFDictionaryRef userInfo); 50 | -------------------------------------------------------------------------------- /kextfind_commands.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_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. Please obtain a copy of the License at 10 | * http://www.opensource.apple.com/apsl/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | * 21 | * @APPLE_LICENSE_HEADER_END@ 22 | */ 23 | #ifndef _KEXTFIND_COMMANDS_H_ 24 | #define _KEXTFIND_COMMANDS_H_ 25 | 26 | #include 27 | #include 28 | 29 | #include "kextfind_main.h" 30 | 31 | void printKext( 32 | OSKextRef theKext, 33 | PathSpec relativePath, 34 | Boolean extra_info, 35 | char lineEnd); 36 | 37 | void printKextProperty( 38 | OSKextRef theKext, 39 | CFStringRef propKey, 40 | char lineEnd); 41 | void printKextMatchProperty( 42 | OSKextRef theKext, 43 | CFStringRef propKey, 44 | char lineEnd); 45 | void printKextArches( 46 | OSKextRef theKext, 47 | char lineEnd, 48 | Boolean printLineEnd); 49 | 50 | void printKextDependencies( 51 | OSKextRef theKext, 52 | PathSpec pathSpec, 53 | Boolean extra_info, 54 | char lineEnd); 55 | void printKextDependents( 56 | OSKextRef theKext, 57 | PathSpec pathSpec, 58 | Boolean extra_info, 59 | char lineEnd); 60 | void printKextPlugins( 61 | OSKextRef theKext, 62 | PathSpec pathSpec, 63 | Boolean extra_info, 64 | char lineEnd); 65 | 66 | void printKextInfoDictionary( 67 | OSKextRef theKext, 68 | PathSpec pathSpec, 69 | char lineEnd); 70 | void printKextExecutable( 71 | OSKextRef theKext, 72 | PathSpec pathSpec, 73 | char lineEnd); 74 | 75 | CFStringRef copyPathForKext( 76 | OSKextRef theKext, 77 | PathSpec pathSpec); 78 | 79 | CFStringRef copyKextInfoDictionaryPath( 80 | OSKextRef theKext, 81 | PathSpec pathSpec); 82 | CFStringRef copyKextExecutablePath( 83 | OSKextRef theKext, 84 | PathSpec pathSpec); 85 | 86 | #endif /* _KEXTFIND_COMMANDS_H_ */ -------------------------------------------------------------------------------- /kextfind_main.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_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. Please obtain a copy of the License at 10 | * http://www.opensource.apple.com/apsl/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | * 21 | * @APPLE_LICENSE_HEADER_END@ 22 | */ 23 | #ifndef _KEXTFIND_H_ 24 | #define _KEXTFIND_H_ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | #include 34 | #include 35 | 36 | 37 | #include "kext_tools_util.h" 38 | #include "QEQuery.h" 39 | 40 | #pragma mark Basic Types & Constants 41 | /******************************************************************************* 42 | * Constants 43 | *******************************************************************************/ 44 | 45 | enum { 46 | kKextfindExitOK = EX_OK, 47 | 48 | // don't actually exit with this, it's just a sentinel value 49 | kKextfindExitHelp = 33, 50 | }; 51 | 52 | /******************************************************************************* 53 | * Data types. 54 | *******************************************************************************/ 55 | 56 | /* I originally thought this was a good idea, but changed my mind. I'm leaving 57 | * the code in case someone hates it, but kextfind will just always be picky, 58 | * now. 59 | */ 60 | typedef enum { 61 | kKextfindMeek = -1, 62 | kKextfindQuibbling = 0, 63 | kKextfindPicky = 1 64 | } KextfindAssertiveness; 65 | 66 | typedef enum { 67 | kPathsFull = 0, 68 | kPathsRelative, 69 | kPathsNone 70 | } PathSpec; 71 | 72 | /* The query context is passed as user data to the query engine. 73 | */ 74 | typedef struct { 75 | 76 | /* These fields are set by command-line options and govern global behavior 77 | * during the search. 78 | */ 79 | KextfindAssertiveness assertiveness; 80 | const NXArchInfo * defaultArch; 81 | 82 | Boolean caseInsensitive; 83 | Boolean extraInfo; // currently unused, see EXTRA_INFO ifdefs 84 | PathSpec pathSpec; 85 | Boolean substrings; 86 | 87 | CFMutableArrayRef searchURLs; 88 | 89 | /* These fields are set by the parsing callbacks to determine what 90 | * expensive operations the kext manager needs to perform before the 91 | * query can be evaluated. 92 | */ 93 | Boolean checkLoaded; 94 | 95 | /* Kext integrity is no longer used on SnowLeopard. We read the 96 | * flags but no kext will ever match them now. 97 | */ 98 | Boolean checkIntegrity; 99 | 100 | /* This field is set by the parsing callbacks. If no commands are given 101 | * in the query, a default "print" will be executed for each matching 102 | * kext. 103 | */ 104 | Boolean commandSpecified; 105 | 106 | /* If false, the report logic will print the report header as needed. 107 | */ 108 | Boolean reportStarted; 109 | 110 | /* If true, the report log will print a tab before the next value. 111 | */ 112 | Boolean reportRowStarted; 113 | 114 | } QueryContext; 115 | 116 | /******************************************************************************* 117 | * Function prototypes. 118 | *******************************************************************************/ 119 | ExitStatus readArgs( 120 | int argc, 121 | char * const * argv, 122 | QueryContext * toolArgs); 123 | ExitStatus checkArgs(QueryContext * toolArgs); 124 | Boolean checkSearchItem(const char * pathname, Boolean logFlag); 125 | fat_iterator createFatIteratorForKext(OSKextRef aKext); 126 | void usage(UsageLevel level); 127 | 128 | 129 | #endif /* _KEXTFIND_H_ */ 130 | -------------------------------------------------------------------------------- /kextfind_report.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_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. Please obtain a copy of the License at 10 | * http://www.opensource.apple.com/apsl/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | * 21 | * @APPLE_LICENSE_HEADER_END@ 22 | */ 23 | #ifndef _KEXTFIND_REPORT_H_ 24 | #define _KEXTFIND_REPORT_H_ 25 | 26 | #include "QEQuery.h" 27 | #include "kextfind_tables.h" 28 | #include "kextfind_query.h" 29 | 30 | /* These arenn't processed by getopt or QEQuery, we just look for them. 31 | */ 32 | #define kKeywordReport "-report" 33 | #define kNoReportHeader "-no-header" 34 | 35 | #define kPredNameSymbol "-symbol" 36 | #define kPredCharSymbol "-sym" 37 | 38 | /******************************************************************************* 39 | * Query Engine Callbacks 40 | * 41 | * The Query Engine invokes these as it finds keywords from the above list 42 | * in the command line or the query being reportEvaluated. 43 | *******************************************************************************/ 44 | Boolean reportParseProperty( 45 | CFMutableDictionaryRef element, 46 | int argc, 47 | char * const argv[], 48 | uint32_t * num_used, 49 | void * user_data, 50 | QEQueryError * error); 51 | 52 | Boolean reportParseShorthand( 53 | CFMutableDictionaryRef element, 54 | int argc, 55 | char * const argv[], 56 | uint32_t * num_used, 57 | void * user_data, 58 | QEQueryError * error); 59 | 60 | Boolean reportEvalProperty( 61 | CFDictionaryRef element, 62 | void * object, 63 | void * user_data, 64 | QEQueryError * error); 65 | 66 | Boolean reportEvalMatchProperty( 67 | CFDictionaryRef element, 68 | void * object, 69 | void * user_data, 70 | QEQueryError * error); 71 | 72 | Boolean reportParseFlag( 73 | CFMutableDictionaryRef element, 74 | int argc, 75 | char * const argv[], 76 | uint32_t * num_used, 77 | void * user_data, 78 | QEQueryError * error); 79 | 80 | Boolean reportEvalFlag( 81 | CFDictionaryRef element, 82 | void * object, 83 | void * user_data, 84 | QEQueryError * error); 85 | 86 | Boolean reportParseArch( 87 | CFMutableDictionaryRef element, 88 | int argc, 89 | char * const argv[], 90 | uint32_t * num_used, 91 | void * user_data, 92 | QEQueryError * error); 93 | 94 | Boolean reportEvalArch( 95 | CFDictionaryRef element, 96 | void * object, 97 | void * user_data, 98 | QEQueryError * error); 99 | 100 | Boolean reportEvalArchExact( 101 | CFDictionaryRef element, 102 | void * object, 103 | void * user_data, 104 | QEQueryError * error); 105 | 106 | Boolean reportParseCommand( 107 | CFMutableDictionaryRef element, 108 | int argc, 109 | char * const argv[], 110 | uint32_t * num_used, 111 | void * user_data, 112 | QEQueryError * error); 113 | 114 | Boolean reportParseDefinesOrReferencesSymbol( 115 | CFMutableDictionaryRef element, 116 | int argc, 117 | char * const argv[], 118 | uint32_t * num_used, 119 | void * user_data, 120 | QEQueryError * error); 121 | 122 | Boolean reportEvalDefinesOrReferencesSymbol( 123 | CFDictionaryRef element, 124 | void * object, 125 | void * user_data, 126 | QEQueryError * error); 127 | 128 | Boolean reportEvalCommand( 129 | CFDictionaryRef element, 130 | void * object, 131 | void * user_data, 132 | QEQueryError * error); 133 | 134 | #endif /* _KEXTFIND_REPORT_H_ */ 135 | -------------------------------------------------------------------------------- /kextfind_tables.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_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. Please obtain a copy of the License at 10 | * http://www.opensource.apple.com/apsl/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | * 21 | * @APPLE_LICENSE_HEADER_END@ 22 | */ 23 | #include "kextfind_tables.h" 24 | #include "kextfind_query.h" 25 | #include "kextfind_report.h" 26 | 27 | int longopt = 0; 28 | 29 | struct option opt_info[] = { 30 | // real options 31 | { kOptNameHelp, no_argument, NULL, kOptHelp }, 32 | { kOptNameCaseInsensitive, no_argument, NULL, kOptCaseInsensitive }, 33 | { kOptNameSearchItem, required_argument, NULL, kOptSearchItem }, 34 | { kOptNameSystemExtensions, no_argument, NULL, kOptSystemExtensions }, 35 | { kOptNameDefaultArch, required_argument, &longopt, kLongOptDefaultArch }, 36 | { kOptNameSubstring, no_argument, NULL, kOptSubstring }, 37 | #ifdef EXTRA_INFO 38 | { kOptNameExtraInfo, no_argument, &longopt, kLongOptExtraInfo }, 39 | #endif 40 | { kOptNameRelativePaths, no_argument, &longopt, kLongOptRelativePaths }, 41 | { kOptNameNoPaths, no_argument, &longopt, kLongOptNoPaths }, 42 | #ifdef MEEK_PICKY 43 | { kOptNameMeek, no_argument, &longopt, kLongOptMeek }, 44 | { kOptNamePicky, no_argument, &longopt, kLongOptPicky }, 45 | #endif /* MEEK_PICKY */ 46 | 47 | /* We register the query predicates so that they are handled correctly 48 | * even with the few short options we have (without these, -invalid gets 49 | * recognized as -i plus more options, and -false as '-f alse'). 50 | * 51 | * Query "options" are handled by simply terminating the getopt loop. 52 | */ 53 | QUERY_PREDICATES 54 | 55 | QUERY_COMMANDS 56 | 57 | { &kKeywordReport[1], no_argument, &longopt, kLongOptQueryPredicate }, 58 | 59 | { NULL, 0, NULL, 0 } // sentinel to terminate list 60 | }; 61 | 62 | /* Each long ("name") predicate is used to register at least a parse callback, 63 | * but not always an eval callback; some sets of predicates get funneled 64 | * together *after* parsing, so we register them here with their own triggers 65 | * but at parse time their predicates get reset to the shared one so that at 66 | * eval time they use the same function. 67 | * 68 | * The -property, and -property-exists keywords, for example, both parse into 69 | * -property predicates, but the other two set some data in the query element 70 | * that the single evalProperty() function looks for and uses to tweak its 71 | * behavior. 72 | */ 73 | struct querySetup queryCallbackList[] = { 74 | { CFSTR(kPredNameProperty), CFSTR(kPredCharProperty), 75 | parseProperty, evalProperty }, 76 | { CFSTR(kPredNamePropertyExists), CFSTR(kPredCharPropertyExists), 77 | parseProperty, NULL }, 78 | 79 | { CFSTR(kPredNameMatchProperty), CFSTR(kPredCharMatchProperty), 80 | parseMatchProperty, evalMatchProperty }, 81 | { CFSTR(kPredNameMatchPropertyExists), CFSTR(kPredCharMatchPropertyExists), 82 | parseMatchProperty, NULL }, 83 | 84 | { CFSTR(kPredNameLoaded), NULL, 85 | parseFlag, NULL }, 86 | { CFSTR(kPredNameValid), CFSTR(kPredCharValid), 87 | parseFlag, NULL }, 88 | { CFSTR(kPredNameAuthentic), CFSTR(kPredCharAuthentic), 89 | parseFlag, NULL }, 90 | { CFSTR(kPredNameDependenciesMet), CFSTR(kPredCharDependenciesMet), 91 | parseFlag, NULL }, 92 | { CFSTR(kPredNameLoadable), CFSTR(kPredCharLoadable), 93 | parseFlag, NULL }, 94 | { CFSTR(kPredNameWarnings), CFSTR(kPredCharWarnings), 95 | parseFlag, NULL }, 96 | { CFSTR(kPredNameIsLibrary), CFSTR(kPredCharIsLibrary), 97 | parseFlag, NULL }, 98 | 99 | { CFSTR(kPredNameDuplicate), CFSTR(kPredCharDuplicate), 100 | parseFlag, NULL }, 101 | 102 | { CFSTR(kPredNameInvalid), CFSTR(kPredCharInvalid), 103 | parseFlag, NULL }, 104 | { CFSTR(kPredNameInauthentic), CFSTR(kPredCharInauthentic), 105 | parseFlag, NULL }, 106 | { CFSTR(kPredNameDependenciesMissing), CFSTR(kPredCharDependenciesMissing), 107 | parseFlag, NULL }, 108 | { CFSTR(kPredNameNonloadable), CFSTR(kPredCharNonloadable), 109 | parseFlag, NULL }, 110 | 111 | { CFSTR(kPredNameHasPlugins), NULL, 112 | parseFlag, NULL }, 113 | { CFSTR(kPredNameIsPlugin), NULL, 114 | parseFlag, NULL }, 115 | { CFSTR(kPredNameHasDebugProperties), NULL, 116 | parseFlag, NULL }, 117 | { CFSTR(kPredNameIsKernelResource), NULL, 118 | parseFlag, NULL }, 119 | 120 | { CFSTR(kPredNameVersion), CFSTR(kPredCharVersion), 121 | parseVersion, evalVersion }, 122 | { CFSTR(kPredNameCompatibleWithVersion), NULL, 123 | parseCompatibleWithVersion, evalCompatibleWithVersion }, 124 | { CFSTR(kPredNameIntegrity), NULL, 125 | parseIntegrity, evalIntegrity }, 126 | 127 | { CFSTR(kPredNameArch), NULL, 128 | parseArch, evalArch }, 129 | { CFSTR(kPredNameArchExact), CFSTR(kPredCharArchExact), 130 | parseArch, evalArchExact }, 131 | { CFSTR(kPredNameExecutable), CFSTR(kPredCharExecutable), 132 | parseFlag, NULL }, 133 | { CFSTR(kPredNameNoExecutable), CFSTR(kPredCharNoExecutable), 134 | parseFlag, NULL }, 135 | { CFSTR(kPredNameDefinesSymbol), CFSTR(kPredCharDefinesSymbol), 136 | parseDefinesOrReferencesSymbol, evalDefinesOrReferencesSymbol }, 137 | { CFSTR(kPredNameReferencesSymbol), CFSTR(kPredCharReferencesSymbol), 138 | parseDefinesOrReferencesSymbol, evalDefinesOrReferencesSymbol }, 139 | 140 | { CFSTR(kPredNameBundleID), CFSTR(kPredCharBundleID), 141 | parseShorthand, NULL }, 142 | { CFSTR(kPredNameBundleName), CFSTR(kPredCharBundleName), 143 | parseBundleName, evalBundleName }, 144 | 145 | { CFSTR(kPredNameRoot), CFSTR(kPredCharRoot), 146 | parseShorthand, NULL }, 147 | { CFSTR(kPredNameConsole), CFSTR(kPredCharConsole), 148 | parseShorthand, NULL }, 149 | { CFSTR(kPredNameLocalRoot), CFSTR(kPredCharLocalRoot), 150 | parseShorthand, NULL }, 151 | { CFSTR(kPredNameNetworkRoot), CFSTR(kPredCharNetworkRoot), 152 | parseShorthand, NULL }, 153 | { CFSTR(kPredNameSafeBoot), CFSTR(kPredCharSafeBoot), 154 | parseShorthand, NULL }, 155 | 156 | { CFSTR(kPredNameEcho), NULL, 157 | parseCommand, NULL }, 158 | { CFSTR(kPredNamePrint), NULL, 159 | parseCommand, NULL }, 160 | { CFSTR(kPredNamePrint0), NULL, 161 | parseCommand, NULL }, 162 | { CFSTR(kPredNamePrintDiagnostics), CFSTR(kPredCharPrintDiagnostics), 163 | parseCommand, NULL }, 164 | { CFSTR(kPredNamePrintProperty), CFSTR(kPredCharPrintProperty), 165 | parseCommand, NULL }, 166 | { CFSTR(kPredNamePrintArches), CFSTR(kPredCharPrintArches), 167 | parseCommand, NULL }, 168 | { CFSTR(kPredNamePrintDependencies), NULL, 169 | parseCommand, NULL }, 170 | { CFSTR(kPredNamePrintDependents), NULL, 171 | parseCommand, NULL }, 172 | { CFSTR(kPredNamePrintIntegrity), NULL, 173 | parseCommand, NULL }, 174 | { CFSTR(kPredNamePrintPlugins), NULL, 175 | parseCommand, NULL }, 176 | { CFSTR(kPredNamePrintInfoDictionary), CFSTR(kPredCharPrintInfoDictionary), 177 | parseCommand, NULL }, 178 | { CFSTR(kPredNamePrintExecutable), CFSTR(kPredCharPrintExecutable), 179 | parseCommand, NULL }, 180 | 181 | { CFSTR(kPredNameExec), NULL, parseExec, evalExec }, 182 | 183 | /* These two special predicates are used internally for all "flag" and 184 | * command precidates, which all reset their predicates at parse time and 185 | * save the original keyword. 186 | */ 187 | { CFSTR(kPredNameFlag), NULL, 188 | NULL, evalFlag }, 189 | { CFSTR(kPredNameCommand), NULL, 190 | NULL, evalCommand }, 191 | 192 | { NULL, NULL, NULL, NULL } // sentinel to terminate list 193 | 194 | }; 195 | 196 | /* The report callback list reuses many query and command predicate keywords, 197 | * but parses and evaluates a lot of them differently! 198 | */ 199 | struct querySetup reportCallbackList[] = { 200 | { CFSTR(kPredNameProperty), CFSTR(kPredCharProperty), 201 | reportParseProperty, reportEvalProperty }, 202 | 203 | { CFSTR(kPredNameLoaded), NULL, 204 | reportParseFlag, NULL }, 205 | { CFSTR(kPredNameValid), CFSTR(kPredCharValid), 206 | reportParseFlag, NULL }, 207 | { CFSTR(kPredNameAuthentic), CFSTR(kPredCharAuthentic), 208 | reportParseFlag, NULL }, 209 | { CFSTR(kPredNameDependenciesMet), CFSTR(kPredCharDependenciesMet), 210 | reportParseFlag, NULL }, 211 | { CFSTR(kPredNameLoadable), CFSTR(kPredCharLoadable), 212 | reportParseFlag, NULL }, 213 | { CFSTR(kPredNameWarnings), CFSTR(kPredCharWarnings), 214 | reportParseFlag, NULL }, 215 | { CFSTR(kPredNameIsLibrary), CFSTR(kPredCharIsLibrary), 216 | reportParseFlag, NULL }, 217 | 218 | { CFSTR(kPredNameHasPlugins), NULL, 219 | reportParseFlag, NULL }, 220 | { CFSTR(kPredNameIsPlugin), NULL, 221 | reportParseFlag, NULL }, 222 | { CFSTR(kPredNameHasDebugProperties), NULL, 223 | reportParseFlag, NULL }, 224 | { CFSTR(kPredNameIsKernelResource), NULL, 225 | reportParseFlag, NULL }, 226 | { CFSTR(kPredNameIntegrity), NULL, 227 | reportParseFlag, NULL }, 228 | 229 | { CFSTR(kPredNameVersion), CFSTR(kPredCharVersion), 230 | reportParseShorthand, reportEvalProperty }, 231 | 232 | { CFSTR(kPredNameArch), NULL, 233 | reportParseArch, reportEvalArch }, 234 | { CFSTR(kPredNameArchExact), CFSTR(kPredCharArchExact), 235 | reportParseArch, reportEvalArchExact }, 236 | { CFSTR(kPredNameExecutable), CFSTR(kPredCharExecutable), 237 | reportParseFlag, NULL }, 238 | { CFSTR(kPredNameSymbol), CFSTR(kPredCharSymbol), 239 | reportParseDefinesOrReferencesSymbol, reportEvalDefinesOrReferencesSymbol }, 240 | 241 | { CFSTR(kPredNameBundleID), CFSTR(kPredCharBundleID), 242 | reportParseShorthand, NULL }, 243 | { CFSTR(kPredNameBundleName), CFSTR(kPredCharBundleName), 244 | reportParseCommand, NULL }, 245 | 246 | { CFSTR(kPredNameDuplicate), CFSTR(kPredCharDuplicate), 247 | reportParseFlag, NULL }, 248 | 249 | { CFSTR(kPredNamePrint), NULL, 250 | reportParseCommand, NULL }, 251 | { CFSTR(kPredNamePrintProperty), CFSTR(kPredCharPrintProperty), 252 | reportParseCommand, NULL }, 253 | { CFSTR(kPredNamePrintArches), CFSTR(kPredCharPrintArches), 254 | reportParseCommand, NULL }, 255 | { CFSTR(kPredNamePrintDependencies), NULL, 256 | reportParseCommand, NULL }, 257 | { CFSTR(kPredNamePrintDependents), NULL, 258 | reportParseCommand, NULL }, 259 | { CFSTR(kPredNamePrintPlugins), NULL, 260 | reportParseCommand, NULL }, 261 | { CFSTR(kPredNamePrintIntegrity), NULL, 262 | reportParseCommand, NULL }, 263 | { CFSTR(kPredNamePrintInfoDictionary), CFSTR(kPredCharPrintInfoDictionary), 264 | reportParseCommand, NULL }, 265 | { CFSTR(kPredNamePrintExecutable), CFSTR(kPredCharPrintExecutable), 266 | reportParseCommand, NULL }, 267 | 268 | /* These two special predicates are used internally for all "flag" and 269 | * command precidates, which all reset their predicates at reportParse time and 270 | * save the original keyword. 271 | */ 272 | { CFSTR(kPredNameFlag), NULL, 273 | NULL, reportEvalFlag }, 274 | { CFSTR(kPredNameCommand), NULL, 275 | NULL, reportEvalCommand }, 276 | 277 | { NULL, NULL, NULL, NULL } // sentinel to terminate list 278 | 279 | }; 280 | -------------------------------------------------------------------------------- /kextlibs.8: -------------------------------------------------------------------------------- 1 | .Dd November 14, 2012 2 | .Os Darwin 3 | .Dt KEXTLIBS 8 4 | .Sh NAME 5 | .Nm kextlibs 6 | .Nd find OSBundleLibraries needed by a kext 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Ar options 10 | .Op Fl - 11 | .Ar kext Li \&.\|.\|. 12 | .Sh DESCRIPTION 13 | The 14 | .Nm 15 | utility searches for library kexts that define symbols 16 | needed for linking by 17 | .Ar kext , 18 | printing their bundle identifiers and versions to 19 | .Pa stdout . 20 | If the kext has a multiple-architecture executable, 21 | libraries are resolved for each architecture. 22 | If any symbols are not found, or are found in multiple libraries, 23 | the numbers of such symbols are printed to standard error 24 | after the library kext information for each architecture. 25 | .Pp 26 | A handy use of 27 | .Nm 28 | is to run it with just the 29 | .Fl xml 30 | flag and pipe the output to 31 | .Xr pbcopy(1) ; 32 | if the exit status is zero 33 | (indicating no undefined or multiply-defined symbols), 34 | you can open your kext's 35 | .Pa Info.plist 36 | file in a text editor 37 | and paste the library declarations over the OSBundleLibraries property. 38 | .Pp 39 | You can use 40 | .Nm 41 | to find libraries for older releases of Mac OS X 42 | using the 43 | .Fl repository 44 | option to specify an extensions folder to search 45 | other than the extensions directories for the root volume 46 | (although releases prior to Mac OS X 10.6 (Snow Leopard) 47 | don't check for architecture-specific properties, 48 | so be sure to check the output and edit as needed). 49 | If you don't explicitly specify a repository directory, 50 | .Nm 51 | searches the root volume's /System/Library/Extensions and /Library/Extensions directories. 52 | .Sh OPTIONS 53 | .Bl -tag -width -indent 54 | .It Fl h , help 55 | Print a help message describing each option flag and exit with a success result, 56 | regardless of any other options on the command line. 57 | .It Fl all-symbols 58 | Print reports on all symbols that remain undefined, 59 | all symbols that have been resolved in one library kext each, 60 | and all symbols that have multiple definitions in different library kexts. 61 | Equivalent to specifying all of 62 | .Fl undef-symbols , 63 | .Fl onedef-symbols , 64 | and 65 | .Fl multdef-symbols . 66 | Normally only the number of missing and duplicate symbols is printed. 67 | .It Fl c , Fl compatible-versions 68 | Print the compatible version rather than the current version. 69 | .It Fl multdef-symbols 70 | Print all undefined symbols from 71 | .Ar kext 72 | found in more than one library kext, 73 | followed by those library kexts' bundle identifiers 74 | and versions (or compatible versions if 75 | .Fl compatible-versions 76 | was specified). 77 | Normally only the number of multiply-defined symbols is printed. 78 | .It Fl non-kpi 79 | Search the compatibility kext, com.apple.kernel.6.0, 80 | rather than any of the com.apple.kpi.* system kexts. 81 | Use of this option is not recommended: 82 | The exact kernel component (mach, bsd, libkern, or iokit) 83 | cannot be determined, 84 | and the compatible version of com.apple.kernel 85 | is locked to its current version, 86 | so kexts linking against it can only load against that exact version. 87 | .It Fl onedef-symbols 88 | Print all undefined symbols from 89 | .Ar kext 90 | found in exactly one library kext, 91 | followed by that library kext's bundle identifier 92 | and version (or compatible version if 93 | .Fl compatible-versions 94 | was specified). 95 | Normally nothing is printed about symbols that are found once. 96 | .It Fl r Ar directory , Fl repository Ar directory 97 | Search 98 | .Ar directory 99 | for dependencies. 100 | This option may be specified multiple times. 101 | You can use this to get library declarations 102 | relative to a set of extensions other than those of the running system 103 | (such as for a different release of Mac OS X), 104 | or to include a side directory of library kexts. 105 | Note: If you specify a directory with this option, 106 | the system extensions folders are not implicitly searched. 107 | See 108 | .Fl system-extensions . 109 | .It Fl e , Fl system-extensions 110 | Add /System/Library/Extensions and /Library/Extensions to the list of directories to search. 111 | If you don't specify any directories or kexts, this is used by default. 112 | .It Fl undef-symbols 113 | Print all undefined symbols from 114 | .Ar kext 115 | that can't be found in any library kexts. 116 | Normally only the number of symbols not found is printed. 117 | .It Fl unsupported 118 | Search unsupported library kexts for symbols (by default they are not searched). 119 | .It Fl v Li [ 0-6 | 0x#### Ns Li ] , Fl verbose Li [ 0-6 | 0x#### Ns Li ] 120 | Verbose mode; print information about program operation. 121 | Higher levels of verbosity include all lower levels. 122 | You can specify a level from 0-6, 123 | or a hexadecimal log specification 124 | (as described in 125 | .Xr kext_logging 8 Ns No ). 126 | For 127 | .Nm , 128 | the decimal levels 1-6 generally have little effect. 129 | .It Fl xml 130 | Print an XML fragment to 131 | .Pa stdout 132 | suitable for copying and pasting directly 133 | into an 134 | .Pa Info.plist 135 | file. 136 | This option prints 137 | information about libraries to 138 | .Pa stdout , 139 | and then prints 140 | information 141 | about symbols to 142 | .Pa stderr. 143 | In XML mode, if the libraries for all architectures 144 | are the same, only one set of OSBundleLibraries is printed; 145 | if any differ from any others, 146 | architecture-specific listings for all architectures are printed 147 | (OSBundleLibraries_i386, OSBundleLibraries_x86_64, and so on). 148 | .Pp 149 | .It Fl - 150 | End of options. 151 | .El 152 | .Sh FILES 153 | .Bl -tag -width "/System/Library/Extensions/" -compact 154 | .It Pa /System/Library/Extensions/ 155 | The standard system repository of kernel extensions. 156 | .It Pa /Library/Extensions/ 157 | The standard repository of non Apple kernel extensions. 158 | .El 159 | .Sh DIAGNOSTICS 160 | The 161 | .Nm 162 | utility exits with a status of 0 on completion 163 | if all undefined symbols are found exactly once; 164 | with a status of 1 if any undefined symbols remain, 165 | or with a status of 2 if any symbols 166 | are found in more than one library kext 167 | (whether or not any undefined symbols remain), 168 | and with another nonzero status on some other problem. 169 | .Sh BUGS 170 | .Nm 171 | uses a simple algorithm of string matching to resolve symbols, 172 | and does not apply any of the patching that the full link process does. 173 | This can cause it to fail when searching for symbols 174 | in a kext built against an SDK for a prior release of Mac OS X 175 | than the one on which 176 | .Nm 177 | is being used. 178 | In such cases, you can run 179 | .Nm 180 | against the Extensions folder of that prior release 181 | using the 182 | .Fl repository 183 | option. 184 | .Pp 185 | Many single-letter options are inconsistent in meaning 186 | with (or directly contradictory to) the same letter options 187 | in other kext tools. 188 | .Sh SEE ALSO 189 | .Xr kextutil 8 , 190 | .Xr kextfind 8 , 191 | .Xr kext_logging 8 192 | -------------------------------------------------------------------------------- /kextlibs_main.h: -------------------------------------------------------------------------------- 1 | /* 2 | * kextlibs_main.h 3 | * kext_tools 4 | * 5 | * Created by Nik Gervae on 5/03/08. 6 | * Copyright 2008 Apple Inc. All rights reserved. 7 | * 8 | */ 9 | #ifndef _KEXTLIBS_MAIN_H 10 | #define _KEXTLIBS_MAIN_H 11 | 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | 18 | #include 19 | 20 | #include "kext_tools_util.h" 21 | 22 | #pragma mark Basic Types & Constants 23 | /******************************************************************************* 24 | * Constants 25 | *******************************************************************************/ 26 | enum { 27 | kKextlibsExitOK = EX_OK, 28 | kKextlibsExitUndefineds = 1, 29 | kKextlibsExitMultiples = 2, 30 | 31 | // don't actually exit with this, it's just a sentinel value 32 | kKextlibsExitHelp = 33 33 | }; 34 | 35 | #pragma mark Command-line Option Definitions 36 | /******************************************************************************* 37 | * Command-line options. This data is used by getopt_long_only(). 38 | * 39 | * Options common to all kext tools are in kext_tools_util.h. 40 | *******************************************************************************/ 41 | 42 | #define kOptNameXML "xml" 43 | #define kOptNameCompatible "compatible-versions" 44 | #define kOptNameAllSymbols "all-symbols" 45 | #define kOptNameUndefSymbols "undef-symbols" 46 | #define kOptNameOnedefSymbols "onedef-symbols" 47 | #define kOptNameMultdefSymbols "multdef-symbols" 48 | #define kOptNameNonKPI "non-kpi" 49 | #define kOptNameUnsupported "unsupported" 50 | #define kOptNameLibraryRefs "library-references" 51 | 52 | #define kOptCompatible 'c' 53 | #define kOptSystemExtensions 'e' 54 | #define kOptRepository 'r' 55 | 56 | #define kOptChars "cehr:" 57 | 58 | /* Options with no single-letter variant. */ 59 | // Do not use -1, that's getopt() end-of-args return value 60 | // and can cause confusion 61 | #define kLongOptLongindexHack (-2) 62 | #define kLongOptXML (-3) 63 | #define kLongOptAllSymbols (-4) 64 | #define kLongOptUndefSymbols (-5) 65 | #define kLongOptOnedefSymbols (-6) 66 | #define kLongOptMultdefSymbols (-7) 67 | #define kLongOptNonKPI (-8) 68 | #define kLongOptUnsupported (-9) 69 | 70 | int longopt = 0; 71 | 72 | struct option sOptInfo[] = { 73 | { kOptNameHelp, no_argument, NULL, kOptHelp }, 74 | { kOptNameSystemExtensions, no_argument, NULL, kOptSystemExtensions }, 75 | { kOptNameRepository, required_argument, NULL, kOptRepository }, 76 | { kOptNameCompatible, no_argument, NULL, kOptCompatible }, 77 | { kOptNameXML, no_argument, &longopt, kLongOptXML }, 78 | { kOptNameAllSymbols, no_argument, &longopt, kLongOptAllSymbols }, 79 | { kOptNameUndefSymbols, no_argument, &longopt, kLongOptUndefSymbols }, 80 | { kOptNameOnedefSymbols, no_argument, &longopt, kLongOptOnedefSymbols }, 81 | { kOptNameMultdefSymbols, no_argument, &longopt, kLongOptMultdefSymbols }, 82 | { kOptNameNonKPI, no_argument, &longopt, kLongOptNonKPI }, 83 | { kOptNameUnsupported, no_argument, &longopt, kLongOptUnsupported }, 84 | 85 | { kOptNameQuiet, no_argument, NULL, kOptQuiet }, 86 | { kOptNameVerbose, optional_argument, NULL, kOptVerbose }, 87 | 88 | { NULL, 0, NULL, 0 } // sentinel to terminate list 89 | }; 90 | 91 | #pragma mark Tool Args Structure 92 | /******************************************************************************* 93 | * Tool Args Structure 94 | *******************************************************************************/ 95 | typedef struct { 96 | Boolean flagSysKexts; 97 | Boolean flagXML; 98 | Boolean flagCompatible; 99 | Boolean flagPrintUndefSymbols; 100 | Boolean flagPrintOnedefSymbols; 101 | Boolean flagPrintMultdefSymbols; 102 | Boolean flagNonKPI; 103 | Boolean flagAllowUnsupported; 104 | CFMutableArrayRef repositoryURLs; // must release 105 | char * kextName; // do not free; from argv 106 | CFURLRef kextURL; // must release 107 | OSKextRef theKext; 108 | } KextlibsArgs; 109 | 110 | typedef struct { 111 | CFArrayRef libKexts; 112 | CFDictionaryRef undefSymbols; 113 | CFDictionaryRef onedefSymbols; 114 | CFDictionaryRef multdefSymbols; 115 | CFArrayRef multdefLibs; 116 | } KextlibsInfo; 117 | 118 | #pragma mark Function Prototypes 119 | /******************************************************************************* 120 | * Function Prototypes 121 | *******************************************************************************/ 122 | ExitStatus readArgs( 123 | int argc, 124 | char * const * argv, 125 | KextlibsArgs * toolArgs); 126 | ExitStatus addRepository( 127 | KextlibsArgs * toolArgs, 128 | const char * optarg); 129 | ExitStatus printLibs( 130 | KextlibsArgs * toolArgs, 131 | const NXArchInfo * arch, 132 | CFArrayRef libKexts, 133 | Boolean trailingNewlineFlag); 134 | ExitStatus printProblems( 135 | KextlibsArgs * toolArgs, 136 | const NXArchInfo * arch, 137 | CFDictionaryRef undefSymbols, 138 | CFDictionaryRef onedefSymbols, 139 | CFDictionaryRef multdefSymbols, 140 | CFArrayRef multdefLibs, 141 | Boolean printArchFlag, 142 | Boolean trailingNewlineFlag); 143 | ExitStatus printResults( 144 | KextlibsArgs * toolArgs, 145 | const NXArchInfo * arch, 146 | Boolean archSpecific, 147 | CFArrayRef libKexts, 148 | CFDictionaryRef undefSymbols, 149 | CFDictionaryRef onedefSymbols, 150 | CFDictionaryRef multdefSymbols, 151 | CFArrayRef multdefLibs); 152 | void printUndefSymbol(const void * key, const void * value, void * context); 153 | void printOnedefSymbol(const void * key, const void * value, void * context); 154 | void printMultdefSymbol(const void * key, const void * value, void * context); 155 | 156 | static void usage(UsageLevel usageLevel); 157 | 158 | #endif /* _KEXTLIBS_MAIN_H */ 159 | -------------------------------------------------------------------------------- /kextload-entitlements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.private.kernel.get-kext-info 6 | 7 | com.apple.rootless.kext-management 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /kextload.8: -------------------------------------------------------------------------------- 1 | .Dd November 14, 2012 2 | .Os Darwin 3 | .Dt KEXTLOAD 8 4 | .Sh NAME 5 | .Nm kextload 6 | .Nd load kernel extensions (kexts) into the kernel 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Ar options 10 | .Op Fl - 11 | .Op Ar kext Li \&.\|.\|. 12 | .Sh DESCRIPTION 13 | The 14 | .Nm 15 | program is used to explicitly load kernel extensions (kexts). 16 | For most kexts, 17 | .Nm 18 | must run as the superuser (root). 19 | Kexts installed under 20 | .Pa /System/ 21 | with an 22 | OSBundleAllowUserLoad 23 | property set to true 24 | may be loaded via 25 | .Nm 26 | by non-root users. 27 | .Pp 28 | .Em Notice: 29 | On Mac OS X 10.6 (Snow Leopard), the developer functionality of 30 | .Nm 31 | has moved to the new program 32 | .Xr kextutil 8 ; 33 | all developer-related options have been removed from 34 | .Nm 35 | and are no longer recognized. 36 | On Mac OS X 10.6 (Snow Leopard), 37 | .Nm 38 | simply forwards a load request to 39 | .Xr kextd 8 , 40 | which performs all communication with the kernel. 41 | .Pp 42 | .Nm 43 | is a formal interface for kext loading in all versions 44 | of Darwin OS and Mac OS X. 45 | Software and installers can rely on its presence 46 | and invoke it in order to load kexts. 47 | Note that long options are present as of Mac OS X 10.6 (Snow Leopard). 48 | .Pp 49 | Mac OS X 10.6 (Snow Leopard) introduces 50 | C functions for loading kexts: 51 | .Xr KextManagerLoadKextWithIdentifier() 52 | and 53 | .Xr KextManagerLoadKextWithURL() , 54 | which are described in Apple's developer documentation. 55 | .Pp 56 | .Sh ARGUMENTS AND OPTIONS 57 | .Bl -tag -width -indent 58 | .It Ar kext 59 | The pathname of a kext bundle to load. 60 | The kext's plugins are available for dependency resolution. 61 | Kexts can also be specified by CFBundleIdentifier with the 62 | .Fl bundle-id 63 | option. 64 | .It Fl b Ar identifier , Fl bundle-id Ar identifier 65 | Look up the kext whose CFBundleIdentifier is 66 | .Ar identifier 67 | within the set of known kexts and load it. 68 | The kext of the highest CFBundleVersion with the given identifier is used; 69 | in the case of version ties, 70 | the last such kext specified on the command line is used. 71 | See the 72 | .Fl dependency 73 | and 74 | .Fl repository 75 | options for more information. 76 | .It Fl d Ar kext , Fl dependency Ar kext 77 | Add 78 | .Ar kext 79 | and its plugins to the set of known kexts for resolving dependencies. 80 | This is useful for adding a single kext from a directory 81 | while excluding the others. 82 | See the 83 | .Fl repository 84 | option for more information. 85 | .It Fl h , Fl help 86 | Print a help message describing each option flag and exit with a success result, 87 | regardless of any other options on the command line. 88 | .It Fl q , Fl quiet 89 | Quiet mode; print no informational or error messages. 90 | .It Fl r Ar directory , Fl repository Ar directory 91 | Use 92 | .Ar directory 93 | as a repository of kexts. 94 | This adds to the set of known kexts for resolving dependencies 95 | or looking up by CFBundleIdentifier when using the 96 | .Fl bundle-id 97 | option. 98 | This is not recursive; only kexts directly within the directory, 99 | and their plugins, are scanned. 100 | See also the 101 | .Fl dependency 102 | option. 103 | .It Fl v Li [ 0-6 | 0x#### Ns Li ] , Fl verbose Li [ 0-6 | 0x#### Ns Li ] 104 | Verbose mode; print information about program operation. 105 | Higher levels of verbosity include all lower levels. 106 | You can specify a level from 0-6, 107 | or a bitmask of flags as a hexadecimal number prefixed with 0x 108 | (as described in 109 | .Xr kext_logging 8 Ns No ). 110 | Because 111 | .Nm 112 | messages 113 | .Xr kextd 8 , 114 | to perform the actual work of loading, 115 | the decimal levels 1-6 generally have little effect. 116 | You may wish to use 117 | .Xr kextutil 8 118 | if you want verbose output about the kext loading operation. 119 | .Pp 120 | .It Fl - 121 | End of all options. Only kext names follow. 122 | .El 123 | .Sh EXAMPLES 124 | To load a kext, run 125 | .Nm 126 | and supply a kext bundle name; 127 | no options are required: 128 | .Bd -literal -offset "xxx" 129 | kextload TabletDriver.kext 130 | .Ed 131 | .Pp 132 | Alternatively, you can use the 133 | .Fl bundle-id 134 | .Li ( Ns Fl b Ns Li ) 135 | option to specify a kext by its CFBundleIdentifier: 136 | .Bd -literal -offset "xxx" 137 | kextload -bundle-id com.mycompany.driver.TabletDriver 138 | .Ed 139 | .Pp 140 | With no additional options 141 | .Nm 142 | looks in the extensions directories 143 | .Li ( Ns Pa /System/Library/Extensions/ 144 | and 145 | .Pa /Library/Extensions/ Ns Li ) 146 | for a kext with the given CFBundleIdentifier. 147 | Adding repository directories with the 148 | .Fl repository 149 | option or individual kexts with the 150 | .Fl dependency 151 | option expands the set of kexts that 152 | .Nm 153 | looks among for dependency resolution and for loading by bundle identifier: 154 | .Bd -literal -offset "xxx" 155 | kextload -repository /Applications/MyApp.app/Contents/Resources \\ 156 | TabletDriver.kext 157 | .Ed 158 | .Pp 159 | .Sh FILES 160 | .Bl -tag -width "/System/Library/Extensions/" -compact 161 | .It Pa /System/Library/Extensions/ 162 | The standard system repository of kernel extensions 163 | .It Pa /Library/Extensions/ 164 | The standard repository of non Apple kernel extensions 165 | .El 166 | .Sh DIAGNOSTICS 167 | .Nm 168 | exits with a zero status if all kexts specified load successfully 169 | (or are already loaded). 170 | If any kext fails to load, 171 | .Nm 172 | prints an error message for that kext, 173 | continues trying to load any remaining kexts, 174 | then exits with a nonzero status. 175 | .Pp 176 | For a kext to be loadable, it must be 177 | valid, authenticated, and all dependencies of the kext must be available and loadable. 178 | A valid kext has a well formed bundle, info dictionary, 179 | and an executable built for the running kernel's architecture. 180 | An authentic kext's component files, 181 | not including plugins, 182 | are owned by root:wheel, 183 | with permissions nonwritable by group and other. 184 | If your kext fails to load, try using 185 | .Xr kextutil 8 186 | to examine the kext for problems. 187 | .Sh SEE ALSO 188 | .Xr kextcache 8 , 189 | .Xr kextd 8 , 190 | .Xr kextstat 8 , 191 | .Xr kextunload 8 , 192 | .Xr kextutil 8 , 193 | .Xr kext_logging 8 194 | -------------------------------------------------------------------------------- /kextload_main.h: -------------------------------------------------------------------------------- 1 | /* 2 | * kextload_main.h 3 | * kext_tools 4 | * 5 | * Created by Nik Gervae on 11/08/08. 6 | * Copyright 2008 Apple Inc. All rights reserved. 7 | * 8 | */ 9 | #ifndef _KEXTLOAD_MAIN_H 10 | #define _KEXTLOAD_MAIN_H 11 | 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | 18 | #include 19 | 20 | #include "kext_tools_util.h" 21 | 22 | #pragma mark Basic Types & Constants 23 | /******************************************************************************* 24 | * Constants 25 | *******************************************************************************/ 26 | 27 | enum { 28 | kKextloadExitOK = EX_OK, 29 | 30 | kKextloadExitUnspecified = 10, 31 | 32 | // don't actually exit with this, it's just a sentinel value 33 | kKextloadExitHelp = 33, 34 | }; 35 | 36 | #pragma mark Command-line Option Definitions 37 | /******************************************************************************* 38 | * Command-line options. This data is used by getopt_long_only(). 39 | * 40 | * Options common to all kext tools are in kext_tools_util.h. 41 | *******************************************************************************/ 42 | #define kOptNameDependency "dependency" 43 | 44 | #define kOptNameTests "print-diagnostics" 45 | 46 | // Obsolete options that might be used for a production load 47 | #define kOptNameNoCaches "no-caches" 48 | #define kOptNameNoLoadedCheck "no-loaded-check" 49 | #define kOptNameTests "print-diagnostics" 50 | 51 | #define kOptNameLongindexHack "________" 52 | 53 | #define kOptDependency 'd' 54 | #define kOptRepository 'r' 55 | 56 | // Obsolete options that might be used for a production load 57 | #define kOptNoCaches 'c' 58 | #define kOptNoLoadedCheck 'D' 59 | #define kOptTests 't' 60 | 61 | /* Options with no single-letter variant. */ 62 | // Do not use -1, that's getopt() end-of-args return value 63 | // and can cause confusion 64 | #define kLongOptLongindexHack (-2) 65 | #define kLongOptArch (-3) 66 | 67 | #define kOptChars "b:cd:Dhqr:tv" 68 | 69 | int longopt = 0; 70 | 71 | struct option sOptInfo[] = { 72 | { kOptNameLongindexHack, no_argument, &longopt, kLongOptLongindexHack }, 73 | { kOptNameHelp, no_argument, NULL, kOptHelp }, 74 | { kOptNameBundleIdentifier, required_argument, NULL, kOptBundleIdentifier }, 75 | { kOptNameDependency, required_argument, NULL, kOptDependency }, 76 | { kOptNameRepository, required_argument, NULL, kOptRepository }, 77 | 78 | { kOptNameQuiet, no_argument, NULL, kOptQuiet }, 79 | { kOptNameVerbose, optional_argument, NULL, kOptVerbose }, 80 | { kOptNameTests, no_argument, NULL, kOptTests }, 81 | 82 | // Obsolete options that might be used for a production load 83 | { kOptNameNoCaches, no_argument, NULL, kOptNoCaches }, 84 | { kOptNameNoLoadedCheck, no_argument, NULL, kOptNoLoadedCheck }, 85 | { kOptNameTests, no_argument, NULL, kOptTests }, 86 | 87 | { NULL, 0, NULL, 0 } // sentinel to terminate list 88 | }; 89 | 90 | typedef struct { 91 | CFMutableArrayRef kextIDs; // -b; must release 92 | CFMutableArrayRef dependencyURLs; // -d; must release 93 | CFMutableArrayRef repositoryURLs; // -r; must release 94 | CFMutableArrayRef kextURLs; // kext args; must release 95 | CFMutableArrayRef scanURLs; // all URLs to scan 96 | CFArrayRef allKexts; // all opened kexts 97 | } KextloadArgs; 98 | 99 | #pragma mark Function Prototypes 100 | /******************************************************************************* 101 | * Function Prototypes 102 | *******************************************************************************/ 103 | 104 | ExitStatus readArgs( 105 | int argc, 106 | char * const * argv, 107 | KextloadArgs * toolArgs); 108 | ExitStatus checkArgs(KextloadArgs * toolArgs); 109 | 110 | ExitStatus checkAccess(void); 111 | 112 | ExitStatus loadKextsViaKextd(KextloadArgs * toolArgs); 113 | ExitStatus loadKextsIntoKernel(KextloadArgs * toolArgs); 114 | 115 | ExitStatus exitStatusForOSReturn(OSReturn osReturn); 116 | 117 | static void usage(UsageLevel usageLevel); 118 | 119 | #endif /* _KEXTLOAD_MAIN_H */ 120 | -------------------------------------------------------------------------------- /kextmanager.defs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2008 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 | #include 29 | -------------------------------------------------------------------------------- /kextmanager_async.defs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007 Apple Inc. All rights reserved. 3 | * 4 | * @APPLE_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. Please obtain a copy of the License at 10 | * http://www.opensource.apple.com/apsl/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | * 21 | * @APPLE_LICENSE_HEADER_END@ 22 | */ 23 | 24 | /* 25 | * FILE: kextmanager_async.defs 26 | * AUTH: Soren Spies (sspies) 27 | * DATE: 3 September 2007 (Copyright Apple, Inc) 28 | * DESC: MiG definitions for kextd's async replies to waiting lockers 29 | */ 30 | 31 | #include 32 | #include 33 | 34 | import ; 35 | 36 | // length must match MNAMELEN (sys/mount.h) 37 | #if __DARWIN_64_BIT_INO_T 38 | type mountpoint_t = array [MAXPATHLEN] of char; 39 | #else 40 | type mountpoint_t = array [90] of char; 41 | #endif 42 | 43 | subsystem kextmanager_reply 70100; // +100 from kextmanager_mig.defs 44 | 45 | // skip aligns message IDs with IOKitUser/kext.subproj/kextmanager_mig.defs 46 | skip; /* kextmanager_path_for_bundle_id */ 47 | skip; /* kextmanager_create_property_value_array */ 48 | skip; /* kextmanager_user_did_log_in */ 49 | skip; /* kextmanager_user_will_log_out */ 50 | skip; /* kextmanager_get_logged_in_userid */ 51 | skip; /* kextmanager_record_nonsecure_kextload */ 52 | 53 | // replies to kextmanager_lock_reboot 54 | simpleroutine lock_reboot_reply( 55 | replyPart : mach_port_move_send_once_t; 56 | rval : kern_return_t, RetCode; 57 | busyVol : mountpoint_t; 58 | busyStatus : int); 59 | 60 | simpleroutine lock_volume_reply( 61 | replyPart : mach_port_move_send_once_t; 62 | rval : kern_return_t, RetCode; 63 | lockStatus : int); 64 | -------------------------------------------------------------------------------- /kextstat-entitlements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.private.kernel.get-kext-info 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /kextstat.8: -------------------------------------------------------------------------------- 1 | .Dd March 13, 2014 2 | .Os Darwin 3 | .Dt KEXTSTAT 8 4 | .Sh NAME 5 | .Nm kextstat 6 | .Nd display status of loaded kernel extensions (kexts) 7 | .Sh SYNOPSIS 8 | .Nm kextstat 9 | .Op Fl a 10 | .Op Fl h 11 | .Op Fl k 12 | .Op Fl l 13 | .Op Fl b Ar identifier 14 | .Li \&.\|.\|. 15 | .Sh DESCRIPTION 16 | The 17 | .Nm 18 | utility displays the status of any kexts 19 | currently loaded in the kernel. 20 | The following information is shown for each loaded kext: 21 | .Bl -tag -width indentXX 22 | .It Index 23 | The load index of the kext (used to track linkage references). 24 | Gaps in the list indicate kexts that have been unloaded. 25 | .It Refs 26 | The number of references to this kext by others. 27 | If nonzero, the kext cannot be unloaded. 28 | .It Address 29 | The address in kernel space where the kext has been loaded. 30 | .It Size 31 | The number of bytes of kernel memory that the kext occupies. 32 | If this is zero, the kext is a built-in part of the kernel 33 | that has a record as a kext for resolving dependencies among kexts. 34 | .It Wired 35 | The number of wired bytes of kernel memory that the kext occupies. 36 | .It Architecture (if the -a option is used) 37 | The architecture of the kext. 38 | .It Name 39 | The CFBundleIdentifier of the kext. 40 | .It (Version) 41 | The CFBundleVersion of the kext. 42 | .It 43 | The index numbers of all other kexts that this kext 44 | has a reference to. 45 | .El 46 | .Sh OPTIONS 47 | These options are available: 48 | .Bl -tag -width indentXX 49 | .It Fl a , Fl arch 50 | Print the architecture of the kext. 51 | .It Fl b Ar identifier , Fl bundle-id Ar identifier 52 | Display the status of only the kext with 53 | the given bundle identifier. 54 | This option trumps the 55 | .Fl no-kernel 56 | option; 57 | if both are given and a kernel component is specified, 58 | its information is shown. 59 | .It Fl h , Fl help 60 | Print a help message describing each option flag and exit with a success result, 61 | regardless of any other options on the command line. 62 | .It Fl k , Fl no-kernel 63 | Don't show information for built-in components of the kernel. 64 | .It Fl l , Fl list-only 65 | Print the list of loaded kexts only and omit the header 66 | (useful for running output through text-analysis tools). 67 | .It Fl s , Fl sort 68 | Sort the list by load address. 69 | .El 70 | .Sh DIAGNOSTICS 71 | The 72 | .Nm 73 | utility exits with a status of 0 on success 74 | and with a nonzero status if an error occurs. 75 | .Sh SEE ALSO 76 | .Xr kextcache 8 , 77 | .Xr kextd 8 , 78 | .Xr kextload 8 , 79 | .Xr kextunload 8 , 80 | .Xr kextutil 8 81 | -------------------------------------------------------------------------------- /kextstat_main.h: -------------------------------------------------------------------------------- 1 | /* 2 | * kextstat_main.h 3 | * kext_tools 4 | * 5 | * Created by Nik Gervae on 5/03/08. 6 | * Copyright 2008, 2014 Apple Inc. All rights reserved. 7 | * 8 | */ 9 | #ifndef _KEXTSTAT_MAIN_H 10 | #define _KEXTSTAT_MAIN_H 11 | 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | 18 | #include 19 | 20 | #include "kext_tools_util.h" 21 | 22 | #pragma mark Basic Types & Constants 23 | /******************************************************************************* 24 | * Constants 25 | *******************************************************************************/ 26 | enum { 27 | kKextstatExitOK = EX_OK, 28 | kKextstatExitError = 1, 29 | 30 | // don't think we use it 31 | kKextstatExitUnspecified = 11, 32 | 33 | // don't actually exit with this, it's just a sentinel value 34 | kKextstatExitHelp = 33 35 | }; 36 | 37 | #pragma mark Command-line Option Definitions 38 | /******************************************************************************* 39 | * Command-line options. This data is used by getopt_long_only(). 40 | * 41 | * Options common to all kext tools are in kext_tools_util.h. 42 | *******************************************************************************/ 43 | 44 | #define kOptNameNoKernelComponents "no-kernel" 45 | #define kOptNameListOnly "list-only" 46 | #define kOptNameArchitecture "arch" 47 | #define kOptNameSort "sort" 48 | 49 | #define kOptNoKernelComponents 'k' 50 | #define kOptListOnly 'l' 51 | #define kOptArchitecture 'a' 52 | #define kOptSort 's' 53 | 54 | #if 0 55 | // bundle-id,version,compatible-version,is-kernel,is-interface,retaincount,path,uuid,started,prelinked,index,address,size,wired,dependencies,classes,cputype,cpusubtype 56 | CFBundleIdentifier 57 | CFBundleVersion 58 | kOSBundleCompatibleVersionKey 59 | kOSKernelResourceKey 60 | kOSBundleIsInterfaceKey 61 | kOSBundlePathKey 62 | kOSBundleUUIDKey 63 | kOSBundleStartedKey 64 | kOSBundlePrelinkedKey 65 | kOSBundleLoadTagKey 66 | kOSBundleLoadAddressKey 67 | kOSBundleLoadSizeKey 68 | kOSBundleWiredSizeKey 69 | kOSBundleDependenciesKey 70 | kOSBundleMetaClassesKey 71 | #endif 72 | 73 | #define kOptChars "b:hkla" 74 | 75 | /* Options with no single-letter variant. */ 76 | // Do not use -1, that's getopt() end-of-args return value 77 | // and can cause confusion 78 | #define kLongOptLongindexHack (-2) 79 | 80 | int longopt = 0; 81 | 82 | struct option sOptInfo[] = { 83 | { kOptNameHelp, no_argument, NULL, kOptHelp }, 84 | { kOptNameBundleIdentifier, required_argument, NULL, kOptBundleIdentifier }, 85 | { kOptNameNoKernelComponents, no_argument, NULL, kOptNoKernelComponents }, 86 | { kOptNameListOnly, no_argument, NULL, kOptListOnly }, 87 | { kOptNameSort, no_argument, NULL, kOptSort }, 88 | { kOptNameArch, no_argument, NULL, kOptArchitecture }, 89 | 90 | { NULL, 0, NULL, 0 } // sentinel to terminate list 91 | }; 92 | 93 | #pragma mark Tool Args Structure 94 | /******************************************************************************* 95 | * Tool Args Structure 96 | *******************************************************************************/ 97 | typedef struct { 98 | Boolean flagNoKernelComponents; 99 | Boolean flagListOnly; 100 | Boolean flagShowArchitecture; 101 | Boolean flagSortByLoadAddress; 102 | CFMutableArrayRef bundleIDs; // must release 103 | 104 | CFDictionaryRef loadedKextInfo; // must release 105 | const NXArchInfo * runningKernelArch; // do not free 106 | } KextstatArgs; 107 | 108 | #pragma mark Function Prototypes 109 | /******************************************************************************* 110 | * Function Prototypes 111 | *******************************************************************************/ 112 | ExitStatus readArgs(int argc, char * const * argv, KextstatArgs * toolArgs); 113 | void printKextInfo(CFDictionaryRef kextInfo, KextstatArgs * toolArgs); 114 | 115 | Boolean getNumValue(CFNumberRef aNumber, CFNumberType type, void * valueOut); 116 | int compareKextInfo(const void * vKextInfo1, const void * vKextInfo2); 117 | int compareKextInfoLoadAddress(const void * vKextInfo1, const void * vKextInfo2); 118 | 119 | CFComparisonResult compareNumbers( 120 | const void * val1, 121 | const void * val2, 122 | void * context); 123 | 124 | static void usage(UsageLevel usageLevel); 125 | 126 | #endif /* _KEXTSTAT_MAIN_H */ 127 | -------------------------------------------------------------------------------- /kextunload.8: -------------------------------------------------------------------------------- 1 | .Dd March 6, 2009 2 | .Os Darwin 3 | .Dt KEXTUNLOAD 8 4 | .Sh NAME 5 | .Nm kextunload 6 | .Nd terminate driver I/O Kit driver instances and unload kernel extensions (kexts) 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Ar options 10 | .Op Fl - 11 | .Op Ar kext Li \&.\|.\|. 12 | .Sh DESCRIPTION 13 | The 14 | .Nm 15 | program is used to terminate and unregister I/O Kit objects 16 | associated with a kernel extension (kext) 17 | and to unload the code and personalities for that kext. 18 | .Nm 19 | must run with superuser privileges. 20 | .Pp 21 | If another loaded kext has a dependency on the kext being unloaded, 22 | the unload will fail. 23 | You can determine whether a kext has dependents using the 24 | .Xr kextstat 8 25 | tool. 26 | .Pp 27 | .Nm 28 | is a formal interface for unloading kexts in the Darwin OS and 29 | in Mac OS X. 30 | Software and installers can rely on its presence 31 | and invoke it in order to unload kexts. 32 | Note that long options are present as of Mac OS X 10.6 (Snow Leopard). 33 | .Pp 34 | The arguments and options are: 35 | .Bl -tag -width -indent 36 | .It Ar kext 37 | Unload the loaded kext whose bundle identifier matches 38 | the CFBundleIdentifier of 39 | .Ar kext . 40 | All instances of IOService subclasses defined by the loaded kext 41 | and in the IOService plane of the I/O Registry are terminated; 42 | the kext is checked to make sure no instances 43 | of its libkern C++ classes remain; 44 | the kext's C++ static destructores and module stop routine are invoked; 45 | then the kext's executable and IOKitPersonalities are unloaded from the kernel. 46 | Failure at any stage prevents kext unload. 47 | .It Fl b Ar identifier , Fl bundle-id Ar identifier 48 | Unload executable and IOKitPersonalities (as described immediately above) 49 | for the kext whose CFBundleIdentifier is 50 | .Ar identifier . 51 | .It Fl c Ar classname , Fl class Ar classname 52 | Terminate all instances of class 53 | .Ar classname 54 | that are in the IOService plane of the I/O Registry, 55 | if possible, 56 | but do not unload the defining kext or its IOKitPersonalities. 57 | New load requests for devices that were driven 58 | by these terminated instances 59 | may result in the same class being instantiated at any time. 60 | .It Fl h , Fl help 61 | Print a help message describing each option flag and exit with a success result, 62 | regardless of any other options on the command line. 63 | .It Fl m Ar identifier 64 | Same as 65 | .Fl b 66 | (remains for backward compatibility). 67 | .It Fl p , Fl personalities-only 68 | Terminate services and remove personalities only; 69 | do not unload kexts. 70 | .It Fl q , Fl quiet 71 | Quiet mode; print no informational or error messages. 72 | .It Fl v Li [ 0-6 | 0x#### Ns Li ] , Fl verbose Li [ 0-6 | 0x#### Ns Li ] 73 | Verbose mode; print information about program operation. 74 | Higher levels of verbosity include all lower levels. 75 | By default 76 | .Nm 77 | prints only warnings and errors. 78 | You can specify a level from 0-6, 79 | or a hexadecimal log specification 80 | (as described in 81 | .Xr kext_logging 8 Ns No ). 82 | The levels of verbose output are: 83 | .Bl -tag -width "1 (or none)" 84 | .It 0 85 | Print only errors (that is, suppress warnings); see also 86 | .Fl quiet . 87 | .It 1 (or none) 88 | Print basic information about program operation. 89 | .It 2 90 | Prints information about unload stages. 91 | .It 3 92 | Prints information about removal of personalities. 93 | .It 4 94 | Prints information about module stop functions and C++ class destruction. 95 | .It 5 96 | Prints detailed information internal operations such as bookkeping. 97 | .It 6 98 | Identical to level 5 for 99 | .Nm . 100 | .El 101 | .Pp 102 | Unlike in other kext tools, 103 | the 104 | .Fl verbose 105 | flag in 106 | .Nm 107 | applies to all kexts 108 | (that is, it turns on hexadecimal bit 0x8 by default). 109 | See 110 | .Xr kext_logging 8 111 | for more information on verbose logging. 112 | .El 113 | .Sh DIAGNOSTICS 114 | .Nm 115 | exits with a zero status upon success, 116 | or prints an error message and exits with a nonzero status upon failure. 117 | .Sh BUGS 118 | Many single-letter options are inconsistent in meaning 119 | with (or directly contradictory to) the same letter options 120 | in other kext tools. 121 | .Sh SEE ALSO 122 | .Xr kextcache 8 , 123 | .Xr kextd 8 , 124 | .Xr kextload 8 , 125 | .Xr kextstat 8 , 126 | .Xr kext_logging 8 127 | -------------------------------------------------------------------------------- /kextunload_main.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_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. Please obtain a copy of the License at 10 | * http://www.opensource.apple.com/apsl/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | * 21 | * @APPLE_LICENSE_HEADER_END@ 22 | */ 23 | #ifndef _KEXTUNLOAD_MAIN_H 24 | #define _KEXTUNLOAD_MAIN_H 25 | 26 | #include 27 | 28 | #include 29 | #include 30 | 31 | #include "kext_tools_util.h" 32 | 33 | #pragma mark Basic Types & Constants 34 | /******************************************************************************* 35 | * Constants 36 | *******************************************************************************/ 37 | enum { 38 | kKextunloadExitOK = EX_OK, 39 | kKextunloadExitNotFound = 1, 40 | kKextunloadExitNotPrivileged = 2, 41 | kKextunloadExitPartialFailure = 3, 42 | 43 | // don't think we use it 44 | kKextunloadExitUnspecified = 11, 45 | 46 | // don't actually exit with this, it's just a sentinel value 47 | kKextunloadExitHelp = 33 48 | }; 49 | 50 | #pragma mark Command-line Option Definitions 51 | /******************************************************************************* 52 | * Command-line options. This data is used by getopt_long_only(). 53 | * 54 | * Options common to all kext tools are in kext_tools_util.h. 55 | *******************************************************************************/ 56 | 57 | #define kOptNameClassName "class" 58 | #define kOptNamePersonalitiesOnly "personalities-only" 59 | 60 | // really old option letter for "module", same as bundle id 61 | #define kOptClassName 'c' 62 | #define kOptModule 'm' 63 | #define kOptPersonalitiesOnly 'p' 64 | 65 | #define kOptChars "b:c:hm:pqr:v" 66 | 67 | int longopt = 0; 68 | 69 | struct option sOptInfo[] = { 70 | { kOptNameHelp, no_argument, NULL, kOptHelp }, 71 | 72 | { kOptNameBundleIdentifier, required_argument, NULL, kOptBundleIdentifier }, 73 | 74 | { kOptNameClassName, required_argument, NULL, kOptClassName }, 75 | { kOptNamePersonalitiesOnly, no_argument, NULL, kOptPersonalitiesOnly }, 76 | 77 | { kOptNameQuiet, required_argument, NULL, kOptQuiet }, 78 | { kOptNameVerbose, optional_argument, NULL, kOptVerbose }, 79 | 80 | { NULL, 0, NULL, 0 } // sentinel to terminate list 81 | }; 82 | 83 | 84 | #pragma mark Tool Args Structure 85 | /******************************************************************************* 86 | * Tool Args Structure 87 | *******************************************************************************/ 88 | typedef struct { 89 | Boolean unloadPersonalities; // -p 90 | uint32_t terminateOption; // -p 91 | 92 | CFMutableArrayRef kextURLs; // args 93 | CFMutableArrayRef kextBundleIDs; // -b/-m -- array of C strings! 94 | CFMutableArrayRef kextClassNames; // -c -- array of C strings! 95 | 96 | CFMutableArrayRef kexts; // any kexts created from URLs 97 | } KextunloadArgs; 98 | 99 | #pragma mark Function Prototypes 100 | /******************************************************************************* 101 | * Function Prototypes 102 | *******************************************************************************/ 103 | ExitStatus readArgs( 104 | int argc, 105 | char * const * argv, 106 | KextunloadArgs * toolArgs); 107 | ExitStatus checkArgs(KextunloadArgs * toolArgs); 108 | ExitStatus createKextsIfNecessary(KextunloadArgs * toolArgs); 109 | 110 | ExitStatus terminateKextClasses( 111 | KextunloadArgs * toolArgs, 112 | Boolean * fatal); 113 | ExitStatus unloadKextsByIdentifier( 114 | KextunloadArgs * toolArgs, 115 | Boolean * fatal); 116 | ExitStatus unloadKextsByURL( 117 | KextunloadArgs * toolArgs, 118 | Boolean * fatal); 119 | ExitStatus unloadKextWithIdentifier( 120 | CFStringRef kextIdentifier, 121 | KextunloadArgs * toolArgs, 122 | Boolean * fatal); 123 | 124 | ExitStatus formatKernResult(kern_return_t kernResult); 125 | void usage(UsageLevel usageLevel); 126 | 127 | #endif /* _KEXTUNLOAD_MAIN_H */ 128 | -------------------------------------------------------------------------------- /kextutil-entitlements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.private.kernel.get-kext-info 6 | 7 | com.apple.rootless.kext-management 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /kextutil_main.h: -------------------------------------------------------------------------------- 1 | /* 2 | * kextutil_main.h 3 | * kext_tools 4 | * 5 | * Created by Nik Gervae on 4/24/08. 6 | * Copyright 2008 Apple Inc. All rights reserved. 7 | * 8 | */ 9 | #ifndef _KEXTUTIL_MAIN_H 10 | #define _KEXTUTIL_MAIN_H 11 | 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | 18 | #include 19 | 20 | #include "kext_tools_util.h" 21 | 22 | #pragma mark Basic Types & Constants 23 | /******************************************************************************* 24 | * Constants 25 | *******************************************************************************/ 26 | 27 | enum { 28 | kKextutilExitOK = EX_OK, 29 | kKextutilExitNotFound, 30 | kKextutilExitArchNotFound, 31 | kKextutilExitUserAbort, 32 | kKextutilExitKextBad, 33 | kKextutilExitSafeBoot, 34 | kKextutilExitLoadFailed, 35 | kKextutilExitInteractionRequired, 36 | 37 | // don't think we use it 38 | kKextutilExitUnspecified = 11, 39 | 40 | // don't actually exit with this, it's just a sentinel value 41 | kKextutilExitHelp = 33, 42 | kKextutilExitNoStart 43 | }; 44 | 45 | #pragma mark Command-line Option Definitions 46 | /******************************************************************************* 47 | * Command-line options. This data is used by getopt_long_only(). 48 | * 49 | * Options common to all kext tools are in kext_tools_util.h. 50 | *******************************************************************************/ 51 | #define kOptNamePersonality "personality" 52 | #define kOptNameDependency "dependency" 53 | 54 | #define kOptNameNoCaches "no-caches" 55 | #define kOptNameNoLoadedCheck "no-loaded-check" 56 | #define kOptNameNoSystemExtensions "no-system-extensions" 57 | 58 | #define kOptNameInteractive "interactive" 59 | #define kOptNameInteractiveAll "interactive-all" 60 | 61 | #define kOptNameLoadOnly "load-only" 62 | #define kOptNameMatchOnly "match-only" 63 | #define kOptNameNoLoad "no-load" 64 | #define kOptNameSymbolsDirectory "symbols" 65 | #define kOptNameAddress "address" 66 | #define kOptNameUseKernelAddresses "use-load-addresses" 67 | 68 | #define kOptNameTests "print-diagnostics" 69 | #define kOptNameNoResolveDependencies "no-resolve-dependencies" 70 | 71 | #define kOptNameLongindexHack "________" 72 | 73 | #define kOptPersonality 'p' 74 | #define kOptKernel 'k' 75 | #define kOptDependency 'd' 76 | #define kOptRepository 'r' 77 | 78 | #define kOptNoCaches 'c' 79 | #define kOptNoLoadedCheck 'D' 80 | #define kOptNoSystemExtensions 'e' 81 | 82 | #define kOptInteractive 'i' 83 | #define kOptInteractiveAll 'I' 84 | 85 | #define kOptLoadOnly 'l' 86 | #define kOptMatchOnly 'm' 87 | #define kOptNoLoad 'n' 88 | #define kOptSymbolsDirectory 's' 89 | #define kOptAddress 'a' 90 | #define kOptUseKernelAddresses 'A' 91 | // arch is down below 92 | 93 | #define kOptTests 't' 94 | #define kOptSafeBoot 'x' 95 | #define kOptNoAuthentication 'z' 96 | #define kOptNoResolveDependencies 'Z' 97 | 98 | /* Options with no single-letter variant. */ 99 | // Do not use -1, that's getopt() end-of-args return value 100 | // and can cause confusion 101 | #define kLongOptLongindexHack (-2) 102 | #define kLongOptArch (-3) 103 | #define kLongOptLegacyLayout (-4) 104 | 105 | #define kOptChars "a:Ab:cd:DehiIk:lmnp:qr:s:tvxzZ" 106 | 107 | int longopt = 0; 108 | 109 | struct option sOptInfo[] = { 110 | { kOptNameLongindexHack, no_argument, &longopt, kLongOptLongindexHack }, 111 | { kOptNameHelp, no_argument, NULL, kOptHelp }, 112 | { kOptNameBundleIdentifier, required_argument, NULL, kOptBundleIdentifier }, 113 | { kOptNamePersonality, required_argument, NULL, kOptPersonality }, 114 | { kOptNameKernel, required_argument, NULL, kOptKernel }, 115 | { kOptNameDependency, required_argument, NULL, kOptDependency }, 116 | { kOptNameRepository, required_argument, NULL, kOptRepository }, 117 | { kOptNameNoCaches, no_argument, NULL, kOptNoCaches }, 118 | { kOptNameNoLoadedCheck, no_argument, NULL, kOptNoLoadedCheck }, 119 | { kOptNameNoSystemExtensions, no_argument, NULL, kOptNoSystemExtensions }, 120 | { kOptNameInteractive, no_argument, NULL, kOptInteractive }, 121 | { kOptNameInteractiveAll, no_argument, NULL, kOptInteractiveAll }, 122 | { kOptNameLoadOnly, no_argument, NULL, kOptLoadOnly }, 123 | { kOptNameMatchOnly, no_argument, NULL, kOptMatchOnly }, 124 | { kOptNameNoLoad, no_argument, NULL, kOptNoLoad }, 125 | { kOptNameSymbolsDirectory, required_argument, NULL, kOptSymbolsDirectory }, 126 | { kOptNameAddress, required_argument, NULL, kOptAddress }, 127 | { kOptNameUseKernelAddresses, no_argument, NULL, kOptUseKernelAddresses }, 128 | { kOptNameQuiet, no_argument, NULL, kOptQuiet }, 129 | { kOptNameVerbose, optional_argument, NULL, kOptVerbose }, 130 | { kOptNameTests, no_argument, NULL, kOptTests }, 131 | { kOptNameSafeBoot, no_argument, NULL, kOptSafeBoot }, 132 | { kOptNameNoAuthentication, no_argument, NULL, kOptNoAuthentication }, 133 | { kOptNameNoResolveDependencies, no_argument, NULL, kOptNoResolveDependencies }, 134 | { kOptNameArch, required_argument, &longopt, kLongOptArch }, 135 | 136 | { NULL, 0, NULL, 0 } // sentinel to terminate list 137 | }; 138 | 139 | typedef struct { 140 | /* These are ints so we can check for multiply set real easy. 141 | */ 142 | int flag_n; // used to sanity-check -n, -l, -m 143 | int flag_l; // before setting behavior-changing 144 | int flag_m; // variables doLoad & doStartMatching 145 | 146 | Boolean getAddressesFromKernel; // -A 147 | Boolean useRepositoryCaches; // -c to turn off 148 | Boolean useSystemExtensions; // -e to turn off 149 | 150 | Boolean overwriteSymbols; // -i/-I turns off 151 | OSKextExcludeLevel interactiveLevel; // -i/-I turns on 152 | 153 | Boolean doLoad; // -l: load but no matching 154 | Boolean doStartMatching; // -m: don't load, start matching 155 | // -n: don't do either 156 | 157 | Boolean printDiagnostics; // -t 158 | Boolean safeBootMode; // -x 159 | Boolean skipAuthentication; // -z 160 | Boolean skipDependencies; // -Z (and with -t only!) 161 | Boolean checkLoadedForDependencies; // -D to turn off (obsolete) 162 | Boolean logFilterChanged; 163 | 164 | CFMutableDictionaryRef loadAddresses; // -a; must release 165 | CFMutableArrayRef kextIDs; // -b; must release 166 | CFMutableArrayRef personalityNames; // -p; must release 167 | CFMutableArrayRef dependencyURLs; // -d; must release 168 | CFMutableArrayRef repositoryURLs; // -r; must release 169 | CFMutableArrayRef kextURLs; // kext args; must release 170 | CFMutableArrayRef scanURLs; // all URLs to scan 171 | 172 | CFURLRef kernelURL; // overriden by -kernel option 173 | CFDataRef kernelFile; // contents of kernelURL 174 | CFURLRef symbolDirURL; // -s option; 175 | const NXArchInfo * archInfo; // set by -arch 176 | } KextutilArgs; 177 | 178 | #pragma mark Function Prototypes 179 | /******************************************************************************* 180 | * Function Prototypes 181 | *******************************************************************************/ 182 | 183 | ExitStatus readArgs( 184 | int argc, 185 | char * const * argv, 186 | KextutilArgs * toolArgs); 187 | ExitStatus checkArgs(KextutilArgs * toolArgs); 188 | void adjustLogFilterForInteractive(KextutilArgs * toolArgs); 189 | ExitStatus createKextsToProcess( 190 | KextutilArgs * toolArgs, 191 | CFArrayRef * outArray, 192 | Boolean * fatal); 193 | ExitStatus processKexts( 194 | CFArrayRef kextURLsToUse, 195 | KextutilArgs * toolArgs); 196 | ExitStatus processKext( 197 | OSKextRef aKext, 198 | KextutilArgs * toolArgs, 199 | Boolean * fatal); 200 | ExitStatus runTestsOnKext( 201 | OSKextRef aKext, 202 | char * kextPathCString, 203 | KextutilArgs * toolArgs, 204 | Boolean * fatal); 205 | ExitStatus loadKext( 206 | OSKextRef aKext, 207 | char * kextPathCString, 208 | KextutilArgs * toolArgs, 209 | Boolean * fatal); 210 | 211 | void notifyNonsecureKextload(OSKextRef aKext); 212 | 213 | ExitStatus generateKextSymbols( 214 | OSKextRef aKext, 215 | char * kextPathCString, 216 | KextutilArgs * toolArgs, 217 | Boolean saveFlag, 218 | Boolean * fatal); 219 | void setKextLoadAddress( 220 | const void * vKey, 221 | const void * vValue, 222 | void * vContext); 223 | int requestLoadAddress( 224 | OSKextRef aKext); 225 | ExitStatus startKextsAndSendPersonalities( 226 | OSKextRef aKext, 227 | KextutilArgs * toolArgs, 228 | Boolean * fatal); 229 | ExitStatus startKext( 230 | OSKextRef aKext, 231 | char * kextPathCString, 232 | KextutilArgs * toolArgs, 233 | Boolean * started, 234 | Boolean * yesToAll, 235 | Boolean * fatal); 236 | ExitStatus sendPersonalities( 237 | OSKextRef aKext, 238 | char * kextPathCString, 239 | KextutilArgs * toolArgs, 240 | Boolean isMainFlag, 241 | Boolean * yesToAll, 242 | Boolean * fatal); 243 | 244 | Boolean serializeLoad( 245 | KextutilArgs * toolArgs, 246 | Boolean loadFlag); 247 | static void usage(UsageLevel usageLevel); 248 | 249 | extern kern_return_t kextmanager_lock_kextload( 250 | mach_port_t server, 251 | mach_port_t client, 252 | int * lockstatus); 253 | kern_return_t kextmanager_unlock_kextload( 254 | mach_port_t server, 255 | mach_port_t client); 256 | 257 | #endif /* _KEXTUTIL_MAIN_H */ 258 | -------------------------------------------------------------------------------- /mkext1_file.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_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. Please obtain a copy of the License at 10 | * http://www.opensource.apple.com/apsl/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | * 21 | * @APPLE_LICENSE_HEADER_END@ 22 | */ 23 | 24 | #ifndef __MKEXT1_FILE_H__ 25 | #define __MKEXT1_FILE_H__ 26 | 27 | CFDataRef createMkext1ForArch(const NXArchInfo * arch, CFArrayRef archiveKexts, 28 | Boolean compress); 29 | 30 | #endif /* __MKEXT1_FILE_H__ */ 31 | -------------------------------------------------------------------------------- /mkextunpack.8: -------------------------------------------------------------------------------- 1 | .Dd March 6, 2009 2 | .Os Darwin 3 | .Dt MKEXTUNPACK 8 4 | .Sh NAME 5 | .Nm mkextunpack 6 | .Nd extract or list the contents of a multikext (mkext) archive 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl v 10 | .Op Fl a Ar arch 11 | .Op Fl d Ar output_directory 12 | .Ar mkext_file 13 | .Sh DESCRIPTION 14 | The 15 | .Nm 16 | program lists the contents of a multikext file, 17 | .Ar mkext_file , 18 | or unarchives the contents into 19 | .Ar output_directory 20 | (which must exist). 21 | The 22 | .Fl v 23 | option causes 24 | .Nm 25 | to print the name if each kext as it finds them. 26 | .Sh DIAGNOSTICS 27 | .Nm 28 | exits with a zero status upon success. 29 | Upon failure, it prints an error message 30 | and exits with a nonzero status. 31 | .Pp 32 | With a nonsegreated format 1 mkext file, 33 | wherein each kext may contain a universal binary, 34 | .Nm 35 | simply unpacks the contents. 36 | With an mkext file segregated by architecture 37 | (that is, with distinct internal archives of architecture-specific kexts), 38 | .Nm 39 | attempts by default to unpack or list kexts 40 | for the current machine's architecture. 41 | To choose a particular architecture 42 | to extract or list, 43 | use the 44 | .Fl a 45 | option. 46 | .Pp 47 | There is no simple way to unpack a segregated mkext file 48 | into a set of kexts with universal binaries, 49 | but you can unpack each of its component architectures 50 | to separate directories for examination. 51 | .Sh SEE ALSO 52 | .Xr kextcache 8 53 | .Sh BUGS 54 | Many single-letter options are inconsistent in meaning 55 | with (or directly contradictory to) the same letter options 56 | in other kext tools. 57 | .Pp 58 | For version 1 mkext files, note that the file format 59 | doesn't record the original filenames 60 | of the kexts, so 61 | .Nm 62 | has to guess at what they are. 63 | It does this by using the value of the CFBundleExecutable 64 | property of the kext's info dictionary 65 | (Project Builder sets this to the base name of the kext 66 | bundle by default, but the developer can change it). 67 | If that property doesn't exist, the last component of the 68 | CFBundleIdentifier is used. 69 | Duplicates have an incrementing index appended to the name. 70 | Kexts that have no CFBundleExecutable or CFBundleIdentifier property 71 | are named 72 | .Do Ns Pa NameUnknown- Ns Ar n Ns Pa .kext Dc Ns , 73 | where 74 | .Ar n 75 | is a number. 76 | -------------------------------------------------------------------------------- /pgo.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | #define PGO_FILENAME_BASE "/var/log/pgo" 15 | #define PGO_FILE_MODE 0755 16 | 17 | static 18 | char *pgo_read_metadata(void *buffer, size_t size, char *key) 19 | { 20 | size_t keylen = strlen(key); 21 | 22 | struct pgo_metadata_footer footer; 23 | if (size < sizeof(footer)) 24 | { 25 | return NULL; 26 | } 27 | 28 | memcpy(&footer, buffer + size - sizeof(footer), sizeof(footer)); 29 | 30 | char *pairs = (buffer + size) - ntohl(footer.offset_to_pairs); 31 | if ((void*)pairs < buffer) { 32 | return NULL; 33 | } 34 | 35 | uint32_t num_pairs = ntohl(footer.number_of_pairs); 36 | while (num_pairs > 0 && (void*)pairs < buffer + size) 37 | { 38 | size_t pairlen = strnlen(pairs, ((char*)buffer + size) - pairs); 39 | if ((void*)(pairs + pairlen) >= buffer + size) 40 | { 41 | return NULL; 42 | } 43 | if (0 == memcmp(key, pairs, keylen) && pairs[keylen] == '=') 44 | { 45 | return pairs + keylen + 1; 46 | } 47 | num_pairs--; 48 | pairs += pairlen + 1; 49 | } 50 | return NULL; 51 | } 52 | 53 | static 54 | void *pgo_thread_main(void *context) 55 | { 56 | OSKextRef kext = (OSKextRef) context; 57 | void *buffer = NULL; 58 | int fd = -1; 59 | 60 | uuid_t uuid; 61 | 62 | CFDataRef uuid_dataref = OSKextCopyUUIDForArchitecture(kext, NULL); 63 | if (uuid_dataref) 64 | { 65 | assert(CFDataGetLength(uuid_dataref) == sizeof(uuid)); 66 | memcpy(&uuid, CFDataGetBytePtr(uuid_dataref), sizeof(uuid)); 67 | CFRelease(uuid_dataref); 68 | } 69 | else 70 | { 71 | goto fail; 72 | } 73 | 74 | CFStringRef id = OSKextGetIdentifier(kext); 75 | if (!id) 76 | { 77 | goto fail; 78 | } 79 | 80 | char id_rep[NAME_MAX]; 81 | Boolean b = CFStringGetFileSystemRepresentation(id, id_rep, sizeof(id_rep)); 82 | if (!b) 83 | { 84 | goto fail; 85 | } 86 | 87 | ssize_t size = grab_pgo_data(&uuid, PGO_METADATA, NULL, 0); 88 | if (size < 0) 89 | { 90 | OSKextLog(kext, kOSKextLogErrorLevel, "failed to get size of pgo buffer: %s", strerror(errno)); 91 | goto fail; 92 | } 93 | 94 | buffer = malloc(size); 95 | if (!buffer) { 96 | OSKextLog(kext, kOSKextLogErrorLevel, "failed to allocate pgo buffer"); 97 | goto fail; 98 | } 99 | 100 | size= grab_pgo_data(&uuid, PGO_METADATA | PGO_WAIT_FOR_UNLOAD, buffer, size); 101 | if (size < 0) 102 | { 103 | OSKextLog(kext, kOSKextLogErrorLevel, "failed to get size of pgo buffer: %s", strerror(errno)); 104 | goto fail; 105 | } 106 | 107 | char *instance = pgo_read_metadata(buffer, size, "INSTANCE"); 108 | if (!instance) { 109 | OSKextLog(kext, kOSKextLogErrorLevel, "no metadata in pgo buffer"); 110 | } 111 | 112 | mkdir(PGO_FILENAME_BASE, PGO_FILE_MODE); 113 | 114 | char filename[PATH_MAX]; 115 | snprintf(filename, sizeof(filename), "%s/%s", PGO_FILENAME_BASE, id_rep); 116 | mkdir (filename, PGO_FILE_MODE); 117 | 118 | snprintf(filename, sizeof(filename), "%s/%s/%s", PGO_FILENAME_BASE, id_rep, instance); 119 | fd = fopen(filename, "w"); 120 | 121 | fd = open(filename, O_WRONLY|O_CREAT); 122 | if (fd < 0) 123 | { 124 | OSKextLog(kext, kOSKextLogErrorLevel, "error (%s) while opening pgo output file: %s", 125 | strerror(errno), filename); 126 | goto fail; 127 | } 128 | 129 | unsigned char *p = buffer; 130 | ssize_t r; 131 | while (size > 0) { 132 | errno = 0; 133 | r = write(fd, p, size); 134 | if (r > 0) { 135 | p += r; 136 | size -= r; 137 | } else { 138 | OSKextLog(kext, kOSKextLogErrorLevel, "error writing pgo file: %s", strerror(errno)); 139 | goto fail; 140 | } 141 | } 142 | 143 | fail: 144 | CFRelease(kext); 145 | if (buffer) { 146 | free(buffer); 147 | } 148 | if (fd > 0) { 149 | close(fd); 150 | } 151 | return NULL; 152 | } 153 | 154 | void pgo_start_thread(OSKextRef kext) 155 | { 156 | CFRetain(kext); 157 | pthread_t thread; 158 | int r; 159 | r = pthread_create(&thread, NULL, pgo_thread_main, kext); 160 | if (r) 161 | { 162 | OSKextLog(kext, kOSKextLogErrorLevel, "failed to create thread"); 163 | CFRelease(kext); 164 | } 165 | } 166 | 167 | bool pgo_scan_kexts(CFArrayRef array) 168 | { 169 | CFIndex i; 170 | bool found = false; 171 | 172 | for (i = 0; i < CFArrayGetCount(array); i++) 173 | { 174 | CFDictionaryRef dict = (CFDictionaryRef) CFArrayGetValueAtIndex(array, i); 175 | 176 | assert(CFGetTypeID(dict) == CFDictionaryGetTypeID()); 177 | 178 | CFStringRef id = CFDictionaryGetValue(dict, CFSTR("CFBundleIdentifier")); 179 | CFStringRef ver = CFDictionaryGetValue(dict, CFSTR("CFBundleVersion")); 180 | 181 | if (!id || !ver || 182 | CFGetTypeID(id) != CFStringGetTypeID() || 183 | CFGetTypeID(ver) != CFStringGetTypeID()) 184 | { 185 | continue; 186 | } 187 | 188 | OSKextRef kext = OSKextGetKextWithIdentifierAndVersion(id, OSKextParseVersionCFString(ver)); 189 | 190 | if (!kext) { 191 | continue; 192 | } 193 | 194 | CFDataRef uuid = OSKextCopyUUIDForArchitecture(kext, NULL); 195 | if (!uuid) { 196 | continue; 197 | } 198 | assert(CFDataGetLength(uuid) == sizeof(uuid_t)); 199 | ssize_t size = grab_pgo_data((uuid_t*)CFDataGetBytePtr(uuid), PGO_METADATA, NULL, 0); 200 | if (size < 0) { 201 | continue; 202 | } 203 | pgo_start_thread(kext); 204 | found = true; 205 | } 206 | 207 | return found; 208 | } 209 | -------------------------------------------------------------------------------- /pgo.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef PGO_H 3 | #define PGO_H 4 | 5 | void pgo_start_thread(OSKextRef kext); 6 | 7 | bool pgo_scan_kexts(CFArrayRef kexts); 8 | 9 | #endif /* PGO_H */ 10 | -------------------------------------------------------------------------------- /safecalls.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007 Apple Inc. All rights reserved. 3 | * 4 | * @APPLE_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. Please obtain a copy of the License at 10 | * http://www.opensource.apple.com/apsl/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | * 21 | * @APPLE_LICENSE_HEADER_END@ 22 | */ 23 | /* 24 | * FILE: safecalls.h 25 | * AUTH: Soren Spies (sspies) 26 | * DATE: 16 June 2006 (Copyright Apple Computer, Inc) 27 | * DESC: picky syscalls (constrained to one volume) 28 | * 29 | * CAVEAT: fchdir is used heavily ... until we have openat(2) and/or 30 | * per-thread chdir, this code is not safe to use on multiple threads. 31 | * we attempt to restore CWD within each call, but failure is not returned 32 | * 33 | */ 34 | 35 | #include 36 | 37 | // secure versions of common syscalls (only if args on vol specified by fd) 38 | 39 | // O_EXCL added if O_CREAT specified 40 | int sopen(int fdvol, const char *path, int flags, mode_t mode); 41 | // WARNING: child will point to basename() [static] data 42 | // additionally, caller must close non-(-1) olddir if requested (cf. restoredir) 43 | int schdir(int fdvol, const char *path, int *olddir); 44 | int schdirparent(int fdvol, const char *path, int *olddir, char childname[PATH_MAX]); 45 | int restoredir(int savedir); // check errors if you want them 46 | 47 | // these are trivially implemented with the above 48 | int smkdir(int fdvol, const char *path, mode_t mode); 49 | int srmdir(int fdvol, const char *path); 50 | int sunlink(int fdvol, const char *path); 51 | // srename only renames within a directory; uses basename(newname) 52 | int srename(int fdvol, const char *oldpath, const char *newname); 53 | 54 | // uses FTS to recurse downwards, calling sunlink and srmdir as appropriate 55 | int sdeepunlink(int fdvol, char *path); // fts_open won't take const char* 56 | // overwrite a file with zeros; attempt to ftruncate; no unlink; ENOENT okay 57 | int szerofile(int fdvol, const char *path); 58 | // 'mkdir -p' (recursively applies mode) 59 | int sdeepmkdir(int fdvol, const char *path, mode_t mode); 60 | // creates intermediate directories for you; only copies one file 61 | int scopyitem(int srcvolfd, const char *src, int dstvolfd, const char *dst); 62 | 63 | #ifndef STRICT_SAFETY 64 | #define STRICT_SAFETY 1 65 | #endif 66 | #if STRICT_SAFETY 67 | 68 | // #define open() // #error use sopen (need a chicken) 69 | #define chdir() // #error use schdir 70 | 71 | #define mkdir() // #error use smkdir 72 | #define rmdir() // #error use srmdir 73 | #define unlink() // #error use sunlink 74 | #define rename() // #error srename 75 | 76 | #define copyfile() // #error use scopyfile 77 | 78 | #endif // STRICT_SAFETY 79 | -------------------------------------------------------------------------------- /security.h: -------------------------------------------------------------------------------- 1 | /* 2 | * security.h 3 | * kext_tools 4 | * 5 | * Copyright 20012 Apple Inc. All rights reserved. 6 | * 7 | */ 8 | #ifndef _SECURITY_H 9 | #define _SECURITY_H 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | // 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #define kMessageTracerDomainKey "com.apple.message.domain" 25 | #define kMessageTracerHashKey "com.apple.message.hash" 26 | #define kMessageTracerBundleIDKey "com.apple.message.bundleID" 27 | #define kMessageTracerVersionKey "com.apple.message.version" 28 | #define kMessageTracerKextNameKey "com.apple.message.kextname" 29 | #define kMessageTracerFatKey "com.apple.message.fat" 30 | #define kMessageTracerArchKey "com.apple.message.architecture" 31 | 32 | #define kMessageTracerTeamIdKey "com.apple.message.teamid" 33 | #define kMessageTracerSubjectCNKey "com.apple.message.subjectcn" 34 | #define kMessageTracerIssuerCNKey "com.apple.message.issuercn" 35 | 36 | #define kMessageTracerSignatureTypeKey "com.apple.message.signaturetype" 37 | #define kMessageTracerPathKey "com.apple.message.kextpath" 38 | 39 | #define kAppleKextWithAppleRoot \ 40 | "Apple kext with Apple root" 41 | #define k3rdPartyKextWithAppleRoot \ 42 | "3rd-party kext with Apple root" 43 | #define k3rdPartyKextWithoutAppleRoot \ 44 | "3rd-party kext without Apple root" 45 | #define k3rdPartyKextWithDevIdPlus \ 46 | "3rd-party kext with devid+ certificate" 47 | #define k3rdPartyKextWithRevokedDevIdPlus \ 48 | "3rd-party kext with revoked devid+ certificate" 49 | #define kUnsignedKext \ 50 | "Unsigned kext" 51 | 52 | /* "com.apple.libkext.kext.loading" was used in 10.8 53 | * "com.apple.libkext.kext.loading.v3" is used in 10.9 */ 54 | #define kMTKextLoadingDomain "com.apple.libkext.kext.loading.v3" 55 | #define kMTKextBlockedDomain "com.apple.libkext.kext.blocked" 56 | 57 | void messageTraceExcludedKext(OSKextRef aKext); 58 | void recordKextLoadListForMT(CFArrayRef kextList); 59 | void recordKextLoadForMT(OSKextRef aKext); 60 | 61 | OSStatus checkKextSignature(OSKextRef aKext, 62 | Boolean checkExceptionList, 63 | Boolean earlyBoot); 64 | OSStatus checkSignaturesOfDependents(OSKextRef theKext, 65 | Boolean checkExceptionList, 66 | Boolean earlyBoot); 67 | Boolean isInExceptionList(OSKextRef theKext, CFURLRef theKextURL, Boolean useCache); 68 | Boolean isInLibraryExtensionsFolder(OSKextRef theKext); 69 | Boolean isInSystemLibraryExtensionsFolder(OSKextRef theKext); 70 | //Boolean isDevMode(void); 71 | Boolean isPrelinkedKernelAutoRebuildDisabled(void); 72 | Boolean isInvalidSignatureAllowed(void); 73 | Boolean isKextdRunning(void); 74 | int callSecKeychainMDSInstall( void ); 75 | 76 | #endif // _SECURITY_H 77 | --------------------------------------------------------------------------------