XPC is a a low-level (libSystem) interprocess communication mechanism that is based on serialized property lists.

Posts under XPC tag

57 Posts
Sort by:

Post

Replies

Boosts

Views

Activity

Audio Server Plugin entitlements and communication
I am currently working on planning a multi-component software system that consists of an Audio Server Plugin and an application for user interaction. I have very little experience with IPC/XPC and its performance implications, so I hope I can find a little guidance here. The Audio Server plugin publishes a number of multi-channel output devices on which it should perform computations and pass the result on to a different Core Audio device. My concerns here are: Can the plugin directly access other CoreAudio devices for audio output or is this prohibited by the sandboxing? If it cannot, would relaying the audio data via XPC be a good idea in terms of low latency stability? Can I use metal compute from within the Audio Server plugin? I have not found any information about metal related sandboxing entitlements. I am also concerned about performance implications as above. Regarding the user interface application, I would like to know: If a process that has not been started by launchd can communicate with the Audio Server plugin using XPC. If not, would a user agent instead of an app be a better choice? Or are there other communication channels that would work with sandboxing? Thank you very much! Andreas
0
0
773
Feb ’24
Migrating from pkg installer to Service Management
Hello, we are currently working on a plan to migrate our app suite from Developer ID binaries inside a simple pkg installer to macOS app store distribution. The reason we are using an installer is that there are multiple binaries inside that communicate via XPC and we need to install the respective launchd plist in /Library/LaunchDaemons and /Library/LaunchAgents: 1 root daemon 1 agent that has minimal UI and lives in the system menu bar 1 embedded command line utility in user agent 1 embedded FileProvider extension in user agent 1 embedded Action Extension in user agent 1 agent that only does OAuth stuff Looking through Updating helper executables from earlier versions of macOS I can install the root daemon with SMAppService.daemon(plistName:) and the OAuth helper with SMAppService.agent(plistName:). For the main application I only found SMAppService.mainApp which does not accept a property list configuration. Therefore, I have no place to put my MachServices array and so the File Provider extension, the Action Extension, and the embedded command line utility have no way to talk to the user agent. Currently, XPC is used in between these processes: user agent -> root daemon command line utility -> user agent action extension -> user agent file provider extension -> user agent user agent -> file provider extension: that already works through NSFileProviderServicing I know app-to-app communication only works through launchd for security reasons, but these applications are all part of the same app group (except the root daemon obviously). My question is what is the proper way of starting the user agent so XPC from other binaries just work ™️? Any input is much appreciated!
6
0
900
Sep ’24
XPC, memory allocation, and much confusion
I asked a similar question last year, and got no responses. I've written a much simpler (no network extension!) case that seems to demonstrate what I'm confused about. Simple app with an XPC service. I have an ObjectiveC class TestObject which has an NSString* and an NSData* (which I never actually use). I have a protocol defined in Swift: @objc protocol XPCTestServiceProtocol { func logData(entry: TestObject) -> Void func logData(entry: TestObject, completion: ((String) -> Void)) } In the Switt XPC service, the code is: class XPCTestService: NSObject, XPCTestServiceProtocol { var totalBytes = 0 var lastName = "" @objc func logData(entry: TestObject) { totalBytes += (entry.data?.count ?? 0) } @objc func logData(entry: TestObject, completion: ((String) -> Void)) { totalBytes += (entry.data?.count ?? 0) completion("Finished") } I've got this code in the ObjC app: id<XPCTestServiceProtocol> proxy = [self.connection remoteObjectProxyWithErrorHandler:^(NSError* error) { self.stopRun = YES; NSLog(@"Proxy got error %@", error); }]; while (self.stopRun == NO) { @synchronized (self) { NSNumber *objNum = [NSNumber numberWithUnsignedLongLong:self.count++]; NSString *objName = [NSString stringWithFormat:@"Object %@", objNum]; TestObject __weak *toWeak = to; #if USE_COMPLETION [proxy logDataWithEntry:to completion:^(NSString *str) { to = nil; }]; #else [proxy logDataWithEntry:to]; #endif } } attached to a start button (and self.stopRun is set by a stop button, this is all super simple). So I run that, start the test, and things start going (122k calls/second it says). According to Activity Monitor, my app is using about 1gbyte after 20 seconds or so. However, if I run it under Instruments' Leaks template... Activity Monitor says it's used only about 60mbytes. (And at the end of the run, Instruments says it's used about 30mbytes.) Now... if I use the completion and a synchronous proxy, then even without Instruments, Activity Monitor says it's 60mbytes or so. Is the memory reported by Activity Monitor real? Or not real?
12
0
1k
Feb ’24
Setup LaunchAgent in Xcode
Hi there :) I try to put an Xcode project in place within a LaunchAgent. The ultimate goal is to have an "application" with two component: macOS application with just an basic UI all the logic happens in a LaunchAgent that runs on background and is launch at startup. The macOS app uses XPC to send messages to the agent that will run either the app is opened or not. I struggled at first having this error (for the agent): An XPC Service cannot be run directly. Then I found using MachServices key in the .plist of the agent fixes the issue, plus: let listener = NSXPCListener.init(machServiceName: "com.tonygo.NetworkMonitorAgent") Then I wonder: Do we have somewhere a documentation about how to setup a LaunchAgent in Xcode I create the plist of the agent on side and run it manually, I could do this in a more automatic way How could I package a macOS applciation that will contains the agent, install it and load the agent? Note: This is mainly for learning and understanding what we could do at each level (XPCService, LaunchAgents, LaunchDaemon, etc.).
23
0
2.5k
Feb ’24
Using `SecCodeCopyGuestWithAttributes` with auditToken results in `100001 - UNIX[Operation not permitted]`
Hi everyone :) I'm exploring XPC these days; more specifically, I'm trying to establish a connection between a macOS application and an XPC service. I succeeded in establishing the connection, but now I'm trying to verify the incoming connection by using SecCodeCopyGuestWithAttributes, passing it an audit token. But I got the following error: 2024-01-18 10:43:06.805435+0100 DemoService[1627:7118397] [logging-persist] cannot open file at line 46922 of [554764a6e7] 2024-01-18 10:43:06.805452+0100 DemoService[1627:7118397] [logging-persist] os_unix.c:46922: (0) open(/private/var/db/DetachedSignatures) - Undefined error: 0 Cannot get SecCode: 100001 - UNIX[Operation not permitted] Audit token: Optional(32 bytes) The last two lines come from my code: class XPCClientValidator { var secCodeOptional: SecCode? = nil; func identifyGuest(for connection: NSXPCConnection) -> Bool { let auditToken = AuditToken.extractToken(from: connection) let hostSecCode: SecCode? = nil; // This is a way to indicate that the code signing root of trust hould be used as host. let attributes = [ kSecGuestAttributeAudit: auditToken ] as CFDictionary let secFlags = SecCSFlags(rawValue: 0) // Asks a code host to identify the guest given the audit token let status: OSStatus = SecCodeCopyGuestWithAttributes(hostSecCode, attributes, secFlags, &self.secCodeOptional) if (status != errSecSuccess) { let msg = SecCopyErrorMessageString(status, nil)! print("Cannot get SecCode: \(status) - \(msg)") print("Audit token: \(String(describing: auditToken))") return false } guard let _ = secCodeOptional else { NSLog("Couldn't unwrap the secCode") return false } return true } } I saw a few posts on the forum, but nothing helped me to solve this issue. The complete source code is here: https://github.com/tony-go/XPCDemo/tree/secure-xpc Note: If you want to reproduce it, you have to: start the app type a random input click on "uppercase it"
5
0
927
Jan ’24
IPC between two processes
I am looking for a solution to transfer data between two completely separate processes (not from the same group). I did a lot of research, but the solutions were mostly for processes that are in a group. Is there a method? (It doesn't matter if the app is sandboxed, I can disable it). My goal is to communicate between a bundle(plugin) that is activated on the Mac login page and an XPC service and transfer data from the service to the bundle.
3
0
898
Dec ’23
XPC Connection with Network Extension fails after upgrade
Hi Team, I have a Network Extension application and UI frontend for it. The UI frontend talks to the Network Extension using XPC, as provided by NEMachServiceName. On M2 machine, The application and XPC connection works fine on clean installation. But, when the application is upgraded, the XPC connection keeps failing. Upgrade steps: PreInstall script kills the running processes, both UI and Network Extension Let installation continue PostInstall script to launch the application after installation complete. Following code is successful to the point of resume from UI application NSXPCInterface *exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(IPCUIObject)]; newConnection.exportedInterface = exportedInterface; newConnection.exportedObject = delegate; NSXPCInterface *remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(IPCExtObject)]; newConnection.remoteObjectInterface = remoteObjectInterface; self.currentConnection = newConnection; [newConnection resume]; But it fails to get the object id<IPCExtObject> providerProxy = [self.currentConnection remoteObjectProxyWithErrorHandler:^(NSError *registerError) { }]; Please note, this only fails for M2. For M1, this exact code is running fine. Additionally, if I uninstall the application by dropping it in Trash and then installing the newer version, then too, the application works fine.
2
0
674
Dec ’23
XPC Rendezvous, com.apple.security.inherit and LaunchAgent
I’m trying to implement XPC Rendezvous like Quinn described in many awesome posts on here but I’m now at a stuck point were I just have no idea. I want to communicate with a Safari extension via XPC and also a helper application which led me to XPC Rendezvous (https://developer.apple.com/forums/thread/715338) because a XPC Service in the Extension is scoped to the container. I then made a Command Line Target and added it like its described here (https://developer.apple.com/documentation/xcode/embedding-a-helper-tool-in-a-sandboxed-app ) and also took the xpc test code and inspiration to set up my launch agent from here (https://developer.apple.com/documentation/servicemanagement/updating_your_app_package_installer_to_use_the_new_service_management_api). This command line tool should do the management for the XPC connections because it’s not in the sandboxed container. The tool sets up the xpc connection like in the sample code directly and not in a XPC Service added via a Target template. It exposes the Mach Service. And that looks like its building fine after some fighting but the service just wont start - I saw it trying in console and after running it in Xcode and finally finding the crash report - it brought me there (https://developer.apple.com/forums/thread/706390) I have Process is not in an inherited sandbox. - and thinking about it, it makes sense because I first thought its just because it ran through Xcode, but its crashing this way also as a LaunchAgent. I mean it does make sense - there is nothing to inherit because it’s spawned by launchd - and that’s what I want isn’t it - to make the Rendezvous? Okay I thought now removing com.apple.security.inherit brings it in its own Sandbox (its needs sandboxing) but this also crashes the process because of the sandbox. Also after adding it to the App Group. What am I missing here or what do I want to accomplish? Do I want to inherit the sandbox? I guess not the helper should have its own. The only difference I see in comparison to SMAppServiceSampleCode is it moves the product in Copy Bundle Resources, and I have a Copy Files Phase with Destination: Executables (Like the other sample code said - and that’s looks “more correct” - and well SMAppServiceSampleCode isn’t sandboxed. I then tried making a new Command Line Target and just added App Sandbox Capability and tried to run this fresh one - and that also crashes. This makes me think I’m just ****** somewhere but I have read now everything I could find. I’m happy to provide any Code or crash logs but I dont know what part is really relevant here, It looks like the LaunchAgent gets installed correctly and wants to run but the sandbox is preventing me. The Bundle Identifier and XPC device name of the helper starts with my teamID (I got that from here https://developer.apple.com/forums/thread/703702) What could I be doing wrong? Thanks a lot! Benjamin
7
0
1.6k
Dec ’23
Secure XPC service call
I would like to develop a macOS application in Swift. This application will consist of 2 programs: a main program to be run by the user (standard account) and another one that will run with root privileges. The second program will only be invoked to perform privileged tasks. Running the main program under root permanently would be too risky. XPC will be used to trigger calls from the main program to the privileged program. How can I secure the privileged program to ensure that the calling program is indeed my main program and not another unauthorized program?
1
0
634
Dec ’23
XPC Service Connection Invalidated Immediately on Launch
Development Environment: Xcode Version: 14.3.1 macOS Ventura Version: 13.6.2 Architecture: Intel I am developing a macOS app with an accompanying XPC service and am encountering an issue where the XPC connection is immediately invalidated upon trying to establish it. The error message received is: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named com.appname.macos.app-name-xpc was invalidated." UserInfo={NSDebugDescription=The connection to service named com.appname.macos.app-name-xpc was invalidated: failed at lookup with error 3 - No such process.} Here's what I have verified so far: The XPC service has the correct CFBundleIdentifier and is located within the Contents/XPCServices directory of my app's bundle. Info.plist for the XPC service has ServiceType set to Bundled. The XPC service target's Installation Directory is the default location for XPC services (@executable_path/../XPCServices). Code signing and entitlements have been verified for both the main app and the XPC service, and disabling the sandbox doesn't resolve the issue. The main app and XPC service are part of the same App Group, and both have the App Sandbox capability enabled. Here's a snippet of the Swift code that establishes the XPC connection: let xpcConnection = NSXPCConnection(serviceName: "com.appname.macos.app-name-xpc") xpcConnection.remoteObjectInterface = NSXPCInterface(with: ServiceProtocol.self) xpcConnection.resume() And here's the ServiceProtocol for reference: @objc public protocol ServiceProtocol: NSObjectProtocol { @objc func executeUnixExecutable(arguments: [String], completionHandler: @escaping (ResultType) -> Void) func interruptUnixExecutable() func closeUnixExecutablePipes() } When I run the app, the connection is invalidated without any further details as to why. I'm not sure if I'm missing a configuration step or if there's an issue with my XPC service setup. Has anyone experienced this issue or have suggestions on what else I can check to resolve this?
2
0
3k
Apr ’24
XPC Resources
XPC is the preferred inter-process communication (IPC) mechanism on Apple platforms. XPC has three APIs: The high-level NSXPCConnection API, for Objective-C and Swift The low-level Swift API, introduced with macOS 14 The low-level C API, which, while callable from all languages, works best with C-based languages General: DevForums tag: XPC Creating XPC services documentation NSXPCConnection class documentation Low-level API documentation XPC has extensive man pages — For the low-level API, start with the xpc man page; this is the original source for the XPC C API documentation and still contains titbits that you can’t find elsewhere. Also read the xpcservice.plist man page, which documents the property list format used by XPC services. Daemons and Services Programming Guide archived documentation WWDC 2012 Session 241 Cocoa Interprocess Communication with XPC — This is no longer available from the Apple Developer website )-: Technote 2083 Daemons and Agents — It hasn’t been updated in… well… decades, but it’s still remarkably relevant. TN3113 Testing and Debugging XPC Code With an Anonymous Listener XPC and App-to-App Communication DevForums post Validating Signature Of XPC Process DevForums post Related tags include: Inter-process communication, for other IPC mechanisms Service Management, for installing and uninstalling Service Management login items, launchd agents, and launchd daemons Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com"
0
0
2.0k
Mar ’24
is XPC from app to CMIOExtension possible?
I built an app which hosts a CMIOExtension. The app works, and it can activate the extension. The extension loads in e.g. Photo Booth and shows the expected video (a white horizontal line which moves down the picture). I have a couple of questions about this though. The sample Camera Extension is built with a CMIOExtension dictionary with just one entry, CMIOExtensionMachServiceName which is $(TeamIdentifierPrefix)$(PRODUCT_BUNDLE_IDENTIFIER) This Mach service name won't work though. When attempting to activate the extension, sysextd says that the extensions has an invalid mach service name or is not signed, the value must be prefixed with one of the App Groups in the entitlement. So in order to get the sample extension to activate from my app, I have to change its CMIOExtensionMachServiceName to <my team ID>.com.mycompany.my-app-group.<myextensionname> Is this to be expected? The template CMIOExtension generates its own video using a timer. My app is intended to capture video from a source, filter that video, then feed it to the CMIOExtension, somehow. The template creates an app group called "$(TeamIdentifierPrefix)com.example.app-group", which suggests that it might be possible to use XPC to send frames from the app to the extension. However, I've been unable to do so. I've used NSXPCConnection * connection = [[NSXPCConnection alloc] initWithMachServiceName:, using the CMIOExtensionMachServiceName with no options and with the NSXPCConnectionPrivileged option. I've tried NSXPCConnection * connection = [[NSXPCConnection alloc] initWithServiceName: using the extension's bundle identifier. In all cases when I send the first message I get an error in the remote object proxy's handler: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named <whatever name I try> was invalidated: failed at lookup with error 3 - No such process." According to the "Daemons and Services Programming Guide" an XPC service should have a CFBundlePackageType of XPC!, but a CMIOExtension is of type SYSX. It can't be both. Does the CMIOExtension loading apparatus cook up a synthetic name for the XPC service, and if so, what is it? If none, how is one expected to get pixel buffers into the camera extension?
19
0
7.9k
Dec ’23
XPC, Swift, ObjC, and arrays
I create a protocol that had, among other things: @objc func setList(_: [MyType], withReply: @escaping (Error?) -> Void) The daemon part is in Swift, while the calling part is in Objective-C. Because why not? (Actually, because the calling part has to deal with C++ code, so that's ObjC++; however, I wanted the stronger typing and runtime checking for the daemon part, so I wrote it in Swift.) The ObjC part uses NSArray<MyType*>. I set up an NSXPCConnection link, and create a (synchronous) proxy with the right protocol name. But when I try to do the XPC setList call, I get an error. I assume that's because it doesn't like the signature. (Surely this is logged somewhere? I couldn't find it, if so. 😩) But... if I have a signature of @objc func addItem(_: MyType, withReply: @escaping (Error?) -> Void), then it works. So I assume it's the array. (Oh, I've also tried it without the @objc; the protocol itself is defined as @objc.) I've tried changing to protocol signature to using NSArray, but same thing.
7
0
1.4k
Jun ’24
Swift Process with Psuedo Terminal (PTY)
Hi! I'm looking for some insight and guidance on using the Foundation.Process type with a PTY (Psuedo Terminal) so that the subprocess can accept input and behave as if it was running via a terminal. The reason for needing a PTY is that for programs like ssh or in my case (xcodes) which ask for user input including passwords, running these via Foundation.Process does not display the prompts to the user as the output is usually buffered (this works fine in the Xcode debugger console but when running via a real terminal that is buffered the prompts are never displayed in the terminal) Looking at other threads it seems like correct approach here is create a PTY and use the filehandles to attach to the Process. While I've got this to work to the point where prompts are now shown, I cant seem to figure out how to pass input back to the process as these are being controlled by the PTY. Here is my Process setup: let process = Process() // Setup the process with path, args, etc... // Setup the PTY handles var parentDescriptor: Int32 = 0 var childDescriptor: Int32 = 0 guard Darwin.openpty(&parentDescriptor, &childDescriptor, nil, nil, nil) != -1 else {   fatalError("Failed to spawn PTY") } parentHandle = FileHandle(fileDescriptor: parentDescriptor, closeOnDealloc: true) childHandle = FileHandle(fileDescriptor: childDescriptor, closeOnDealloc: true) process.standardInput = childHandle process.standardOutput = childHandle process.standardError = childHandle With this setup I then read the parent handle and output any result it gets (such as the input prompts): parentHandle?.readabilityHandler = { handle in   guard let line = String(data: handle.availableData, encoding: .utf8), !line.isEmpty else {     return   }   logger.notice("\(line)") } When process.run() is executed the program runs and I can see it asks for Apple ID: input in my terminal, however, when typing input into the terminal the process does not seem to react to this input. I've tried forwarding the FileHandle.standardInput: FileHandle.standardInput.readabilityHandler = { handle in   parentHandle?.write(handle.availableData) } But this doesn't seem to work either. What is the recommended way to setup a PTY with Foundation.Process for executing arbitrary programs and having them behave as if they were being run in a terminal context? Most of the resources I found online are about other languages and I'd like to stick with Foundation.Process vs. doing anything custom in C/C++ if possible as it just makes it easier to reason about / maintain. The resources for Swift on this topic are very lacking and I've checked out some open source projects that claim to do this but most require manually sending input to the PTY handle vs. accepting them from the user in a terminal. Any insight / help is very much appreciated!
9
0
3.4k
Mar ’24
Validating Signature Of XPC Process
Quinn, you've often suggested that to validate the other side of an XPC connection, we should use the audit token. But that's not available from the XPC object, whereas the PID is. So everyone uses the PID. While looking for something completely unrelated, I found this in the SecCode.h file OSStatus SecCodeCreateWithXPCMessage(xpc_object_t message, SecCSFlags flags, SecCodeRef * __nonnull CF_RETURNS_RETAINED target); Would this be the preferred way to do this now? At least from 11.0 and up. Like I said, I was looking for something completely unrelated and found this and don't have the cycles right now to try it. But it looks promising from the description and I wanted to check in with you about it in case you can say yes or no before I get a chance to test it. Thanks
8
0
6.4k
Mar ’24