Opened 4 months ago

Closed 4 months ago

Last modified 4 months ago

#73160 closed defect (fixed)

MacPorts doesn’t set the supplementary group list when changing privileges

Reported by: markmentovai (Mark Mentovai) Owned by: jmroot (Joshua Root)
Priority: Normal Milestone: MacPorts 2.11.6
Component: base Version: 2.11.5
Keywords: Cc: breun (Nils Breunese), jmroot (Joshua Root), ryandesign (Ryan Carsten Schmidt), reneeotten (Renee Otten)
Port:

Description

From #73008, and in particular, that bug’s comment:36, comment:39, comment:45, and comment:54:

When MacPorts changes privileges, it doesn’t set the supplementary group list. That results in it retaining membership in any groups that it was originally invoked with. Normally, people will run MacPorts as sudo port …. sudo sets the supplementary group list appropriately for the root user in this case, meaning that even when MacPorts drops privileges, such as to the macports user, it’s actually retaining root’s group membership.

The root user is normally a member of many more groups than the macports user. This is probably representative:

mark@axilla zsh% diff -u <(id -Gn macports | tr ' ' '\n') <(id -Gn root | tr ' ' '\n')    
--- /dev/fd/11	2025-10-24 13:37:57
+++ /dev/fd/12	2025-10-24 13:37:57
@@ -1,6 +1,24 @@
-macports
+wheel
+daemon
+kmem
+sys
+tty
+operator
+procview
+procmod
 everyone
+staff
+certusers
 localaccounts
+admin
 com.apple.sharepoint.group.1
 com.apple.sharepoint.group.2
+_appstore
+_lpadmin
 _lpoperator
+_developer
+_analyticsusers
+com.apple.access_ftp
+com.apple.access_screensharing
+com.apple.access_ssh-disabled
+com.apple.access_remote_ae

There are several groups in there that MacPorts should not have access to when it’s dropped privileges and is running as the macports user, but it retains access to some fairly privileged groups, such as admin. An unprivileged build job running as the macports user would have no impediment to writing into /Applications, for example. This is undesirable, to put it mildly.

In #73008, this came up in a different way. Rather than there being a problem because the unprivileged macports user was running with too much privilege, running with root’s supplementary group membership resulted in it having not enough privilege. Xcode 26 has unbundled the Metal toolchain, which is now installed as an independent component via xcodebuild -downloadComponent MetalToolchain. To use tools from the Metal toolchain (on mac-arm64), cryptexd mounts the Metal toolchain in directory that should be visible to all users.

mark@axilla zsh% xcodebuild -downloadComponent MetalToolchain
Beginning asset download...
Downloaded asset to: /System/Library/AssetsV2/com_apple_MobileAsset_MetalToolchain/4ab058bc1c53034b8c0a9baca6fba2d2b78bb965.asset/AssetData/Restore/022-17211-415.dmg
Done downloading: Metal Toolchain 17A324.

mark@axilla zsh% xcodebuild -showComponent MetalToolchain
Asset Path: /System/Library/AssetsV2/com_apple_MobileAsset_MetalToolchain/4ab058bc1c53034b8c0a9baca6fba2d2b78bb965.asset/AssetData
Build Version: 17A324
Status: installed
Toolchain Identifier: com.apple.dt.toolchain.Metal.32023
Toolchain Search Path: /private/var/run/com.apple.security.cryptexd/mnt/com.apple.MobileAsset.MetalToolchain-v17.1.324.0.t40qgS

mark@axilla zsh% xcodebuild -find metal
/var/run/com.apple.security.cryptexd/mnt/com.apple.MobileAsset.MetalToolchain-v17.1.324.0.t40qgS/Metal.xctoolchain/usr/bin/metal

mark@axilla zsh% xcrun --find metal
/var/run/com.apple.security.cryptexd/mnt/com.apple.MobileAsset.MetalToolchain-v17.1.324.0.t40qgS/Metal.xctoolchain/usr/bin/metal

mark@axilla zsh% xcrun metal --version
Apple metal version 32023.830 (metalfe-32023.830.2)
Target: air64-apple-darwin25.0.0
Thread model: posix
InstalledDir: /private/var/run/com.apple.security.cryptexd/mnt/com.apple.MobileAsset.MetalToolchain-v17.1.324.0.t40qgS/Metal.xctoolchain/usr/metal/current/bin

