Develop kernel-resident device drivers and kernel extensions using Kernel.

Posts under Kernel tag

200 Posts

Post

Replies

Boosts

Views

Activity

How to programmatically determine fixed CPU frequency for memory latency benchmarking on Apple Silicon?
Hi everyone, I am developing a benchmarking tool to measure memory latency (L1/L2/DRAM) on Apple Silicon. I am currently using Xcode Instruments (CPU Counters) to validate my results. In my latest run for a 128 MB buffer with random access, Instruments shows: Latency (cycles): ~259 cycles (derived from LDST_UNIT_OLD_L1D_CACHE_MISS / L1D_CACHE_MISS_LD). Manual Timer Result: ~80 ns. To correlate these two values, I need the exact CPU Frequency (GHz) at the time of the sample. My Questions: Is there a recommended way to programmatically fetch the current frequency of the Performance cores (p-cores) during a benchmark run? Does Apple provide a "nominal" frequency value for M-series chips that we should use for cycle-to-nanosecond conversions? In Instruments, is there a hidden counter or "Average Frequency" metric that I can enable to avoid manual math? Hardware/Software Environment: Tool: Instruments 26.3+ (CPU Counters Template). Chip: A19, iPhone 17 pro. OS: 26.3.
0
0
1.7k
Mar ’26
crhold()/crfree()
When I have to pull in hundreds of commits from upstream, I like to try to make sure things still compile - frequently, to try to limit how far I need to go to back fix things. One issue is missing symbols in the kext, since you won't know until you try to load the kext. And loading the kext each commit is not realistic. So I went and made up a call to something that does not exist, in my case, strqcmp(). I could not get the various tools like kmutil libraries --all-symbols to print out that this function was going to fail, so I wrote a little script (thanks ChatGPT); ./scripts/kpi_check.py --arch arm64e -k module/os/macos/zfs.kext/ First missing symbols: _crfree _crhold _strqcmp Hurrah. But sadly, my brain was then curious as to why crhold() and crfree() work. Worked for years. Only dtrace calls them in XNU sources but otherwise not mentioned there, not listed in my frameworks, nm is not seeing it. Somewhat of a rabbit hole. I don't even need to know, it does work after all. I should just let it go right? and yet... how does it work? My best guess is a symbols.alias pointing it to kauth_cred_ref() somewhere? Maybe? Anyway, pretty low priority but it's an itch...
0
0
139
Jan ’26
Incorrect packet handling in SMBClient MacOS 26.
SMBClient-593 introduces a crtitical bug. When reading and writing data at high volume, the SMBClient no longer properly receives and handle responses from the server. In some cases, the client mishandles the response packet and the following errors are seen in the logs: 2025-12-02 21:36:04.774772-0700 localhost kernel[0]: (smbfs) smb2_smb_parse_write_one: Bad struct size: 0 2025-12-02 21:36:04.774776-0700 localhost kernel[0]: (smbfs) smb2_smb_write: smb2_smb_read_write_async failed with an error 72 2025-12-02 21:36:04.774777-0700 localhost kernel[0]: (smbfs) smbfs_do_strategy: file.txt: WRITE failed with an error of 72 In other cases, the client mishandles the response packet and becomes completely unresponsive, unable to send or receive additional messages, and a forced shutdown of the computer is required to recover. This bug is only present on macos 26. We believe the operative change is in the latest commit, SMBClient-593 beginning at line now 3011 in smb_iod.c. The issue seems to be a race, and occurs much more frequently once throughput exceeds around 10Gbps, and again more frequently above 20Gbps.
6
7
744
Jan ’26
Show / Hide HAL Virtual Audio Device Based on App State
I am developing a macOS virtual audio device using an Audio Server Plug-In (HAL). I want the virtual device to be visible to all applications only when my main app is running, and completely hidden from all apps when the app is closed. The goal is to dynamically control device visibility based on app state without reinstalling the driver.What is the recommended way for the app to notify the HAL plug-in about its running or closed state ? Any guidance on best-practice architecture for this scenario would be appreciated.
1
0
837
Jan ’26
How to connect to a IOUSBHostInterface
I have poked around the web looking for a good example to do this and I haven't found a working example. I need to connect to a USB Device, its multiple ports and supports what looks to be a root port and 4 other ports I am no expert in USB but I do know how to write a kext and client drivers, but thats really not the way to solve this. I need to display the serialized output from these USB ports for a development board. I would rather do this on my Mac than have to cobble up a Linux machine and mess around with Linux. Here is the output from ioreg MCHP-Debug@03100000 <class IOUSBHostDevice, id 0x105f6fdc2, registered, matched, active, busy 0 (20 ms), retain 27> MCHP-Debug@0 <class IOUSBHostInterface, id 0x105f6fdc8, registered, matched, active, busy 0 (13 ms), retain 5> +-o MCHP-Debug@0 <class IOUSBHostInterface, id 0x105f6fdc8, registered, matched, active, busy 0 (13 ms), retain 5> +-o MCHP-Debug@1 <class IOUSBHostInterface, id 0x105f6fdc9, registered, matched, active, busy 0 (11 ms), retain 5> +-o MCHP-Debug@2 <class IOUSBHostInterface, id 0x105f6fdcb, registered, matched, active, busy 0 (9 ms), retain 5> | | | | | +-o MCHP-Debug@3 <class IOUSBHostInterface, id 0x105f6fdcc, registered, matched, active, busy 0 (7 ms), retain 5> I have been able to open a inservice to the device at the top level, but I get an error when I use. usbHostInterface = [[IOUSBHostInterface alloc] initWithIOService:usbDevice options: IOUSBHostObjectInitOptionsNone queue: queue error: &error interestHandler: handler]; Error:Failed to create IOUSBHostInterface. with reason: Unable to obtain configuration descriptor. Assertion failed: (usbHostInterface), function main, file main.m, line 87. I started using DeviceKit but I received signing errors and I shouldn't have to go down that path just to dump data from a USB port? Any suggestions would be great, most of the Apple documentation on USB ports is like 20 years old and the new stuff pushes you towards DeviceKit.
1
0
1.6k
Dec ’25
KDK for current stable version (26.1) missing
The current stable macOS version, 26.1 (build 25B78) is missing a corresponding Kernel Debug Kit (KDK) on the developer downloads page. This means I can't do any kernel-level development tasks currently. For example, if I try to build a new kernel collection with kmutil I get the message Missing Developer Kit: As of macOS 13.0, you will need to install a KDK matching your build 25B78 to rebuild kernel collections. but there is no build 25B78 KDK available to download. The latest 26.1 KDK on the download page is 25B5062e (from a beta I believe) and the final stable KDK for build 25B78 (which kernel development tools require) was never published. Is there any workaround for this to correctly do kernel-level development targeting the latest stable release, or a timeline for when the KDK will release? Thanks!
0
3
787
Nov ’25
No KDKs available for macOS 26.0 Developer Beta 2 and later
As of now, there is no Kernel Debug Kit (KDK) available for macOS 26.0 Developer Betas after the first build. Kernel Debug Kits are crucial for understanding panics and other bugs within custom Kernel Extensions. Without the KDK for the corresponding macOS version, tools like kmutil fail to recognize a KDK and certain functions are disabled. Additionally, as far as I am aware, a KDK for one build of macOS isn't able to be used on a differing build. Especially since this is a developer beta, where developers are updating their software to function with the latest versions of macOS, I'd expect a KDK to be available for more than one build.
7
0
1.6k
Nov ’25
Blocking USB Devices on macOS – DriverKit or Other Recommended Approach
Hi Apple, We are working on a general USB device management solution on macOS for enterprise security. Our goal is to enforce policy-based restrictions on USB devices, such as: For USB storage devices: block mount, read, or write access. For other peripherals (e.g., USB headsets or microphones, raspberry pi, etc): block usage entirely. We know in past, kernel extension would be the way to go, but as kext has been deprecated. And DriverKit is the new advertised framework. At first, DriverKit looked like the right direction. However, after reviewing the documentation more closely, we noticed that using DriverKit for USB requires specific entitlements: DriverKit USB Transport – VendorID DriverKit USB Transport – VendorID and ProductID This raises a challenge: if our solution is meant to cover all types of USB devices, we would theoretically need entitlements for every VendorID/ProductID in existence. My questions are: Is DriverKit actually the right framework for this kind of general-purpose USB device control? If not, what framework or mechanism should we be looking at for enforcing these kinds of policies? We also developed an Endpoint Security product, but so far we haven’t found a relevant Endpoint Security event type that would allow us to achieve this. Any guidance on the correct technical approach would be much appreciated. Thanks in advance for your help.
6
0
1.4k
Sep ’25
macOS 26 kernel open source?
Hi! I was wondering if there will be new XNU version for macOS 26 published open source? As far as I remember, previous version's source code was published the moment the OS was officially released, but not this time. If yes, when we can expect it to be published?
1
0
471
Sep ’25
macos 15.6.1 - BSD sendto() fails for IPv4-mapped IPv6 addresses
There appears to be some unexplained change in behaviour in the recent version of macos 15.6.1 which is causing the BSD socket sendto() syscall to no longer send the data when the source socket is bound to a IPv4-mapped IPv6 address. I have attached a trivial native code which reproduces the issue. What this reproducer does is explained as a comment on that code's main() function: // Creates a AF_INET6 datagram socket, marks it as dual socket (i.e. IPV6_V6ONLY = 0), // then binds the socket to a IPv4-mapped IPv6 address (chosen on the host where this test runs). // // The test then uses sendto() to send some bytes. For the sake of this test, it uses the same IPv4-mapped // IPv6 address as the destination address to sendto(). The test then waits for (a maximum of) 15 seconds to // receive that sent message by calling recvfrom(). // // The test passes on macos (x64 and aarch64) hosts of versions 12.x, 13.x, 14.x and 15.x upto 15.5. // Only on macos 15.6.1 and the recent macos 26, the test fails. Specifically, the first message that is // sent using sendto() is never sent (and thus the recvfrom()) times out. sendto() however returns 0, // incorrectly indicating a successful send. Interesting, if you repeat sendto() a second message from the // same bound socket to the exact same destination address, the send message is indeed correctly sent and // received immediately by the recvfrom(). It's only the first message which goes missing (the test uses // unique content in each message to be sure which exact message was received and it has been observed that // only the second message is received and the first one lost). // // Logs collected using "sudo log collect --last 2m" (after the test program returns) shows the following log // message, which seem relevant: // ... // default kernel cfil_hash_entry_log:6088 <CFIL: Error: sosend_reinject() failed>: // [86868 a.out] <UDP(17) out so 59faaa5dbbcef55d 127846646561221313 127846646561221313 age 0> // lport 65051 fport 65051 laddr 192.168.1.2 faddr 192.168.1.2 hash 201AAC1 // default kernel cfil_service_inject_queue:4472 CFIL: sosend() failed 22 // ... // As noted, this test passes without issues on various macosx version (12 through 15.5), both x64 and aarch64 but always fails against 15.6.1. I have been told that it also fails on the recently released macos 26 but I don't have access to such host to verify it myself. The release notes don't usually contain this level of detail, so it's hard to tell if something changed intentionally or if this is a bug. Should I report this through the feedback assistant? Attached is the source of the reproducer, run it as: clang dgramsend.c ./a.out On macos 15.6.1, you will see that it will fail to send (and thus receive) the message on first attempt but the second one passes: ... created and bound a datagram dual socket to ::ffff:192.168.1.2:65055 ::ffff:192.168.1.2:65055 sendto() ::ffff:192.168.1.2:65055 ---- Attempt 1 ---- sending greeting "hello 1" sendto() succeeded, sent 8 bytes calling recvfrom() receive timed out --------------------- ---- Attempt 2 ---- sending greeting "hello 2" sendto() succeeded, sent 8 bytes calling recvfrom() received 8 bytes: "hello 2" --------------------- TEST FAILED ... The output "log collect --last 2m" contains a related error (and this log message consistently shows up every time you run that reproducer): ... default kernel cfil_hash_entry_log:6088 <CFIL: Error: sosend_reinject() failed>: [86248 a.out] <UDP(17) out so 59faaa5dbbcef55d 127846646561221313 127846646561221313 age 0> lport 65055 fport 65055 laddr 192.168.1.2 faddr 192.168.1.2 hash 201AAC1 default kernel cfil_service_inject_queue:4472 CFIL: sosend() failed 22 ... I don't know what it means though. dgramsend.c
2
0
485
Sep ’25
Network framework crashes on fork
Hello, I have a Cocoa application from which I fork a new process (helper sort of) and it crashes on fork due to some cleanup code probably registered with pthreads_atfork() in Network framework. This is crash from the child process: Application Specific Information: *** multi-threaded process forked *** BUG IN CLIENT OF LIBPLATFORM: os_unfair_lock is corrupt Abort Cause 258 crashed on child side of fork pre-exec Thread 0 Crashed:: Dispatch queue: com.apple.main-thread 0 libsystem_platform.dylib 0x194551238 _os_unfair_lock_corruption_abort + 88 1 libsystem_platform.dylib 0x19454c788 _os_unfair_lock_lock_slow + 332 2 Network 0x19b1b4af0 nw_path_shared_necp_fd + 124 3 Network 0x19b1b4698 -[NWConcrete_nw_path_evaluator dealloc] + 72 4 Network 0x19af9d970 __nw_dictionary_dispose_block_invoke + 32 5 libxpc.dylib 0x194260210 _xpc_dictionary_apply_apply + 68 6 libxpc.dylib 0x19425c9a0 _xpc_dictionary_apply_node_f + 156 7 libxpc.dylib 0x1942600e8 xpc_dictionary_apply + 136 8 Network 0x19acd5210 -[OS_nw_dictionary dealloc] + 112 9 Network 0x19b1beb08 nw_path_release_globals + 120 10 Network 0x19b3d4fa0 nw_settings_child_has_forked() + 312 11 libsystem_pthread.dylib 0x100c8f7c8 _pthread_atfork_child_handlers + 76 12 libsystem_c.dylib 0x1943d9944 fork + 112 (...) I'm trying to create a child process with boost::process::child which does basically just a fork() followed by execv() and I do it before the - [NSApplication run] is called. Is it know bug or behavior which I've run into? Also what is a correct way to spawn child processes in Cocoa applications? As far as my understanding goes the basically all the available APIs (e.g. posix, NSTask) should be more or less the same thing calling the same syscalls. So forking the process early before main run loop starts and not starting another NSApplication in forked child should be ok ...or not?
4
0
3k
Sep ’25
VNOP_MONITOR+vnode_notify() operation details
After perusing the sources of Apple's SMB and NFS clients' implementation of VNOP_MONITOR, my understanding of how VNOP_MONITOR+vnode_notify() operate is as follows: A user-space process advertises an interest in monitoring a file or directory via kqueue(2)/kevent(2). VFS calls the filesystem's implementation of VNOP_MONITOR. VNOP_MONITOR forwards the commencing or terminating of monitoring events request to the filesystem server. Network filesystem client nodes call vnode_notify() to notify the underlying VFS of a filesystem event, e.g. file/directory creation/removal, etc. What I'm still vague about is how does the server communicate back to client nodes that an event of interest has occurred? I'd appreciate being enlightened on the operation of `VNOP_MONITOR+vnode_notify()' in a network filesystem setting.
1
0
218
Aug ’25
Support for Multi-Homed IPv6 Networks, esp. RFC 8028
Hi everyone, I’m running a dual-homed IPv6-mostly LAN where two on-link routers advertise distinct global Provider-Assigned prefixes (one per ISP). On Linux, the host stack appears to follow RFC 8028. It keeps one default route per prefix, and packets appear to leave through a router that recognises their source address and pass ISP BCP 38 (https://datatracker.ietf.org/doc/bcp38/) checks. On macOS Sequoia, I'm only seeing a single un-scoped default route. As a result, traffic sourced from prefix B often exits via router A and is dropped upstream. Questions: Is the single-default-per-interface model in macOS an intentional design choice or simply legacy behaviour that has not yet been updated to RFC 8028? Does the kernel perform any hidden next-hop selection that isn’t reflected in netstat -rn output? Are there any road-map items for fully adopting RFC 8028 in macOS? As a bonus, I'd be very interested in any info you might be able to provide on the status of implementation/support for https://datatracker.ietf.org/doc/html/rfc8978 (Reaction of IPv6 Stateless Address Autoconfiguration (SLAAC) to Flash-Renumbering Events).
2
0
500
Jul ’25
Hardlinks reported as non-existing on macOS Sequoia for 3rd party FS
After creating a hardlink on a distributed filesystem of my own via: % ln f.txt hlf.txt Neither the original file, f.txt, nor the hardlink, hlf.txt, are immediately accessible, e.g. via cat(1) with ENOENT returned. A short time later though, both the original file and the hardlink are accessible. Both files can be stat(1)ed though, which confirms that vnop_getattr returns success for both files. Dtruss(1) indicates it's the open(2) syscall that fails: % sudo dtruss -f cat hlf.txt 2038/0x4f68: open("hlf.txt\0", 0x0, 0x0) = -1 Err#2 ;ENOENT 2038/0x4f68: write_nocancel(0x2, "cat: \0", 0x5) = 5 0 2038/0x4f68: write_nocancel(0x2, "hlf.txt\0", 0x7) = 7 0 2038/0x4f68: write_nocancel(0x2, ": \0", 0x2) = 2 0 2038/0x4f68: write_nocancel(0x2, "No such file or directory\n\0", 0x1A) = 26 0 Dtrace(1)ing my KEXT no longer works on macOS Sequoia, so based on the diagnostics print statements I inserted into my KEXT, the following sequence of calls is observed: vnop_lookup(hlf.txt) -&gt; EJUSTRETURN ;ln(1) vnop_link(hlf.txt) -&gt; KERN_SUCCESS ;ln(1) vnop_lookup(hlf.txt) -&gt; KERN_SUCCESS ;cat(1) vnop_open(/) ; I expected to see vnop_open(hlf.txt) here instead of the parent directory. Internally, hardlinks are created in vnop_link via a call to vnode_setmultipath with cache_purge_negatives called on the destination directory. On macOS Monterey for example, where the same code does result in hardlinks being accessible, the following calls are made: vnop_lookup(hlf.txt) -&gt; EJUSTRETURN ;ln(1) vnop_link(hlf.txt) -&gt; KERN_SUCCESS ;ln(1) vnop_lookup(hlf.txt) -&gt; KERN_SUCCESS ;cat(1) vnop_open(hlf.txt) -&gt; KERN_SUCCESS ;cat(1) Not sure how else to debug this. Perusing the kernel sources for uses of VISHARDLINK, VNOP_LINK and vnode_setmultipath call sites did not clear things up for me. Any pointers would be greatly appreciated.
3
0
380
Jul ’25
Kext loads well after launchd and early os_log entries rarely appear in unified log
Is there a way to ensure a kernel extension in the Auxiliary Kernel Collection loads (and runs its start routines) before launchd? I'm emitting logs via os_log_t created with an os_log_create (custom subsystem/category) in both my KMOD's start function and the IOService::start() function. Those messages-- which both say "I've been run"-- inconsistently show up in log show --predicate 'subsystem == "com.bluefalconhd.pandora"' --last boot, which makes me think they are running very early. However, I also record timestamps (using mach_absolute_time, etc.) and expose them to user space through an IOExternalMethod. The results (for the most recent boot): hayes@fortis Pandora/tests main % build/pdtest Pandora Metadata: kmod_start_time: Time: 2025-07-22 14:11:32.233 Mach time: 245612546 Nanos since boot: 10233856083 (10.23 seconds) io_service_start_time: Time: 2025-07-22 14:11:32.233 Mach time: 245613641 Nanos since boot: 10233901708 (10.23 seconds) user_client_init_time: Time: 2025-07-22 14:21:42.561 Mach time: 14893478355 Nanos since boot: 620561598125 (620.56 seconds) hayes@fortis Pandora/tests main % ps -p 1 -o lstart= Tue Jul 22 14:11:27 2025 Everything in the kernel extension appears to be loading after launchd (PID 1) starts. Also, the kext isn't doing anything crazy which could cause that kind of delay. For reference, here's the Info.plist: <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CFBundleExecutable</key> <string>Pandora</string> <key>CFBundleIdentifier</key> <string>com.bluefalconhd.Pandora</string> <key>CFBundleName</key> <string>Pandora</string> <key>CFBundlePackageType</key> <string>KEXT</string> <key>CFBundleVersion</key> <string>1.0.7</string> <key>IOKitPersonalities</key> <dict> <key>Pandora</key> <dict> <key>CFBundleIdentifier</key> <string>com.bluefalconhd.Pandora</string> <key>IOClass</key> <string>Pandora</string> <key>IOMatchCategory</key> <string>Pandora</string> <key>IOProviderClass</key> <string>IOResources</string> <key>IOResourceMatch</key> <string>IOKit</string> <key>IOUserClientClass</key> <string>PandoraUserClient</string> </dict> </dict> <key>OSBundleLibraries</key> <dict> <key>com.apple.kpi.dsep</key> <string>24.2.0</string> <key>com.apple.kpi.iokit</key> <string>24.2.0</string> <key>com.apple.kpi.libkern</key> <string>24.2.0</string> <key>com.apple.kpi.mach</key> <string>24.2.0</string> </dict> </dict> </plist> My questions are: A. Why don't the early logs (from KMOD's start function and IOService::start) consistently appear in the unified log, while logs later in IOExternalMethods do? B. How can I force this kext to load earlier-- ideally before launchd? Thanks in advance for any guidance!
0
0
663
Jul ’25
FSKit caching by kernel and performance
I've faced with some performance issues developing my readonly filesystem using fskit. For below screenshot: enumerateDirectory returns two hardcoded items, compiled with release config 3000 readdirsync are done from nodejs. macos 15.5 (24F74) I see that getdirentries syscall takes avg 121us. Because all other variables are minimised, it seems like it's fskit<->kernel overhead. This itself seems like a big number. I need to compare it with fuse though to be sure. But what fuse has and fskit seams don't (I checked every page in fskit docs) is kernel caching. Fuse supports: caching lookups (entry_timeout) negative lookups (entry_timeout) attributes (attr_timeout) readdir (via opendir cache_readdir and keep_cache) read and write ops but thats another topic. And afaik it works for both readonly and read-write file systems, because kernel can assume (if client is providing this) that cache is valid until kernel do write operations on corresponding inodes (create, setattr, write, etc). Questions are: is 100+us reasonable overhead for fskit? is there any way to do caching by kernel. If not currently, any plans to implement? Also, additional performance optimisation could be done by providing lower level api when we can operate with raw inodes (Uint64), this will eliminate overhead from storing, removing and retrieving FSItems in hashmap.
2
1
418
Jul ’25
OpenDirectory module causes bootloop (kernel panic) on restart
With macOS 15, and DSPlugin support removal we searched for an alternative method to be able to inject users/groups into the system dynamically. We tried to write an OpenDirectory XPC based module based on the documentation and XCode template which can be found here: https://developer.apple.com/library/archive/releasenotes/NetworkingInternetWeb/RN_OpenDirectory/chapters/chapter-1.xhtml.html It is more or less working, until I restart the computer: then macOS kernel panics 90% of the time. When the panic occurs, our code does not seem to get run at all, I only see my logs in the beginning of main() when the machine successfully starts. I have verified this also by logging to file. Also tried replacing the binary with eg a shell script, or a "return 0" empty main function, that also triggers the panic. But, if I remove my executable (from /Library/OpenDirectory/Modules/com.quest.vas.xpc/Contents/MacOS/com.quest.vas), that saves the day always, macOS boots just fine. Do you have an idea what can cause this behavior? I can share the boot logs for the boot loops and/or panic file. Do you have any other way (other than OpenDirectory module) to inject users/groups into the system dynamically nowadays? (MDM does not seem a viable option for us)
3
0
1.1k
Jul ’25
How to programmatically determine fixed CPU frequency for memory latency benchmarking on Apple Silicon?
Hi everyone, I am developing a benchmarking tool to measure memory latency (L1/L2/DRAM) on Apple Silicon. I am currently using Xcode Instruments (CPU Counters) to validate my results. In my latest run for a 128 MB buffer with random access, Instruments shows: Latency (cycles): ~259 cycles (derived from LDST_UNIT_OLD_L1D_CACHE_MISS / L1D_CACHE_MISS_LD). Manual Timer Result: ~80 ns. To correlate these two values, I need the exact CPU Frequency (GHz) at the time of the sample. My Questions: Is there a recommended way to programmatically fetch the current frequency of the Performance cores (p-cores) during a benchmark run? Does Apple provide a "nominal" frequency value for M-series chips that we should use for cycle-to-nanosecond conversions? In Instruments, is there a hidden counter or "Average Frequency" metric that I can enable to avoid manual math? Hardware/Software Environment: Tool: Instruments 26.3+ (CPU Counters Template). Chip: A19, iPhone 17 pro. OS: 26.3.
Replies
0
Boosts
0
Views
1.7k
Activity
Mar ’26
crhold()/crfree()
When I have to pull in hundreds of commits from upstream, I like to try to make sure things still compile - frequently, to try to limit how far I need to go to back fix things. One issue is missing symbols in the kext, since you won't know until you try to load the kext. And loading the kext each commit is not realistic. So I went and made up a call to something that does not exist, in my case, strqcmp(). I could not get the various tools like kmutil libraries --all-symbols to print out that this function was going to fail, so I wrote a little script (thanks ChatGPT); ./scripts/kpi_check.py --arch arm64e -k module/os/macos/zfs.kext/ First missing symbols: _crfree _crhold _strqcmp Hurrah. But sadly, my brain was then curious as to why crhold() and crfree() work. Worked for years. Only dtrace calls them in XNU sources but otherwise not mentioned there, not listed in my frameworks, nm is not seeing it. Somewhat of a rabbit hole. I don't even need to know, it does work after all. I should just let it go right? and yet... how does it work? My best guess is a symbols.alias pointing it to kauth_cred_ref() somewhere? Maybe? Anyway, pretty low priority but it's an itch...
Replies
0
Boosts
0
Views
139
Activity
Jan ’26
Incorrect packet handling in SMBClient MacOS 26.
SMBClient-593 introduces a crtitical bug. When reading and writing data at high volume, the SMBClient no longer properly receives and handle responses from the server. In some cases, the client mishandles the response packet and the following errors are seen in the logs: 2025-12-02 21:36:04.774772-0700 localhost kernel[0]: (smbfs) smb2_smb_parse_write_one: Bad struct size: 0 2025-12-02 21:36:04.774776-0700 localhost kernel[0]: (smbfs) smb2_smb_write: smb2_smb_read_write_async failed with an error 72 2025-12-02 21:36:04.774777-0700 localhost kernel[0]: (smbfs) smbfs_do_strategy: file.txt: WRITE failed with an error of 72 In other cases, the client mishandles the response packet and becomes completely unresponsive, unable to send or receive additional messages, and a forced shutdown of the computer is required to recover. This bug is only present on macos 26. We believe the operative change is in the latest commit, SMBClient-593 beginning at line now 3011 in smb_iod.c. The issue seems to be a race, and occurs much more frequently once throughput exceeds around 10Gbps, and again more frequently above 20Gbps.
Replies
6
Boosts
7
Views
744
Activity
Jan ’26
Show / Hide HAL Virtual Audio Device Based on App State
I am developing a macOS virtual audio device using an Audio Server Plug-In (HAL). I want the virtual device to be visible to all applications only when my main app is running, and completely hidden from all apps when the app is closed. The goal is to dynamically control device visibility based on app state without reinstalling the driver.What is the recommended way for the app to notify the HAL plug-in about its running or closed state ? Any guidance on best-practice architecture for this scenario would be appreciated.
Replies
1
Boosts
0
Views
837
Activity
Jan ’26
How to connect to a IOUSBHostInterface
I have poked around the web looking for a good example to do this and I haven't found a working example. I need to connect to a USB Device, its multiple ports and supports what looks to be a root port and 4 other ports I am no expert in USB but I do know how to write a kext and client drivers, but thats really not the way to solve this. I need to display the serialized output from these USB ports for a development board. I would rather do this on my Mac than have to cobble up a Linux machine and mess around with Linux. Here is the output from ioreg MCHP-Debug@03100000 <class IOUSBHostDevice, id 0x105f6fdc2, registered, matched, active, busy 0 (20 ms), retain 27> MCHP-Debug@0 <class IOUSBHostInterface, id 0x105f6fdc8, registered, matched, active, busy 0 (13 ms), retain 5> +-o MCHP-Debug@0 <class IOUSBHostInterface, id 0x105f6fdc8, registered, matched, active, busy 0 (13 ms), retain 5> +-o MCHP-Debug@1 <class IOUSBHostInterface, id 0x105f6fdc9, registered, matched, active, busy 0 (11 ms), retain 5> +-o MCHP-Debug@2 <class IOUSBHostInterface, id 0x105f6fdcb, registered, matched, active, busy 0 (9 ms), retain 5> | | | | | +-o MCHP-Debug@3 <class IOUSBHostInterface, id 0x105f6fdcc, registered, matched, active, busy 0 (7 ms), retain 5> I have been able to open a inservice to the device at the top level, but I get an error when I use. usbHostInterface = [[IOUSBHostInterface alloc] initWithIOService:usbDevice options: IOUSBHostObjectInitOptionsNone queue: queue error: &error interestHandler: handler]; Error:Failed to create IOUSBHostInterface. with reason: Unable to obtain configuration descriptor. Assertion failed: (usbHostInterface), function main, file main.m, line 87. I started using DeviceKit but I received signing errors and I shouldn't have to go down that path just to dump data from a USB port? Any suggestions would be great, most of the Apple documentation on USB ports is like 20 years old and the new stuff pushes you towards DeviceKit.
Replies
1
Boosts
0
Views
1.6k
Activity
Dec ’25
KDK for current stable version (26.1) missing
The current stable macOS version, 26.1 (build 25B78) is missing a corresponding Kernel Debug Kit (KDK) on the developer downloads page. This means I can't do any kernel-level development tasks currently. For example, if I try to build a new kernel collection with kmutil I get the message Missing Developer Kit: As of macOS 13.0, you will need to install a KDK matching your build 25B78 to rebuild kernel collections. but there is no build 25B78 KDK available to download. The latest 26.1 KDK on the download page is 25B5062e (from a beta I believe) and the final stable KDK for build 25B78 (which kernel development tools require) was never published. Is there any workaround for this to correctly do kernel-level development targeting the latest stable release, or a timeline for when the KDK will release? Thanks!
Replies
0
Boosts
3
Views
787
Activity
Nov ’25
No KDKs available for macOS 26.0 Developer Beta 2 and later
As of now, there is no Kernel Debug Kit (KDK) available for macOS 26.0 Developer Betas after the first build. Kernel Debug Kits are crucial for understanding panics and other bugs within custom Kernel Extensions. Without the KDK for the corresponding macOS version, tools like kmutil fail to recognize a KDK and certain functions are disabled. Additionally, as far as I am aware, a KDK for one build of macOS isn't able to be used on a differing build. Especially since this is a developer beta, where developers are updating their software to function with the latest versions of macOS, I'd expect a KDK to be available for more than one build.
Replies
7
Boosts
0
Views
1.6k
Activity
Nov ’25
Blocking USB Devices on macOS – DriverKit or Other Recommended Approach
Hi Apple, We are working on a general USB device management solution on macOS for enterprise security. Our goal is to enforce policy-based restrictions on USB devices, such as: For USB storage devices: block mount, read, or write access. For other peripherals (e.g., USB headsets or microphones, raspberry pi, etc): block usage entirely. We know in past, kernel extension would be the way to go, but as kext has been deprecated. And DriverKit is the new advertised framework. At first, DriverKit looked like the right direction. However, after reviewing the documentation more closely, we noticed that using DriverKit for USB requires specific entitlements: DriverKit USB Transport – VendorID DriverKit USB Transport – VendorID and ProductID This raises a challenge: if our solution is meant to cover all types of USB devices, we would theoretically need entitlements for every VendorID/ProductID in existence. My questions are: Is DriverKit actually the right framework for this kind of general-purpose USB device control? If not, what framework or mechanism should we be looking at for enforcing these kinds of policies? We also developed an Endpoint Security product, but so far we haven’t found a relevant Endpoint Security event type that would allow us to achieve this. Any guidance on the correct technical approach would be much appreciated. Thanks in advance for your help.
Replies
6
Boosts
0
Views
1.4k
Activity
Sep ’25
macOS 26 kernel open source?
Hi! I was wondering if there will be new XNU version for macOS 26 published open source? As far as I remember, previous version's source code was published the moment the OS was officially released, but not this time. If yes, when we can expect it to be published?
Replies
1
Boosts
0
Views
471
Activity
Sep ’25
macos 15.6.1 - BSD sendto() fails for IPv4-mapped IPv6 addresses
There appears to be some unexplained change in behaviour in the recent version of macos 15.6.1 which is causing the BSD socket sendto() syscall to no longer send the data when the source socket is bound to a IPv4-mapped IPv6 address. I have attached a trivial native code which reproduces the issue. What this reproducer does is explained as a comment on that code's main() function: // Creates a AF_INET6 datagram socket, marks it as dual socket (i.e. IPV6_V6ONLY = 0), // then binds the socket to a IPv4-mapped IPv6 address (chosen on the host where this test runs). // // The test then uses sendto() to send some bytes. For the sake of this test, it uses the same IPv4-mapped // IPv6 address as the destination address to sendto(). The test then waits for (a maximum of) 15 seconds to // receive that sent message by calling recvfrom(). // // The test passes on macos (x64 and aarch64) hosts of versions 12.x, 13.x, 14.x and 15.x upto 15.5. // Only on macos 15.6.1 and the recent macos 26, the test fails. Specifically, the first message that is // sent using sendto() is never sent (and thus the recvfrom()) times out. sendto() however returns 0, // incorrectly indicating a successful send. Interesting, if you repeat sendto() a second message from the // same bound socket to the exact same destination address, the send message is indeed correctly sent and // received immediately by the recvfrom(). It's only the first message which goes missing (the test uses // unique content in each message to be sure which exact message was received and it has been observed that // only the second message is received and the first one lost). // // Logs collected using "sudo log collect --last 2m" (after the test program returns) shows the following log // message, which seem relevant: // ... // default kernel cfil_hash_entry_log:6088 <CFIL: Error: sosend_reinject() failed>: // [86868 a.out] <UDP(17) out so 59faaa5dbbcef55d 127846646561221313 127846646561221313 age 0> // lport 65051 fport 65051 laddr 192.168.1.2 faddr 192.168.1.2 hash 201AAC1 // default kernel cfil_service_inject_queue:4472 CFIL: sosend() failed 22 // ... // As noted, this test passes without issues on various macosx version (12 through 15.5), both x64 and aarch64 but always fails against 15.6.1. I have been told that it also fails on the recently released macos 26 but I don't have access to such host to verify it myself. The release notes don't usually contain this level of detail, so it's hard to tell if something changed intentionally or if this is a bug. Should I report this through the feedback assistant? Attached is the source of the reproducer, run it as: clang dgramsend.c ./a.out On macos 15.6.1, you will see that it will fail to send (and thus receive) the message on first attempt but the second one passes: ... created and bound a datagram dual socket to ::ffff:192.168.1.2:65055 ::ffff:192.168.1.2:65055 sendto() ::ffff:192.168.1.2:65055 ---- Attempt 1 ---- sending greeting "hello 1" sendto() succeeded, sent 8 bytes calling recvfrom() receive timed out --------------------- ---- Attempt 2 ---- sending greeting "hello 2" sendto() succeeded, sent 8 bytes calling recvfrom() received 8 bytes: "hello 2" --------------------- TEST FAILED ... The output "log collect --last 2m" contains a related error (and this log message consistently shows up every time you run that reproducer): ... default kernel cfil_hash_entry_log:6088 <CFIL: Error: sosend_reinject() failed>: [86248 a.out] <UDP(17) out so 59faaa5dbbcef55d 127846646561221313 127846646561221313 age 0> lport 65055 fport 65055 laddr 192.168.1.2 faddr 192.168.1.2 hash 201AAC1 default kernel cfil_service_inject_queue:4472 CFIL: sosend() failed 22 ... I don't know what it means though. dgramsend.c
Replies
2
Boosts
0
Views
485
Activity
Sep ’25
Network framework crashes on fork
Hello, I have a Cocoa application from which I fork a new process (helper sort of) and it crashes on fork due to some cleanup code probably registered with pthreads_atfork() in Network framework. This is crash from the child process: Application Specific Information: *** multi-threaded process forked *** BUG IN CLIENT OF LIBPLATFORM: os_unfair_lock is corrupt Abort Cause 258 crashed on child side of fork pre-exec Thread 0 Crashed:: Dispatch queue: com.apple.main-thread 0 libsystem_platform.dylib 0x194551238 _os_unfair_lock_corruption_abort + 88 1 libsystem_platform.dylib 0x19454c788 _os_unfair_lock_lock_slow + 332 2 Network 0x19b1b4af0 nw_path_shared_necp_fd + 124 3 Network 0x19b1b4698 -[NWConcrete_nw_path_evaluator dealloc] + 72 4 Network 0x19af9d970 __nw_dictionary_dispose_block_invoke + 32 5 libxpc.dylib 0x194260210 _xpc_dictionary_apply_apply + 68 6 libxpc.dylib 0x19425c9a0 _xpc_dictionary_apply_node_f + 156 7 libxpc.dylib 0x1942600e8 xpc_dictionary_apply + 136 8 Network 0x19acd5210 -[OS_nw_dictionary dealloc] + 112 9 Network 0x19b1beb08 nw_path_release_globals + 120 10 Network 0x19b3d4fa0 nw_settings_child_has_forked() + 312 11 libsystem_pthread.dylib 0x100c8f7c8 _pthread_atfork_child_handlers + 76 12 libsystem_c.dylib 0x1943d9944 fork + 112 (...) I'm trying to create a child process with boost::process::child which does basically just a fork() followed by execv() and I do it before the - [NSApplication run] is called. Is it know bug or behavior which I've run into? Also what is a correct way to spawn child processes in Cocoa applications? As far as my understanding goes the basically all the available APIs (e.g. posix, NSTask) should be more or less the same thing calling the same syscalls. So forking the process early before main run loop starts and not starting another NSApplication in forked child should be ok ...or not?
Replies
4
Boosts
0
Views
3k
Activity
Sep ’25
VNOP_MONITOR+vnode_notify() operation details
After perusing the sources of Apple's SMB and NFS clients' implementation of VNOP_MONITOR, my understanding of how VNOP_MONITOR+vnode_notify() operate is as follows: A user-space process advertises an interest in monitoring a file or directory via kqueue(2)/kevent(2). VFS calls the filesystem's implementation of VNOP_MONITOR. VNOP_MONITOR forwards the commencing or terminating of monitoring events request to the filesystem server. Network filesystem client nodes call vnode_notify() to notify the underlying VFS of a filesystem event, e.g. file/directory creation/removal, etc. What I'm still vague about is how does the server communicate back to client nodes that an event of interest has occurred? I'd appreciate being enlightened on the operation of `VNOP_MONITOR+vnode_notify()' in a network filesystem setting.
Replies
1
Boosts
0
Views
218
Activity
Aug ’25
Support for Multi-Homed IPv6 Networks, esp. RFC 8028
Hi everyone, I’m running a dual-homed IPv6-mostly LAN where two on-link routers advertise distinct global Provider-Assigned prefixes (one per ISP). On Linux, the host stack appears to follow RFC 8028. It keeps one default route per prefix, and packets appear to leave through a router that recognises their source address and pass ISP BCP 38 (https://datatracker.ietf.org/doc/bcp38/) checks. On macOS Sequoia, I'm only seeing a single un-scoped default route. As a result, traffic sourced from prefix B often exits via router A and is dropped upstream. Questions: Is the single-default-per-interface model in macOS an intentional design choice or simply legacy behaviour that has not yet been updated to RFC 8028? Does the kernel perform any hidden next-hop selection that isn’t reflected in netstat -rn output? Are there any road-map items for fully adopting RFC 8028 in macOS? As a bonus, I'd be very interested in any info you might be able to provide on the status of implementation/support for https://datatracker.ietf.org/doc/html/rfc8978 (Reaction of IPv6 Stateless Address Autoconfiguration (SLAAC) to Flash-Renumbering Events).
Replies
2
Boosts
0
Views
500
Activity
Jul ’25
Hardlinks reported as non-existing on macOS Sequoia for 3rd party FS
After creating a hardlink on a distributed filesystem of my own via: % ln f.txt hlf.txt Neither the original file, f.txt, nor the hardlink, hlf.txt, are immediately accessible, e.g. via cat(1) with ENOENT returned. A short time later though, both the original file and the hardlink are accessible. Both files can be stat(1)ed though, which confirms that vnop_getattr returns success for both files. Dtruss(1) indicates it's the open(2) syscall that fails: % sudo dtruss -f cat hlf.txt 2038/0x4f68: open("hlf.txt\0", 0x0, 0x0) = -1 Err#2 ;ENOENT 2038/0x4f68: write_nocancel(0x2, "cat: \0", 0x5) = 5 0 2038/0x4f68: write_nocancel(0x2, "hlf.txt\0", 0x7) = 7 0 2038/0x4f68: write_nocancel(0x2, ": \0", 0x2) = 2 0 2038/0x4f68: write_nocancel(0x2, "No such file or directory\n\0", 0x1A) = 26 0 Dtrace(1)ing my KEXT no longer works on macOS Sequoia, so based on the diagnostics print statements I inserted into my KEXT, the following sequence of calls is observed: vnop_lookup(hlf.txt) -&gt; EJUSTRETURN ;ln(1) vnop_link(hlf.txt) -&gt; KERN_SUCCESS ;ln(1) vnop_lookup(hlf.txt) -&gt; KERN_SUCCESS ;cat(1) vnop_open(/) ; I expected to see vnop_open(hlf.txt) here instead of the parent directory. Internally, hardlinks are created in vnop_link via a call to vnode_setmultipath with cache_purge_negatives called on the destination directory. On macOS Monterey for example, where the same code does result in hardlinks being accessible, the following calls are made: vnop_lookup(hlf.txt) -&gt; EJUSTRETURN ;ln(1) vnop_link(hlf.txt) -&gt; KERN_SUCCESS ;ln(1) vnop_lookup(hlf.txt) -&gt; KERN_SUCCESS ;cat(1) vnop_open(hlf.txt) -&gt; KERN_SUCCESS ;cat(1) Not sure how else to debug this. Perusing the kernel sources for uses of VISHARDLINK, VNOP_LINK and vnode_setmultipath call sites did not clear things up for me. Any pointers would be greatly appreciated.
Replies
3
Boosts
0
Views
380
Activity
Jul ’25
Kext loads well after launchd and early os_log entries rarely appear in unified log
Is there a way to ensure a kernel extension in the Auxiliary Kernel Collection loads (and runs its start routines) before launchd? I'm emitting logs via os_log_t created with an os_log_create (custom subsystem/category) in both my KMOD's start function and the IOService::start() function. Those messages-- which both say "I've been run"-- inconsistently show up in log show --predicate 'subsystem == "com.bluefalconhd.pandora"' --last boot, which makes me think they are running very early. However, I also record timestamps (using mach_absolute_time, etc.) and expose them to user space through an IOExternalMethod. The results (for the most recent boot): hayes@fortis Pandora/tests main % build/pdtest Pandora Metadata: kmod_start_time: Time: 2025-07-22 14:11:32.233 Mach time: 245612546 Nanos since boot: 10233856083 (10.23 seconds) io_service_start_time: Time: 2025-07-22 14:11:32.233 Mach time: 245613641 Nanos since boot: 10233901708 (10.23 seconds) user_client_init_time: Time: 2025-07-22 14:21:42.561 Mach time: 14893478355 Nanos since boot: 620561598125 (620.56 seconds) hayes@fortis Pandora/tests main % ps -p 1 -o lstart= Tue Jul 22 14:11:27 2025 Everything in the kernel extension appears to be loading after launchd (PID 1) starts. Also, the kext isn't doing anything crazy which could cause that kind of delay. For reference, here's the Info.plist: <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CFBundleExecutable</key> <string>Pandora</string> <key>CFBundleIdentifier</key> <string>com.bluefalconhd.Pandora</string> <key>CFBundleName</key> <string>Pandora</string> <key>CFBundlePackageType</key> <string>KEXT</string> <key>CFBundleVersion</key> <string>1.0.7</string> <key>IOKitPersonalities</key> <dict> <key>Pandora</key> <dict> <key>CFBundleIdentifier</key> <string>com.bluefalconhd.Pandora</string> <key>IOClass</key> <string>Pandora</string> <key>IOMatchCategory</key> <string>Pandora</string> <key>IOProviderClass</key> <string>IOResources</string> <key>IOResourceMatch</key> <string>IOKit</string> <key>IOUserClientClass</key> <string>PandoraUserClient</string> </dict> </dict> <key>OSBundleLibraries</key> <dict> <key>com.apple.kpi.dsep</key> <string>24.2.0</string> <key>com.apple.kpi.iokit</key> <string>24.2.0</string> <key>com.apple.kpi.libkern</key> <string>24.2.0</string> <key>com.apple.kpi.mach</key> <string>24.2.0</string> </dict> </dict> </plist> My questions are: A. Why don't the early logs (from KMOD's start function and IOService::start) consistently appear in the unified log, while logs later in IOExternalMethods do? B. How can I force this kext to load earlier-- ideally before launchd? Thanks in advance for any guidance!
Replies
0
Boosts
0
Views
663
Activity
Jul ’25
FSKit caching by kernel and performance
I've faced with some performance issues developing my readonly filesystem using fskit. For below screenshot: enumerateDirectory returns two hardcoded items, compiled with release config 3000 readdirsync are done from nodejs. macos 15.5 (24F74) I see that getdirentries syscall takes avg 121us. Because all other variables are minimised, it seems like it's fskit<->kernel overhead. This itself seems like a big number. I need to compare it with fuse though to be sure. But what fuse has and fskit seams don't (I checked every page in fskit docs) is kernel caching. Fuse supports: caching lookups (entry_timeout) negative lookups (entry_timeout) attributes (attr_timeout) readdir (via opendir cache_readdir and keep_cache) read and write ops but thats another topic. And afaik it works for both readonly and read-write file systems, because kernel can assume (if client is providing this) that cache is valid until kernel do write operations on corresponding inodes (create, setattr, write, etc). Questions are: is 100+us reasonable overhead for fskit? is there any way to do caching by kernel. If not currently, any plans to implement? Also, additional performance optimisation could be done by providing lower level api when we can operate with raw inodes (Uint64), this will eliminate overhead from storing, removing and retrieving FSItems in hashmap.
Replies
2
Boosts
1
Views
418
Activity
Jul ’25
OpenDirectory module causes bootloop (kernel panic) on restart
With macOS 15, and DSPlugin support removal we searched for an alternative method to be able to inject users/groups into the system dynamically. We tried to write an OpenDirectory XPC based module based on the documentation and XCode template which can be found here: https://developer.apple.com/library/archive/releasenotes/NetworkingInternetWeb/RN_OpenDirectory/chapters/chapter-1.xhtml.html It is more or less working, until I restart the computer: then macOS kernel panics 90% of the time. When the panic occurs, our code does not seem to get run at all, I only see my logs in the beginning of main() when the machine successfully starts. I have verified this also by logging to file. Also tried replacing the binary with eg a shell script, or a "return 0" empty main function, that also triggers the panic. But, if I remove my executable (from /Library/OpenDirectory/Modules/com.quest.vas.xpc/Contents/MacOS/com.quest.vas), that saves the day always, macOS boots just fine. Do you have an idea what can cause this behavior? I can share the boot logs for the boot loops and/or panic file. Do you have any other way (other than OpenDirectory module) to inject users/groups into the system dynamically nowadays? (MDM does not seem a viable option for us)
Replies
3
Boosts
0
Views
1.1k
Activity
Jul ’25