Read plist from kext - macos

I'd like save a kext setting between OS restarts. As I need the settings after kext been loaded immediately, I can not wait for managing daemon start up. Is it a way for reading/writing kext plist file from kext or some other ways to do that?

Basically, no - you're supposed to store settings in userspace and use a launchd service to set them in the kext. Until your kext receives the settings, it should just use some sane defaults.
One way to truly include settings on kext startup is to add custom attributes to the IOKitPersonality in your kext's info.plist. Obviously, this means that changing settings requires changing the kext itself, but I have heard reports of people actually doing this on Apple's public darwin mailing lists (although Apple employees pitched in to criticise it). Note that the kext cache will not like this: If your userspace program changes settings in the info.plist, it will probably need to increase the bundle version number in order for the kext cache to pick up the change, otherwise the cached/prelinked kext won't see the change. You need to do this within the constraints of the rules for kext bundle versions or it won't be detected as a version increase, or worse, the kext cache will reject the kext outright. Also, don't forget to touch /System/Library/Extensions/ after updating kexts.
Update: modifying a kext's info.plist will no longer work in 10.9 and 10.10 due to the kext signing requirement.
In the specific case where your kext is a storage filter scheme, you can store your settings in a special "super block" of the provider partition. AppleRAID (which is open source) does this, for example. This isn't practical for any other kind of kext, though.

Related

Mac hook function

I used to be able to use mach_override to hook any exported function on Mac OS including Catalina. However, now the target app crashed every time and I check the Console and find the following error:
CODE SIGNING: 30911[app] vm_map_protect can't have both write and exec at the same time
What's going on and is that possible I can bypass it without touching the target app's signature?
The hardened runtime is designed specifically to prevent that sort of hooking. The target app's entitlements would have to opt-in to allowing it. If you find a way around it, Apple would consider that a security hole bug and patch it in a future OS release.
It should work if you disable System Integrity Protection, but I don't know if that suits your purpose.

Same kernel extension (kext), different identifier. How to avoid conflicts?

We use a publicly available kernel extension (http://tuntaposx.sourceforge.net) in our application to add tun/tap network functionality to macOS.
It appears that other applications also use the very same kernel extension, but unfortunately they modified the kext's bundle identifier, which prevents us from checking by the bundle identifier whether the same kernel extension is already loaded when our application tries to load its own copy of the kext.
Is there an alternative way of testing whether a kernel extension with the same functionality is already loaded? Maybe by calling some functions of the kext?

Load OS X kext in the early boot process

I have a working OSX kernel extension which I would like to be automatically loaded at boot time as early as possible. The kext is using KAUTH for monitoring access on a specific path so it seems to me there won't be anything that will request it to be loaded into the kernel. In this case, copying it in /Library/Extensions (at least since Yosemite this is the recommended path for third-party extensions) won't solve my problem.
Is there a possibility to achieve this, whether or not by modifying the code or through some auxiliary configuration?
I already read about using a launchd daemon to use kextload in order to load the extension, as specified in this question, but in my case, I want it to be loaded as early as possible.
Update:
I am using a "generic" kernel extension (linked against BSD library) and not an I/O Kit based one.
I want my extension to be loaded before launchd is started.
You don't explicitly state it in the question, but I infer from the context that you're using a "generic" kernel extension (in contrast to an I/O kit based one)? These are only loaded either because another kext depends on them, or because they are explicitly loaded via kextutil/kextload or the KextManager API.
Contrast this to I/O Kit kexts, which are loaded on-demand when one of their personality dictionaries matches a registered service in the IO registry. This is usually for driving specific devices, but various non-hardware-dependent system services use the mechanism to match the 'IOResources' nub (documentation) which turns up during early boot so any kexts listing it as a provider for a personality also get loaded on boot.
So the solution would be to modify your kext to provide an IOService which matches the IOResources nub. The service itself doesn't really need to do anything if your userspace component already uses another interface to communicate with the kext.
If you don't want to change the kext's code itself, you could possibly create a dummy kext which does this, but declares your main kext as a dependency. This latter method isn't particularly elegant, but should work if for some reason modifying the existing kext is not possible. (Although you'll likely need to modify the info.plist)
If the kext is derived from IOKit and resides in /Library/Extensions clear the cache and it will be automatically loaded at boot. You clear the cache by calling
kextcache -f -update-volume /