mark@axilla zsh% mount | grep MetalToolchain
/dev/disk8s1 on /private/var/run/com.apple.security.cryptexd/mnt/com.apple.MobileAsset.MetalToolchain-v17.1.324.0.t40qgS (apfs, sealed, local, read-only, journaled, nobrowse)

But looking closely at the permissions on the path to the Metal toolchain, there’s one directory in the path, /private/var/run/com.apple.security.cryptexd, that denies its group read and search (x):

mark@axilla zsh% ls -ldfT / /private /private/var /private/var/run /private/var/run/com.apple.security.cryptexd /private/var/run/com.apple.security.cryptexd/mnt /private/var/run/com.apple.security.cryptexd/mnt/com.apple.MobileAsset.MetalToolchain-v17.1.324.0.t40qgS 
drwxr-xr-x  22 root  wheel    704 Sep 25 03:03:32 2025 /
drwxr-xr-x   6 root  wheel    192 Oct 18 14:04:20 2025 /private
drwxr-xr-x  34 root  wheel   1088 Sep 29 16:38:31 2025 /private/var
drwxrwxr-x  35 root  daemon  1120 Oct 24 12:48:05 2025 /private/var/run
drwx---r-x   8 root  daemon   256 Oct 18 14:04:22 2025 /private/var/run/com.apple.security.cryptexd
drwxr-xr-x   3 root  daemon    96 Oct 22 12:47:07 2025 /private/var/run/com.apple.security.cryptexd/mnt
drwxr-xr-x   4 root  wheel    128 Aug  8 22:54:49 2025 /private/var/run/com.apple.security.cryptexd/mnt/com.apple.MobileAsset.MetalToolchain-v17.1.324.0.t40qgS

Normally, the only member of group daemon is root, and root has access to that directory by virtue of being its owner and also by being uid 0 (privileged). So under normal circumstances, everyone—the macports user included—can access /private/var/run/com.apple.security.cryptexd and within.

However, when MacPorts runs as root (sudo macports) and then drops privileges to the macports user without setting its supplementary group list to what’s appropriate for that user, it retains its membership in group daemon. It’s thus unable to access /private/var/run/com.apple.security.cryptexd or anything beneath, including the Metal toolchain. This results build failures for ports that depend on the Metal toolchain.

sudo normally sets supplementary group membership properly by calling setgroups, but this can be skipped by using sudo --preserve-groups. Here, the sudo sudo --user=macports --preserve-groups construct simulates what’s happening to MacPorts: the outer sudo is equivalent to the sudo in sudo macports, and runs the remainder as root, with root’s supplementary group list. The second sudo in the chain simulates port dropping privileges to the macports user (--user=macports) without setting the supplementary group list (--preserve-groups).

admin@axilla zsh% sudo sudo --user=macports --preserve-groups ls -ldfT / /private /private/var /private/var/run /private/var/run/com.apple.security.cryptexd /private/var/run/com.apple.security.cryptexd/mnt /private/var/run/com.apple.security.cryptexd/mnt/com.apple.MobileAsset.MetalToolchain-v17.1.324.0.t40qgS
ls: /private/var/run/com.apple.security.cryptexd/mnt: Permission denied
ls: /private/var/run/com.apple.security.cryptexd/mnt/com.apple.MobileAsset.MetalToolchain-v17.1.324.0.t40qgS: Permission denied
drwxr-xr-x  22 root  wheel    704 Sep 25 03:03:32 2025 /
drwxr-xr-x   6 root  wheel    192 Oct 18 14:04:20 2025 /private
drwxr-xr-x  34 root  wheel   1088 Sep 29 16:38:31 2025 /private/var
drwxrwxr-x  35 root  daemon  1120 Oct 24 12:48:05 2025 /private/var/run
drwx---r-x   8 root  daemon   256 Oct 18 14:04:22 2025 /private/var/run/com.apple.security.cryptexd

Because of that, the Metal toolchain isn’t available, even though it’s properly installed on this system:

admin@axilla zsh% sudo sudo --user=macports --preserve-groups xcodebuild -find metal 
2025-10-24 13:50:40.528 xcodebuild[70828:12628266]  IDEDownloadableMetalToolchainCoordinator: Failed to remount the Metal Toolchain: The file “com.apple.MobileAsset.MetalToolchain-v17.1.324.0.t40qgS” couldn’t be opened because you don’t have permission to view it.
2025-10-24 13:50:40.528 xcodebuild[70828:12628295]  IDEDownloadableMetalToolchainCoordinator: Failed to remount the Metal Toolchain: The file “com.apple.MobileAsset.MetalToolchain-v17.1.324.0.t40qgS” couldn’t be opened because you don’t have permission to view it.
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/metal

