Post

Replies

Boosts

Views

Activity

Reply to Request Accessibility Permission from pkg install
I think the iOS platform has shown that strict and granular permission-granting don't necessarily force horrific UI experience, and maybe adopting iOS-style design of your app can smooth this a little. Specifically, having multiple applications - can usually be replaced by having a single Application bundle, code-signed as one, but supporting several binaries, or "Privileged Helpers", or by itself launching Agents/Daemons in either user/system scope. If you build your software so - your user will only need to provide accessibility permission once. Also, there is a reason for restricting developers from introducing Kernel Extensions, which are the most common source of kernel panics, OS hangs and slowdowns, and bad energy management. It's not that Apple does not provide alternatives.In the special case of security/privacy permissions handling - MacOS indeed lags behind iOS, and to my humble opinion - the issue is more of bad documentation, than anything else. Obviously TCC database exists, and performs, since MacOS 10.8 - also, new "Lists" are added with every MacOS release (several were added in Catalina) so it's a living component of the OS. There is also a very important point to make here: Apple sees the end user's "last word" on privacy, as the top priority. not 'root' or 'admin' or 'corporate IT'. That's an on-going struggle. In my company, huge amount of MDM profiles, kernel extensions, amazingly-bad "support" applications, supervision agents and more - are installed on every corporate user's Mac - just to circumvent this. As a result, my 2020 MBPPro 16" takes 3 minutes!!! to boot, and eats up its battery in less than an hour. it also crashes, hangs, and requests reboot about 10 times a week. This is not my Mac's case - but all users' case. What I mean is -- Mac is a Personal computer. If you accept this - your software will usually work nicely. If you don't -- you'll probably end up with "Horrific UI" and weird solutions.
Jun ’20
Reply to Mach Port Leakage - Mojave
Hi, regarding the Process.run() mach port leak bug (BugReporter #46547156) -- are there any news? resolution? workaround? Was this issue resolved in Catalina? (we're at 10.15.5 already...) Also - could you kindly share here some of your debugging code (the library and hooks you described) that can help us investigate a similar problem we experience using NSTask? Thanks!
Jun ’20
Reply to How to setup AVFoundation based view to display CoreImage filtered Live video from Camera?
First off, many thanks!!! The sample clearly does what I (need but failed) to do. Sample is completely modern (SwiftUI, swift 5, MacOS SDK 10.16 etc.) whereas my app's code is all Obj-C, and must run on earlier MacOS versions then Catalina, so it seems I will have lots of work "decompiling" all modern stuff back to the basics I need to use. Will be back with questions, or "hooray!" style reports soon. B.T.W If you use SwiftUI, and programmed this on the Mac, how come you can't simply select the Mac target and test-run it? I'll do it of course (once I get to my office desktop running Catalina. My Mac is 10.14 + Xcode 11.5 on which the sample can't be built. The labs using my Microscopy App have older equipment, and must retain compatibility with old cameras, hardware connections, etc. So I can't always use "latest and greatest". Thanks again.
Jul ’20
Reply to Endpoint Security app launchable from launchd/xcode, not from command line
Hi, I'm jumping on this same cart, with the same error, only in my case I'm in even earlier stage of getting into Endpoint Security --- All I try to do is to build and run the related Apple Sample code as is! It's the "SampleEndpointApp" sample project. In my case, upon receiving from Apple the e-mail granting us the entitlement needed, I went on to create a development provisioning profile for this, and I'm trying to sign the app (and related System Extension) using that. The strange thing is - I see in the sample logs that the system extension was registered and installed - and I see lots of log lines that confirm that the system extension is actually being loaded from some place in the SIP protected parts of the OS. Only there's then an endless stream of error log lines for my App/Extension - nearly every 2-3 seconds another bunch of errors. About half of the error lines are coming from the Sandbox (similar to those the OP is complaining about) and the rest from the actual system extension - basically claiming: error 12:35:04.919059+0200 com.mycompany.mac.prevention.Extension Failed to open service: -536870174 error 12:35:04.919128+0200 com.mycompanty.mac.prevention.Extension Failed to create the ES client: 4 I really need a little light or guidance on this... I haven't even scratched the surface, and already stuck.
Nov ’20
Reply to Can my User-Agent know (be notified) of Configuration profile changes?
No one cared to answer, and I don't have an answer either - but in the mean time I received confirmation from Apple (I opened a tech-support-incident for this issue) that indeed this is a "Bug" or "unexpected behavior" of the operating system. No workaround was suggested by the tech-support engineers. My rather horrible work-around to this scenario is to "poll" by spawning a new instance of the same daemon executable (using NSTask) every few minutes, just so it can call the AXIsProcessTrustedWithOptions method, get a "fresh" and reliable answer and exit with return-code. If that answer is "NO", then I quit+relaunch the original process.
Dec ’20
Reply to XPC Services for a daemon
Have you found the solution? can you advise on how to do this? I'm trying this for days and days now, with very little success --- I have a sample code (from GitHub) that does this, but its daemon is not code-signed at all. When I try to apply this to my own global daemon - the client can't connect to it - its connection is invalidated, and I simply don't know what's wrong and what to don next. So can you spare your findings here, if you finally got it to work?
Jan ’21
Reply to How to publish an XPC Service in a global daemon that employs EndpointSecurity framework?
My daemon is up and running at all times, and is doing its work (some kind of monitoring and blocking of specific authorization events from EndpointSecurity framework). I started this endeavor with a working-order global daemon. My goal is to keep it small fast and safe, but still receive "control commands" from external process, and for that I want it to publish an XPC Service. Of course it does appear in the sudo launchctl list, and I can also launchctl print its state and properties without problem.
Jan ’21
Reply to How to publish an XPC Service in a global daemon that employs EndpointSecurity framework?
I saved and compared the output of launchctl print for both the working sample global-daemon and mine. They both look benign and identical, except for the expected differences (label of the daemon, path of executable, PID and port number of the endpoint). They also both have this environment = { XPC_SERVICE_NAME => com.mycompany.itm.service } entry, which says launchd KNOWS my global daemon should publish an XPC Service by this name. I managed to make another tiny progress, by trying to connect to my global daemon from the UI app of the sample-code I'm using - the one that succeeds in communicating with the sample daemon. I duplicated the code there, and try to talk to the two daemons - each with its own label and protocol. Now, the UI client app no longer calls my connection invalidation handler immediately as I try to get to the remote object proxy and send it a message, like thus:     id ro = [self.myServiceConnection remoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) {         NSLog(@"Error obtaining remote object: %@", error);  }];     if (myServiceRemote) {         [preventionRemote getStatus: ^(NSString * _Nonnull status) {  NSLog(@"Service status: %@", status);  }];     } I get this NSError. 2021-01-17 20:20:38.895040+0200 Client[18858:420994] Error obtaining remote object: Error Domain=NSCocoaErrorDomain Code=4097 "connection to service on pid 0 named com.mycompany.itm.service" UserInfo={NSDebugDescription=connection to service on pid 0 named com.mycompany.itm.service} Now what? I can't figure out how to debug this thing effectively - these are caveman's methods...
Jan ’21
Reply to How to publish an XPC Service in a global daemon that employs EndpointSecurity framework?
Apple dev forum's usability and documentation is in par with the other parts of the OS and frameworks... that is... again I find myself disappointed. Anyway, Yet another hint about this issue (still unresolved, dear Eskimo - I would be so grateful for any ideas...) When my client is sandboxed - I get the "connection invalidation" handler called. when it's NOT sandboxed, I get the NSError 4097 trying to obtain the remoteObjectProxy from the connection. Go figure. The listener on my global daemon is never called for a new connection attemp (so my logs show) so I guess the connection attempt is blocked at the launchd level, or at some security stage - however, I just can't find anything in the logs, and I don't know how WHICH processes and frameworks are involved. The more I read documentation, the more I become confused - There seem to be .plist configurations For XPC Services (that are bundled as a "plugin" within an application) and whose entries may (or not?) be relevant to my case - but where and how would I stick those in my scenario? It's been almost 2 weeks of struggle already, and I don't know where to go next.
Jan ’21
Reply to open(/var/db/DetachedSignatures) - Undefined error:0
I have the same problem (Xcode 12.3, MacOS 10.15 Catalina and 11.1 Big Sur). Our code (a security tool based on the new EndpointSecurity framework) attempts to extract some code-signing information for processes as part of logic that determines whether or not to authorize some user actions) So we execute CFDictionaryRef attributes = (bridge CFDictionaryRef)@{(bridge NSString *)kSecGuestAttributePid : [NSNumber numberWithInt:self.pid] }; SecCSFlags options = kSecCSDefaultFlags; status = SecCodeCopyGuestWithAttributes(NULL, attributes, options, &dynamicCode); and then do some verifications on the dynamicCode -- however, we're flooded with the same logs as the OP, plus, for some reason - despite the method returning success, OS hangs and kills our process immediately at that point (EndpointSecurity clients have this harsh reaction to just about anything, including any attempt to debug, or breakpoint, or run with instruments, or experience certain exceptions etc.). When run outside of the ES context - the code runs just fine, but logs are still emitted, for each execution of the SecCodeCopyGuestWithAttributes
Jan ’21
Reply to NSXPCConnection from LaunchDaemon to LaunchAgent
Hi, have a similar scenario, and have been trying to do this for quite some time, to no avail (my "Agent" isn't a UI-session, but still runs as a daemon on the user's session). My global-daemon (runs in the system domain as root) receives connection from my "Agent", "Agent" can send messages to daemon successfully, and receive results. Now if you could be so kind as to space a few lines of code explaining what it means to "send the anonymous XPC listener endpoint to the daemon" and how can Daemon use this endpoint. I tried several things and they didn't work for me so far. In my case, it's not a "one time" job. Agent connects to Daemon and Daemon needs to regularly report its actions related to the Agent's user (I can have an agent for each user logged in). My current state of code (not working) is: Agent side creating connection: ObjectiveC // lazy property getter (NSXPCConnection *) myXPCConnection { // Create the XPC Connection on demand if (_myXPCConnection == nil) { _myXPCConnection = [[NSXPCConnection alloc] initWithMachServiceName:preventionServiceLabel options:NSXPCConnectionPrivileged]; _myXPCConnection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(myXPCProtocol)]; // Attempt to create a bi-directional connection, so to receive reports from the XPC service. _myXPCConnection.exportedInterface = NSXPCInterface interfaceWithProtocol:@protocol(OITPreventionXPCProtocol)]; _myXPCConnection.exportedObject = self; _myXPCConnection.invalidationHandler = ^{ // on invalidation we simply nullify connection reference, so it will be re-created once app tries to use it again. [[NSOperationQueue mainQueue] addOperationWithBlock:^{ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-retain-cycles" self.myXPCConnection.invalidationHandler = nil; self.myXPCConnection = nil; os_log(preventionUILog, "connection has been invalidated"); #pragma clang diagnostic pop }]; }; _myXPCConnection.interruptionHandler = ^{ // on interruption we simply nullify connection reference, so it will be re-created once app tries to use it again. [[NSOperationQueue mainQueue] addOperationWithBlock:^{ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-retain-cycles" self.myXPCConnection.interruptionHandler = nil; self.myXPCConnection = nil; os_log(preventionUILog, "connection interrupted"); #pragma clang diagnostic pop }]; }; [_myXPCConnection resume]; // New connections always crated and starts in a suspended state } return _myXPCConnection; } Daemon side: ObjectiveC (BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection { assert(listener == _listener); assert(newConnection != nil); BOOL accept = NO; do { // Verify client identity, only accept if client is code-signed by our teamID and if its signingID is of our Agent. if (/* not allowed connection.... then */) break; accept = YES; // we accept connections from processes signed by our development team (proofpoint) // now see who's calling. if (/* it is Agent */) [self.monitor agentConnected:newConnection]; // Configure incoming connection. First, set the interface that the exported object implements. newConnection.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(OITPreventionXPCProtocol)]; // Next set self to be the object the connection exports. All messages sent on the connection to this service will be sent to self to handle. The connection retains the exported object. newConnection.exportedObject = self; newConnection.invalidationHandler = ^{ [[NSOperationQueue mainQueue] addOperationWithBlock:^{ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-retain-cycles" [self.monitor agentDisconnectedForUser:newConnection.effectiveUserIdentifier]; #pragma clang diagnostic pop }]; }; newConnection.interruptionHandler = ^{ [[NSOperationQueue mainQueue] addOperationWithBlock:^{ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-retain-cycles" os_log_info(myLog, "Agent Connection interrupted."); #pragma clang diagnostic pop }]; }; os_log_info(myLog, "XPCListener accepted XPC connection from pid: %d", newConnection.processIdentifier); [newConnection resume]; // New connections always start in a suspended state, start it } while(false); return accept; // Returning YES from this method tells the system that you have accepted this connection. } and last - when Connection is established, and after Daemon receives a message call and replies to Daemon - I try to use the connection from the Daemon side like this: ObjectiveC(void)reportPrevention:(MYEventESInfo * _Nonnull)eventInfo {     uid_t user = eventInfo.processInfo.auid;     NSXPCConnection *agentConnection = [self.connectedAgents objectForKey:@(user)];     if (agentConnection != nil) {         [agentConnection.remoteObjectProxy eventHandled:[eventInfo dictionary]]; // HERE I CRASH WITH EXCEPTION     }     else {         os_log(monitoringLog, "No Agent for Event: %{public}@", eventInfo );     } } Objective-C exception : method 'eventHandled:' unknown to remoteObjectProxy. Any idea what's wrong?
Mar ’21
Reply to Notification/callback mechanism
This post is wonderful, and I'm now trying to establish my "back connection" from daemon-XPC-service back to its user-bound agents. One question though. I AM SURE I read somewhere in The XPC documentation that once established - an XPC connection is bi-directional? doesn't that mean that on some lower-level both parties (the "Daemon-XPC-Service" publishing itself via machServiceName and its (multiple) clients) can initiate "requests" on the same connection? Or maybe I got this wrong and the "bi-directional" part is only the "response" passing back for a "request" ? I'd like a clarification. In my case, NSProgress (oh, lovely NSProgress) isn't enough, and I must pass a dictionary describing some work Deamon-XPC-Service has done that is related to the user's agent (client). Because I may have more than one XPC-client (actually, one per logged-in user) The global notification isn't best choice (unless I could pack there all the data I need to pass, together with the user-ID, so that all agents would listen, and filter for their own user-id) Last - both global-daemon and user-agent can of course be killed/restarted/fail-to-launch because they lack some TCC permissions and so on - how is best to manage such scenario of several clients, each with its own normal and "back" XPC connection to the Daemon?
Mar ’21
Reply to Notification/callback mechanism
Could you clarify how "Client/Agent", after creating an anonymous listener and getting its endpoint, "uses an XPC message to send that to the service." ??? To send something to the service/daemon, Client/Agent side needs to already have established a connection? and how do you send an endpoint in an XPC message? how you obtain it on the other (Service/Daemon) side? and is the new connection-from-endpoint created on the service side unique and maintained for that specific Client/Agent? Can I have more than one?
Mar ’21