I'm working on an enterprise product that's mainly a daemon (with Endpoint Security) without any GUI component. I'm looking into the update process for daemons/agents that was introduced with Ventura (Link), but I have to say that the entire process is just deeply unfun. Really can't stress this enough how unfun.
Anyway...
The product bundle now contains a dedicated Swift executable that calls SMAppService.register for both the daemon and agent.
It registers the app in the system preferences login items menu, but I also get an error.
Error registering daemon: Error Domain=SMAppServiceErrorDomain Code=1 "Operation not permitted" UserInfo={NSLocalizedFailureReason=Operation not permitted}
What could be the reason?
I wouldn't need to activate the items, I just need them to be added to the list, so that I can control them via launchctl.
Which leads me to my next question, how can I control bundled daemons/agents via launchctl? I tried to use launchctl enable and bootstrap, just like I do with daemons under /Library/LaunchDaemons, but all I get is
sudo launchctl enable system/com.identifier.daemon
sudo launchctl bootstrap /Path/to/daemon/launchdplist/inside/bundle/Library/LaunchDaemons/com.blub.plist
Bootstrap failed: 5: Input/output error (not super helpful error message)
I'm really frustrated by the complexity of this process and all of its pitfalls.
Post
Replies
Boosts
Views
Activity
The pidversion of a process with the same pid can increase during its lifetime. Which events, other than exec calls, can cause this increase in the pidversion?
In other words, to what Endpoint Security events, other than fork, exec and exit, do I have to subscribe to get a process's complete and traceable pidversion history?
I need to generate a compile_commands.json for our C++ project. I need it for static code analysis tools as well as enabling clangd usage with other editors.
I've tried two methods but it only works for some files with clangd. The logs of the clangd extension in VS Code indicate only that many files can't be compiled. If it works for a file, it's great, but sadly it's not consistent.
I've used these two approaches to generate the compile_commands.json:
using xcpretty
xcrun xcodebuild -projectmyproject.xcodeproj -scheme myscheme clean build CODE_SIGNING_ALLOWED=NO | xcpretty -r json-compilation-database -o build/compile_commands.json
the recommended way by sonarcloud
xcrun xcodebuild -project myproject.xcodeproj -scheme myscheme \
-configuration Debug clean build CODE_SIGNING_ALLOWED=NO OTHER_CFLAGS="\$(inherited) -gen-cdb-fragment-path \$(PROJECT_DIR)/CompilationDatabase"
sed -e '1s/^/[\'$'\n''/' -e '$s/,$/\'$'\n'']/' MacOS/Source/CompilationDatabase/*.json > MacOS/Source/compile_commands.json
Is there something missing or are there better ways to generate the compile_commands.json without having to write a full cmake definition?
macOS Sonoma 14.4
Xcode 15.3
Hi,
I'm experimenting with C++/Swift interop and am following the official documentation, especially the section "Using Swift APIs of Imported Framework Target".
I'm able to call Swift code from C++ when both Swift and C++ source files belong to the same app bundle or framework target, by importing the -Swift.h header.
However, I'm not able to import the Swift code from a framework using a different C++ target.
This is my test project setup:
testApp is my app bundle and subprocesses is my framework, containing the auto-generated and unchanged subprocesses.h and some example swift code with a single public function. The subprocesses framework is added as a dependency to testApp and the framework has the C++ interoperability enabled.
But when I try to import the auto-generated -Swift.h in main.cpp, it doesn't show up.
What do I need to do so that I can call Swift framework code in a different C++ target? I think I've done everything according to the documentation.
Thanks!
Addendum
I've also experimented with Apple's Xcode example projects. The "Mixing Languages in an Xcode project" (Link) works as expected. I was able to add a command line app target, and when I add the Fibonacci framework as a dependency, I'm able to use #include <Fibonacci/Fibonacci-Swift.h> and access the Swift API.
However, the second of Apple's examples, "Calling APIs Across Language Boundaries" (Link) fails to compile out of the box (No member named 'createForest' in 'ForestBuilder::MagicForest').
The dns_util API like dns_parse_packet is marked deprecated as of macOS 13.0. What is the successor? I'm specifically interested in parsing parsing DNS packets captured with libpcap.
As an aside, I was surprised that I didn't get a deprecation warning. We still use Big Sur as deployment target (which seems to control the warning in this case), but of course, we support the newest versions. Is the API guaranteed to work on Sonoma even though it was deprecated with Ventura?
We noticed that sometimes exec messages delivered by Endpoint Security contain unexpected data since Ventura:
When a script is executed by a shell, like zsh, the process data for the responsible and the target process are identical, including the pidversion - but only sporadically. At first, I thought that it might be the case that pidversions are not incremented when a process execs into the same image. But my tests showed that this is not the case, and the pidversion is incremented in any case.
I also tried to trigger this behavior with a program basically recursively execs into itself, but that worked as expected. So far, I've only observed this behavior with shell scripts.
Here is an example:
(lldb) p *(msg->process)
(es_process_t) $7 = {
audit_token = {
val = ([0] = 4294967295, [1] = 0, [2] = 0, [3] = 0, [4] = 0, [5] = 12196, [6] = 100873, [7] = 29277)
}
ppid = 10691
original_ppid = 10691
group_id = 10691
session_id = 10691
codesigning_flags = 570493697
is_platform_binary = true
is_es_client = false
cdhash = "\U00000017\x8e$Y\xd0Z\x90\x8f\x92S\xc3s\xff<\x9c\xd6\xe2a\U00000011V"
signing_id = (length = 13, data = "com.apple.zsh")
team_id = (length = 0, data = 0x0000000000000000)
executable = 0x00000001036bb1e8
tty = nullptr
start_time = (tv_sec = 1669896286, tv_usec = 191693)
responsible_audit_token = {
val = ([0] = 501, [1] = 0, [2] = 0, [3] = 0, [4] = 0, [5] = 10682, [6] = 100349, [7] = 24944)
}
parent_audit_token = {
val = ([0] = 4294967295, [1] = 0, [2] = 0, [3] = 0, [4] = 0, [5] = 10691, [6] = 100873, [7] = 24963)
}
}
(lldb) p *(msg->event.exec.target)
(es_process_t) $8 = {
audit_token = {
val = ([0] = 4294967295, [1] = 0, [2] = 0, [3] = 0, [4] = 0, [5] = 12196, [6] = 100873, [7] = 29277)
}
ppid = 10691
original_ppid = 10691
group_id = 10691
session_id = 10691
codesigning_flags = 570493697
is_platform_binary = true
is_es_client = false
cdhash = "\U00000017\x8e$Y\xd0Z\x90\x8f\x92S\xc3s\xff<\x9c\xd6\xe2a\U00000011V"
signing_id = (length = 13, data = "com.apple.zsh")
team_id = (length = 0, data = 0x0000000000000000)
executable = 0x00000001036bba00
tty = nullptr
start_time = (tv_sec = 1669896286, tv_usec = 191693)
responsible_audit_token = {
val = ([0] = 501, [1] = 0, [2] = 0, [3] = 0, [4] = 0, [5] = 10682, [6] = 100349, [7] = 24944)
}
parent_audit_token = {
val = ([0] = 4294967295, [1] = 0, [2] = 0, [3] = 0, [4] = 0, [5] = 10691, [6] = 100873, [7] = 24963)
}
}
Is this an error in Endpoint Security, or am I missing something here?
Steps to reproduce
execute a script repeatedly to trigger the behavior, e.g.
for i in {1..200000}; do
./script1.sh > /dev/null;
# sleep 1; still happens, but you have to wait longer
done
in another terminal you can use eslogger like this
sudo eslogger exec | jq 'if .process.audit_token.pidversion == .event.exec.target.audit_token.pidversion then "\(input_line_number) pidversion did not change: \(.process.audit_token.pidversion == .event.exec.target.audit_token.pidversion) \(.process.executable.path) -> \(.event.exec.target.executable.path)" else empty end'
which could output something like this:
"3211638 pidversion did not change: true /bin/zsh -> /bin/zsh"
I want to compile curl in a such a way that it can access the macOS keychain for certificate lookup. I have added an internal company CA certificate to my system keychain and am trusting it.
When I build curl as described in the curl docs (which I am apparently not allowed to link) with Secure Transport I am able to connect to a server with a certificate signed by our internal CA. However, this does not work as root.
./curl company.com # works
sudo ./curl company.com # invalid certificate chain
When I repeat the same tests with the curl version that ships with the os, it works in both cases. Same results with a small example program when I link against my build vs linking against Apple's curl.
I've also tried to compile it with libressl (with and without Secure Transport) but then keychain access doesn't even work as normal user.
Any idea what's going wrong? How does Apple compile curl so that it works as root?
Is it possible to tell whether a process has crashed with ES or to get a notification when a crash happens?
I was looking at the stat field of es_event_exit_t in combination with the macros like WTERMSIG from wait (2), but that probably wouldn't be enough? A process could be terminated by a signal without a crash (e.g. by sending SIGSEGV via terminal).
I ultimately want to analyze a crash report as soon as the crash report is available. Currently that's done by subscribing to ES_EVENT_TYPE_NOTIFY_CREATE but this approach comes with a few drawbacks.
I'm looking at the JSON of an .ips crash report on macOS 12.3.
"uptime" : 21000,
"procLaunch" : "2022-03-28 12:12:34.0643 +0200",
"procRole" : "Unspecified",
"version" : 2,
"userID" : 0,
"deployVersion" : 210,
"modelCode" : "MacBookPro18,1",
"procStartAbsTime" : 514306295821,
"coalitionID" : 2566,
"osVersion" : {
"train" : "macOS 12.3",
"build" : "21E230",
"releaseType" : "User"
},
"captureTime" : "2022-03-28 12:12:45.1086 +0200",
"incident" : "3B40D69B-0019-46D7-AD93-B73D02A4B636",
"bug_type" : "309",
"pid" : 17162,
"procExitAbsTime" : 514570783723,
I was expecting the field procStartAbsTime and procExitAbsTime to be UNIX timestamps, but that would result in dates in 1986.
What format are they and how can they be converted?
Also I noticed that BigSur creates both the old .crash and the new .ips format crash reports, even for the exact same crash, not at the same time though. So one time it creates a .crash, the next time an .ips.
FB9843414
Just encountered a very annoying bug in Xcode. Let's say you want to link a static library like C++ fmt. If the directory you specify as library search path contains both a dynamic libfmt.dylib as well as the static libfmt.a version of that library, Xcode will choose the .dylib version - regardless whether you explicitly specified the .a binary under the target's build phases.
Hopefully this nasty bug can finally be fixed. This stackoverflow post is over 4 years old, but saved my sanity.
We distribute an macOS app bundle with a main executable, a helper executable, a nested app bundle and an XPCService.
myApp.app
└── Contents
├── _CodeSignature
│ └── CodeResources
├── embedded.provisionprofile
├── Info.plist
├── MacOS
│ ├── myHelperApp.app
│ │ └── Contents...
│ ├── mainExecutable
│ └── helperExecutable
├── PkgInfo
└── XPCServices
└── myXPCService.xpc
└── Contents...
Our mainExecutable requires FullDiskAccess and the helperExecutable requires Accessibility Access. Since this a product for enterprise customers, the TCC permissions usually get granted via a PPPC profile.
What would be a good bundle identifier naming scheme for such a structure? com.example.myApp for the main app bundle/executable and com.example.myApp.helperExecutable etc. for all additional targets?
When creating the PPPC profile, do I only refer to the bundle identifier of the main bundle com.example.myApp? If so, does that mean that every executable in that bundle has these privileges? At least this is what the manual approach would suggest, where the user can drag an entire app bundle to the privacy settings.
The helperExecutable gets copied into the bundle during the build process. But when it is run from its Xcode scheme, it is run from the build directory, outside the final bundle. This requires the helper binary to be extra granted Accessibility permissions, at least during development. Is there a better way?
Thanks (Quinn)!
Hi,
I've used Xcode's conversion tool to convert a chrome extension. However, the tool throws warnings for basically every key and permission in the manifest.json file. It does create an Xcode project though. I've validated the manifest.json against 3 different json standards and no issues were detected. I'm using the latest version of Monterey and Xcode.
╰─$ xcrun safari-web-extension-converter --objc --macos-only .
objc[2832]: Class AMSupportURLConnectionDelegate is implemented in both /usr/lib/libamsupport.dylib (0x21686f130) and /Library/Apple/System/Library/PrivateFrameworks/MobileDevice.framework/Versions/A/MobileDevice (0x108b4c2c8). One of the two will be used. Which one is undefined.
objc[2832]: Class AMSupportURLSession is implemented in both /usr/lib/libamsupport.dylib (0x21686f180) and /Library/Apple/System/Library/PrivateFrameworks/MobileDevice.framework/Versions/A/MobileDevice (0x108b4c318). One of the two will be used. Which one is undefined.
Xcode Project Location: [...]/Browser Extensions/Chrome extension/DistPublic
App Name: [...]
App Bundle Identifier: com.yourCompany.[...]
Platform: macOS
Language: Objective-C
Warning: The following keys in your manifest.json are not supported by your current version of Safari. If these are critical to your extension, you should review your code to see if you need to make changes to support Safari:
description
webRequestBlocking
persistent
version
nativeMessaging
<all_urls>
tabs
scripts
storage
alarms
manifest_version
webRequest
name
icons
The only permission that I found is really not supported is webRequestBlocking. But even if I remove it, the tool still complains about the rest.
Any idea what is causing this behavior?
Hi,
I have a macOS app bundle with multiple binaries. I can create an archive, notarize it and export the app bundle all within Xcode. But when I try to export the archive from the command line I get an error message:
╰─$ xcodebuild -exportArchive -archivePath myarchive.xcarchive -exportOptionsPlist myarchiveExportOptions.plist -exportPath ~/Desktop -verbose
2021-12-06 09:03:39.241 xcodebuild[15117:509468] [MT] IDEDistribution: -[IDEDistributionLogging _createLoggingBundleAtPath:]: Created bundle at path "/var/folders/qj/55jnf34d0dz7nrjmw9kkvj6c0000gn/T/....xcdistributionlogs".
error: exportArchive: helperBinary does not support provisioning profiles.
Error Domain=IDEProvisioningErrorDomain Code=10 "helperBinary does not support provisioning profiles." UserInfo={IDEDistributionIssueSeverity=3, NSLocalizedDescription=helperBinary does not support provisioning profiles., NSLocalizedRecoverySuggestion=helperBinary does not support provisioning profiles, but provisioning profile "$myprofile distribution" has been manually specified. Remove this item from the "provisioningProfiles" dictionary in your Export Options property list.}
** EXPORT FAILED **
This is the export options plist I use (that's the one Xcode has exported):
<?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>destination</key>
<string>export</string>
<key>method</key>
<string>developer-id</string>
<key>provisioningProfiles</key>
<dict>
<key>$BUNDLE_ID</key>
<string>"$myprofile distribution"</string>
</dict>
<key>signingCertificate</key>
<string>Developer ID Application</string>
<key>signingStyle</key>
<string>manual</string>
<key>teamID</key>
<string>...</string>
</dict>
</plist>
How can I exclude the helper binary for the provisioning profile during the export of the archive? The main executable uses endpoint security. I tried to add a second key for the helper binary to specify no provisioning profile, but that didn't work either.
Note: I already posted this question but wasn't able to edit it anymore. So I had to repost it in order to improve the readability (not ideal).
Hi,
I have a macOS app bundle with multiple binaries. I can create an archive, notarize it and export the app bundle all within Xcode. But when I try to export the archive from the command line I get an error message:
╰─$ xcodebuild -exportArchive -archivePath myarchive.xcarchive -exportOptionsPlist myarchiveExportOptions.plist -exportPath ~/Desktop -verbose
2021-12-06 09:03:39.241 xcodebuild[15117:509468] [MT] IDEDistribution: -[IDEDistributionLogging _createLoggingBundleAtPath:]: Created bundle at path "/var/folders/qj/55jnf34d0dz7nrjmw9kkvj6c0000gn/T/....xcdistributionlogs".
error: exportArchive: helperBinary does not support provisioning profiles.
Error Domain=IDEProvisioningErrorDomain Code=10 "helperBinary does not support provisioning profiles." UserInfo={IDEDistributionIssueSeverity=3, NSLocalizedDescription=helperBinary does not support provisioning profiles., NSLocalizedRecoverySuggestion=helperBinary does not support provisioning profiles, but provisioning profile someName distribution has been manually specified. Remove this item from the "provisioningProfiles" dictionary in your Export Options property list.}
** EXPORT FAILED **
This is the export options plist I use (that's the one Xcode has exported):
<?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>destination</key>
<string>export</string>
<key>method</key>
<string>developer-id</string>
<key>provisioningProfiles</key>
<dict>
<key>...</key>
<string>someName distribution</string>
</dict>
<key>signingCertificate</key>
<string>Developer ID Application</string>
<key>signingStyle</key>
<string>manual</string>
<key>teamID</key>
<string>...</string>
</dict>
</plist>
How can I exclude the helper binary for the provisioning profile during the export of the archive? The main executable uses endpoint security.
I couldn't find an event type to subscribe to for identifying user logins (SSH, GUI). As an alternative approach I investigated the possibility of monitoring process events e.g. for loginwindow.
However, I noticed that this doesn't seem to work either, because the user id and audit session id changes from root 0/system session 100001 right after exec to the respective user's id (e.g. 501) and his gui session id (e.g.100005) after successful authentication. Since I couldn't find any evidence for a fork or exec event, I assume that something like setuid is used internally.
Is there any way one could get notified for events which change the process' context (like setuid or a session id change)?
Are there events for user logins/sessions I've overlooked?