I am looking for inputs to better understand MacOS entitlements. I ask this in context of OpenJDK project, which builds and ships the JDK. The build process makes uses of make
tool and thus doesn't involving building through the XCode
product. The JDK itself is a Java language platform providing applications a set of standard APIs. The implementation of these standard APIs internally involves calling platform specific native library functions. In this discussion, I would like to focus on the networking functions that the implementation uses. Almost all of these networking functions and syscalls that the internal implementation uses are BSD socket related. Imagine calls to socket()
, connect()
, getsockopt()
, setsockopt()
, getaddrinfo()
, sendto()
, listen()
, accept()
and several such.
The JDK that's built through make
is then packaged and made available for installation. The packaging itself varies, but for this discussion, I'll focus on the .tar.gz archived packaging. Within this archive there are several executables (for example: java
, javac
and others) and several libraries. My understanding, based on what I have read of MacOS entitlements is that, the entitlements are set on the executable and any libraries that would be loaded and used by that executable will be evaluated against the entitlements of the executable (please correct me if I misunderstand).
Reading through the list of entitlements noted here https://developer.apple.com/documentation/bundleresources/entitlements, the relevant entitlements that an executable (like "java") which internally invokes BSD socket related syscalls and library functions, appear to be:
com.apple.security.network.client
- https://developer.apple.com/documentation/bundleresources/entitlements/com.apple.security.network.client
com.apple.security.network.server
- https://developer.apple.com/documentation/bundleresources/entitlements/com.apple.security.network.server
com.apple.developer.networking.multicast
- https://developer.apple.com/documentation/bundleresources/entitlements/com.apple.developer.networking.multicast
Is my understanding correct that these are the relevant ones for MacOS? Are there any more entitlements that are of interest? Would it then mean that the executables (java
for example) would have to enroll for these entitlements to be allowed to invoke those functions at runtime?
Reading through https://developer.apple.com/documentation/bundleresources/entitlements, I believe that even when an executable is configured with these entitlements, when the application is running if that executable makes use of any operations for which it has an entitlement, the user is still prompted (through a UI notification) whether or not to allow the operation. Did I understand it right?
The part that isn't clear from that documentation is, if the executable hasn't been configured with a relevant entitlement, what happens when the executable invokes on such operation. Will the user see a UI notification asking permission to allow the operation (just like if an entitlement was configured)? Or does that operation just fail in some behind the scenes way?
Coming back to the networking specific entitlements, I found a couple of places in the MacOS documentation where it is claimed that the com.apple.developer.networking.multicast
entitlement is only applicable on iOS. In fact, the entitlement definition page for it https://developer.apple.com/documentation/bundleresources/entitlements/com.apple.developer.networking.multicast says:
"Your app must have this entitlement to send or receive IP multicast or broadcast on iOS. It also allows your app to browse and advertise arbitrary Bonjour service types."
Yet, that same page, a few lines above, shows "macOS 10.0+". So, is com.apple.developer.networking.multicast
entitlement necessary for an executable running on MacOS which deals with multicasting using BSD sockets?
As a more general comment about the documentation, I see that the main entitlements page here https://developer.apple.com/documentation/bundleresources/entitlements categorizes some of these entitlements under specific categories, for example, notice how some entitlements are categorized under "App Clips". I think it would be useful if there was a category for "BSD sockets" and under that it would list all relevant entitlements that are applicable, even if it means repeating the entitlement names across different categories. I think that will make it easier to identify the relevant entitlements.
Finally, more as a long term question, how does one watch or keep track of these required entitlements for these operations. What I mean is, is it expected that application developers keep visiting the macos documentation, like these pages, to know that a new entitlement is now required in a new macos (update) release? Or are there other ways to keep track of it? For example, if a newer macos requires a new entitlement, then when (an already built) executable is run on that version of macos, perhaps generate a notification or some kind of explicit error which makes it clear what entitlement is missing? I have read through https://developer.apple.com/documentation/bundleresources/diagnosing-issues-with-entitlements but that page focuses on identifying such issues when a executable is being built and doesn't explain the case where an executable has already been shipped with X entitlements and a new Y entitlement is now required to run on a newer version of macos.
jaikiran, Thanks for asking about this here. Any changes you make to OpenJDK will benefit a lot of developers, so it’s good to get these detailed nailed down.
Lemme separate out the various topics…
That’s correct. Creating distribution-signed code for macOS is really clear about this:
You apply entitlements to a main executable.
and:
Don’t apply entitlements to library code.
The above means that, as a Java VM developer, you don’t have direct control over the entitlements applied to your code. I have a couple of hints on that front:
-
Most third-party tools have some sort of ‘packaging’ process that wraps the developer’s code into an app that the user can double click in the Finder. This is a good place to encode your knowledge about what entitlements you need. For example, if your JIT needs
com.apple.security.cs.allow-jit
, your packager can either fails if it’s not present, or just add it unilaterally. -
On macOS it’s possible to programmatically determine what entitlements the executable of the current process was signed with. You could use that to trap at runtime, with a nice clear message, if you’re run in a process with the wrong entitlements. Lemme know if you’re interested in exploring that and I’ll dig up some examples.
That varies by API:
-
Most APIs just fail, returning some sort of error. That’s certainly the case for the entitlements you mentioned.
-
Some APIs trap.
-
Some APIs silently do nothing.
-
Or log something and then do nothing.
As others have noted, these only apply if the App Sandbox is enabled. See App Sandbox Resources for more about that technology.
There’s one subtlety related to the App Sandbox. If a sandboxed app spawns a child process, that process inherits the parent’s static sandbox. The child process is running a main executable, but that executable should not use normal sandbox entitlements. Rather, sign it with com.apple.security.app-sandbox
and com.apple.security.inherit
. For more on this, see:
-
Embedding a command-line tool in a sandboxed app documentation
-
Resolving App Sandbox Inheritance Problems here on the forums
I wanna stress that this only applies to sandbox entitlements. Other entitlements, like com.apple.security.cs.allow-jit
, behave normally in this case.
One of my colleagues has already pointed you at TN3179 Understanding local network privacy, which has a bunch of info on this topic.
As to whether this entitlement is required on macOS, that’s definitely not the case. TN3179 says that, but you have to join the dots.
The “macOS 10.0+” at the top of this page is just wrong. I filed a bug and we fixed that a while back (r. 105890246). Sadly, that patch seems to have come unstuck, so I’ve filed a new bug (r. 146015779).
The hardened runtime enables a bunch of additional security checks. None of them are related to networking. Some of them are very important to a Java VM author, most notably the com.apple.security.cs.allow-jit
-> com.apple.security.cs.allow-unsigned-executable-memory
-> com.apple.security.cs.disable-executable-page-protection
cascade. My advice on that front:
-
This sequence is a trade off between increasing programmer convenience and decreasing security.
com.apple.security.cs.allow-jit
is the most secure, but requires extra work in your code. -
Only set one of these entitlements, because each is a superset of its predecessor.
-
com.apple.security.cs.disable-executable-page-protection
is rarely useful. Indeed, on Apple silicon [1] it’s the same ascom.apple.security.cs.allow-unsigned-executable-memory
.
If you want to investigate moving from com.apple.security.cs.allow-unsigned-executable-memory
to com.apple.security.cs.allow-jit
, lemme know because there are a bunch of additional resources on that topic.
[1] I’m talking about native code here. If you’re running under Rosetta and thus generating Intel code, this distinction is still relevant.
There are two ways we typically announce new constraints like this:
-
Announcements on Developer > News — That has an RSS feed which is well worth monitoring.
-
In WWDC sessions
But, yeah, this can be tricky. When we add constraints we usually try to do it in a binary compatible way, so that existing apps continue to run. However:
-
That’s not always possible.
-
In some cases the constraint only applies to updated apps, either via an App Store ingestion check or via a linked-on-or-later check.
Another pain point for Java developers is TCC, that is, the various permissions in System Settings > Privacy & Security. The specific problem is that Java developers often use a script as their main executable. I talk about this more in the TCC and Main Executables section of On File System Permissions.
I expect the above will give you plenty to think about |-: Reply here if you have any follow-up questions.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"