#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
(*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;
/* Default is no change to role */
(*psattrp)->psa_darwin_role = POSIX_SPAWN_DARWIN_ROLE_NONE;
+
+ (*psattrp)->psa_max_addr = 0;
}
return (err);
{
_posix_spawnattr_t psattr;
_posix_spawn_port_actions_t acts;
- int newnum;
if (attr == NULL || *attr == NULL)
return EINVAL;
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;
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
* 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;
}
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);
+
+}
/*
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));
if (gidarray == NULL)
return EINVAL;
- if (ngroups > NGROUPS)
+ if (ngroups > NGROUPS || ngroups < 0)
return EINVAL;
psattr = *(_posix_spawnattr_t *)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
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);
*(_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;
}
}
} else
ret = __posix_spawn(pid, path, NULL, argv, envp);
+out:
if (ret < 0)
ret = errno;
errno = saveerrno;