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

Posts under Kernel tag

200 Posts

Post

Replies

Boosts

Views

Activity

Kernel panic in mac_label_verify()
Accessing a directory on my custom distributed filesystem results in a kernel panic. According to the backtrace, the last function called before the panic is triggered is mac_label_verify(). See the backtrace file attached. mac_label_verify-panic.txt The panic manifests itself given the following conditions: Machine-a: make a directory in Finder. Machine-b: remove the directory created on machine-a in Finder. Machine-a: access the directory removed on machine-b in Finder. Kernel panic ensues. The panic is reproducible on both Apple Silicon and x86-64. The backtrace is for x86-64 as I wasn't able to symbolicate it on Apple Silicon. Not sure how to tackle this one. Any pointers would be much appreciated.
15
0
1.5k
Mar ’25
Any recent changes to dlopen() implementation?
In some recent releases of macos (14.x and 15.x), we have noticed what seems to be a slower dlopen() implementation. I don't have any numbers to support this theory. I happened to notice this "slowness" when investigating something unrelated. In one part of the code we have a call of the form: const char * fooBarLib = ....; dlopen(fooBarLib, RTLD_NOW + RTLD_GLOBAL); It so happened that due to some timing related issues, the process was crashing. A slow execution of code in this part of the code would trigger an issue in some other part of the code that would then lead to a process crash. The crash itself isn't a concern, because it's an internal issue that will addressed in the application code. What was interesting is that the slowness appears to be contributed by the call to dlopen(). Specifically, whenever a slowness was observed, the crash reports showed stack frames of the form: Thread 1: 0 dyld 0x18f08b5b4 _kernelrpc_mach_vm_protect_trap + 8 1 dyld 0x18f08f540 vm_protect + 52 2 dyld 0x18f0b87e0 lsl::MemoryManager::writeProtect(bool) + 204 3 dyld 0x18f0a7fe4 invocation function for block in dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const + 932 4 dyld 0x18f0e629c invocation function for block in dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const + 172 5 dyld 0x18f0d9c38 invocation function for block in dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const + 496 6 dyld 0x18f08c2dc dyld3::MachOFile::forEachLoadCommand(Diagnostics&, void (load_command const*, bool&) block_pointer) const + 300 7 dyld 0x18f0d8bcc dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const + 192 8 dyld 0x18f0db5a0 dyld3::MachOFile::forEachInitializerPointerSection(Diagnostics&, void (unsigned int, unsigned int, bool&) block_pointer) const + 160 9 dyld 0x18f0e5f90 dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const + 432 10 dyld 0x18f0a7bb4 dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const + 176 11 dyld 0x18f0af190 dyld4::JustInTimeLoader::runInitializers(dyld4::RuntimeState&) const + 36 12 dyld 0x18f0a8270 dyld4::Loader::runInitializersBottomUp(dyld4::RuntimeState&, dyld3::Array<dyld4::Loader const*>&, dyld3::Array<dyld4::Loader const*>&) const + 312 13 dyld 0x18f0ac560 dyld4::Loader::runInitializersBottomUpPlusUpwardLinks(dyld4::RuntimeState&) const::$_0::operator()() const + 180 14 dyld 0x18f0a8460 dyld4::Loader::runInitializersBottomUpPlusUpwardLinks(dyld4::RuntimeState&) const + 412 15 dyld 0x18f0c089c dyld4::APIs::dlopen_from(char const*, int, void*) + 2432 16 libjli.dylib 0x1025515b4 DoFooBar + 56 17 libjli.dylib 0x10254d2c0 Hello_World_Launch + 1160 18 helloworld 0x10250bbb4 main + 404 19 libjli.dylib 0x102552148 apple_main + 88 20 libsystem_pthread.dylib 0x18f4132e4 _pthread_start + 136 21 libsystem_pthread.dylib 0x18f40e0fc thread_start + 8 So, out of curiosity, have there been any known changes in the implementation of dlopen() which might explain the slowness? Like I noted, I don't have concrete numbers, but to quantify the slowness I don't think it's slower by a noticeable amount - maybe a few milli seconds. I guess what I am trying to understand is, whether there's anything that needs attention here.
3
0
765
Mar ’25
Kernel panic related to Watchdog in custom virtual file system
Hi. I am facing a panic in distributed virtual filesystem of my own making. The panic arises on attempt of copying a large folder, or writing a large file (both around 20gb). An important note here is that the amount of files we try to copy is larger than available space (for testing purposes, the virtual file system had a capacity of 18 gigabytes). The panic arises somewhere on 12-14gigabytes deep into copying. On the moment of panic, there are still several gigabytes of storage left. The problem is present for sure for such architectures and macOS versions: Sonoma 14.7.1 arm64e Monterey 12.7.5 arm64e Ventura 13.7.1 intel Part from panic log from Ventura 13.7.1 intel, with symbolicated addresses: panic(cpu 2 caller 0xffffff80191a191a): watchdog timeout: no checkins from watchdogd in 90 seconds (48 total checkins since monitoring last enabled) Panicked task 0xffffff907c99f698: 191 threads: pid 0: kernel_task Backtrace (CPU 2), panicked thread: 0xffffff86e359cb30, Frame : Return Address 0xffffffff001d7bb0 : 0xffffff8015e70c7d mach_kernel : _handle_debugger_trap + 0x4ad 0xffffffff001d7c00 : 0xffffff8015fc52e4 mach_kernel : _kdp_i386_trap + 0x114 0xffffffff001d7c40 : 0xffffff8015fb4df7 mach_kernel : _kernel_trap + 0x3b7 0xffffffff001d7c90 : 0xffffff8015e11971 mach_kernel : _return_from_trap + 0xc1 0xffffffff001d7cb0 : 0xffffff8015e70f5d mach_kernel : _DebuggerTrapWithState + 0x5d 0xffffffff001d7da0 : 0xffffff8015e70607 mach_kernel : _panic_trap_to_debugger + 0x1a7 0xffffffff001d7e00 : 0xffffff80165db9a3 mach_kernel : _panic_with_options + 0x89 0xffffffff001d7ef0 : 0xffffff80191a191a com.apple.driver.watchdog : IOWatchdog::userspacePanic(OSObject*, void*, IOExternalMethodArguments*) (.cold.1) 0xffffffff001d7f20 : 0xffffff80191a10a1 com.apple.driver.watchdog : IOWatchdog::checkWatchdog() + 0xd7 0xffffffff001d7f50 : 0xffffff80174f960b com.apple.driver.AppleSMC : SMCWatchDogTimer::watchdogThread() + 0xbb 0xffffffff001d7fa0 : 0xffffff8015e1119e mach_kernel : _call_continuation + 0x2e Kernel Extensions in backtrace: com.apple.driver.watchdog(1.0)[BD08CE2D-77F5-358C-8F0D-A570540A0BE7]@0xffffff801919f000->0xffffff80191a1fff com.apple.driver.AppleSMC(3.1.9)[DD55DA6A-679A-3797-947C-0B50B7B5B659]@0xffffff80174e7000->0xffffff8017503fff dependency: com.apple.driver.watchdog(1)[BD08CE2D-77F5-358C-8F0D-A570540A0BE7]@0xffffff801919f000->0xffffff80191a1fff dependency: com.apple.iokit.IOACPIFamily(1.4)[D342E754-A422-3F44-BFFB-DEE93F6723BC]@0xffffff8018446000->0xffffff8018447fff dependency: com.apple.iokit.IOPCIFamily(2.9)[481BF782-1F4B-3F54-A34A-CF12A822C40D]@0xffffff80188b6000->0xffffff80188e7fff Process name corresponding to current thread (0xffffff86e359cb30): kernel_task Boot args: keepsyms=1 Mac OS version: 22H221 Kernel version: Darwin Kernel Version 22.6.0: Thu Sep 5 20:48:48 PDT 2024; root:xnu-8796.141.3.708.1~1/RELEASE_X86_64 The origin of the problem is surely inside my filesystem. However, the panic happens not there but somewhere in watchdog. As far as I can tell, the source code for watchdog is not available for public. I can't understand what causes the panic. Let's say we have run out of space. Couldn't write data. Writing received a proper error message and aborted. That's what is expected. However, it is unclear for why the panic arises.
4
0
715
Feb ’25
Subdirectory navigation fails for several GUI apps on custom VFS.
Hi. I am developing a custom virtual file system and facing such behaviour: Upon using some graphical apps, for example Adobe Media Encoder, attempting to navigate inside my filesystem deeper than root folder will fail - nothing will happen on "double click" on that subfolder. Another problem, is that whether I try to re-navigate into root directory, it will be empty. The problem is not present for most GUI apps - for example navigation inside Finder, upon choosing download path for file in Safari, apps like Microsoft Word, Excel and other range of applications work totally correctly. A quick note here. From what I have seen - all apps that work correctly actually have calls to VFS_VGET - a predefined vfs layer hook. Whether the Adobe Media Encoder does not call for it - neither in my filesystem, nor in Samba, so my guess is that some applications have different browsing and retrieving algorithm. Is there anything I should examine further ? Default routines (vnop_open, vnop_lookup, vnop_readdir, vnop_close) behave as expected, without any errors. P.S. This application (Adobe Media Encoder) works properly on Samba.
3
0
456
Feb ’25
Missing Developer Kit for build 22H417
I cannot find this specific KDK for my build 22H417. I need help locating and downloading this Developer Kit. Error Domain=KMErrorDomain Code=34 "Missing Developer Kit: As of macOS 13.0, you will need to install a KDK matching your build 22H417 to rebuild kernel collections." UserInfo={NSLocalizedDescription=Missing Developer Kit: As of macOS 13.0, you will need to install a KDK matching your build 22H417 to rebuild kernel collections.} I
0
0
374
Feb ’25
Debugging Broken Pipes
SIGPIPE is an ongoing source of grief on Apple systems [1]. I’ve talked about it numerous times here on the forums. It cropped up again today, so I decided to collect my experiences into one post. If you have questions or comments, please put them in a new thread. Put it in the App & System Services > Core OS topic area so that I see it. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" [1] Well, on Unix-y systems in general, but my focus is Apple systems (-: Debugging Broken Pipes On Unix-y systems, writing to a pipe whose read side is closed will raise a SIGPIPE signal. The default disposition of that signal is to terminate your process [1]. Broken pipe terminations are tricky to debug on Apple systems because the termination doesn’t generate a crash report. For example, consider this code: let (read, write) = try FileDescriptor.pipe() // This write works. try write.writeAll("Hello Cruel World!".utf8) let msg = try read.read(maxCount: 256) … do something with `msg` … // But if you close the read side… try read.close() // … the write call raises a `SIGPIPE`. try write.writeAll("Goodbye Cruel World!".utf8) Note This code relies on some extensions to FileDescriptor type that make it easier to call the pipe and write system calls. For more information about how I set that up, see Calling BSD Sockets from Swift. If you put this in an iOS app and run it outside of Xcode, the app will terminate without generating a crash report. This logic also applies to BSD Sockets. Writing to a disconnected socket may also trigger a SIGPIPE. This applies to the write system call and all the send variants: send, sendto, and sendmsg). IMPORTANT Broken pipe terminations are even more troubling with sockets because sockets are commonly used for networking, where you have no control over the remote peer. It’s easy to reproduce this signal with Unix domain sockets: let (read, write) = try FileDescriptor.socketPair(AF_UNIX, SOCK_STREAM, 0) // This write works. try write.writeAll("Hello Cruel World!".utf8) let msg = try read.read(maxCount: 256) … do something with `msg` … // But if you close the read side… try read.close() // … the write call raises a `SIGPIPE`. try write.writeAll("Goodbye Cruel World!".utf8) However, this isn’t limited to just Unix domain sockets; TCP sockets are a common source of broken pipe terminations. [1] At first blush this API design might seem bananas, but it kinda makes sense in the context of traditional Unix command-line tools. Confirm the Problem The primary symptom of a broken pipe problem is that your app terminates without generating a crash report. Unfortunately, that’s not definitive. There are other circumstances where your app can terminate without generating a crash report. For example, another common cause of such terminations is the app calling exit. There all two ways you can confirm this problem. The first relies on Xcode. Run your app in the Xcode debugger and, if it suddenly stops with the message Terminated due to signal 13, you know you’ve been terminated because of a broken pipe. IMPORTANT Double check that the signal number is 13, the value of SIGPIPE. If you can’t reproduce the problem in Xcode, look in the system log. When an app terminates the system records information about the reason. The exact log message varies from platform to platform, and from OS version to OS version. However, in the case of a SIGPIPE termination there’s usually a log entry containing PIPE or SIGPIPE, or that references signal 13. For example, on iOS 18.2.1, I see this log entry: type: default time: 11:59:00.321882+0000 process: SpringBoard subsystem: com.apple.runningboard category: process message: Firing exit handlers for 16876 with context <RBSProcessExitContext| specific, status:<RBSProcessExitStatus| domain:signal(2) code:SIGPIPE(13)>> The log message contains both SIGPIPE and the SIGPIPE signal number, 13. For more information about accessing the system log, see Your Friend the System Log. Locate the Problem Once you’ve confirmed that you have a broken pipe problem, you need to locate the source of it. That is, what code within your process is writing to a broken pipe? If you can reproduce the problem in Xcode, configure LLDB to stop on SIGPIPE signals: (lldb) process handle -s true SIGPIPE NAME PASS STOP NOTIFY =========== ===== ===== ====== SIGPIPE true true false When the process writes to a broken pipe, Xcode stops in the debugger. Look at the backtrace in the Debug navigator to find the offending write. If you can’t reproduce the problem in Xcode, one option is to add a signal handler that catches the SIGPIPE and triggers a crash. For example: #include <signal.h> static void sigpipeHandler(int sigNum) { __builtin_trap(); } extern void installSIGPIPEHandler(void) { signal(SIGPIPE, sigpipeHandler); } Here the signal handler, sigpipeHandler, forces a crash by calling the __builtin_trap function. IMPORTANT This code is in C, and uses __builtin_trap rather than abort, because of the very restricted environment in which the signal handler runs [1]. With this signal handler in place, writing to a broken pipe generates a crash report. Within that crash report, the crashing thread backtrace gives you a hint as to the location of the offending write. For example: 0 SIG-PIPETest … sigpipeHandler + 8 1 libsystem_platform.dylib … _sigtramp + 56 2 libswiftSystem.dylib … closure #1 in FileDescriptor._writeAll<A>(_:) + 100 3 libswiftSystem.dylib … partial apply for closure #1 in FileDescriptor._writeAll<A>(_:) + 20 4 libswiftSystem.dylib … partial apply for closure #1 in Sequence._withRawBufferPointer<A>(_:) + 108 5 libswiftCore.dylib … String.UTF8View.withContiguousStorageIfAvailable<A>(_:) + 108 6 libswiftCore.dylib … protocol witness for Sequence.withContiguousStorageIfAvailable<A>(_:) in conform… 7 libswiftCore.dylib … dispatch thunk of Sequence.withContiguousStorageIfAvailable<A>(_:) + 32 8 libswiftSystem.dylib … Sequence._withRawBufferPointer<A>(_:) + 472 9 libswiftSystem.dylib … FileDescriptor._writeAll<A>(_:) + 104 10 SIG-PIPETest … FileDescriptor.writeAll<A>(_:) + 28 … Note The write system call is not shown in the backtrace. That’s because the crash reporter is not backtracing correctly across the signal handler stack frame that was inserted by the kernel between frames 1 and 2 [1]. Fortunately that doesn’t matter here, because we primarily care about our code, which is visible in frame 10. I can’t see any problem with putting this code in your development build, or even deploying it to your beta testers. Think carefully before putting it in a production build that you deploy to all your users. Signal handlers are tricky [1]. [1] For all the gory details on that topic, see Implementing Your Own Crash Reporter for more information about that issue. [2] This is one of the gory details covered by Implementing Your Own Crash Reporter. Resolve the Problem The best way to resolve this problem depends on whether it’s being caused by a pipe or a socket. The socket case is easy: Use the SO_NOSIGPIPE socket option to disable SIGPIPE on the socket. Once you do that, writing to the socket when it’s disconnected will return an EPIPE error rather than raising the SIGPIPE signal. For example, you might tweak the code above like so: let (read, write) = try FileDescriptor.socketPair(AF_UNIX, SOCK_STREAM, 0) try read.setSocketOption(SOL_SOCKET, SO_NOSIGPIPE, 1 as CInt) try write.setSocketOption(SOL_SOCKET, SO_NOSIGPIPE, 1 as CInt) Note Again, this is using helpers from Calling BSD Sockets from Swift. The situation with pipes is tricky. Apple systems have no way to disable SIGPIPE on a pipe, leaving you with two less-than-ideal options: Disable SIGPIPE globally. To do this, call signal with SIG_IGN: signal(SIGPIPE, SIG_IGN) The downside to this approach is that affects the entire process. You can’t, for example, use this technique in library code. Switch to Unix domain sockets. Rather than use a pipe for your IPC, use Unix domain sockets instead. As they’re both file descriptors, it’s usually quite straightforward to make this change. The downside here is obvious: You need to modify your IPC code. That might be problematic, for example, if this IPC code is embedded in a framework that you don’t build from source.
0
0
867
Jan ’25
AppleDouble, aka dotbar, files not removed via Finder
I've having trouble deleting AppleDouble files residing on my custom filesystem through Finder. This also affects files that use the AppleDouble naming convention, i.e. their names start with '._', but aren't AppleDoubles themselves. dtrace output In vnop_readdir, 'struct dent/dentry' is set up for dotbar files and written to the uio_t buffer. It's just that my vnop_remove is never called for dotbar files, and I don't understand why not. Dotbar files are removed successfully, when deleted through command line. For SMBClients, vnop_readdir is followed by vnop_access, followed by vnop_lookup, followed by vnop_remove of dotbar files. SMBClient rm dotbar files dtrace output Implementing vnop_access for my filesystem did not result in the combination of vnop_lookup and vnop_remove being called for dotbar files. Perusing the kernel sources, I observed the following functions that might be involved, but I have not way of verifying this, as none of the functions of interest are dtrace(1)-able, rmdir_remove_orphaned_appleDouble() in particular. rmdir_remove_orphaned_appleDouble() -> VNOP_READDIR(). rmdirat_internal() -> rmdir_remove_orphaned_appleDouble() unlinkat()-> rmdirat_internal() rmdir()-> rmdirat_internal() Any pointers on how dotbar files may be removed through Finder would be greatly appreciated.
1
0
720
Jan ’25
kernel_sysctlbyname("kern.hostname") returns EPERM
Attempting to acquire the value of the 'kern.hostname' ctl from a kext by calling sysctlbyname() returns EPERM with no hostname returned. sysctlbyname() is aliased to kernel_sysctlbyname(): config/Libkern.exports:839:_sysctlbyname:_kernel_sysctlbyname Looking at the implementation of kernel_sysctlbyname(), EPERM is returned by sysctl_root(). Not sure how to correctly identify the point of failure. Alternately, calling sysctlbyname("hw.ncpu") does return the value set for the ctl. The kext was compiled with SYSCTL_DEF_ENABLED defined to have the relevant section of sys/sysctl.h enabled. bsd_hostname() is a private symbol which is inaccessible to my kext. % sysctl -n kern.hostname does return the host name, so the ctl must be set. Is it possible to get the name of a host from the context of my kext? Thanks.
1
0
693
Jan ’25
The curious case of the "IOKit Driver" Xcode target.
Firstly, I realise that Kexts are deprecated. And for my needs, user-space IOKit from an application might be more than I’ll ever need, but I can’t help ensuring I’ve got all my ducks in a row while I’m designing an app. I noticed in the above Kext deprecation notice that it’s more about specific APIs that are deprecated rather than the kext mechanism itself (no mention of IOKit kernel APIs there). Along with the fact that a reboot would be required and various other policy changes. While reading up on System Extensions and the various newer tools, DriverKit, Endpoint Security etc, I’ve noticed there’s no mention of this “IOKit Driver” target/deliverable in the Xcode template chooser. It looks like, from the requirements, that DriverKit is aimed at hardware manufacturers, with a need to request the DriverKit entitlement for development. With respect to Apple’s internal Kext deprecation roadmap, how safe is it to build a product that relies on using an IOKit Driver and are there any requirements similar to DriverKit? Would a developer need to request an entitlement? If I developed an app using user-space IOKit and, for illustration purposes let’s say I also included an IOKit Driver in the app bundle. If I used the IOKit API, including header file constants only (no digging around in the IORegistryExplorer for non-public keys), as Apple intends them to be used, would this fall foul of any App Store rules that anyone is aware of? Put another way, would making use of an IOKit Driver disqualify my app from being distributed via the App Store, similar to an Endpoint Security extension? As an aside, there are a lot of API in the ES Framework that could be used to build apps that have nothing to do with Endpoint Security. File system related apps for example. It’s a shame there isn’t an enhanced middle ground between FSEvents and Endpoint Security framework.
3
0
1.2k
Dec ’24
Subsequent expansion of same archive fails due to name collision
Extracting an archive into the same directory on my custom filesystem more than once fails with the following message: Unable to finish expanding 'misc.tar.xz' into 'extractme'. Could not move 'misc' into destination directory. I.e. initial extraction succeeds with archive contents extracted into extractme/misc. Subsequent extraction fails to rename extractme.sb-db71cd27-lFjN1f/misc to extractme/misc 2. This behaviour is observed on macOS Monterey and Ventura. It does work as expected on macOS Sonoma though. Dtrace(1)-ing the archive being extracted over smbfs results in the following sequence of calls being made: 2 -> smbfs_vnop_lookup AUHelperService-2163 -> extractme/misc 2 nameiop:0 2 <- smbfs_vnop_lookup AUHelperService-2163 -> extractme/misc 2 -> 2 ;ENOENT 2 -> smbfs_vnop_lookup AUHelperService-2163 -> extractme.sb-db71cd27-lFjN1f/misc nameiop:0x2 ;DELETE 2 <- smbfs_vnop_lookup AUHelperService-2163 -> extractme.sb-db71cd27-lFjN1f/misc -> 0 2 -> smbfs_vnop_lookup AUHelperService-2163 -> extractme/misc 2 nameiop:0x3 ;RENAME 2 <- smbfs_vnop_lookup AUHelperService-2163 -> extractme/misc 2 -> EJUSTRETURN 1 -> smbfs_vnop_rename AUHelperService-2163 -> extractme.sb-db71cd27-lFjN1f/misc -> extractme/nil 2 <- smbfs_vnop_rename AUHelperService-2163 -> extractme.sb-db71cd27-lFjN1f/misc -> extractme/nil -> 0 2 -> smbfs_vnop_lookup AUHelperService-2163 -> TheRooT/extractme/misc 2 nameiop:0 3 <- smbfs_vnop_lookup AUHelperService-2163 -> TheRooT/extractme/misc 2 -> 0 ;Successful lookup What I don't understand is what causes vnop_lookup to be called for misc to be removed from the temporary directory and renamed into 'misc 2' and placed in the destination directory, 'extractme' via vnop_rename? I had a look at smbfs_vnop_lookup and rename and didn't see anything that would cause 'misc 2' to come into being. Based on the output of the dtrace(1) script running on my custom filesystem, there are no vnop_lookup and vnop_rename calls being made to remove the 'misc' directory from the temporary directory and to rename it to 'misc 2' and place it in the destination directory at extractme. Archive extraction proceeds no further after extracting the archive contents into the temporary directory. What am I missing?
1
0
730
Oct ’24
How to enable PCIDriverKit Bus Leader? (and Memory Space enable?)
I am porting a working kernel extension IOKit driver to a DriverKit system extension. Our device is a PCI device accessed through Thunderbolt. The change from IOPCIFamily to PCIDriverKit has some differences in approach, though. Namely, in IOKit / IOPCIFamily, this was the correct way to become Bus Leader: mPCIDevice->setBusLeadEnable(true); // setBusMasterEnable(..) deprecated in OS 12.4 but now, PCIDriverKit's IOPCIDevice does not have that function. Instead I am doing the following: // Set Bus Leader and Memory Space enable uint16_t commandRegister = 0; ivars->mPCIDevice->ConfigurationRead16(kIOPCIConfigurationOffsetCommand, &commandRegister); commandRegister |= (kIOPCICommandBusLead | kIOPCICommandMemorySpace); ivars->mPCIDevice->ConfigurationWrite16(kIOPCIConfigurationOffsetCommand, commandRegister); But I am not convinced this is working (I am still experiencing unexpected errors when attempting to DMA from our device, using the same steps that work for the kernel extension). The only hint I can find in the online documentation is here, which reads: Note The endpoint driver is responsible for enabling the Memory Space Enable and Bus Master Enable settings each time it configures the PCI device. When a crash occurs, or when the system unloads your driver, the system disables these features. ...but that does not state directly how to enable bus leader status. What is the "PCIDriverKit approved" way to become bus leader? Is there a way to verify/confirm that a device is bus leader? (This would be helpful to prove that bus leadership is not the issue for DMA errors, as well as to confirm that bus leadership was granted). Thanks in advance!
1
0
1.1k
Oct ’24
Reasonable time for fix to easy-to-reproduce kernel panic?
Since I haven't heard so much as a peep from Apple on this, I thought I'd take a poll here on how long I could expect an easily reproducible (albeit possibly obscure) kernel panic to be fixed. I was under the impression that kernel panics were a big deal but it's been almost 2 months since I updated from macOS 14 to macOS 15.0 dev beta 7 / public beta 5 when I originally came across and reported a panic triggered while playing StarCraft II. I've been able to consistently trigger panics playing certain (maybe all) Co-op maps in SC2 and since my first report Aug 22, I've filed 8 additional bug reports, each automatically generated after hitting yet another panic. (I'm not sure exactly who is able to view these but for what it's worth, these are the reports I've filed so far: FB14886510, FB14905773, FB14960435, FB15304609, FB15391195, FB15467943, FB15468127, FB15491485, FB15491684.) A few other people have reported the issue to SC2's developer, Blizzard, and apparently Blizzard has acknowledged they're aware of the problem so it's safe to rule out the possibility of a hardware defect or other issue specific only to my computer. The logs point the blame at the AppleDCP driver, although I suppose the problem could technically be in the DCP firmware instead. Regardless, Apple's code is clearly at fault here. I'll admit the importance of a video game isn't exactly like keeping the power on at a hospital but I don't know why it would be deemed particularly unimportant either. At 53 days in, am I wrong to expect this to have been fixed by now or is Apple really being that slow?
1
1
789
Oct ’24
Kernel Development Kit Missing
Hello, It seems like the Kernel Debug Kit for macOS 15.0.1 (24A348) is missing from the list of downloads at developer.apple.com. It would be great if you could add them to the list of available downloads. When trying to rebuild the kernel it fails with the following error message: Error Domain=KMErrorDomain Code=34 "Missing Developer Kit: As of macOS 13.0, you will need to install a KDK matching your build 24A348 to rebuild kernel collections." UserInfo={NSLocalizedDescription=Missing Developer Kit: As of macOS 13.0, you will need to install a KDK matching your build 24A348 to rebuild kernel collections.} But my macOS version is 15.0.1. Is there a workaround for this?
1
0
1.1k
Oct ’24
What are the locking rules for VFS and VNOP operations?
I'm observing all sorts of race conditions occurring in various VNOPs my custom filesystem implements. I'm inclined to attribute this to my implementation not following the locking rules expected by the system of a 3rd party filesystem as well as it should. I've looked at how locking is done in Apple's own implementation of Samba and NFS clients. The Samba client uses read/write locks to protect its node from data races. While the NFS client uses mutex locks for the same purpose. I realised that I don't have a clear model in my head of how locking should be done properly. Thus my question, what are the locking rules for VFS and VNOP operations? Thanks.
4
0
981
Oct ’24
vnop_lookup returning ENOENT aborts rm(1)
When recursively removing a directory with a large number of entries that resides on my custom filesystem, rm(1) aborts with ENOENT. % rm -Rv /Volumes/myfs/linux-kernel/linux-6.10.6 [...] /Volumes/myfs/linux-kernel/linux-6.10.6/include/drm/bridge/aux-bridge.h /Volumes/myfs/linux-kernel/linux-6.10.6/include/drm/bridge/dw_hdmi.h rm: fts_read: No such file or directory I'm observing the following sequence of calls being made. 2024-09-17 17:58:25 vnops.c:281 myfs_vnop_lookup: rm-936 -> dw_hdmi.h ;initial lookup call 2024-09-17 17:58:25 vnops.c:315 myfs_vnop_lookup: -> cache_lookup(dw_hdmi.h) 2024-09-17 17:58:25 vnops.c:317 myfs_vnop_lookup: <- cache_lookup(dw_hdmi.h) -> 0 ;cache miss 2024-09-17 17:58:25 rpc.c:431 myfsLookup: rm-936 -> dw_hdmi.h ;do remote lookup 2024-09-17 17:58:25 rpc.c:500 myfsLookup: -> myfs_lookup_rpc(dw_hdmi.h) 2024-09-17 17:58:25 rpc.c:502 myfsLookup: <- myfs_lookup_rpc(dw_hdmi.h) -> 0 ;file found and added to vfs cache 2024-09-17 17:58:25 vnops.c:281 myfs_vnop_lookup: rm-936 -> dw_hdmi.h ;subsequent lookup call 2024-09-17 17:58:25 vnops.c:315 myfs_vnop_lookup: -> cache_lookup(dw_hdmi.h) 2024-09-17 17:58:25 vnops.c:317 myfs_vnop_lookup: <- cache_lookup(dw_hdmi.h) -> -1 ;cache hit 2024-09-17 17:58:25 vnops.c:1478 myfs_vnop_remove: -> myfs_unlink(dw_hdmi.h) ;unlink sequence 2024-09-17 17:58:25 rpc.c:1992 myfs_unlink: -> myfs_unlink_rpc(dw_hdmi.h) 2024-09-17 17:58:25 rpc.c:1994 myfs_unlink: <- myfs_unlink_rpc(dw_hdmi.h) -> 0 ;remote unlink succeeded 2024-09-17 17:58:25 vnops.c:1480 myfs_vnop_remove: <- myfs_unlink(dw_hdmi.h) -> 0 2024-09-17 17:58:25 vnops.c:1487 myfs_vnop_remove: -> cache_purge(dw_hdmi.h) 2024-09-17 17:58:25 vnops.c:1489 myfs_vnop_remove: <- cache_purge(dw_hdmi.h) 2024-09-17 17:58:25 vnops.c:1499 myfs_vnop_remove: -> vnode_recycle(dw_hdmi.h) 2024-09-17 17:58:25 vnops.c:1501 myfs_vnop_remove: <- vnode_recycle(dw_hdmi.h) 2024-09-17 17:58:27 vnops.c:281 myfs_vnop_lookup: fseventsd-101 -> dw_hdmi.h ;another lookup; why? 2024-09-17 17:58:27 vnops.c:315 myfs_vnop_lookup: -> cache_lookup(dw_hdmi.h) 2024-09-17 17:58:27 vnops.c:317 myfs_vnop_lookup: <- cache_lookup(dw_hdmi.h) -> 0 2024-09-17 17:58:27 rpc.c:431 myfsLookup: fseventsd-101 -> dw_hdmi.h 2024-09-17 17:58:27 rpc.c:500 myfsLookup: -> myfs_lookup_rpc(dw_hdmi.h) 2024-09-17 17:58:27 rpc.c:502 myfsLookup: <- myfs_lookup_rpc(dw_hdmi.h) -> ENOENT(2) 2024-09-17 17:58:27 vnops.c:371 myfs_vnop_lookup: SET(NNEGNCENTRIES): dw_hdmi.h 2024-09-17 17:58:27 vnops.c:373 myfs_vnop_lookup: ENOENT(2) <- shouldAddToNegativeNameCache(dw_hdmi.h) I checked the value of vnode's v_iocount when vnop_remove and vnop_reclaim are being called. Each vnop_remove and followed by vnop_reclaim with v_iocount set to 1 in both calls, as expected. What I don't understand is why after removing the file is there another lookup call being made, which returns ENOENT to rm(1), which causes it to abort. Any pointers on what could be amiss there would be much appreciated.
3
0
792
Sep ’24
How do I limit C program memory allocation to 1 virtual page on macOS Sonoma?
Hello I was wondering if there is a way to ensure that a C program I am writing can only write to 1 virtual page. I am trying to test how space efficient different Mallocs are and I need a way to ensure that the OS will not try to swap out pages making the space efficiency test pointless. I am on Mac OS Sonoma v14.5.
Replies
7
Boosts
0
Views
795
Activity
Mar ’25
Kernel panic in mac_label_verify()
Accessing a directory on my custom distributed filesystem results in a kernel panic. According to the backtrace, the last function called before the panic is triggered is mac_label_verify(). See the backtrace file attached. mac_label_verify-panic.txt The panic manifests itself given the following conditions: Machine-a: make a directory in Finder. Machine-b: remove the directory created on machine-a in Finder. Machine-a: access the directory removed on machine-b in Finder. Kernel panic ensues. The panic is reproducible on both Apple Silicon and x86-64. The backtrace is for x86-64 as I wasn't able to symbolicate it on Apple Silicon. Not sure how to tackle this one. Any pointers would be much appreciated.
Replies
15
Boosts
0
Views
1.5k
Activity
Mar ’25
Any recent changes to dlopen() implementation?
In some recent releases of macos (14.x and 15.x), we have noticed what seems to be a slower dlopen() implementation. I don't have any numbers to support this theory. I happened to notice this "slowness" when investigating something unrelated. In one part of the code we have a call of the form: const char * fooBarLib = ....; dlopen(fooBarLib, RTLD_NOW + RTLD_GLOBAL); It so happened that due to some timing related issues, the process was crashing. A slow execution of code in this part of the code would trigger an issue in some other part of the code that would then lead to a process crash. The crash itself isn't a concern, because it's an internal issue that will addressed in the application code. What was interesting is that the slowness appears to be contributed by the call to dlopen(). Specifically, whenever a slowness was observed, the crash reports showed stack frames of the form: Thread 1: 0 dyld 0x18f08b5b4 _kernelrpc_mach_vm_protect_trap + 8 1 dyld 0x18f08f540 vm_protect + 52 2 dyld 0x18f0b87e0 lsl::MemoryManager::writeProtect(bool) + 204 3 dyld 0x18f0a7fe4 invocation function for block in dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const + 932 4 dyld 0x18f0e629c invocation function for block in dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const + 172 5 dyld 0x18f0d9c38 invocation function for block in dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const + 496 6 dyld 0x18f08c2dc dyld3::MachOFile::forEachLoadCommand(Diagnostics&, void (load_command const*, bool&) block_pointer) const + 300 7 dyld 0x18f0d8bcc dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const + 192 8 dyld 0x18f0db5a0 dyld3::MachOFile::forEachInitializerPointerSection(Diagnostics&, void (unsigned int, unsigned int, bool&) block_pointer) const + 160 9 dyld 0x18f0e5f90 dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const + 432 10 dyld 0x18f0a7bb4 dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const + 176 11 dyld 0x18f0af190 dyld4::JustInTimeLoader::runInitializers(dyld4::RuntimeState&) const + 36 12 dyld 0x18f0a8270 dyld4::Loader::runInitializersBottomUp(dyld4::RuntimeState&, dyld3::Array<dyld4::Loader const*>&, dyld3::Array<dyld4::Loader const*>&) const + 312 13 dyld 0x18f0ac560 dyld4::Loader::runInitializersBottomUpPlusUpwardLinks(dyld4::RuntimeState&) const::$_0::operator()() const + 180 14 dyld 0x18f0a8460 dyld4::Loader::runInitializersBottomUpPlusUpwardLinks(dyld4::RuntimeState&) const + 412 15 dyld 0x18f0c089c dyld4::APIs::dlopen_from(char const*, int, void*) + 2432 16 libjli.dylib 0x1025515b4 DoFooBar + 56 17 libjli.dylib 0x10254d2c0 Hello_World_Launch + 1160 18 helloworld 0x10250bbb4 main + 404 19 libjli.dylib 0x102552148 apple_main + 88 20 libsystem_pthread.dylib 0x18f4132e4 _pthread_start + 136 21 libsystem_pthread.dylib 0x18f40e0fc thread_start + 8 So, out of curiosity, have there been any known changes in the implementation of dlopen() which might explain the slowness? Like I noted, I don't have concrete numbers, but to quantify the slowness I don't think it's slower by a noticeable amount - maybe a few milli seconds. I guess what I am trying to understand is, whether there's anything that needs attention here.
Replies
3
Boosts
0
Views
765
Activity
Mar ’25
lsof how to get the process;s fd info?
https://github.com/apple-oss-distributions/lsof/blob/c48c28f51e82a5d682a4459bdbdc42face73468f/lsof/dialects/darwin/libproc/dproc.c#L753 proc_pidinfo(pid, PROC_PIDLISTFILEPORTS, 0, NULL, 0)) the retval of proc_pidinfo is always zero how lsof works?
Replies
1
Boosts
0
Views
361
Activity
Feb ’25
Kernel panic related to Watchdog in custom virtual file system
Hi. I am facing a panic in distributed virtual filesystem of my own making. The panic arises on attempt of copying a large folder, or writing a large file (both around 20gb). An important note here is that the amount of files we try to copy is larger than available space (for testing purposes, the virtual file system had a capacity of 18 gigabytes). The panic arises somewhere on 12-14gigabytes deep into copying. On the moment of panic, there are still several gigabytes of storage left. The problem is present for sure for such architectures and macOS versions: Sonoma 14.7.1 arm64e Monterey 12.7.5 arm64e Ventura 13.7.1 intel Part from panic log from Ventura 13.7.1 intel, with symbolicated addresses: panic(cpu 2 caller 0xffffff80191a191a): watchdog timeout: no checkins from watchdogd in 90 seconds (48 total checkins since monitoring last enabled) Panicked task 0xffffff907c99f698: 191 threads: pid 0: kernel_task Backtrace (CPU 2), panicked thread: 0xffffff86e359cb30, Frame : Return Address 0xffffffff001d7bb0 : 0xffffff8015e70c7d mach_kernel : _handle_debugger_trap + 0x4ad 0xffffffff001d7c00 : 0xffffff8015fc52e4 mach_kernel : _kdp_i386_trap + 0x114 0xffffffff001d7c40 : 0xffffff8015fb4df7 mach_kernel : _kernel_trap + 0x3b7 0xffffffff001d7c90 : 0xffffff8015e11971 mach_kernel : _return_from_trap + 0xc1 0xffffffff001d7cb0 : 0xffffff8015e70f5d mach_kernel : _DebuggerTrapWithState + 0x5d 0xffffffff001d7da0 : 0xffffff8015e70607 mach_kernel : _panic_trap_to_debugger + 0x1a7 0xffffffff001d7e00 : 0xffffff80165db9a3 mach_kernel : _panic_with_options + 0x89 0xffffffff001d7ef0 : 0xffffff80191a191a com.apple.driver.watchdog : IOWatchdog::userspacePanic(OSObject*, void*, IOExternalMethodArguments*) (.cold.1) 0xffffffff001d7f20 : 0xffffff80191a10a1 com.apple.driver.watchdog : IOWatchdog::checkWatchdog() + 0xd7 0xffffffff001d7f50 : 0xffffff80174f960b com.apple.driver.AppleSMC : SMCWatchDogTimer::watchdogThread() + 0xbb 0xffffffff001d7fa0 : 0xffffff8015e1119e mach_kernel : _call_continuation + 0x2e Kernel Extensions in backtrace: com.apple.driver.watchdog(1.0)[BD08CE2D-77F5-358C-8F0D-A570540A0BE7]@0xffffff801919f000->0xffffff80191a1fff com.apple.driver.AppleSMC(3.1.9)[DD55DA6A-679A-3797-947C-0B50B7B5B659]@0xffffff80174e7000->0xffffff8017503fff dependency: com.apple.driver.watchdog(1)[BD08CE2D-77F5-358C-8F0D-A570540A0BE7]@0xffffff801919f000->0xffffff80191a1fff dependency: com.apple.iokit.IOACPIFamily(1.4)[D342E754-A422-3F44-BFFB-DEE93F6723BC]@0xffffff8018446000->0xffffff8018447fff dependency: com.apple.iokit.IOPCIFamily(2.9)[481BF782-1F4B-3F54-A34A-CF12A822C40D]@0xffffff80188b6000->0xffffff80188e7fff Process name corresponding to current thread (0xffffff86e359cb30): kernel_task Boot args: keepsyms=1 Mac OS version: 22H221 Kernel version: Darwin Kernel Version 22.6.0: Thu Sep 5 20:48:48 PDT 2024; root:xnu-8796.141.3.708.1~1/RELEASE_X86_64 The origin of the problem is surely inside my filesystem. However, the panic happens not there but somewhere in watchdog. As far as I can tell, the source code for watchdog is not available for public. I can't understand what causes the panic. Let's say we have run out of space. Couldn't write data. Writing received a proper error message and aborted. That's what is expected. However, it is unclear for why the panic arises.
Replies
4
Boosts
0
Views
715
Activity
Feb ’25
Subdirectory navigation fails for several GUI apps on custom VFS.
Hi. I am developing a custom virtual file system and facing such behaviour: Upon using some graphical apps, for example Adobe Media Encoder, attempting to navigate inside my filesystem deeper than root folder will fail - nothing will happen on "double click" on that subfolder. Another problem, is that whether I try to re-navigate into root directory, it will be empty. The problem is not present for most GUI apps - for example navigation inside Finder, upon choosing download path for file in Safari, apps like Microsoft Word, Excel and other range of applications work totally correctly. A quick note here. From what I have seen - all apps that work correctly actually have calls to VFS_VGET - a predefined vfs layer hook. Whether the Adobe Media Encoder does not call for it - neither in my filesystem, nor in Samba, so my guess is that some applications have different browsing and retrieving algorithm. Is there anything I should examine further ? Default routines (vnop_open, vnop_lookup, vnop_readdir, vnop_close) behave as expected, without any errors. P.S. This application (Adobe Media Encoder) works properly on Samba.
Replies
3
Boosts
0
Views
456
Activity
Feb ’25
Missing Developer Kit for build 22H417
I cannot find this specific KDK for my build 22H417. I need help locating and downloading this Developer Kit. Error Domain=KMErrorDomain Code=34 "Missing Developer Kit: As of macOS 13.0, you will need to install a KDK matching your build 22H417 to rebuild kernel collections." UserInfo={NSLocalizedDescription=Missing Developer Kit: As of macOS 13.0, you will need to install a KDK matching your build 22H417 to rebuild kernel collections.} I
Replies
0
Boosts
0
Views
374
Activity
Feb ’25
Debugging Broken Pipes
SIGPIPE is an ongoing source of grief on Apple systems [1]. I’ve talked about it numerous times here on the forums. It cropped up again today, so I decided to collect my experiences into one post. If you have questions or comments, please put them in a new thread. Put it in the App & System Services > Core OS topic area so that I see it. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" [1] Well, on Unix-y systems in general, but my focus is Apple systems (-: Debugging Broken Pipes On Unix-y systems, writing to a pipe whose read side is closed will raise a SIGPIPE signal. The default disposition of that signal is to terminate your process [1]. Broken pipe terminations are tricky to debug on Apple systems because the termination doesn’t generate a crash report. For example, consider this code: let (read, write) = try FileDescriptor.pipe() // This write works. try write.writeAll("Hello Cruel World!".utf8) let msg = try read.read(maxCount: 256) … do something with `msg` … // But if you close the read side… try read.close() // … the write call raises a `SIGPIPE`. try write.writeAll("Goodbye Cruel World!".utf8) Note This code relies on some extensions to FileDescriptor type that make it easier to call the pipe and write system calls. For more information about how I set that up, see Calling BSD Sockets from Swift. If you put this in an iOS app and run it outside of Xcode, the app will terminate without generating a crash report. This logic also applies to BSD Sockets. Writing to a disconnected socket may also trigger a SIGPIPE. This applies to the write system call and all the send variants: send, sendto, and sendmsg). IMPORTANT Broken pipe terminations are even more troubling with sockets because sockets are commonly used for networking, where you have no control over the remote peer. It’s easy to reproduce this signal with Unix domain sockets: let (read, write) = try FileDescriptor.socketPair(AF_UNIX, SOCK_STREAM, 0) // This write works. try write.writeAll("Hello Cruel World!".utf8) let msg = try read.read(maxCount: 256) … do something with `msg` … // But if you close the read side… try read.close() // … the write call raises a `SIGPIPE`. try write.writeAll("Goodbye Cruel World!".utf8) However, this isn’t limited to just Unix domain sockets; TCP sockets are a common source of broken pipe terminations. [1] At first blush this API design might seem bananas, but it kinda makes sense in the context of traditional Unix command-line tools. Confirm the Problem The primary symptom of a broken pipe problem is that your app terminates without generating a crash report. Unfortunately, that’s not definitive. There are other circumstances where your app can terminate without generating a crash report. For example, another common cause of such terminations is the app calling exit. There all two ways you can confirm this problem. The first relies on Xcode. Run your app in the Xcode debugger and, if it suddenly stops with the message Terminated due to signal 13, you know you’ve been terminated because of a broken pipe. IMPORTANT Double check that the signal number is 13, the value of SIGPIPE. If you can’t reproduce the problem in Xcode, look in the system log. When an app terminates the system records information about the reason. The exact log message varies from platform to platform, and from OS version to OS version. However, in the case of a SIGPIPE termination there’s usually a log entry containing PIPE or SIGPIPE, or that references signal 13. For example, on iOS 18.2.1, I see this log entry: type: default time: 11:59:00.321882+0000 process: SpringBoard subsystem: com.apple.runningboard category: process message: Firing exit handlers for 16876 with context <RBSProcessExitContext| specific, status:<RBSProcessExitStatus| domain:signal(2) code:SIGPIPE(13)>> The log message contains both SIGPIPE and the SIGPIPE signal number, 13. For more information about accessing the system log, see Your Friend the System Log. Locate the Problem Once you’ve confirmed that you have a broken pipe problem, you need to locate the source of it. That is, what code within your process is writing to a broken pipe? If you can reproduce the problem in Xcode, configure LLDB to stop on SIGPIPE signals: (lldb) process handle -s true SIGPIPE NAME PASS STOP NOTIFY =========== ===== ===== ====== SIGPIPE true true false When the process writes to a broken pipe, Xcode stops in the debugger. Look at the backtrace in the Debug navigator to find the offending write. If you can’t reproduce the problem in Xcode, one option is to add a signal handler that catches the SIGPIPE and triggers a crash. For example: #include <signal.h> static void sigpipeHandler(int sigNum) { __builtin_trap(); } extern void installSIGPIPEHandler(void) { signal(SIGPIPE, sigpipeHandler); } Here the signal handler, sigpipeHandler, forces a crash by calling the __builtin_trap function. IMPORTANT This code is in C, and uses __builtin_trap rather than abort, because of the very restricted environment in which the signal handler runs [1]. With this signal handler in place, writing to a broken pipe generates a crash report. Within that crash report, the crashing thread backtrace gives you a hint as to the location of the offending write. For example: 0 SIG-PIPETest … sigpipeHandler + 8 1 libsystem_platform.dylib … _sigtramp + 56 2 libswiftSystem.dylib … closure #1 in FileDescriptor._writeAll<A>(_:) + 100 3 libswiftSystem.dylib … partial apply for closure #1 in FileDescriptor._writeAll<A>(_:) + 20 4 libswiftSystem.dylib … partial apply for closure #1 in Sequence._withRawBufferPointer<A>(_:) + 108 5 libswiftCore.dylib … String.UTF8View.withContiguousStorageIfAvailable<A>(_:) + 108 6 libswiftCore.dylib … protocol witness for Sequence.withContiguousStorageIfAvailable<A>(_:) in conform… 7 libswiftCore.dylib … dispatch thunk of Sequence.withContiguousStorageIfAvailable<A>(_:) + 32 8 libswiftSystem.dylib … Sequence._withRawBufferPointer<A>(_:) + 472 9 libswiftSystem.dylib … FileDescriptor._writeAll<A>(_:) + 104 10 SIG-PIPETest … FileDescriptor.writeAll<A>(_:) + 28 … Note The write system call is not shown in the backtrace. That’s because the crash reporter is not backtracing correctly across the signal handler stack frame that was inserted by the kernel between frames 1 and 2 [1]. Fortunately that doesn’t matter here, because we primarily care about our code, which is visible in frame 10. I can’t see any problem with putting this code in your development build, or even deploying it to your beta testers. Think carefully before putting it in a production build that you deploy to all your users. Signal handlers are tricky [1]. [1] For all the gory details on that topic, see Implementing Your Own Crash Reporter for more information about that issue. [2] This is one of the gory details covered by Implementing Your Own Crash Reporter. Resolve the Problem The best way to resolve this problem depends on whether it’s being caused by a pipe or a socket. The socket case is easy: Use the SO_NOSIGPIPE socket option to disable SIGPIPE on the socket. Once you do that, writing to the socket when it’s disconnected will return an EPIPE error rather than raising the SIGPIPE signal. For example, you might tweak the code above like so: let (read, write) = try FileDescriptor.socketPair(AF_UNIX, SOCK_STREAM, 0) try read.setSocketOption(SOL_SOCKET, SO_NOSIGPIPE, 1 as CInt) try write.setSocketOption(SOL_SOCKET, SO_NOSIGPIPE, 1 as CInt) Note Again, this is using helpers from Calling BSD Sockets from Swift. The situation with pipes is tricky. Apple systems have no way to disable SIGPIPE on a pipe, leaving you with two less-than-ideal options: Disable SIGPIPE globally. To do this, call signal with SIG_IGN: signal(SIGPIPE, SIG_IGN) The downside to this approach is that affects the entire process. You can’t, for example, use this technique in library code. Switch to Unix domain sockets. Rather than use a pipe for your IPC, use Unix domain sockets instead. As they’re both file descriptors, it’s usually quite straightforward to make this change. The downside here is obvious: You need to modify your IPC code. That might be problematic, for example, if this IPC code is embedded in a framework that you don’t build from source.
Replies
0
Boosts
0
Views
867
Activity
Jan ’25
AppleDouble, aka dotbar, files not removed via Finder
I've having trouble deleting AppleDouble files residing on my custom filesystem through Finder. This also affects files that use the AppleDouble naming convention, i.e. their names start with '._', but aren't AppleDoubles themselves. dtrace output In vnop_readdir, 'struct dent/dentry' is set up for dotbar files and written to the uio_t buffer. It's just that my vnop_remove is never called for dotbar files, and I don't understand why not. Dotbar files are removed successfully, when deleted through command line. For SMBClients, vnop_readdir is followed by vnop_access, followed by vnop_lookup, followed by vnop_remove of dotbar files. SMBClient rm dotbar files dtrace output Implementing vnop_access for my filesystem did not result in the combination of vnop_lookup and vnop_remove being called for dotbar files. Perusing the kernel sources, I observed the following functions that might be involved, but I have not way of verifying this, as none of the functions of interest are dtrace(1)-able, rmdir_remove_orphaned_appleDouble() in particular. rmdir_remove_orphaned_appleDouble() -> VNOP_READDIR(). rmdirat_internal() -> rmdir_remove_orphaned_appleDouble() unlinkat()-> rmdirat_internal() rmdir()-> rmdirat_internal() Any pointers on how dotbar files may be removed through Finder would be greatly appreciated.
Replies
1
Boosts
0
Views
720
Activity
Jan ’25
kernel_sysctlbyname("kern.hostname") returns EPERM
Attempting to acquire the value of the 'kern.hostname' ctl from a kext by calling sysctlbyname() returns EPERM with no hostname returned. sysctlbyname() is aliased to kernel_sysctlbyname(): config/Libkern.exports:839:_sysctlbyname:_kernel_sysctlbyname Looking at the implementation of kernel_sysctlbyname(), EPERM is returned by sysctl_root(). Not sure how to correctly identify the point of failure. Alternately, calling sysctlbyname("hw.ncpu") does return the value set for the ctl. The kext was compiled with SYSCTL_DEF_ENABLED defined to have the relevant section of sys/sysctl.h enabled. bsd_hostname() is a private symbol which is inaccessible to my kext. % sysctl -n kern.hostname does return the host name, so the ctl must be set. Is it possible to get the name of a host from the context of my kext? Thanks.
Replies
1
Boosts
0
Views
693
Activity
Jan ’25
The curious case of the "IOKit Driver" Xcode target.
Firstly, I realise that Kexts are deprecated. And for my needs, user-space IOKit from an application might be more than I’ll ever need, but I can’t help ensuring I’ve got all my ducks in a row while I’m designing an app. I noticed in the above Kext deprecation notice that it’s more about specific APIs that are deprecated rather than the kext mechanism itself (no mention of IOKit kernel APIs there). Along with the fact that a reboot would be required and various other policy changes. While reading up on System Extensions and the various newer tools, DriverKit, Endpoint Security etc, I’ve noticed there’s no mention of this “IOKit Driver” target/deliverable in the Xcode template chooser. It looks like, from the requirements, that DriverKit is aimed at hardware manufacturers, with a need to request the DriverKit entitlement for development. With respect to Apple’s internal Kext deprecation roadmap, how safe is it to build a product that relies on using an IOKit Driver and are there any requirements similar to DriverKit? Would a developer need to request an entitlement? If I developed an app using user-space IOKit and, for illustration purposes let’s say I also included an IOKit Driver in the app bundle. If I used the IOKit API, including header file constants only (no digging around in the IORegistryExplorer for non-public keys), as Apple intends them to be used, would this fall foul of any App Store rules that anyone is aware of? Put another way, would making use of an IOKit Driver disqualify my app from being distributed via the App Store, similar to an Endpoint Security extension? As an aside, there are a lot of API in the ES Framework that could be used to build apps that have nothing to do with Endpoint Security. File system related apps for example. It’s a shame there isn’t an enhanced middle ground between FSEvents and Endpoint Security framework.
Replies
3
Boosts
0
Views
1.2k
Activity
Dec ’24
Investigating kext memory leak with lldb and KDK
Is there a way I can use the lldb user defined commands, which I can load from a KDK, to determine how much memory my kext has consumed? Is there a way to figure out what size blocks they are? I have already run the showallclasses command and the output has assured me that I am not leaking any objects which are defined by my driver's classes. Thanks, Tim
Replies
1
Boosts
0
Views
722
Activity
Dec ’24
How to apply for permission to read process memory
I saw that the vmmap program uses task-read_for_pid, and I want to use the task-read_for_pid export function to read process memory and check for any issues, but I don't have permission. How can I apply for it
Replies
3
Boosts
0
Views
506
Activity
Dec ’24
Subsequent expansion of same archive fails due to name collision
Extracting an archive into the same directory on my custom filesystem more than once fails with the following message: Unable to finish expanding 'misc.tar.xz' into 'extractme'. Could not move 'misc' into destination directory. I.e. initial extraction succeeds with archive contents extracted into extractme/misc. Subsequent extraction fails to rename extractme.sb-db71cd27-lFjN1f/misc to extractme/misc 2. This behaviour is observed on macOS Monterey and Ventura. It does work as expected on macOS Sonoma though. Dtrace(1)-ing the archive being extracted over smbfs results in the following sequence of calls being made: 2 -> smbfs_vnop_lookup AUHelperService-2163 -> extractme/misc 2 nameiop:0 2 <- smbfs_vnop_lookup AUHelperService-2163 -> extractme/misc 2 -> 2 ;ENOENT 2 -> smbfs_vnop_lookup AUHelperService-2163 -> extractme.sb-db71cd27-lFjN1f/misc nameiop:0x2 ;DELETE 2 <- smbfs_vnop_lookup AUHelperService-2163 -> extractme.sb-db71cd27-lFjN1f/misc -> 0 2 -> smbfs_vnop_lookup AUHelperService-2163 -> extractme/misc 2 nameiop:0x3 ;RENAME 2 <- smbfs_vnop_lookup AUHelperService-2163 -> extractme/misc 2 -> EJUSTRETURN 1 -> smbfs_vnop_rename AUHelperService-2163 -> extractme.sb-db71cd27-lFjN1f/misc -> extractme/nil 2 <- smbfs_vnop_rename AUHelperService-2163 -> extractme.sb-db71cd27-lFjN1f/misc -> extractme/nil -> 0 2 -> smbfs_vnop_lookup AUHelperService-2163 -> TheRooT/extractme/misc 2 nameiop:0 3 <- smbfs_vnop_lookup AUHelperService-2163 -> TheRooT/extractme/misc 2 -> 0 ;Successful lookup What I don't understand is what causes vnop_lookup to be called for misc to be removed from the temporary directory and renamed into 'misc 2' and placed in the destination directory, 'extractme' via vnop_rename? I had a look at smbfs_vnop_lookup and rename and didn't see anything that would cause 'misc 2' to come into being. Based on the output of the dtrace(1) script running on my custom filesystem, there are no vnop_lookup and vnop_rename calls being made to remove the 'misc' directory from the temporary directory and to rename it to 'misc 2' and place it in the destination directory at extractme. Archive extraction proceeds no further after extracting the archive contents into the temporary directory. What am I missing?
Replies
1
Boosts
0
Views
730
Activity
Oct ’24
How to enable PCIDriverKit Bus Leader? (and Memory Space enable?)
I am porting a working kernel extension IOKit driver to a DriverKit system extension. Our device is a PCI device accessed through Thunderbolt. The change from IOPCIFamily to PCIDriverKit has some differences in approach, though. Namely, in IOKit / IOPCIFamily, this was the correct way to become Bus Leader: mPCIDevice->setBusLeadEnable(true); // setBusMasterEnable(..) deprecated in OS 12.4 but now, PCIDriverKit's IOPCIDevice does not have that function. Instead I am doing the following: // Set Bus Leader and Memory Space enable uint16_t commandRegister = 0; ivars->mPCIDevice->ConfigurationRead16(kIOPCIConfigurationOffsetCommand, &commandRegister); commandRegister |= (kIOPCICommandBusLead | kIOPCICommandMemorySpace); ivars->mPCIDevice->ConfigurationWrite16(kIOPCIConfigurationOffsetCommand, commandRegister); But I am not convinced this is working (I am still experiencing unexpected errors when attempting to DMA from our device, using the same steps that work for the kernel extension). The only hint I can find in the online documentation is here, which reads: Note The endpoint driver is responsible for enabling the Memory Space Enable and Bus Master Enable settings each time it configures the PCI device. When a crash occurs, or when the system unloads your driver, the system disables these features. ...but that does not state directly how to enable bus leader status. What is the "PCIDriverKit approved" way to become bus leader? Is there a way to verify/confirm that a device is bus leader? (This would be helpful to prove that bus leadership is not the issue for DMA errors, as well as to confirm that bus leadership was granted). Thanks in advance!
Replies
1
Boosts
0
Views
1.1k
Activity
Oct ’24
Reasonable time for fix to easy-to-reproduce kernel panic?
Since I haven't heard so much as a peep from Apple on this, I thought I'd take a poll here on how long I could expect an easily reproducible (albeit possibly obscure) kernel panic to be fixed. I was under the impression that kernel panics were a big deal but it's been almost 2 months since I updated from macOS 14 to macOS 15.0 dev beta 7 / public beta 5 when I originally came across and reported a panic triggered while playing StarCraft II. I've been able to consistently trigger panics playing certain (maybe all) Co-op maps in SC2 and since my first report Aug 22, I've filed 8 additional bug reports, each automatically generated after hitting yet another panic. (I'm not sure exactly who is able to view these but for what it's worth, these are the reports I've filed so far: FB14886510, FB14905773, FB14960435, FB15304609, FB15391195, FB15467943, FB15468127, FB15491485, FB15491684.) A few other people have reported the issue to SC2's developer, Blizzard, and apparently Blizzard has acknowledged they're aware of the problem so it's safe to rule out the possibility of a hardware defect or other issue specific only to my computer. The logs point the blame at the AppleDCP driver, although I suppose the problem could technically be in the DCP firmware instead. Regardless, Apple's code is clearly at fault here. I'll admit the importance of a video game isn't exactly like keeping the power on at a hospital but I don't know why it would be deemed particularly unimportant either. At 53 days in, am I wrong to expect this to have been fixed by now or is Apple really being that slow?
Replies
1
Boosts
1
Views
789
Activity
Oct ’24
Kernel Development Kit Missing
Hello, It seems like the Kernel Debug Kit for macOS 15.0.1 (24A348) is missing from the list of downloads at developer.apple.com. It would be great if you could add them to the list of available downloads. When trying to rebuild the kernel it fails with the following error message: Error Domain=KMErrorDomain Code=34 "Missing Developer Kit: As of macOS 13.0, you will need to install a KDK matching your build 24A348 to rebuild kernel collections." UserInfo={NSLocalizedDescription=Missing Developer Kit: As of macOS 13.0, you will need to install a KDK matching your build 24A348 to rebuild kernel collections.} But my macOS version is 15.0.1. Is there a workaround for this?
Replies
1
Boosts
0
Views
1.1k
Activity
Oct ’24
NVMe Admin commands(like security send/receive) using IONVMeFaimly driver
Is there an option to create a macOS filter driver for the IONVMeFamily Driver that would enable sending NVMe Admin commands( likes security send , security receive, Firmware download)? This approach would allow us to reuse the IO path provided by the family driver.
Replies
0
Boosts
1
Views
708
Activity
Oct ’24
What are the locking rules for VFS and VNOP operations?
I'm observing all sorts of race conditions occurring in various VNOPs my custom filesystem implements. I'm inclined to attribute this to my implementation not following the locking rules expected by the system of a 3rd party filesystem as well as it should. I've looked at how locking is done in Apple's own implementation of Samba and NFS clients. The Samba client uses read/write locks to protect its node from data races. While the NFS client uses mutex locks for the same purpose. I realised that I don't have a clear model in my head of how locking should be done properly. Thus my question, what are the locking rules for VFS and VNOP operations? Thanks.
Replies
4
Boosts
0
Views
981
Activity
Oct ’24
vnop_lookup returning ENOENT aborts rm(1)
When recursively removing a directory with a large number of entries that resides on my custom filesystem, rm(1) aborts with ENOENT. % rm -Rv /Volumes/myfs/linux-kernel/linux-6.10.6 [...] /Volumes/myfs/linux-kernel/linux-6.10.6/include/drm/bridge/aux-bridge.h /Volumes/myfs/linux-kernel/linux-6.10.6/include/drm/bridge/dw_hdmi.h rm: fts_read: No such file or directory I'm observing the following sequence of calls being made. 2024-09-17 17:58:25 vnops.c:281 myfs_vnop_lookup: rm-936 -> dw_hdmi.h ;initial lookup call 2024-09-17 17:58:25 vnops.c:315 myfs_vnop_lookup: -> cache_lookup(dw_hdmi.h) 2024-09-17 17:58:25 vnops.c:317 myfs_vnop_lookup: <- cache_lookup(dw_hdmi.h) -> 0 ;cache miss 2024-09-17 17:58:25 rpc.c:431 myfsLookup: rm-936 -> dw_hdmi.h ;do remote lookup 2024-09-17 17:58:25 rpc.c:500 myfsLookup: -> myfs_lookup_rpc(dw_hdmi.h) 2024-09-17 17:58:25 rpc.c:502 myfsLookup: <- myfs_lookup_rpc(dw_hdmi.h) -> 0 ;file found and added to vfs cache 2024-09-17 17:58:25 vnops.c:281 myfs_vnop_lookup: rm-936 -> dw_hdmi.h ;subsequent lookup call 2024-09-17 17:58:25 vnops.c:315 myfs_vnop_lookup: -> cache_lookup(dw_hdmi.h) 2024-09-17 17:58:25 vnops.c:317 myfs_vnop_lookup: <- cache_lookup(dw_hdmi.h) -> -1 ;cache hit 2024-09-17 17:58:25 vnops.c:1478 myfs_vnop_remove: -> myfs_unlink(dw_hdmi.h) ;unlink sequence 2024-09-17 17:58:25 rpc.c:1992 myfs_unlink: -> myfs_unlink_rpc(dw_hdmi.h) 2024-09-17 17:58:25 rpc.c:1994 myfs_unlink: <- myfs_unlink_rpc(dw_hdmi.h) -> 0 ;remote unlink succeeded 2024-09-17 17:58:25 vnops.c:1480 myfs_vnop_remove: <- myfs_unlink(dw_hdmi.h) -> 0 2024-09-17 17:58:25 vnops.c:1487 myfs_vnop_remove: -> cache_purge(dw_hdmi.h) 2024-09-17 17:58:25 vnops.c:1489 myfs_vnop_remove: <- cache_purge(dw_hdmi.h) 2024-09-17 17:58:25 vnops.c:1499 myfs_vnop_remove: -> vnode_recycle(dw_hdmi.h) 2024-09-17 17:58:25 vnops.c:1501 myfs_vnop_remove: <- vnode_recycle(dw_hdmi.h) 2024-09-17 17:58:27 vnops.c:281 myfs_vnop_lookup: fseventsd-101 -> dw_hdmi.h ;another lookup; why? 2024-09-17 17:58:27 vnops.c:315 myfs_vnop_lookup: -> cache_lookup(dw_hdmi.h) 2024-09-17 17:58:27 vnops.c:317 myfs_vnop_lookup: <- cache_lookup(dw_hdmi.h) -> 0 2024-09-17 17:58:27 rpc.c:431 myfsLookup: fseventsd-101 -> dw_hdmi.h 2024-09-17 17:58:27 rpc.c:500 myfsLookup: -> myfs_lookup_rpc(dw_hdmi.h) 2024-09-17 17:58:27 rpc.c:502 myfsLookup: <- myfs_lookup_rpc(dw_hdmi.h) -> ENOENT(2) 2024-09-17 17:58:27 vnops.c:371 myfs_vnop_lookup: SET(NNEGNCENTRIES): dw_hdmi.h 2024-09-17 17:58:27 vnops.c:373 myfs_vnop_lookup: ENOENT(2) <- shouldAddToNegativeNameCache(dw_hdmi.h) I checked the value of vnode's v_iocount when vnop_remove and vnop_reclaim are being called. Each vnop_remove and followed by vnop_reclaim with v_iocount set to 1 in both calls, as expected. What I don't understand is why after removing the file is there another lookup call being made, which returns ENOENT to rm(1), which causes it to abort. Any pointers on what could be amiss there would be much appreciated.
Replies
3
Boosts
0
Views
792
Activity
Sep ’24