#include <strings.h>
#include <mach/port.h>
#include <mach/exception_types.h>
-
-#if TARGET_OS_EMBEDDED
+#include <mach/coalition.h> /* for COALITION_TYPE_MAX */
#include <sys/kern_memorystatus.h>
-#endif
/*
* posix_spawnattr_init
(*psattrp)->short_padding = 0;
(*psattrp)->flags_padding = 0;
- (*psattrp)->int_padding = 0;
-
- /*
- * The default value of this attribute shall be an no
- * process control on resource starvation
- */
- (*psattrp)->psa_apptype = 0;
+ /* Default is no new apptype requested */
+ (*psattrp)->psa_apptype = POSIX_SPAWN_PROCESS_TYPE_DEFAULT;
/* Jetsam related */
(*psattrp)->psa_jetsam_flags = 0;
(*psattrp)->psa_priority = -1;
- (*psattrp)->psa_high_water_mark = -1;
+ (*psattrp)->psa_memlimit_active = -1;
+ (*psattrp)->psa_memlimit_inactive = -1;
/* Default is no CPU usage monitor active. */
(*psattrp)->psa_cpumonitor_percent = 0;
/* Default is no MAC policy extensions. */
(*psattrp)->psa_mac_extensions = NULL;
+
+ /* Default is to inherit parent's coalition(s) */
+ (*psattrp)->psa_coalition_info = NULL;
+
+ (*psattrp)->psa_persona_info = NULL;
+
+ /*
+ * old coalition field
+ * For backwards compatibility reasons, we set this to 1
+ * which is the first valid coalition id. This will allow
+ * newer user space code to properly spawn processes on
+ * older kernels
+ * (they will just all end up in the same coalition).
+ */
+ (*psattrp)->psa_reserved = 1;
+
+ /* Default is no new clamp */
+ (*psattrp)->psa_qos_clamp = POSIX_SPAWN_PROC_CLAMP_NONE;
+
+ /* Default is no change to role */
+ (*psattrp)->psa_darwin_role = POSIX_SPAWN_DARWIN_ROLE_NONE;
}
return (err);
* EINVAL The value specified by attr is invalid.
*/
static int posix_spawn_destroyportactions_np(posix_spawnattr_t *);
+static int posix_spawn_destroycoalition_info_np(posix_spawnattr_t *);
+static int posix_spawn_destroypersona_info_np(posix_spawnattr_t *);
int
posix_spawnattr_destroy(posix_spawnattr_t *attr)
psattr = *(_posix_spawnattr_t *)attr;
posix_spawn_destroyportactions_np(attr);
+ posix_spawn_destroycoalition_info_np(attr);
+ posix_spawn_destroypersona_info_np(attr);
free(psattr);
*attr = NULL;
return 0;
}
+/*
+ * posix_spawn_destroycoalition_info_np
+ * Description: clean up coalition_info struct in posix_spawnattr_t attr
+ */
+static int
+posix_spawn_destroycoalition_info_np(posix_spawnattr_t *attr)
+{
+ _posix_spawnattr_t psattr;
+ struct _posix_spawn_coalition_info *coal_info;
+
+ if (attr == NULL || *attr == NULL)
+ return EINVAL;
+
+ psattr = *(_posix_spawnattr_t *)attr;
+ coal_info = psattr->psa_coalition_info;
+ if (coal_info == NULL)
+ return EINVAL;
+
+ psattr->psa_coalition_info = NULL;
+ free(coal_info);
+ return 0;
+}
+
+/*
+ * posix_spawn_destroypersona_info_np
+ * Description: clean up persona_info struct in posix_spawnattr_t attr
+ */
+static int
+posix_spawn_destroypersona_info_np(posix_spawnattr_t *attr)
+{
+ _posix_spawnattr_t psattr;
+ struct _posix_spawn_persona_info *persona;
+
+ if (attr == NULL || *attr == NULL)
+ return EINVAL;
+
+ psattr = *(_posix_spawnattr_t *)attr;
+ persona = psattr->psa_persona_info;
+ if (persona == NULL)
+ return EINVAL;
+
+ psattr->psa_persona_info = NULL;
+ free(persona);
+ return 0;
+}
+
/*
* posix_spawn_appendportaction_np
* Description: append a port action, grow the array if necessary
return (0);
}
-#if TARGET_OS_EMBEDDED
+
/*
- * posix_spawnattr_setjetsam
+ * posix_spawnattr_setjetsam_ext
*
* Description: Set jetsam attributes for the spawn attribute object
* referred to by 'attr'.
*
* Parameters: flags The flags value to set
* priority Relative jetsam priority
- * high_water_mark Value in pages; resident page
- * counts above this level can
- * result in termination
+ * memlimit_active Value in megabytes; memory footprint
+ * above this level while process is
+ * active may result in termination.
+ * memlimit_inactive Value in megabytes; memory footprint
+ * above this level while process is
+ * inactive may result in termination.
*
* Returns: 0 Success
*/
int
-posix_spawnattr_setjetsam(posix_spawnattr_t * __restrict attr,
- short flags, int priority, int high_water_mark)
+posix_spawnattr_setjetsam_ext(posix_spawnattr_t * __restrict attr,
+ short flags, int priority, int memlimit_active, int memlimit_inactive)
{
_posix_spawnattr_t psattr;
return EINVAL;
psattr = *(_posix_spawnattr_t *)attr;
-
+
psattr->psa_jetsam_flags = flags;
psattr->psa_jetsam_flags |= POSIX_SPAWN_JETSAM_SET;
psattr->psa_priority = priority;
- psattr->psa_high_water_mark = high_water_mark;
+ psattr->psa_memlimit_active = memlimit_active;
+ psattr->psa_memlimit_inactive = memlimit_inactive;
return (0);
}
-#endif
/*
if (extension == NULL)
return ESRCH;
*datap = (void *)(uintptr_t)extension->data;
- if (datalenp != NULL)
- *datalenp = extension->datalen;
+ if (datalenp != NULL) {
+ *datalenp = (size_t)extension->datalen;
+ }
return 0;
}
return 0;
}
+int posix_spawnattr_setcoalition_np(const posix_spawnattr_t * __restrict attr,
+ uint64_t coalitionid, int type, int role)
+{
+ _posix_spawnattr_t psattr;
+ struct _posix_spawn_coalition_info *coal_info;
+
+ if (attr == NULL || *attr == NULL) {
+ return EINVAL;
+ }
+ if (type < 0 || type > COALITION_TYPE_MAX)
+ return EINVAL;
+
+ psattr = *(_posix_spawnattr_t *)attr;
+
+ coal_info = psattr->psa_coalition_info;
+ if (!coal_info) {
+ coal_info = (struct _posix_spawn_coalition_info *)malloc(sizeof(*coal_info));
+ if (!coal_info)
+ return ENOMEM;
+ memset(coal_info, 0, sizeof(*coal_info));
+ psattr->psa_coalition_info = coal_info;
+ }
+
+ coal_info->psci_info[type].psci_id = coalitionid;
+ coal_info->psci_info[type].psci_role = role;
+
+ return 0;
+}
+
+
+int posix_spawnattr_set_qos_clamp_np(const posix_spawnattr_t * __restrict attr, uint64_t qos_clamp)
+{
+ _posix_spawnattr_t psattr;
+
+ if (attr == NULL || *attr == NULL) {
+ return EINVAL;
+ }
+
+ if (qos_clamp >= POSIX_SPAWN_PROC_CLAMP_LAST)
+ return EINVAL;
+
+ psattr = *(_posix_spawnattr_t *)attr;
+ psattr->psa_qos_clamp = qos_clamp;
+
+ return 0;
+}
+
+int
+posix_spawnattr_get_qos_clamp_np(const posix_spawnattr_t * __restrict attr, uint64_t * __restrict qos_clampp)
+{
+ _posix_spawnattr_t psattr;
+
+ if (attr == NULL || *attr == NULL) {
+ return EINVAL;
+ }
+
+ psattr = *(_posix_spawnattr_t *)attr;
+ *qos_clampp = psattr->psa_qos_clamp;
+
+ return (0);
+}
+
+int posix_spawnattr_set_darwin_role_np(const posix_spawnattr_t * __restrict attr, uint64_t darwin_role)
+{
+ _posix_spawnattr_t psattr;
+
+ if (attr == NULL || *attr == NULL) {
+ return EINVAL;
+ }
+
+ psattr = *(_posix_spawnattr_t *)attr;
+ psattr->psa_darwin_role = darwin_role;
+
+ return 0;
+}
+
+int
+posix_spawnattr_get_darwin_role_np(const posix_spawnattr_t * __restrict attr, uint64_t * __restrict darwin_rolep)
+{
+ _posix_spawnattr_t psattr;
+
+ if (attr == NULL || *attr == NULL) {
+ return EINVAL;
+ }
+
+ psattr = *(_posix_spawnattr_t *)attr;
+ *darwin_rolep = psattr->psa_darwin_role;
+
+ return (0);
+}
+
+
+int
+posix_spawnattr_set_persona_np(const posix_spawnattr_t * __restrict attr, uid_t persona_id, uint32_t flags)
+{
+ _posix_spawnattr_t psattr;
+ struct _posix_spawn_persona_info *persona;
+
+ if (attr == NULL || *attr == NULL)
+ return EINVAL;
+
+ if (flags & ~POSIX_SPAWN_PERSONA_ALL_FLAGS)
+ return EINVAL;
+
+ psattr = *(_posix_spawnattr_t *)attr;
+
+ persona = psattr->psa_persona_info;
+ if (!persona) {
+ persona = (struct _posix_spawn_persona_info *)malloc(sizeof(*persona));
+ if (!persona)
+ return ENOMEM;
+ persona->pspi_uid = 0;
+ persona->pspi_gid = 0;
+ persona->pspi_ngroups = 0;
+ persona->pspi_groups[0] = 0;
+
+ psattr->psa_persona_info = persona;
+ }
+
+ persona->pspi_id = persona_id;
+ persona->pspi_flags = flags;
+
+ return 0;
+}
+
+int
+posix_spawnattr_set_persona_uid_np(const posix_spawnattr_t * __restrict attr, uid_t uid)
+{
+ _posix_spawnattr_t psattr;
+ struct _posix_spawn_persona_info *persona;
+
+ if (attr == NULL || *attr == NULL)
+ return EINVAL;
+
+ psattr = *(_posix_spawnattr_t *)attr;
+ persona = psattr->psa_persona_info;
+ if (!persona)
+ return EINVAL;
+
+ if (!(persona->pspi_flags & (POSIX_SPAWN_PERSONA_FLAGS_OVERRIDE | POSIX_SPAWN_PERSONA_FLAGS_VERIFY)))
+ return EINVAL;
+
+ persona->pspi_uid = uid;
+
+ persona->pspi_flags |= POSIX_SPAWN_PERSONA_UID;
+
+ return 0;
+}
+
+int
+posix_spawnattr_set_persona_gid_np(const posix_spawnattr_t * __restrict attr, gid_t gid)
+{
+ _posix_spawnattr_t psattr;
+ struct _posix_spawn_persona_info *persona;
+
+ if (attr == NULL || *attr == NULL)
+ return EINVAL;
+
+ psattr = *(_posix_spawnattr_t *)attr;
+ persona = psattr->psa_persona_info;
+ if (!persona)
+ return EINVAL;
+
+ if (!(persona->pspi_flags & (POSIX_SPAWN_PERSONA_FLAGS_OVERRIDE | POSIX_SPAWN_PERSONA_FLAGS_VERIFY)))
+ return EINVAL;
+
+ persona->pspi_gid = gid;
+
+ persona->pspi_flags |= POSIX_SPAWN_PERSONA_GID;
+
+ return 0;
+}
+
+int
+posix_spawnattr_set_persona_groups_np(const posix_spawnattr_t * __restrict attr, int ngroups, gid_t *gidarray, uid_t gmuid)
+{
+ _posix_spawnattr_t psattr;
+ struct _posix_spawn_persona_info *persona;
+
+ if (attr == NULL || *attr == NULL)
+ return EINVAL;
+
+ if (gidarray == NULL)
+ return EINVAL;
+
+ if (ngroups > NGROUPS)
+ return EINVAL;
+
+ psattr = *(_posix_spawnattr_t *)attr;
+ persona = psattr->psa_persona_info;
+ if (!persona)
+ return EINVAL;
+
+ if (!(persona->pspi_flags & (POSIX_SPAWN_PERSONA_FLAGS_OVERRIDE | POSIX_SPAWN_PERSONA_FLAGS_VERIFY)))
+ return EINVAL;
+
+ persona->pspi_ngroups = ngroups;
+ for (int i = 0; i < ngroups; i++)
+ persona->pspi_groups[i] = gidarray[i];
+
+ persona->pspi_gmuid = gmuid;
+
+ persona->pspi_flags |= POSIX_SPAWN_PERSONA_GROUPS;
+
+ return 0;
+}
+
+
+
/*
* posix_spawn
*
ad.mac_extensions_size = PS_MAC_EXTENSIONS_SIZE(
ad.mac_extensions->psmx_count);
}
+ if (psattr->psa_coalition_info != NULL) {
+ ad.coal_info_size = sizeof(struct _posix_spawn_coalition_info);
+ ad.coal_info = psattr->psa_coalition_info;
+ }
+ if (psattr->psa_persona_info != NULL) {
+ ad.persona_info_size = sizeof(struct _posix_spawn_persona_info);
+ ad.persona_info = psattr->psa_persona_info;
+ }
}
if (file_actions != NULL && *file_actions != NULL) {
_posix_spawn_file_actions_t psactsp =