]> git.saurik.com Git - apple/xnu.git/blobdiff - libsyscall/wrappers/spawn/posix_spawn.c
xnu-3789.41.3.tar.gz
[apple/xnu.git] / libsyscall / wrappers / spawn / posix_spawn.c
index 3d8369be090bb7a079f55297e74ba173bf5c8c98..be3e94cea94c47f092f869a3848e0b9bc836b0d1 100644 (file)
 #include <strings.h>
 #include <mach/port.h>
 #include <mach/exception_types.h>
 #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>
 #include <sys/kern_memorystatus.h>
-#endif
 
 /*
  * posix_spawnattr_init
 
 /*
  * posix_spawnattr_init
@@ -115,19 +113,15 @@ posix_spawnattr_init(posix_spawnattr_t *attr)
 
                 (*psattrp)->short_padding = 0; 
                 (*psattrp)->flags_padding = 0; 
 
                 (*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;
 
                /* 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 CPU usage monitor active. */
                (*psattrp)->psa_cpumonitor_percent = 0;
@@ -135,6 +129,27 @@ posix_spawnattr_init(posix_spawnattr_t *attr)
 
                /* Default is no MAC policy extensions. */
                (*psattrp)->psa_mac_extensions = NULL;
 
                /* 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);
        }
 
        return (err);
@@ -162,6 +177,8 @@ posix_spawnattr_init(posix_spawnattr_t *attr)
  *             EINVAL  The value specified by attr is invalid.
  */
 static int posix_spawn_destroyportactions_np(posix_spawnattr_t *);
  *             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)
 
 int
 posix_spawnattr_destroy(posix_spawnattr_t *attr)
@@ -173,6 +190,8 @@ posix_spawnattr_destroy(posix_spawnattr_t *attr)
 
        psattr = *(_posix_spawnattr_t *)attr;
        posix_spawn_destroyportactions_np(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;
 
        free(psattr);
        *attr = NULL;
@@ -737,6 +756,52 @@ posix_spawn_destroyportactions_np(posix_spawnattr_t *attr)
        return 0;
 }
 
        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
 /*
  * posix_spawn_appendportaction_np
  * Description: append a port action, grow the array if necessary
@@ -1266,24 +1331,27 @@ posix_spawnattr_getcpumonitor(posix_spawnattr_t * __restrict attr,
        return (0);
 }
 
        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
  *
  * 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
  *
  * 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;
 
 {
        _posix_spawnattr_t psattr;
 
@@ -1291,15 +1359,15 @@ posix_spawnattr_setjetsam(posix_spawnattr_t * __restrict attr,
                return EINVAL;
 
        psattr = *(_posix_spawnattr_t *)attr;
                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_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);
 }
 
        return (0);
 }
-#endif
 
 
 /*
 
 
 /*
@@ -1379,8 +1447,9 @@ posix_spawnattr_getmacpolicyinfo_np(const posix_spawnattr_t * __restrict attr,
        if (extension == NULL)
                return ESRCH;
        *datap = (void *)(uintptr_t)extension->data;
        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;
 }
 
@@ -1424,6 +1493,215 @@ posix_spawnattr_setmacpolicyinfo_np(posix_spawnattr_t * __restrict attr,
        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
  *
 /*
  * posix_spawn
  *
@@ -1497,6 +1775,14 @@ posix_spawn(pid_t * __restrict pid, const char * __restrict path,
                                ad.mac_extensions_size = PS_MAC_EXTENSIONS_SIZE(
                                                ad.mac_extensions->psmx_count);
                        }
                                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 =
                }
                if (file_actions != NULL && *file_actions != NULL) {
                        _posix_spawn_file_actions_t psactsp =