Detect if OS X kernel extension is loadable

I'm attempting to write an application that talks to a custom USB device. We have written a driver (kext) that is automatically loaded when the USB device is attached to the computer. It is installed into the appropriate location (/System/Library/Extensions & /Library/Extensions) during the installation process.
In my application (.app), I need to be able to confirm that this kext is installed and is loadable on the user's computer.
My initial thought was to use the "System" command and get the result of "kextstat | grep mykext". However, kextstat only shows the kernel extensions that are loaded. (It's possible the application can be launched before the user has attached the USB device).
The only other thing that I can think of is to use "kextfind | grep mykext" to determine if the kext exists, however, I don't know if it is loadable or not. (ie. it could exist, but someone messed with the plist file, and now the signature fails, so it won't ever be loaded)
I know that it's possible, because Apple's System Profiler is able to list all of the extensions, if they are loaded, and if they are loadable.
From the kextutil man page:
kextutil prints diagnostic information about kexts by default, but some options cause certain tests to be skipped. To ensure that all tests are performed, use the -print-diagnostics (-t) option. The -print-diagnostics option is typically used with -no-load (-n) after a load failure to pinpoint a problem. It can be used with any other set of options, however.
Note: when the -no-load (-n) option is used then sudo (root user) isn't required.

Can't Unload Kernel Extension; Classes Have Instances

I'm writing an OSX kernel extension for an audio device driver (it's software, but emulates a hardware device).
During development, it'd be convenient to completely uninstall existing old versions and then build and install the new version from scratch. However, this occasionally seems to not be possible without a system restart.
The program itself is not running and the source files have been deleted from the /System/Library/Extensions/ dir.
But kextstat reveals a single instance:
$ kextstat | grep 'com.foo.driver.bar'
219 0 0xfff123 0x5000 0x5000 com.foo.driver.bar (0.0.1) <102 5 4 3>
(...meaning:)
Index Refs Address Size Wired Name (Version) <Linked Against>
So there are 0 Refs to my driver instance, but kextunload will sometimes fail, complaining of existing instances:
$ sudo kextunload -b com.foo.driver.bar
(kernel) Can't unload kext com.foo.driver.bar; classes have instances:
(kernel) Kext com.foo.driver.bar class FooBarDriver has 1 instance.
(kernel) Kext com.foo.driver.bar class com_foo_driver_bar has 1 instance.
Failed to unload com.foo.driver.bar - (libkern/kext) kext is in use or retained (cannot unload).
When this happens, there's no way to "force" unload the kext (that I know of).
Am I right in guessing that this single instance still exists because of a reference held in memory by the running OS kernel? That doesn't seem right, because then kextunload would always fail. So why does kextunload only sometimes require a system restart to "fully" unload all driver instances?
Running kextunload for an IOKit kext will (if no other kexts depend on it) cause the kernel to attempt to terminate() any instances of classes in that kext which are in the I/O Kit registry. It will then wait a bit and check if any of that kext's classes still have instances. If not, it will unload the kext. If instances remain, kextunload fails (the terminated instances stay terminated, though; by this I mean that I/O kit matching is not re-run on their providers).
So somehow, you're still ending up with live instances.
One possibility is that your objects are refusing to terminate(). This can happen if they have clients that won't give up control, e.g. you can't unload the driver for a disk with a mounted file system on top. Userspace clients that don't respond to termination messages are another example.
Otherwise, the instances terminate, but are not freed. Since they seem to be of two of your main driver classes, if you don't have any user clients that won't give up their claim, I'm going to go out on a limb and suggest that you might have a circular reference. If that's not it, you'll just have to hunt for retain()s which are not matched by a release(). I give some tips on how to track these down in this answer.
If the instances terminate and are deregistered, they will no longer appear in the output of the ioreg commandline tool, so that's an easy way of checking which of the two cases applies here.

Resources