diff --git a/App/entitlements.plist b/App/entitlements.plist
index 6d9f8d4c..4b616799 100644
--- a/App/entitlements.plist
+++ b/App/entitlements.plist
@@ -8,6 +8,12 @@
com.apple.private.security.no-container
+ com.apple.private.security.storage.AppDataContainers
+
+ com.apple.private.security.storage-exempt.heritable
+
+ com.apple.private.persona-mgmt
+
com.apple.security.iokit-user-client-class
IOUserClient
diff --git a/Common/Controllers/SubProcess.swift b/Common/Controllers/SubProcess.swift
index 5cfdce42..b9a00b24 100644
--- a/Common/Controllers/SubProcess.swift
+++ b/Common/Controllers/SubProcess.swift
@@ -170,6 +170,19 @@ class SubProcess {
posix_spawn_file_actions_adddup2(&actions, fds.replica, STDERR_FILENO)
defer { posix_spawn_file_actions_destroy(&actions) }
+ var attr: posix_spawnattr_t!
+ posix_spawnattr_init(&attr)
+ defer { posix_spawnattr_destroy(&attr) }
+ #if !(targetEnvironment(simulator) || targetEnvironment(macCatalyst))
+ if !Self.loginIsShell {
+ // Spawn `login` as the super user even in a jailed state, where the rootfs has the
+ // nosuid option set.
+ posix_spawnattr_set_persona_np(&attr, 99, POSIX_SPAWN_PERSONA_FLAGS_OVERRIDE)
+ posix_spawnattr_set_persona_uid_np(&attr, 0)
+ posix_spawnattr_set_persona_gid_np(&attr, 0)
+ }
+ #endif
+
// TODO: At some point, come up with some way to keep track of working directory changes.
// When opening a new tab, we can switch straight to the previous tab’s working directory.
let argv: [UnsafeMutablePointer?]
@@ -189,7 +202,7 @@ class SubProcess {
}
var pid = pid_t()
- let result = ie_posix_spawn(&pid, Self.login, &actions, nil, argv, envp)
+ let result = ie_posix_spawn(&pid, Self.login, &actions, &attr, argv, envp)
close(fds.replica)
if result != 0 {
// Fork failed.
diff --git a/Common/Supporting Files/NewTermCommon.h b/Common/Supporting Files/NewTermCommon.h
index 26e9a9d6..50d3ccc3 100644
--- a/Common/Supporting Files/NewTermCommon.h
+++ b/Common/Supporting Files/NewTermCommon.h
@@ -20,4 +20,11 @@ static inline int ie_posix_spawn(pid_t *pid, const char *path, const posix_spawn
#else
extern int ie_getpwuid_r(uid_t uid, struct passwd *pw, char *buf, size_t buflen, struct passwd **pwretp);
extern int ie_posix_spawn(pid_t *pid, const char *path, const posix_spawn_file_actions_t *file_actions, const posix_spawnattr_t *attrp, char *const argv[], char *const envp[]);
+
+#define POSIX_SPAWN_PERSONA_FLAGS_OVERRIDE ((uint32_t) 1)
+
+// https://github.com/apple-oss-distributions/xnu/blob/1031c584a5e37aff177559b9f69dbd3c8c3fd30a/libsyscall/wrappers/spawn/spawn_private.h#L87-L89
+extern int posix_spawnattr_set_persona_np(const posix_spawnattr_t *attr, uid_t persona_id, uint32_t flags);
+extern int posix_spawnattr_set_persona_uid_np(const posix_spawnattr_t *attr, uid_t uid);
+extern int posix_spawnattr_set_persona_gid_np(const posix_spawnattr_t *attr, gid_t gid);
#endif