]> git.saurik.com Git - apple/xnu.git/blobdiff - libsyscall/wrappers/spawn/posix_spawn.c
xnu-4903.241.1.tar.gz
[apple/xnu.git] / libsyscall / wrappers / spawn / posix_spawn.c
index 4c36d0e9016017f86ed0015ed5b2cef881cfa2cf..20083809a4358086a258c044cef1324f6d0164d2 100644 (file)
@@ -39,7 +39,7 @@
 #include <mach/port.h>
 #include <mach/exception_types.h>
 #include <mach/coalition.h> /* for COALITION_TYPE_MAX */
-
+#include <sys/kern_memorystatus.h>
 
 /*
  * posix_spawnattr_init
@@ -123,6 +123,9 @@ posix_spawnattr_init(posix_spawnattr_t *attr)
                (*psattrp)->psa_memlimit_active = -1;
                (*psattrp)->psa_memlimit_inactive = -1;
 
+               /* Default is no thread limit */
+               (*psattrp)->psa_thread_limit = 0;
+
                /* Default is no CPU usage monitor active. */
                (*psattrp)->psa_cpumonitor_percent = 0;
                (*psattrp)->psa_cpumonitor_interval = 0;
@@ -150,6 +153,8 @@ posix_spawnattr_init(posix_spawnattr_t *attr)
 
                /* Default is no change to role */
                (*psattrp)->psa_darwin_role = POSIX_SPAWN_DARWIN_ROLE_NONE;
+
+               (*psattrp)->psa_max_addr = 0;
        }
 
        return (err);
