I believe this is a general problem when writing low-level security and monitoring tools.
The EndpointSecurity framework provides lots of information for the events it allows to Monitor (and/or Authorize) but all these are "kernel level" details, that usually don't allow understanding (and aggregating) low-level events according to User Intent
e.g. Saving all attachments of an e-mail message from Apple Mail program to a USB-disk, will create a long series of low-level file-system events, some preliminary (touching and verifying the destination can fit the attachments) some for moving/copying, some for rounding-up, some for indexing those files on the new volume, and so on.
Is it possible to somehow obtain the NSUserActivity object/instance/Identifier related to such low-level event? Is the kernel itself aware of user activities?
Any hint or suggestion or strategy will be greatly appreciated
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Hi.
I'm implementing UNUserNotificationCenter delegate method:
userNotificationCenter(_:didReceive:withCompletionHandler:)
in MacOS Big-Sur and Catalina, in order to be notified when user dismisses local notifications of my App. (we also handle UNNotificationDefaultActionIdentifier to focus our UI on the item related to the clicked notification, and we also support 2 custom actionIDs.
It all basically works, and even the UNNotificationDismissActionIdentifier arrives at the delegate when user dismisses a single notification. (presses the X shaped button on the top-left).
However, when we have a thread of notifications (grouped by some unique threadID, and looks like a stack onscreen) and the user presses the X and then the "Clear all" button to dismiss the whole thread --
the delegate is only called once, for one arbitrary notification in the stack, and there is no way for me to know that a whole thread was dismissed.
Am I doing something wrong?
Is this a limitation of the delegate protocol?
Is this a bug in UNUserNotificationCenter implementation?
Is there a workaround, or some trick to know that a whole bunch of notifications were dismissed?
Here's my delegate code (sans irrelevant code...)
// Handle notification back-actions
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(nonnull UNNotificationResponse *)response
withCompletionHandler:(nonnull void (^)(void))completionHandler API_AVAILABLE(macos(10.14)) {
NSString *actionId = response.actionIdentifier;
UNNotificationRequest *request = response.notification.request;
NSString *requestId = request.identifier;
NSString *userActionIdentifier = request.content.threadIdentifier;
NSDictionary * myInfo = request.content.userInfo;
if ([actionId isEqualToString:UNNotificationDefaultActionIdentifier]) { // user opened the application from the notification
if ([self.delegate respondsToSelector:@selector(displayThread:forInfo)]) {
dispatch_async(dispatch_get_main_queue(), ^{
[self.delegate displayThread:userActionIdentifier forInfo: myInfo];
});
}
completionHandler();
return;
}
NSString *userReply = nil;
if ([actionId isEqualToString:UNNotificationDismissActionIdentifier]) { // user dismissed the notification
os_log_debug(myLog, "Notification: %{public}@ dismissed", requestId);
}
else { // custom action
NSString *categoryId = response.notification.request.content.categoryIdentifier;
if ([categoryId isEqualToString:OITNotification.copyAction]) {
os_log_debug(myLog, "Notification: %{public}@ dismissed with custom action:%{public}@", requestId, actionId);
}
if ([categoryId isEqualToString:OITPreventionNotification.copyActionWithReply]) {
if ([actionId isEqualToString:@"other"]) {
userReply = [(UNTextInputNotificationResponse*)response userText];
os_log_debug(myLog, "Notification: %{public}@ User custom reply: %{public}@", requestId, userReply);
}
else {
userReply = actionId;
os_log_debug(myLog, "Notification: %{public}@ User Action: %{public}@", requestId, actionId);
}
}
}
if ([self.delegate respondsToSelector:@selector(notification:dismissedWithReply:)]) {
[self.delegate notification:myInfo dismissedWithReply:userReply];
}
[self removeModelIdentifiers:@[response.notification.request.identifier]];
completionHandler();
return;
}
Please ignore the tedious handling of custom actions - my problem is only with "Clear All" thread dismissals. I bring the code just for completeness, in the hopes that someone sees a fault I can't see ---
Thank you very much.
Hi.
I'm writing a framework, and invest a lot in commenting classes, methods, etc. My API is Objective-C, but the issue is same with Swift code too.
If I follow Apple's documentation about the Markup language of code-comments, then in Xcode QuickHelp lot of my formatting simply does not show.
Here are Apple docs on the matter
Here is a sample of class definition comment,
/*!
@brief Comprehensive set of prevention rules.
@discussion OITPreventionSettings instance encapsulates a complete set of prevention "rules" dictated and provided by Backend, controlling the behavior of ITProtector.
At any moment, there can only be a single "ruling" instance of OITPreventionSettings, assigned (synchronously and atomically) to the OITPrevention, while other instances may exist in other states of initialization/demise.
Responsibilities of the class:
* Receive and store a "Settings JSON" from backend (either as File, String or NSDictionary)
* Parse the settings JSON, extract relevant policy clauses, parse their array of prevention rules
* Provide comprehensive parsing errors if rules cannot be applied.
* Compile and own a hierarchy of OITPreventionPolicy and OITPreventionRule objects, with internal representation of the rules, that can be used to fast-decide authorization/prevention events.
* Apply rules to Endpoint-Security event, returning both verdict (actions bit-mask), and the rule-Id responsible for the decision.
Irresponsibilities of the class:
* to decide *when* to become the "active" settings
* to apply itself and evaluate ES events
* Being immutable, It can't change its policies and rules nor their internal representations. Any change of settings require a new instance of OITPreventionSettings.
*/
@interface OITPreventionSettings : NSObject {
}
As you can see in the attached Xcode quick-help window screenshot
, none of the lists appear as lists, and even line-breaks don't apply.
Many other formatting rules don't show either. Is this Apple bug? my misunderstanding? what's the point in documenting something that doesn't and actually never worked?
Hi.
I develop an EndpointSecurity Client (running as root in the system-domain - a launchDaemon defined in /Library/LaunchDaemons/com.company.daemon-name.plist
I register to few "AUTH" events, which I handle on a high-priority concurrent dispatch_queue, using fairly efficient code - so to ensure I meet the EndpointSecurity message deadlines. These are the event types I register for:
ES_EVENT_TYPE_AUTH_EXEC,
ES_EVENT_TYPE_AUTH_OPEN,
ES_EVENT_TYPE_AUTH_CREATE,
ES_EVENT_TYPE_AUTH_CLONE,
ES_EVENT_TYPE_AUTH_RENAME,
ES_EVENT_TYPE_AUTH_EXCHANGEDATA
My daemon seems to handle events in very high loads without a hitch, usually takes round 0.1%-1% of the CPU and almost never more than 10-20MB of RAM - it's very lightweight, and works fine.
HOWEVER - on some customer Macs (Enterprise Macs with lots of IT background processes on them - antivirus packages, software-updaters, and remote-control tools, I see crash logs of my tool, occurring usually when the Mac is unattended (late night, or Mac is asleep). They all have this in common.
The crash reason:
Exception Codes: 0x0000000000000000, 0x0000000000000000
Termination Reason: Namespace ENDPOINTSECURITY, Code 2 EndpointSecurity client terminated because it failed to respond to a message before its deadline
I've done fair statistics, and the minimum deadlines I get are ~30 seconds (LOTS OF TIME!!!) whereas my code usually takes no more than 10 milliseconds to respond to EndpointSecurity framework.
But the crash log also shows that all "working threads" (code-blocks on my Event-Handling dispatch_queue) are stuck in the same OS call - namely:
6 AppKit 0x7ff80db366b4 -[NSWorkspace isFilePackageAtPath:] + 104
In most cases I have 6 or 8 such concurrent blocks pending. This is not the bottom of the stack - they all look like this:
Thread 4:: Dispatch queue: Event Handling Queue
0 libsystem_kernel.dylib 0x7ff809f94e0e __getattrlist + 10
1 CoreServicesInternal 0x7ff80cffbe98 corePropertyProviderPrepareValues(__CFURL const*, __FileCache*, __CFString const* const*, void const**, long, void const*, __CFError**) + 798
2 CoreServicesInternal 0x7ff80cffbb19 prepareValuesForBitmap(__CFURL const*, __FileCache*, _FilePropertyBitmap*, __CFError**) + 394
3 CoreServicesInternal 0x7ff80cff8421 _FSURLCopyResourcePropertyForKeyInternal(__CFURL const*, __CFString const*, void*, void*, __CFError**, unsigned char) + 277
4 CoreFoundation 0x7ff80a084e50 CFURLCopyResourcePropertyForKey + 96
5 CoreFoundation 0x7ff80a09904e -[NSURL getResourceValue:forKey:error:] + 110
6 AppKit 0x7ff80db366b4 -[NSWorkspace isFilePackageAtPath:] + 104
7 ITProtector 0x10ed8da73 0x10ed58000 + 219763
Bottom line is my code - which calls NSWorkspace to determine if a file I need to Authorize is a bundle or not.
My conclusion is that the call hangs forever because (Maybe?) LaunchServices, or the File-system service are busy or pushing back or very busy doing something - I don't know, and I can't reproduce on any of my Macs - As I say this randomly happens on customer Macs when they're unattended.
I now have two distinct problems using -[NSWorkspace isFilePackageAtPath:] (or any alternative I found so far).
The call is usually very fast - but now I can't know in advance how much time it will take.
The call and all its alternatives - are synchronous. Haven't found asynchronous replacement I could call, to introduce my own "timeouts" on the issue.
I need help here - what can cause this API to hang for over a minute? Where to start looking? last - What activity of the OS can impose such long block on this fairly basic File-system query?
Any idea or suggestion or lead would be greatly appreciated.
Thanks!
Contents of sample ITProtector.ips crash log
I am experiencing strange crashes in my (ObjC) code, that insinuate some memory corruption (mostly running SHA256 decryption for file data
in my code there's a
// return object that was stored in encrypted file
- (id) objectFromEncryptedFile:(NSString *)filePath
{
// read MYCrypto object that includes encrypted object of any class
MYCrypto *encData = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
// decrypt, unarchive and return
return [encData objectFromEncryptedData:encData.data];
}
That seems to be called from different queues that are not synchronized.
It came to me that maybe NSKeyedUnarchiver is not "thread safe" and maybe unarchiveObjectWithFile is not reentrant?
Couldn't find anything in the normal documentation, but most of the old docs are no longer searchable.
Can someone shed light on this?