In the macOS 14.0 SDK, environment and library constraints were introduced, which made defense against common attack vectors relatively simple (especially with the LightWeightCodeRequirements framework added in 14.4).
Now, the application I'm working on must support macOS 13.0 too, so I was looking into alternatives that do work for those operating systems as well.
What I found myself is that the SecCode/SecStaticCode APIs in the Security Framework do offer very similar fashion checks as the LightWeightCodeRequirements framework does:
SecCodeCopySigningInformation can return values like signing identifier, team identifier, code requirement string and so on.
SecStaticCodeCreateWithPath can return a SecStaticCode object to an executable/app bundle on the file system.
Let's say, I would want to protect myself against launchd executable swap.
From macOS 14.0 onward, I would use a Spawn Constraint for this, directly in the launchd.plist file.
Before macOS 14.0, I would create a SecStaticCode object for the executable path found in the launchd.plist, and then examine its SecCodeCopySigningInformation dictionary. If the expectations are met, only then would I execute the launchd.plist-defined executable or connect to it via XPC.
Are these two equivalent? If not, what are the differences?
XPC
RSS for tagXPC is a a low-level (libSystem) interprocess communication mechanism that is based on serialized property lists.
Posts under XPC tag
74 Posts
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
I have several processes maintaining NSXPConnection to an XPC service. The connections are bi-directional. Each side service and clients) of the connection exports an object, and an XPCInterface. The @protocols are different - to the service, and from the service to clients.
So long as all the "clients" fully implement their "call-back" @protocol, there's no problem. All works fine.
However - If a client does NOT implement a method in the "call back protocol", or completely neglects to export an object, or interface - and the service attempts to call back using the nonexistent method -- the XPC connection invalidates immediately.
So far - expected behaviour.
However, if I want the service to behave to the client a little like a "delegate" style -- and check first whether the client "respondsToSelector" or even - supports an interface BEFORE calling it, then this doesn't work.
When my XPC service tries the following on a client connection:
if (xpcConnection.remoteObjectInterface == nil)
os_log_error(myXPCLog, "client has no remote interface);
the condition is never met - i.e. the "remoteObjectInterface is never nil even when the client does NOT configure its NSXPCConnection with any incoming NSXPCInterface, and does not set an "exportedObject"
Furthermore, the next check:
if ([proxy respondsToSelector:@selector(downloadFiltersForCustomer:withReply:)]) {
}
will not only fail - but will drop the connection. The client side gets the invalidation with the following error:
<NSXPCConnection: 0x600000b20000> connection to service with pid 2477 named com.proofpoint.ecd: received an undecodable message for proxy 1 (no exported object to receive message). Dropping message.
I guess the "undecidable message" is the respondsToSelector - because the code doesn't get to attempt anything else afterwards, the connection drops.
Is there a way to do this check "quietly", or suffering only "interruption", but without losing the connection,
I'm attempting to install a NetworkExtension as a system extension, using the OSSystemExtensionManager.shared.submitRequest(request) API call. I can see from console logs and systemextensionsctl that my system extension is getting installed, but the OSSystemExtensionRequestDelegate I attach to the request never gets a callback.
In the console logs I see:
com.apple.sx default 14:13:25.811827+0400 sysextd activateDecision found entry to replace: com.coder.Coder-Desktop.VPN, BundleVersion(CFBundleShortVersionString: "1.0", CFBundleVersion: "1")
default 14:13:25.811888+0400 sysextd initial activation decision: requestAppReplaceAction(<sysextd.Extension: 0xa94030100>)
com.apple.sx default 14:13:25.811928+0400 sysextd notifying client of activation conflict
com.apple.xpc default 14:13:25.812156+0400 Coder Desktop [0x154f2d5b0] invalidated because the current process cancelled the connection by calling xpc_connection_cancel()
com.apple.xpc default 14:13:25.813924+0400 sysextd [0xa941d4280] invalidated because the client process (pid 2599) either cancelled the connection or exited
com.apple.sx default 14:13:25.814027+0400 sysextd client connection (pid 2599) invalidated
It appears that something within my app process is cancelling the XPC connection to sysextd, but I'm certainly not calling it from within my code. Presumably something within the OSSystemExtension* APIs are cancelling the connection but I don't know why. It seems to be happening very quickly (within a few hundred ms) after sending the request, and before sysextd can reply.
What could cause this connection to be canceled?
Hello, I'm developing a Mac application that uses a network extension. I'm trying to implement XPC to pass data between my main app and system extension and I'm using the SimpleFirewall demo app as a guide to do this. One thing I can't understand is how the ViewController in the SimpleFirewall main app has access to the class IPCConnection in the SimpleFirewallExtension without it being public and without SimpleFirewallExtension being imported in ViewController.
Topic:
App & System Services
SubTopic:
Processes & Concurrency
Tags:
XPC
System Extensions
Network Extension
hello everyone
On iOS18.0+, app crashed at BSXPCCnx:com.apple.backboard.hid-services.xpc (BSCnx:client:BKHIDEventDeliveryObserver) when app enter background sometimes
crash stacktrace:
Crashed: BSXPCCnx:com.apple.backboard.hid-services.xpc (BSCnx:client:BKHIDEventDeliveryObserver)
0 libsystem_pthread.dylib 0x4078 pthread_mutex_lock + 12
1 ilink_live 0xbd884 (缺少 UUID 973fe6c5058c35bda98679b0c8aa0129)
2 ilink_live 0xb75fc (缺少 UUID 973fe6c5058c35bda98679b0c8aa0129)
3 libsystem_c.dylib 0x23190 __cxa_finalize_ranges + 492
4 libsystem_c.dylib 0x22f8c exit + 32
5 BackBoardServices 0x31b78 -[BKSHIDEventObserver init] + 98
6 BoardServices 0x1dc78 __31-[BSServiceConnection activate]_block_invoke.182 + 128
7 BoardServices 0x1beb4 __61-[BSXPCServiceConnectionEventHandler _connectionInvalidated:]_block_invoke + 196
8 BoardServices 0x4a58 BSXPCServiceConnectionExecuteCallOut + 240
9 BoardServices 0x1d6e8 -[BSXPCServiceConnectionEventHandler _connectionInvalidated:] + 180
10 libdispatch.dylib 0x2248 _dispatch_call_block_and_release + 32
11 libdispatch.dylib 0x3fa8 _dispatch_client_callout + 20
12 libdispatch.dylib 0xb5cc _dispatch_lane_serial_drain + 768
13 libdispatch.dylib 0xc158 _dispatch_lane_invoke + 432
14 libdispatch.dylib 0xb42c _dispatch_lane_serial_drain + 352
15 libdispatch.dylib 0xc158 _dispatch_lane_invoke + 432
16 libdispatch.dylib 0x1738c _dispatch_root_queue_drain_deferred_wlh + 288
17 libdispatch.dylib 0x16bd8 _dispatch_workloop_worker_thread + 540
18 libsystem_pthread.dylib 0x3680 _pthread_wqthread + 288
19 libsystem_pthread.dylib 0x1474 start_wqthread + 8
when crash happened ,most of time app recieved CBManagerStateResetting and CBManagerStateUnsupported event
i would appreciate any insights or recommendations on how to resolve this issue
thx
crash_stacktrace.txt
Hi,
I'm trying to create a launch daemon that uses XPC to receive requests from an unprivileged app. Ultimately both components will be written in Go. For now I'm trying to write a PoC in Objective-C to make sure I get everything right, so I'm compiling / signing from the CLI, and writing plist files by hand -- I'm not using XCode.
My current daemon code is pretty much the same as the boilerplate code that XCode generates when creating a new 'XPC Service':
#import <stdio.h>
#include <xpc/xpc.h>
int main(int argc, char *argv[]) {
xpc_rich_error_t error;
dispatch_queue_t queue = dispatch_queue_create("com.foobar.daemon", DISPATCH_QUEUE_SERIAL);
xpc_listener_t listener = xpc_listener_create(
"com.foobar.daemon",
queue,
XPC_LISTENER_CREATE_NONE,
^(xpc_session_t _Nonnull peer) {
xpc_session_set_incoming_message_handler(peer, ^(xpc_object_t _Nonnull message) {
int64_t firstNumber = xpc_dictionary_get_int64(message, "firstNumber");
int64_t secondNumber = xpc_dictionary_get_int64(message, "secondNumber");
// Create a reply and send it back to the client.
xpc_object_t reply = xpc_dictionary_create_reply(message);
xpc_dictionary_set_int64(reply, "result", firstNumber + secondNumber);
xpc_rich_error_t replyError = xpc_session_send_message(peer, reply);
if (replyError) {
printf("Reply failed, error: %s", xpc_rich_error_copy_description(replyError));
}
});
},
&error);
if (error != NULL) {
printf("ERROR: %s\n", xpc_rich_error_copy_description(error));
exit(1);
}
printf("Created listener: %s", xpc_listener_copy_description(listener));
// Resuming the serviceListener starts this service. This method does not return.
dispatch_main();
return 0;
}
I'm compiling, signing and installing my daemon with the following commands:
build_foobar() {
clang -Wall -x objective-c -o com.foobar.daemon poc/main.m
codesign --force --verify --verbose --options=runtime \
--identifier="com.foobar.daemon" \
--sign="Mac Developer: Albin Kerouanton (XYZ)" \
--entitlements=poc/entitlements.plist \
com.foobar.daemon
}
install_foobar() {
sudo cp com.foobar.daemon /Library/PrivilegedHelperTools/com.foobar.daemon
sudo cp poc/com.foobar.daemon.plist /Library/LaunchDaemons/com.foobar.daemon.plist
sudo launchctl bootout system/com.foobar.daemon || true
sudo launchctl bootstrap system /Library/LaunchDaemons/com.foobar.daemon.plist
}
Here's the content of my entitlements.plist file:
<?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>com.apple.application-identifier</key>
<string>ABCD.com.foobar.daemon</string>
</dict>
</plist>
And finally, here's my launchd plist file:
<?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>Label</key>
<string>com.foobar.daemon</string>
<key>Program</key>
<string>/Library/PrivilegedHelperTools/com.foobar.daemon</string>
<key>ProgramArguments</key>
<array>
<string>/Library/PrivilegedHelperTools/com.foobar.daemon</string>
</array>
<key>RunAtLoad</key>
<false/>
<key>StandardOutPath</key>
<string>/tmp/com.foobar.daemon.out.log</string>
<key>StandardErrorPath</key>
<string>/tmp/com.foobar.daemon.err.log</string>
<key>Debug</key>
<true/>
</dict>
</plist>
Whenever I start my service using sudo launchctl start com.foobar.daemon, it exits with the following error message:
ERROR: Unable to activate listener: failed at listener activation with error 1 - Operation not permitted
System logs don't show anything interesting -- they're just repeating the same error message. I tried to add / remove some properties from both the entitlement and the launchd plist file but to no avail.
Any idea what's going wrong?
Hello,
My team has developed a DNS proxy for macOS. We have this set up with a system extension that interacts with the OS, and an always-running daemon that does all the heavy lifting. Communication between the two is DNS request and response packet traffic.
With this architecture what are best practices for how the system extension communicates with a daemon?
We tried making the daemon a socket server, but the system extension could not connect to it.
We tried using XPC but it did not work and we could not understand the errors that were returned.
So what is the best way to do this sort of thing?
Topic:
App & System Services
SubTopic:
Processes & Concurrency
Tags:
XPC
System Extensions
Network Extension
Service Management
Hi everyone,
I’m encountering a crash in my app and need help understanding what’s causing it and how to resolve it.
As stated in the crash report, the issue is caused by exceeding the system-wide per-process port limit. Can you tell me how to locate and identify why this is happening?
Below are the full report of the crash log:
crash.log
Summary of Crash:
-------------------------------------
Translated Report (Full Report Below)
-------------------------------------
Incident Identifier: B509FF2B-C8D8-4E9F-B664-E24464CFD5F8
CrashReporter Key: b390cfe931a83efde49bd8b523023a275b55ef64
Hardware Model: iPhone14,2
Process: MyApp [22515]
Path: /private/var/containers/Bundle/Application/F73212A7-4CB9-485A-A8B7-8114F4E9A9AB/MyApp.app/MyApp
Identifier: com.beeasy.app.id.enterprise
Version: 3.41.38-ID-MySDKMemory-12261114 (3.41.38-ID-MySDKMemory-12261114)
Code Type: ARM-64 (Native)
Role: Foreground
Parent Process: launchd [1]
Coalition: com.beeasy.app.id.enterprise [515]
Date/Time: 2024-12-29 01:29:48.3023 +0800
Launch Time: 2024-12-26 16:38:36.7895 +0800
OS Version: iPhone OS 16.6.1 (20G81)
Release Type: User
Baseband Version: 2.80.01
Report Version: 104
Exception Type: EXC_RESOURCE (SIGKILL)
Exception Codes: 0x000000000001c1d6, 0x0000000000000000
Termination Reason: PORT_SPACE 14123288431433990614 (Limit 115158 ports) Exceeded system-wide per-process Port Limit
Triggered by Thread: 64
Thread 64 name: AURemoteIO::IOThread
Thread 64 Crashed:
0 libsystem_kernel.dylib 0x20ce5eca4 mach_msg2_trap + 8
1 libsystem_kernel.dylib 0x20ce71b74 mach_msg2_internal + 80
2 libsystem_kernel.dylib 0x20ce71e4c mach_msg_overwrite + 540
3 libsystem_kernel.dylib 0x20ce5f1e8 mach_msg + 24
4 libEmbeddedSystemAUs.dylib 0x238bb2148 void* caulk::thread_proxy<std::__1::tuple<caulk::thread::attributes, AURemoteIO::IOThread::IOThread(AURemoteIO&, caulk::thread::attributes const&, caulk::mach::os_workgroup_managed const&)::'lambda'(), std::__1::tuple<>>>(void*) + 556
5 libsystem_pthread.dylib 0x22dcda6b8 _pthread_start + 148
6 libsystem_pthread.dylib 0x22dcd9b88 thread_start + 8
I'm try to monitor all processes by ES client. But I found the process name is different from the Activity Monitor displayed. As shown in the picture below, there are ShareSheetUI(Pages) and ShareSheetUI(Finder) processes in Activity Monitor, but I can only get the same name ShareSheetUI, I thought of many ways to display the name in parentheses, but nothing worked, so there is a way to display the process name like Activity Monitor?
Hi,
My iphone 12 has been restarting unexpectedly, and often followed by wifi, bluetooth, and airdrop grayed out. I had to force restart/shutdown several times to turn it on again.
Found this analytics after crash. Please help if somebody know what this means:
ExcUserFault_CategoriesService-2024-12-23-064503.ips
when app enter background,sometimes crash at
BSXPCCnx:com.apple.backboard.hid-services.xpc (BSCnx:client:BKHIDEventDeliveryManager)
this is crash stack:
0 libsystem_pthread.dylib 0x3b30 pthread_mutex_lock + 12
1 ilink_live 0xbd884 (缺少 UUID 973fe6c5058c35bda98679b0c8aa0129)
2 ilink_live 0xb75fc (缺少 UUID 973fe6c5058c35bda98679b0c8aa0129)
3 libsystem_c.dylib 0x23d68 __cxa_finalize_ranges + 492
4 libsystem_c.dylib 0x23b64 exit + 32
5 BackBoardServices 0x579ec -[BKSHIDEventDeliveryManager _initForTestingWithService:] + 98
6 BoardServices 0xbae8 __31-[BSServiceConnection activate]_block_invoke.182 + 128
7 BoardServices 0x17620 __61-[BSXPCServiceConnectionEventHandler _connectionInvalidated:]_block_invoke + 196
8 BoardServices 0x8f64 BSXPCServiceConnectionExecuteCallOut + 240
9 BoardServices 0x18e5c -[BSXPCServiceConnectionEventHandler _connectionInvalidated:] + 180
10 libdispatch.dylib 0x2370 _dispatch_call_block_and_release + 32
11 libdispatch.dylib 0x40d0 _dispatch_client_callout + 20
12 libdispatch.dylib 0xb6d8 _dispatch_lane_serial_drain + 744
13 libdispatch.dylib 0xc214 _dispatch_lane_invoke + 432
14 libdispatch.dylib 0x17258 _dispatch_root_queue_drain_deferred_wlh + 288
15 libdispatch.dylib 0x16aa4 _dispatch_workloop_worker_thread + 540
16 libsystem_pthread.dylib 0x4c7c _pthread_wqthread + 288
17 libsystem_pthread.dylib 0x1488 start_wqthread + 8
when crash happened ,most of time app recieved CBManagerStateResetting and CBManagerStateUnsupported event
I'm developing a file access control system. In order to protect the file content copied out, I'm finding a way to deny user copy file content to other files.
I know there are data transmission between the copied application and pboard service by XPC. But I don't know how to interrupt the data transmission. Or I can do something to stop the copied data send to the Clipboard.
So is there any way to prevent the contents of a file being copied?
Hi,
For one our requirement sendProviderMessage is been used to send some event/message from app to system extension, In my requirement, responseHandler in system extension would get explicitly called approximately after 1 min due to some async download file task.
But observing some strange behavior that responseHandler is getting called implicitly after ~20-30 seconds even before the code hit the place where its called explicitly. And that is the only place I'm calling responseHandler.
Can somebody please help about this strange behavior, Is there any implicit timeout interval associated with the responseHandler.
Thanks &amp; Regards,
Preethi
Hello everyone,
We have an iOS XCFramework that we distribute to our clients, and we're exploring ways to enhance its security. Specifically, we’d like to isolate the most sensitive code by running it in a separate process, making it harder to tamper with.
During our research, we considered using XPC for iOS but found its functionality to be quite limited. We also explored App Extensions, but unfortunately, they cannot be integrated into an XCFramework.
This leads us to the question:
Is it possible to spawn a new process to run in parallel with the main one in iOS?
If so, could you provide guidance or suggest alternative approaches to achieve this within the constraints of iOS development?
Thank you in advance for your insights and advice!
Best regards,
Stoyan