@@ -713,7 +718,6 @@ posix_spawn_growportactions_np(posix_spawnattr_t *attr)
 {
        _posix_spawnattr_t psattr;
        _posix_spawn_port_actions_t acts; 
-       int newnum;
 
        if (attr == NULL || *attr == NULL)
                return EINVAL;
@@ -724,8 +728,14 @@ posix_spawn_growportactions_np(posix_spawnattr_t *attr)
                return EINVAL;
        
        /* Double number of port actions allocated for */
-       newnum = 2 * acts->pspa_alloc;
-       acts = realloc(acts, PS_PORT_ACTIONS_SIZE(newnum));
+       int newnum = 0;
+       if (os_mul_overflow(acts->pspa_alloc, 2, &newnum))
+               return ENOMEM;
+       size_t newsize = PS_PORT_ACTIONS_SIZE(newnum);
+       if (newsize == 0)
+               return ENOMEM;
+
+       acts = realloc(acts, newsize);
        if (acts == NULL)
                return ENOMEM;
        
@@ -1031,8 +1041,13 @@ posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *file_actions)
 static int
 _posix_spawn_file_actions_grow(_posix_spawn_file_actions_t *psactsp)
 {
-       int     new_alloc = (*psactsp)->psfa_act_alloc * 2;
-       _posix_spawn_file_actions_t new_psacts;
+       int newnum = 0;
+       if (os_mul_overflow((*psactsp)->psfa_act_alloc, 2, &newnum))
+               return ENOMEM;
+
+       size_t newsize = PSF_ACTIONS_SIZE(newnum);
+       if (newsize == 0)
+               return ENOMEM;
 
        /*
         * XXX may want to impose an administrative limit here; POSIX does
@@ -1040,13 +1055,14 @@ _posix_spawn_file_actions_grow(_posix_spawn_file_actions_t *psactsp)
         * XXX so it's probably acceptable to just fail catastrophically
         * XXX instead of implementing one.
         */
-       if ((new_psacts = (_posix_spawn_file_actions_t)realloc((*psactsp), PSF_ACTIONS_SIZE(new_alloc))) == NULL) {
-               return (ENOMEM);
+       _posix_spawn_file_actions_t new_psacts;
+       if ((new_psacts = (_posix_spawn_file_actions_t)realloc((*psactsp), newsize)) == NULL) {
+               return ENOMEM;
        }
-       new_psacts->psfa_act_alloc = new_alloc;
+       new_psacts->psfa_act_alloc = newnum;
        *psactsp = new_psacts;
 
-       return (0);
+       return 0;
 }
 
 
@@ -1331,6 +1347,95 @@ posix_spawnattr_getcpumonitor(posix_spawnattr_t * __restrict attr,
        return (0);
 }
 
+#if TARGET_OS_EMBEDDED
+/*
+ * posix_spawnattr_setjetsam
+ *
+ * Description:        Set jetsam attributes for the spawn attribute object
+ *             referred to by 'attr'.
+ *
+ * Parameters: flags                   The flags value to set
+ *             priority                Relative jetsam priority
+ *             memlimit                Value in megabytes; a memory footprint
+ *                                     above this level may result in termination.
+ *                                     Implies both active and inactive limits.
+ *
+ * Returns:    0                       Success
+ *
+ * Note: to be deprecated (not available on desktop)
+ *
+ */
+int
+posix_spawnattr_setjetsam(posix_spawnattr_t * __restrict attr,
+               short flags, int priority, int memlimit)
+{
+       short flags_ext = flags;
+
+        if (flags & POSIX_SPAWN_JETSAM_MEMLIMIT_FATAL) {
+                flags_ext |= POSIX_SPAWN_JETSAM_MEMLIMIT_ACTIVE_FATAL;
+                flags_ext |= POSIX_SPAWN_JETSAM_MEMLIMIT_INACTIVE_FATAL;
+        } else {
+                flags_ext &= ~POSIX_SPAWN_JETSAM_MEMLIMIT_ACTIVE_FATAL;
+                flags_ext &= ~POSIX_SPAWN_JETSAM_MEMLIMIT_INACTIVE_FATAL;
+        }
+
+       return (posix_spawnattr_setjetsam_ext(attr, flags_ext, priority, memlimit, memlimit));
+}
+#endif /* TARGET_OS_EMBEDDED */
+
+/*
+ * 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
+ *             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_ext(posix_spawnattr_t * __restrict attr,
+       short flags, int priority, int memlimit_active, int memlimit_inactive)
+{
+       _posix_spawnattr_t psattr;
+
+       if (attr == NULL || *attr == NULL)
+               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_memlimit_active = memlimit_active;
+       psattr->psa_memlimit_inactive = memlimit_inactive;
+
+       return (0);
+}
+
+int
+posix_spawnattr_set_threadlimit_ext(posix_spawnattr_t * __restrict attr,
+       int thread_limit)
+{
+       _posix_spawnattr_t psattr;
+
+       if (attr == NULL || *attr == NULL)
+               return EINVAL;
+
+       psattr = *(_posix_spawnattr_t *)attr;
+
+       psattr->psa_thread_limit = thread_limit;
+
+       return (0);
+
+}
 
 
 /*
@@ -1443,10 +1548,16 @@ posix_spawnattr_setmacpolicyinfo_np(posix_spawnattr_t * __restrict attr,
                psmx->psmx_count = 0;
        }
        else if (psmx->psmx_count == psmx->psmx_alloc) {
-               psmx = psattr->psa_mac_extensions = reallocf(psmx, PS_MAC_EXTENSIONS_SIZE(psmx->psmx_alloc * 2));
+               int newnum = 0;
+               if (os_mul_overflow(psmx->psmx_alloc, 2, &newnum))
+                       return ENOMEM;
+               size_t extsize = PS_MAC_EXTENSIONS_SIZE(newnum);
+               if (extsize == 0)
+                       return ENOMEM;
+               psmx = psattr->psa_mac_extensions = reallocf(psmx, extsize);
                if (psmx == NULL)
                        return ENOMEM;
-               psmx->psmx_alloc *= 2;
+               psmx->psmx_alloc = newnum;
        }
        extension = &psmx->psmx_extensions[psmx->psmx_count];
        strlcpy(extension->policyname, policyname, sizeof(extension->policyname));
@@ -1641,7 +1752,7 @@ posix_spawnattr_set_persona_groups_np(const posix_spawnattr_t * __restrict attr,
        if (gidarray == NULL)
                return EINVAL;
 
-       if (ngroups > NGROUPS)
+       if (ngroups > NGROUPS || ngroups < 0)
                return EINVAL;
 
        psattr = *(_posix_spawnattr_t *)attr;
@@ -1663,7 +1774,20 @@ posix_spawnattr_set_persona_groups_np(const posix_spawnattr_t * __restrict attr,
        return 0;
 }
 
+int
+posix_spawnattr_set_max_addr_np(const posix_spawnattr_t * __restrict attr, uint64_t max_addr)
+{
+       _posix_spawnattr_t psattr;
+
+       if (attr == NULL || *attr == NULL) {
+               return EINVAL;
+       }
 
+       psattr = *(_posix_spawnattr_t *)attr;
+       psattr->psa_max_addr = max_addr;
+
+       return 0;
+}
 
 /*
  * posix_spawn
@@ -1729,14 +1853,24 @@ posix_spawn(pid_t * __restrict pid, const char * __restrict path,
                        ad.attrp = psattr;
 
                        if (psattr->psa_ports != NULL) {
+                               size_t psact_size = PS_PORT_ACTIONS_SIZE(psattr->psa_ports->pspa_count);
+                               if (psact_size == 0 && psattr->psa_ports->pspa_count != 0) {
+                                       errno = EINVAL;
+                                       ret = -1;
+                                       goto out;
+                               }
                                ad.port_actions = psattr->psa_ports;
-                               ad.port_actions_size = PS_PORT_ACTIONS_SIZE(
-                                               ad.port_actions->pspa_count);
+                               ad.port_actions_size = psact_size;
                        }
                        if (psattr->psa_mac_extensions != NULL) {
+                               size_t macext_size = PS_MAC_EXTENSIONS_SIZE(psattr->psa_mac_extensions->psmx_count);
+                               if (macext_size == 0 && psattr->psa_mac_extensions->psmx_count != 0) {
+                                       errno = EINVAL;
+                                       ret = -1;
+                                       goto out;
+                               }
                                ad.mac_extensions = psattr->psa_mac_extensions;
-                               ad.mac_extensions_size = PS_MAC_EXTENSIONS_SIZE(
-                                               ad.mac_extensions->psmx_count);
+                               ad.mac_extensions_size = macext_size;
                        }
                        if (psattr->psa_coalition_info != NULL) {
                                ad.coal_info_size = sizeof(struct _posix_spawn_coalition_info);
@@ -1752,7 +1886,13 @@ posix_spawn(pid_t * __restrict pid, const char * __restrict path,
                                *(_posix_spawn_file_actions_t *)file_actions;
 
                        if (psactsp->psfa_act_count > 0) {
-                               ad.file_actions_size = PSF_ACTIONS_SIZE(psactsp->psfa_act_count);
+                               size_t fa_size = PSF_ACTIONS_SIZE(psactsp->psfa_act_count);
+                               if (fa_size == 0 && psactsp->psfa_act_count != 0) {
+                                       errno = EINVAL;
+                                       ret = -1;
+                                       goto out;
+                               }
+                               ad.file_actions_size = fa_size;
                                ad.file_actions = psactsp;
                        }
                }
@@ -1761,6 +1901,7 @@ posix_spawn(pid_t * __restrict pid, const char * __restrict path,
        } else
                ret = __posix_spawn(pid, path, NULL, argv, envp);
 
+out:
        if (ret < 0)
                ret = errno;
        errno = saveerrno;