admin@axilla zsh% sudo sudo --user=macports --preserve-groups xcrun -find metal
xcrun: error: couldn't stat toolchains directory: '/var/run/com.apple.security.cryptexd/mnt/com.apple.MobileAsset.MetalToolchain-v17.1.324.0.t40qgS' (errno=Permission denied)
xcrun: error: couldn't stat toolchain: '/var/run/com.apple.security.cryptexd/mnt/com.apple.MobileAsset.MetalToolchain-v17.1.324.0.t40qgS/Metal.xctoolchain' (errno=Permission denied)
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/metal

admin@axilla zsh% sudo sudo --user=macports --preserve-groups xcrun metal --version
error: error: cannot execute tool 'metal' due to missing Metal Toolchain; use: xcodebuild -downloadComponent MetalToolchain

As a temporary workaround in bug 73008 comment 54, I recommend several recovery/remediation steps (as there are several problems related to the new unbundled Metal toolchain, particularly in multi-user scenarios), in conjunction with the use of sudo --preserve-groups port install … to build ports that depend on the Metal toolchain. This construct avoids having sudo establish root’s supplementary group membership, so that by the time port drops privileges to the macports user, it probably won’t be a member of group daemon, and will thus be able to see the Metal toolchain on the filesystem.

The permanent solution to this problem is for MacPorts to properly handle the supplementary group list when it changes privileges. MacPorts will need to make an initgroups (best) or setgroups (acceptable) call to reinitialize the supplemental group list to something appropriate for the unprivileged user when it drops privileges, and pair that with a similar call when it restores root privileges.

Change History (11)

comment:1 Changed 4 months ago by jmroot (Joshua Root)

Milestone: MacPorts Future

comment:2 Changed 4 months ago by jmroot (Joshua Root)

Owner: set to jmroot
Resolution: fixed
Status: newclosed

In 4497293e70b1e43c1fb3937d258e369b0f91e718/macports-base (master):

Call initgroups when changing (e)uid

Closes: #73160

comment:3 Changed 4 months ago by jmroot (Joshua Root)

Milestone: MacPorts FutureMacPorts 2.11.6

comment:4 Changed 4 months ago by reneeotten (Renee Otten)

Thanks Mark and Joshua for taking care of this!

One question: the sudo --user=macports --preserve-groups install .... did not work for me with a local port repository due to a permission error in reading the "statefile", presumably because that directory structure is owned by my normal user account. Does this change in macports-base avoids this permission problem?

comment:5 Changed 4 months ago by reneeotten (Renee Otten)

Cc: reneeotten added

comment:6 Changed 4 months ago by ryandesign (Ryan Carsten Schmidt)

Possibly not; see #73178

comment:7 Changed 4 months ago by jmroot (Joshua Root)

CI was lacking permissions on the Portfile, not the statefile. The latter is in the work directory and so shouldn't be owned by a normal user account.

comment:8 Changed 4 months ago by markmentovai (Mark Mentovai)

#73180 seeks a build of affected ports on the buildbot now that this bug is fixed and MacPorts 2.11.6 has been released.

comment:9 Changed 4 months ago by ryandesign (Ryan Carsten Schmidt)

Did this affect buildbot? I thought it only affected GitHub Actions. If it affected buildbot, can you refer me to the URL of a build that failed because of this?

comment:10 in reply to:  9 Changed 4 months ago by markmentovai (Mark Mentovai)

Replying to ryandesign:

Did this affect buildbot?

This bug, #73160, did.

comment:4 through comment:7 only affected GitHub actions, but those were unrelated to this bug. This bug as originally reported was experienced on the buildbot too.

If it affected buildbot, can you refer me to the URL of a build that failed because of this?

I gave 4 such links in #73180.

comment:11 Changed 4 months ago by ryandesign (Ryan Carsten Schmidt)

Sorry, I lost track of what this ticket was about.

I agree the metal errors did affect buildbot and I understand I may need to perform steps manually on that buildbot worker before a reattempt of those ports would succeed.

Note: See TracTickets for help on using tickets.