2 * Copyright (c) 2006-2012 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 * [SPN] Support for _POSIX_SPAWN
28 #define CONFIG_MEMORYSTATUS 1 // <rdar://problem/13604997>
29 #include <sys/types.h> /* for user_size_t */
31 #include <spawn_private.h>
32 #include <sys/spawn_internal.h>
33 #include <sys/process_policy.h>
36 #include <limits.h> /* for OPEN_MAX, PATH_MAX */
39 #include <mach/port.h>
40 #include <mach/mach_param.h> /* for TASK_PORT_REGISTER_MAX */
41 #include <mach/exception_types.h>
42 #include <mach/coalition.h> /* for COALITION_TYPE_MAX */
43 #include <sys/kern_memorystatus.h>
46 * posix_spawnattr_init
48 * Description: Initialize a spawn attributes object attr with default values
50 * Parameters: attr The spawn attributes object to be
54 * ENOMEM Insufficient memory exists to
55 * initialize the spawn attributes object.
57 * Note: As an implementation detail, the externally visibily type
58 * posix_spawnattr_t is defined to be a void *, and initialization
59 * involves allocation of a memory object. Subsequent changes to
60 * the spawn attributes may result in reallocation under the
63 * Reinitialization of an already initialized spawn attributes
64 * object will result in memory being leaked. Because spawn
65 * attributes are not required to be used in conjunction with a
66 * static initializer, there is no way to distinguish a spawn
67 * attribute with stack garbage from one that's been initialized.
68 * This is arguably an API design error.
71 posix_spawnattr_init(posix_spawnattr_t
*attr
)
73 _posix_spawnattr_t
*psattrp
= (_posix_spawnattr_t
*)attr
;
76 if ((*psattrp
= (_posix_spawnattr_t
)malloc(sizeof(struct _posix_spawnattr
))) == NULL
) {
80 * The default value of this attribute shall be as if no
83 (*psattrp
)->psa_flags
= 0;
86 * The default value of this attribute shall be an empty
89 (*psattrp
)->psa_sigdefault
= 0;
91 /* The default value of this attribute is unspecified */
92 (*psattrp
)->psa_sigmask
= 0;
94 /* The default value of this attribute shall be zero */
95 (*psattrp
)->psa_pgroup
= 0; /* doesn't matter */
97 /* Default is no binary preferences, i.e. use normal grading */
98 memset((*psattrp
)->psa_binprefs
, 0,
99 sizeof((*psattrp
)->psa_binprefs
));
101 /* Default is no port actions to take */
102 (*psattrp
)->psa_ports
= NULL
;
105 * The default value of this attribute shall be an no
106 * process control on resource starvation
108 (*psattrp
)->psa_pcontrol
= 0;
111 * Initializing the alignment paddings.
114 (*psattrp
)->short_padding
= 0;
115 (*psattrp
)->flags_padding
= 0;
117 /* Default is no new apptype requested */
118 (*psattrp
)->psa_apptype
= POSIX_SPAWN_PROCESS_TYPE_DEFAULT
;
121 (*psattrp
)->psa_jetsam_flags
= 0;
122 (*psattrp
)->psa_priority
= -1;
123 (*psattrp
)->psa_memlimit_active
= -1;
124 (*psattrp
)->psa_memlimit_inactive
= -1;
126 /* Default is no thread limit */
127 (*psattrp
)->psa_thread_limit
= 0;
129 /* Default is no CPU usage monitor active. */
130 (*psattrp
)->psa_cpumonitor_percent
= 0;
131 (*psattrp
)->psa_cpumonitor_interval
= 0;
133 /* Default is no MAC policy extensions. */
134 (*psattrp
)->psa_mac_extensions
= NULL
;
136 /* Default is to inherit parent's coalition(s) */
137 (*psattrp
)->psa_coalition_info
= NULL
;
139 (*psattrp
)->psa_persona_info
= NULL
;
141 (*psattrp
)->psa_posix_cred_info
= NULL
;
144 * old coalition field
145 * For backwards compatibility reasons, we set this to 1
146 * which is the first valid coalition id. This will allow
147 * newer user space code to properly spawn processes on
149 * (they will just all end up in the same coalition).
151 (*psattrp
)->psa_reserved
= 1;
153 /* Default is no new clamp */
154 (*psattrp
)->psa_qos_clamp
= POSIX_SPAWN_PROC_CLAMP_NONE
;
156 /* Default is no change to role */
157 (*psattrp
)->psa_darwin_role
= POSIX_SPAWN_DARWIN_ROLE_NONE
;
159 (*psattrp
)->psa_max_addr
= 0;
167 * posix_spawnattr_destroy
169 * Description: Destroy a spawn attributes object that was previously
170 * initialized via posix_spawnattr_init() by freeing any
171 * memory associated with it and setting it to an invalid value.
173 * Parameters: attr The spawn attributes object to be
178 * Notes: The destroyed spawn attribute results in the void * pointer
179 * being set to NULL; subsequent use without reinitialization
180 * will result in explicit program failure (rather than merely
181 * "undefined behaviour").
183 * NOTIMP: Allowed failures (checking NOT required):
184 * EINVAL The value specified by attr is invalid.
186 static int posix_spawn_destroyportactions_np(posix_spawnattr_t
*);
187 static int posix_spawn_destroycoalition_info_np(posix_spawnattr_t
*);
188 static int posix_spawn_destroypersona_info_np(posix_spawnattr_t
*);
189 static int posix_spawn_destroyposix_cred_info_np(posix_spawnattr_t
*);
190 static int posix_spawn_destroymacpolicy_info_np(posix_spawnattr_t
*);
193 posix_spawnattr_destroy(posix_spawnattr_t
*attr
)
195 _posix_spawnattr_t psattr
;
197 if (attr
== NULL
|| *attr
== NULL
) {
201 psattr
= *(_posix_spawnattr_t
*)attr
;
202 posix_spawn_destroyportactions_np(attr
);
203 posix_spawn_destroycoalition_info_np(attr
);
204 posix_spawn_destroypersona_info_np(attr
);
205 posix_spawn_destroyposix_cred_info_np(attr
);
206 posix_spawn_destroymacpolicy_info_np(attr
);
216 * posix_spawnattr_setflags
218 * Description: Set the spawn flags attribute for the spawn attribute object
219 * referred to by 'attr'.
221 * Parameters: attr The spawn attributes object whose flags
223 * flags The flags value to set
227 * NOTIMP: Allowed failures (checking NOT required):
228 * EINVAL The value specified by attr is invalid.
229 * EINVAL The value of the attribute being set is not valid.
232 posix_spawnattr_setflags(posix_spawnattr_t
*attr
, short flags
)
234 _posix_spawnattr_t psattr
;
236 if (attr
== NULL
|| *attr
== NULL
) {
240 psattr
= *(_posix_spawnattr_t
*)attr
;
241 psattr
->psa_flags
= flags
;
248 * posix_spawnattr_getflags
250 * Description: Retrieve the spawn attributes flag for the spawn attributes
251 * object referenced by 'attr' and place them in the memory
252 * location referenced by 'flagsp'
254 * Parameters: attr The spawn attributes object whose flags
255 * are to be retrieved
256 * flagsp A pointer to a short value to receive
262 * *flagps (modified) The flags value from the spawn
265 * NOTIMP: Allowed failures (checking NOT required):
266 * EINVAL The value specified by attr is invalid.
267 * EINVAL The value of the attribute being set is not valid.
270 posix_spawnattr_getflags(const posix_spawnattr_t
* __restrict attr
,
271 short * __restrict flagsp
)
273 _posix_spawnattr_t psattr
;
275 if (attr
== NULL
|| *attr
== NULL
) {
279 psattr
= *(_posix_spawnattr_t
*)attr
;
280 *flagsp
= psattr
->psa_flags
;
287 * posix_spawnattr_getsigdefault
289 * Description: Retrieve the set of signals to be set to default according to
290 * the spawn attribute value referenced by 'attr' and place the
291 * result into the memory containing the sigset_t referenced by
294 * Parameters: attr The spawn attributes object whose
295 * signal set for default signals is to
297 * sigdefault A pointer to the sigset_t to receive
303 * *sigdefault (modified) The signal set of signals to default
304 * from the spawn attributes object
307 posix_spawnattr_getsigdefault(const posix_spawnattr_t
* __restrict attr
,
308 sigset_t
* __restrict sigdefault
)
310 _posix_spawnattr_t psattr
;
312 if (attr
== NULL
|| *attr
== NULL
) {
316 psattr
= *(_posix_spawnattr_t
*)attr
;
317 *sigdefault
= psattr
->psa_sigdefault
;
324 * posix_spawnattr_getpgroup
326 * Description: Obtain the value of the spawn process group attribute from the
327 * spawn attributes object referenced by 'attr' and place the
328 * results in the memory location referenced by 'pgroup'
330 * Parameters: attr The spawn attributes object whose
331 * process group information is to be
333 * pgroup A pointer to the pid_t to receive the
339 * *pgroup (modified) The process group information from the
340 * spawn attributes object
343 posix_spawnattr_getpgroup(const posix_spawnattr_t
* __restrict attr
,
344 pid_t
* __restrict pgroup
)
346 _posix_spawnattr_t psattr
;
348 if (attr
== NULL
|| *attr
== NULL
) {
352 psattr
= *(_posix_spawnattr_t
*)attr
;
353 *pgroup
= psattr
->psa_pgroup
;
360 * posix_spawnattr_getsigmask
362 * Description: Obtain the value of the spawn signal mask attribute from the
363 * spawn attributes object referenced by 'attr' and place the
364 * result into the memory containing the sigset_t referenced by
367 * Parameters: attr The spawn attributes object whose
368 * signal set for masked signals is to
370 * sigmask A pointer to the sigset_t to receive
376 * *sigmask (modified) The signal set of signals to mask
377 * from the spawn attributes object
380 posix_spawnattr_getsigmask(const posix_spawnattr_t
* __restrict attr
,
381 sigset_t
* __restrict sigmask
)
383 _posix_spawnattr_t psattr
;
385 if (attr
== NULL
|| *attr
== NULL
) {
389 psattr
= *(_posix_spawnattr_t
*)attr
;
390 *sigmask
= psattr
->psa_sigmask
;
396 * posix_spawnattr_getbinpref_np
398 * Description: Obtain the value of the spawn binary preferences attribute from
399 * the spawn attributes object referenced by 'attr' and place the
400 * result into the memory referenced by 'pref'.
402 * Parameters: attr The spawn attributes object whose
403 * binary preferences are to be retrieved
404 * count The size of the cpu_type_t array
405 * pref An array of cpu types
406 * ocount The actual number copied
408 * Returns: 0 No binary preferences found
409 * > 0 The number of cpu types (less than
410 * count) copied over from 'attr'.
413 * *pref (modified) The binary preferences array
414 * from the spawn attributes object
417 posix_spawnattr_getbinpref_np(const posix_spawnattr_t
* __restrict attr
,
418 size_t count
, cpu_type_t
*pref
, size_t * __restrict ocount
)
420 _posix_spawnattr_t psattr
;
423 if (attr
== NULL
|| *attr
== NULL
) {
427 psattr
= *(_posix_spawnattr_t
*)attr
;
428 for (i
= 0; i
< count
&& i
< 4; i
++) {
429 pref
[i
] = psattr
->psa_binprefs
[i
];
440 * posix_spawnattr_getpcontrol_np
442 * Description: Retrieve the process control property set default according to
443 * the spawn attribute value referenced by 'attr' and place the
444 * result into the memory containing the control referenced by
447 * Parameters: attr The spawn attributes object whose
448 * signal set for default signals is to
450 * pcontrol A pointer to an int to receive
451 * the process control info
456 * *pcontrol (modified) The signal set of signals to default
457 * from the spawn attributes object
460 posix_spawnattr_getpcontrol_np(const posix_spawnattr_t
* __restrict attr
,
461 int * __restrict pcontrol
)
463 _posix_spawnattr_t psattr
;
465 if (attr
== NULL
|| *attr
== NULL
) {
469 psattr
= *(_posix_spawnattr_t
*)attr
;
470 *pcontrol
= psattr
->psa_pcontrol
;
476 * posix_spawnattr_getprocesstype_np
478 * Description: Retrieve the process specific behaviors and app launch types
479 * spawn attribute value referenced by 'attr' and place the
480 * result into the memory containing the control referenced by
483 * Parameters: attr The spawn attributes object whose
484 * signal set for default signals is to
486 * proctype A pointer to an int to receive
487 * the process type info
492 * *proctype (modified) The process type set to value
493 * from the spawn attributes object
496 posix_spawnattr_getprocesstype_np(const posix_spawnattr_t
* __restrict attr
,
497 int * __restrict proctype
)
499 _posix_spawnattr_t psattr
;
501 if (attr
== NULL
|| *attr
== NULL
) {
505 psattr
= *(_posix_spawnattr_t
*)attr
;
506 *proctype
= psattr
->psa_apptype
;
511 * posix_spawnattr_setsigdefault
513 * Description: Set the set of signals to be set to default for the spawn
514 * attribute value referenced by 'attr' from the memory
515 * containing the sigset_t referenced by 'sigdefault'
517 * Parameters: attr The spawn attributes object whose
518 * signal set for default signals is to
520 * sigdefault A pointer to the sigset_t from which to
521 * obtain the signal set
526 posix_spawnattr_setsigdefault(posix_spawnattr_t
* __restrict attr
,
527 const sigset_t
* __restrict sigdefault
)
529 _posix_spawnattr_t psattr
;
531 if (attr
== NULL
|| *attr
== NULL
) {
535 psattr
= *(_posix_spawnattr_t
*)attr
;
536 psattr
->psa_sigdefault
= *sigdefault
;
543 * posix_spawnattr_setpgroup
545 * Description: Set the value of the spawn process group attribute for the
546 * spawn attributes object referenced by 'attr' from the value
549 * Parameters: attr The spawn attributes object for which
550 * the process group information is to be
552 * pgroup The process group to set
557 posix_spawnattr_setpgroup(posix_spawnattr_t
* attr
, pid_t pgroup
)
559 _posix_spawnattr_t psattr
;
561 if (attr
== NULL
|| *attr
== NULL
) {
565 psattr
= *(_posix_spawnattr_t
*)attr
;
566 psattr
->psa_pgroup
= pgroup
;
573 * posix_spawnattr_setsigmask
575 * Description: Set the set of signals to be masked for the spawn attribute
576 * value referenced by 'attr' from the memory containing the
577 * sigset_t referenced by 'sigmask'
579 * Parameters: attr The spawn attributes object whose
580 * signal set for masked signals is to
582 * sigmask A pointer to the sigset_t from which to
583 * obtain the signal set
588 posix_spawnattr_setsigmask(posix_spawnattr_t
* __restrict attr
,
589 const sigset_t
* __restrict sigmask
)
591 _posix_spawnattr_t psattr
;
593 if (attr
== NULL
|| *attr
== NULL
) {
597 psattr
= *(_posix_spawnattr_t
*)attr
;
598 psattr
->psa_sigmask
= *sigmask
;
605 * posix_spawnattr_setbinpref_np
607 * Description: Set the universal binary preferences for the spawn attribute
608 * value referenced by 'attr' from the memory containing the
609 * cpu_type_t array referenced by 'pref', size of 'count'
611 * Parameters: attr The spawn attributes object whose
612 * binary preferences are to be set
613 * count Size of the array pointed to by 'pref'
614 * pref cpu_type_t array of binary preferences
615 * ocount The actual number copied
617 * Returns: 0 No preferences copied
618 * > 0 Number of preferences copied
620 * Note: The posix_spawnattr_t currently only holds four cpu_type_t's.
621 * If the caller provides more preferences than this limit, they
622 * will be ignored, as reflected in the return value.
625 posix_spawnattr_setbinpref_np(posix_spawnattr_t
* __restrict attr
,
626 size_t count
, cpu_type_t
*pref
, size_t * __restrict ocount
)
628 _posix_spawnattr_t psattr
;
631 if (attr
== NULL
|| *attr
== NULL
) {
635 psattr
= *(_posix_spawnattr_t
*)attr
;
636 for (i
= 0; i
< count
&& i
< 4; i
++) {
637 psattr
->psa_binprefs
[i
] = pref
[i
];
640 /* return number of binprefs copied over */
649 * posix_spawnattr_setpcontrol_np
651 * Description: Set the process control property according to
652 * attribute value referenced by 'attr' from the memory
653 * containing the int value 'pcontrol'
655 * Parameters: attr The spawn attributes object whose
656 * signal set for default signals is to
658 * pcontrol An int value of the process control info
663 posix_spawnattr_setpcontrol_np(posix_spawnattr_t
* __restrict attr
,
666 _posix_spawnattr_t psattr
;
668 if (attr
== NULL
|| *attr
== NULL
) {
672 psattr
= *(_posix_spawnattr_t
*)attr
;
673 psattr
->psa_pcontrol
= pcontrol
;
680 * posix_spawnattr_setprocesstype_np
682 * Description: Set the process specific behaviors and app launch type
683 * attribute value referenced by 'attr' from the memory
684 * containing the int value 'proctype'
686 * Parameters: attr The spawn attributes object whose
687 * signal set for default signals is to
689 * proctype An int value of the process type info
694 posix_spawnattr_setprocesstype_np(posix_spawnattr_t
* __restrict attr
,
697 _posix_spawnattr_t psattr
;
699 if (attr
== NULL
|| *attr
== NULL
) {
703 psattr
= *(_posix_spawnattr_t
*)attr
;
704 psattr
->psa_apptype
= proctype
;
710 * posix_spawn_createportactions_np
711 * Description: create a new posix_spawn_port_actions struct and link
712 * it into the posix_spawnattr.
715 posix_spawn_createportactions_np(posix_spawnattr_t
*attr
)
717 _posix_spawnattr_t psattr
;
718 _posix_spawn_port_actions_t acts
;
720 if (attr
== NULL
|| *attr
== NULL
) {
724 psattr
= *(_posix_spawnattr_t
*)attr
;
725 acts
= (_posix_spawn_port_actions_t
)malloc(PS_PORT_ACTIONS_SIZE(2));
730 acts
->pspa_alloc
= 2;
731 acts
->pspa_count
= 0;
733 psattr
->psa_ports
= acts
;
738 * posix_spawn_growportactions_np
739 * Description: Enlarge the size of portactions if necessary
742 posix_spawn_growportactions_np(posix_spawnattr_t
*attr
)
744 _posix_spawnattr_t psattr
;
745 _posix_spawn_port_actions_t acts
;
747 if (attr
== NULL
|| *attr
== NULL
) {
751 psattr
= *(_posix_spawnattr_t
*)attr
;
752 acts
= psattr
->psa_ports
;
757 /* Double number of port actions allocated for */
759 if (os_mul_overflow(acts
->pspa_alloc
, 2, &newnum
)) {
762 size_t newsize
= PS_PORT_ACTIONS_SIZE(newnum
);
767 acts
= realloc(acts
, newsize
);
772 acts
->pspa_alloc
= newnum
;
773 psattr
->psa_ports
= acts
;
778 * posix_spawn_destroyportactions_np
779 * Description: clean up portactions struct in posix_spawnattr_t attr
782 posix_spawn_destroyportactions_np(posix_spawnattr_t
*attr
)
784 _posix_spawnattr_t psattr
;
785 _posix_spawn_port_actions_t acts
;
787 if (attr
== NULL
|| *attr
== NULL
) {
791 psattr
= *(_posix_spawnattr_t
*)attr
;
792 acts
= psattr
->psa_ports
;
802 * posix_spawn_destroycoalition_info_np
803 * Description: clean up coalition_info struct in posix_spawnattr_t attr
806 posix_spawn_destroycoalition_info_np(posix_spawnattr_t
*attr
)
808 _posix_spawnattr_t psattr
;
809 struct _posix_spawn_coalition_info
*coal_info
;
811 if (attr
== NULL
|| *attr
== NULL
) {
815 psattr
= *(_posix_spawnattr_t
*)attr
;
816 coal_info
= psattr
->psa_coalition_info
;
817 if (coal_info
== NULL
) {
821 psattr
->psa_coalition_info
= NULL
;
827 * posix_spawn_destroypersona_info_np
828 * Description: clean up persona_info struct in posix_spawnattr_t attr
831 posix_spawn_destroypersona_info_np(posix_spawnattr_t
*attr
)
833 _posix_spawnattr_t psattr
;
834 struct _posix_spawn_persona_info
*persona
;
836 if (attr
== NULL
|| *attr
== NULL
) {
840 psattr
= *(_posix_spawnattr_t
*)attr
;
841 persona
= psattr
->psa_persona_info
;
842 if (persona
== NULL
) {
846 psattr
->psa_persona_info
= NULL
;
852 * posix_spawn_destroyposix_cred_info_np
853 * Description: clean up posix_cred_info struct in posix_spawnattr_t attr
856 posix_spawn_destroyposix_cred_info_np(posix_spawnattr_t
*attr
)
858 _posix_spawnattr_t psattr
;
859 struct _posix_spawn_posix_cred_info
*pspci
;
861 if (attr
== NULL
|| *attr
== NULL
) {
865 psattr
= *(_posix_spawnattr_t
*)attr
;
866 pspci
= psattr
->psa_posix_cred_info
;
871 psattr
->psa_posix_cred_info
= NULL
;
877 * posix_spawn_appendportaction_np
878 * Description: append a port action, grow the array if necessary
881 posix_spawn_appendportaction_np(posix_spawnattr_t
*attr
, _ps_port_action_t
*act
)
883 _posix_spawnattr_t psattr
;
884 _posix_spawn_port_actions_t acts
;
886 if (attr
== NULL
|| *attr
== NULL
|| act
== NULL
) {
890 psattr
= *(_posix_spawnattr_t
*)attr
;
891 acts
= psattr
->psa_ports
;
893 // Have any port actions been created yet?
895 int err
= posix_spawn_createportactions_np(attr
);
899 acts
= psattr
->psa_ports
;
902 // Is there enough room?
903 if (acts
->pspa_alloc
== acts
->pspa_count
) {
904 int err
= posix_spawn_growportactions_np(attr
);
908 acts
= psattr
->psa_ports
;
911 // Add this action to next spot in array
912 acts
->pspa_actions
[acts
->pspa_count
] = *act
;
919 * posix_spawnattr_setspecialport_np
921 * Description: Set a new value for a mach special port in the spawned task.
923 * Parameters: attr The spawn attributes object for the
925 * new_port The new value for the special port
926 * which The particular port to be set
927 * (see task_set_special_port for details)
930 * ENOMEM Couldn't allocate memory
933 posix_spawnattr_setspecialport_np(
934 posix_spawnattr_t
*attr
,
935 mach_port_t new_port
,
938 _ps_port_action_t action
= {
939 .port_type
= PSPA_SPECIAL
,
940 .new_port
= new_port
,
943 return posix_spawn_appendportaction_np(attr
, &action
);
947 * posix_spawnattr_setexceptionports_np
949 * Description: Set a new port for a set of exception ports in the spawned task.
951 * Parameters: attr The spawn attributes object for the
953 * mask A bitfield indicating which exceptions
954 * to associate the port with
955 * new_port The new value for the exception port
956 * behavior The default behavior for the port
957 * flavor The default flavor for the port
958 * (see task_set_exception_ports)
963 posix_spawnattr_setexceptionports_np(
964 posix_spawnattr_t
*attr
,
965 exception_mask_t mask
,
966 mach_port_t new_port
,
967 exception_behavior_t behavior
,
968 thread_state_flavor_t flavor
)
970 _ps_port_action_t action
= {
971 .port_type
= PSPA_EXCEPTION
,
973 .new_port
= new_port
,
974 .behavior
= behavior
,
977 return posix_spawn_appendportaction_np(attr
, &action
);
981 * posix_spawnattr_setauditsessionport_np
983 * Description: Set the audit session port rights attribute in the spawned task.
984 * This is used to securely set the audit session information for
987 * Parameters: attr The spawn attributes object for the
989 * au_sessionport The audit session send port right
994 posix_spawnattr_setauditsessionport_np(
995 posix_spawnattr_t
*attr
,
996 mach_port_t au_sessionport
)
998 _ps_port_action_t action
= {
999 .port_type
= PSPA_AU_SESSION
,
1000 .new_port
= au_sessionport
,
1002 return posix_spawn_appendportaction_np(attr
, &action
);
1007 * posix_spawn_file_actions_init
1009 * Description: Initialize a spawn file actions object attr with default values
1011 * Parameters: file_actions The spawn file actions object to be
1014 * Returns: 0 Success
1015 * ENOMEM Insufficient memory exists to
1016 * initialize the spawn file actions
1019 * Note: As an implementation detail, the externally visibily type
1020 * posix_spawn_file_actions_t is defined to be a void *, and
1021 * initialization involves allocation of a memory object.
1022 * Subsequent changes to the spawn file actions may result in
1023 * reallocation under the covers.
1025 * Reinitialization of an already initialized spawn file actions
1026 * object will result in memory being leaked. Because spawn
1027 * file actions are not required to be used in conjunction with a
1028 * static initializer, there is no way to distinguish a spawn
1029 * file actions with stack garbage from one that's been
1030 * initialized. This is arguably an API design error.
1033 posix_spawn_file_actions_init(posix_spawn_file_actions_t
*file_actions
)
1035 _posix_spawn_file_actions_t
*psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1038 if ((*psactsp
= (_posix_spawn_file_actions_t
)malloc(PSF_ACTIONS_SIZE(PSF_ACTIONS_INIT_COUNT
))) == NULL
) {
1041 (*psactsp
)->psfa_act_alloc
= PSF_ACTIONS_INIT_COUNT
;
1042 (*psactsp
)->psfa_act_count
= 0;
1050 * posix_spawn_file_actions_destroy
1052 * Description: Destroy a spawn file actions object that was previously
1053 * initialized via posix_spawn_file_actions_init() by freeing any
1054 * memory associated with it and setting it to an invalid value.
1056 * Parameters: attr The spawn file actions object to be
1059 * Returns: 0 Success
1061 * Notes: The destroyed spawn file actions results in the void * pointer
1062 * being set to NULL; subsequent use without reinitialization
1063 * will result in explicit program failure (rather than merely
1064 * "undefined behaviour").
1066 * NOTIMP: Allowed failures (checking NOT required):
1067 * EINVAL The value specified by file_actions is invalid.
1070 posix_spawn_file_actions_destroy(posix_spawn_file_actions_t
*file_actions
)
1072 _posix_spawn_file_actions_t psacts
;
1074 if (file_actions
== NULL
|| *file_actions
== NULL
) {
1078 psacts
= *(_posix_spawn_file_actions_t
*)file_actions
;
1080 *file_actions
= NULL
;
1087 * _posix_spawn_file_actions_grow
1089 * Description: Grow the available list of file actions associated with the
1090 * pointer to the structure provided; replace the contents of the
1091 * pointer as a side effect.
1093 * Parameters: psactsp Pointer to _posix_spawn_file_actions_t
1096 * Returns: 0 Success
1097 * ENOMEM Insufficient memory for operation
1099 * Notes: This code is common to all posix_spawn_file_actions_*()
1100 * functions, since we use a naieve data structure implementation
1101 * at present. Future optimization will likely change this.
1104 _posix_spawn_file_actions_grow(_posix_spawn_file_actions_t
*psactsp
)
1107 if (os_mul_overflow((*psactsp
)->psfa_act_alloc
, 2, &newnum
)) {
1111 size_t newsize
= PSF_ACTIONS_SIZE(newnum
);
1117 * XXX may want to impose an administrative limit here; POSIX does
1118 * XXX not provide for an administrative error return in this case,
1119 * XXX so it's probably acceptable to just fail catastrophically
1120 * XXX instead of implementing one.
1122 _posix_spawn_file_actions_t new_psacts
;
1123 if ((new_psacts
= (_posix_spawn_file_actions_t
)realloc((*psactsp
), newsize
)) == NULL
) {
1126 new_psacts
->psfa_act_alloc
= newnum
;
1127 *psactsp
= new_psacts
;
1134 * posix_spawn_file_actions_addopen
1136 * Description: Add an open action to the object referenced by 'file_actions'
1137 * that will cause the file named by 'path' to be attempted to be
1138 * opened with flags 'oflag' and mode 'mode', and, if successful,
1139 * return as descriptor 'filedes' to the spawned process.
1141 * Parameters: file_actions File action object to augment
1142 * filedes fd that open is to use
1143 * path path to file to open
1144 * oflag open file flags
1145 * mode open file mode
1147 * Returns: 0 Success
1148 * EBADF The value specified by fildes is
1149 * negative or greater than or equal to
1151 * ENOMEM Insufficient memory exists to add to
1152 * the spawn file actions object.
1154 * NOTIMP: Allowed failures (checking NOT required):
1155 * EINVAL The value specified by file_actions is invalid.
1158 posix_spawn_file_actions_addopen(
1159 posix_spawn_file_actions_t
* __restrict file_actions
,
1160 int filedes
, const char * __restrict path
, int oflag
,
1163 _posix_spawn_file_actions_t
*psactsp
;
1164 _psfa_action_t
*psfileact
;
1166 if (file_actions
== NULL
|| *file_actions
== NULL
) {
1170 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1171 /* Range check; required by POSIX */
1172 if (filedes
< 0 || filedes
>= OPEN_MAX
) {
1176 /* If we do not have enough slots, grow the structure */
1177 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1178 /* need to grow file actions structure */
1179 if (_posix_spawn_file_actions_grow(psactsp
)) {
1185 * Allocate next available slot and fill it out
1187 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1189 psfileact
->psfaa_type
= PSFA_OPEN
;
1190 psfileact
->psfaa_filedes
= filedes
;
1191 psfileact
->psfaa_openargs
.psfao_oflag
= oflag
;
1192 psfileact
->psfaa_openargs
.psfao_mode
= mode
;
1193 strlcpy(psfileact
->psfaa_openargs
.psfao_path
, path
, PATH_MAX
);
1200 * posix_spawn_file_actions_addclose
1202 * Description: Add a close action to the object referenced by 'file_actions'
1203 * that will cause the file referenced by 'filedes' to be
1204 * attempted to be closed in the spawned process.
1206 * Parameters: file_actions File action object to augment
1207 * filedes fd to close
1209 * Returns: 0 Success
1210 * EBADF The value specified by fildes is
1211 * negative or greater than or equal to
1213 * ENOMEM Insufficient memory exists to add to
1214 * the spawn file actions object.
1216 * NOTIMP: Allowed failures (checking NOT required):
1217 * EINVAL The value specified by file_actions is invalid.
1220 posix_spawn_file_actions_addclose(posix_spawn_file_actions_t
*file_actions
,
1223 _posix_spawn_file_actions_t
*psactsp
;
1224 _psfa_action_t
*psfileact
;
1226 if (file_actions
== NULL
|| *file_actions
== NULL
) {
1230 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1231 /* Range check; required by POSIX */
1232 if (filedes
< 0 || filedes
>= OPEN_MAX
) {
1236 /* If we do not have enough slots, grow the structure */
1237 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1238 /* need to grow file actions structure */
1239 if (_posix_spawn_file_actions_grow(psactsp
)) {
1245 * Allocate next available slot and fill it out
1247 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1249 psfileact
->psfaa_type
= PSFA_CLOSE
;
1250 psfileact
->psfaa_filedes
= filedes
;
1257 * posix_spawn_file_actions_adddup2
1259 * Description: Add a dup2 action to the object referenced by 'file_actions'
1260 * that will cause the file referenced by 'filedes' to be
1261 * attempted to be dup2'ed to the descriptor 'newfiledes' in the
1264 * Parameters: file_actions File action object to augment
1265 * filedes fd to dup2
1266 * newfiledes fd to dup2 it to
1268 * Returns: 0 Success
1269 * EBADF The value specified by either fildes
1270 * or by newfiledes is negative or greater
1271 * than or equal to {OPEN_MAX}.
1272 * ENOMEM Insufficient memory exists to add to
1273 * the spawn file actions object.
1275 * NOTIMP: Allowed failures (checking NOT required):
1276 * EINVAL The value specified by file_actions is invalid.
1279 posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t
*file_actions
,
1280 int filedes
, int newfiledes
)
1282 _posix_spawn_file_actions_t
*psactsp
;
1283 _psfa_action_t
*psfileact
;
1285 if (file_actions
== NULL
|| *file_actions
== NULL
) {
1289 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1290 /* Range check; required by POSIX */
1291 if (filedes
< 0 || filedes
>= OPEN_MAX
||
1292 newfiledes
< 0 || newfiledes
>= OPEN_MAX
) {
1296 /* If we do not have enough slots, grow the structure */
1297 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1298 /* need to grow file actions structure */
1299 if (_posix_spawn_file_actions_grow(psactsp
)) {
1305 * Allocate next available slot and fill it out
1307 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1309 psfileact
->psfaa_type
= PSFA_DUP2
;
1310 psfileact
->psfaa_filedes
= filedes
;
1311 psfileact
->psfaa_dup2args
.psfad_newfiledes
= newfiledes
;
1317 * posix_spawn_file_actions_add_fileportdup2_np
1319 * Description: Add a dup2 action to the object referenced by 'file_actions'
1320 * that will cause the file referenced by 'fileport' to be
1321 * attempted to be dup2'ed to the descriptor 'newfiledes' in the
1324 * Parameters: file_actions File action object to augment
1325 * filedes fileport to dup2
1326 * newfiledes fd to dup2 it to
1328 * Returns: 0 Success
1329 * EBADF fileport isn't a valid port, or the
1330 * value specified by newfiledes is
1331 * negative or greater than or equal to
1333 * ENOMEM Insufficient memory exists to add to
1334 * the spawn file actions object.
1336 * NOTIMP: Allowed failures (checking NOT required):
1337 * EINVAL The value specified by file_actions is invalid.
1340 posix_spawn_file_actions_add_fileportdup2_np(
1341 posix_spawn_file_actions_t
*file_actions
,
1342 mach_port_t fileport
, int newfiledes
)
1344 _posix_spawn_file_actions_t
*psactsp
;
1345 _psfa_action_t
*psfileact
;
1347 if (file_actions
== NULL
|| *file_actions
== NULL
) {
1351 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1352 /* Range check; required by POSIX */
1353 if (!MACH_PORT_VALID(fileport
) ||
1354 newfiledes
< 0 || newfiledes
>= OPEN_MAX
) {
1358 /* If we do not have enough slots, grow the structure */
1359 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1360 /* need to grow file actions structure */
1361 if (_posix_spawn_file_actions_grow(psactsp
)) {
1367 * Allocate next available slot and fill it out
1369 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1371 psfileact
->psfaa_type
= PSFA_FILEPORT_DUP2
;
1372 psfileact
->psfaa_fileport
= fileport
;
1373 psfileact
->psfaa_dup2args
.psfad_newfiledes
= newfiledes
;
1379 * posix_spawn_file_actions_addinherit_np
1381 * Description: Add the "inherit" action to the object referenced by
1382 * 'file_actions' that will cause the file referenced by
1383 * 'filedes' to continue to be available in the spawned
1384 * process via the same descriptor.
1386 * Inheritance is the normal default behaviour for
1387 * file descriptors across exec and spawn; but if the
1388 * POSIX_SPAWN_CLOEXEC_DEFAULT flag is set, the usual
1389 * default is reversed for the purposes of the spawn
1390 * invocation. Any pre-existing descriptors that
1391 * need to be made available to the spawned process can
1392 * be marked explicitly as 'inherit' via this interface.
1393 * Otherwise they will be automatically closed.
1395 * Note that any descriptors created via the other file
1396 * actions interfaces are automatically marked as 'inherit'.
1398 * Parameters: file_actions File action object to augment
1399 * filedes fd to inherit.
1401 * Returns: 0 Success
1402 * EBADF The value specified by fildes is
1403 * negative or greater than or equal to
1405 * ENOMEM Insufficient memory exists to add to
1406 * the spawn file actions object.
1408 * NOTIMP: Allowed failures (checking NOT required):
1409 * EINVAL The value specified by file_actions is invalid.
1412 posix_spawn_file_actions_addinherit_np(posix_spawn_file_actions_t
*file_actions
,
1415 _posix_spawn_file_actions_t
*psactsp
;
1416 _psfa_action_t
*psfileact
;
1418 if (file_actions
== NULL
|| *file_actions
== NULL
) {
1422 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1423 /* Range check; required by POSIX */
1424 if (filedes
< 0 || filedes
>= OPEN_MAX
) {
1428 #if defined(POSIX_SPAWN_CLOEXEC_DEFAULT) // TODO: delete this check
1429 /* If we do not have enough slots, grow the structure */
1430 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1431 /* need to grow file actions structure */
1432 if (_posix_spawn_file_actions_grow(psactsp
)) {
1438 * Allocate next available slot and fill it out
1440 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1442 psfileact
->psfaa_type
= PSFA_INHERIT
;
1443 psfileact
->psfaa_filedes
= filedes
;
1450 * posix_spawn_file_actions_addchdir_np
1452 * Description: Add a chdir action to the object referenced by 'file_actions'
1453 * that will cause the current working directory to attempt to be changed
1454 * to that referenced by 'path' in the spawned process.
1456 * Parameters: file_actions File action object to augment
1457 * path path of the desired working directory
1459 * Returns: 0 Success
1460 * ENOMEM Insufficient memory exists to add to
1461 * the spawn file actions object.
1462 * ENAMETOOLONG The supplied path exceeded PATH_MAX.
1464 * NOTIMP: Allowed failures (checking NOT required):
1465 * EINVAL The value specified by file_actions is invalid.
1468 posix_spawn_file_actions_addchdir_np(
1469 posix_spawn_file_actions_t
* __restrict file_actions
,
1470 const char * __restrict path
)
1472 _posix_spawn_file_actions_t
*psactsp
;
1473 _psfa_action_t
*psfileact
;
1475 if (file_actions
== NULL
|| *file_actions
== NULL
) {
1479 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1481 /* If we do not have enough slots, grow the structure */
1482 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1483 /* need to grow file actions structure */
1484 if (_posix_spawn_file_actions_grow(psactsp
)) {
1490 * Allocate next available slot and fill it out
1492 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1494 psfileact
->psfaa_type
= PSFA_CHDIR
;
1495 if (strlcpy(psfileact
->psfaa_chdirargs
.psfac_path
, path
, PATH_MAX
) >= PATH_MAX
) {
1496 (*psactsp
)->psfa_act_count
--;
1497 return ENAMETOOLONG
;
1505 * posix_spawn_file_actions_fchdir_np
1507 * Description: Add a fchdir action to the object referenced by 'file_actions'
1508 * that will cause the current working directory to attempt to be changed
1509 * to that referenced by the descriptor 'filedes' in the spawned process.
1511 * Parameters: file_actions File action object to augment
1512 * filedes fd to chdir to
1514 * Returns: 0 Success
1515 * EBADF The value specified by either fildes is negative or
1516 * greater than or equal to {OPEN_MAX}.
1517 * ENOMEM Insufficient memory exists to add to
1518 * the spawn file actions object.
1520 * NOTIMP: Allowed failures (checking NOT required):
1521 * EINVAL The value specified by file_actions is invalid.
1524 posix_spawn_file_actions_addfchdir_np(posix_spawn_file_actions_t
*file_actions
,
1527 _posix_spawn_file_actions_t
*psactsp
;
1528 _psfa_action_t
*psfileact
;
1530 if (file_actions
== NULL
|| *file_actions
== NULL
) {
1534 psactsp
= (_posix_spawn_file_actions_t
*)file_actions
;
1535 /* Range check; in spirit of POSIX */
1536 if (filedes
< 0 || filedes
>= OPEN_MAX
) {
1540 /* If we do not have enough slots, grow the structure */
1541 if ((*psactsp
)->psfa_act_count
== (*psactsp
)->psfa_act_alloc
) {
1542 /* need to grow file actions structure */
1543 if (_posix_spawn_file_actions_grow(psactsp
)) {
1549 * Allocate next available slot and fill it out
1551 psfileact
= &(*psactsp
)->psfa_act_acts
[(*psactsp
)->psfa_act_count
++];
1553 psfileact
->psfaa_type
= PSFA_FCHDIR
;
1554 psfileact
->psfaa_filedes
= filedes
;
1560 posix_spawnattr_setcpumonitor_default(posix_spawnattr_t
* __restrict attr
)
1562 return posix_spawnattr_setcpumonitor(attr
, PROC_POLICY_CPUMON_DEFAULTS
, 0);
1566 posix_spawnattr_setcpumonitor(posix_spawnattr_t
* __restrict attr
,
1567 uint64_t percent
, uint64_t interval
)
1569 _posix_spawnattr_t psattr
;
1571 if (attr
== NULL
|| *attr
== NULL
) {
1575 psattr
= *(_posix_spawnattr_t
*)attr
;
1577 psattr
->psa_cpumonitor_percent
= percent
;
1578 psattr
->psa_cpumonitor_interval
= interval
;
1584 posix_spawnattr_getcpumonitor(posix_spawnattr_t
* __restrict attr
,
1585 uint64_t *percent
, uint64_t *interval
)
1587 _posix_spawnattr_t psattr
;
1589 if (attr
== NULL
|| *attr
== NULL
) {
1593 psattr
= *(_posix_spawnattr_t
*)attr
;
1595 *percent
= psattr
->psa_cpumonitor_percent
;
1596 *interval
= psattr
->psa_cpumonitor_interval
;
1601 #if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
1603 * posix_spawnattr_setjetsam
1605 * Description: Set jetsam attributes for the spawn attribute object
1606 * referred to by 'attr'.
1608 * Parameters: flags The flags value to set
1609 * priority Relative jetsam priority
1610 * memlimit Value in megabytes; a memory footprint
1611 * above this level may result in termination.
1612 * Implies both active and inactive limits.
1614 * Returns: 0 Success
1616 * Note: to be deprecated (not available on desktop)
1620 posix_spawnattr_setjetsam(posix_spawnattr_t
* __restrict attr
,
1621 short flags
, int priority
, int memlimit
)
1623 short flags_ext
= flags
;
1625 if (flags
& POSIX_SPAWN_JETSAM_MEMLIMIT_FATAL
) {
1626 flags_ext
|= POSIX_SPAWN_JETSAM_MEMLIMIT_ACTIVE_FATAL
;
1627 flags_ext
|= POSIX_SPAWN_JETSAM_MEMLIMIT_INACTIVE_FATAL
;
1629 flags_ext
&= ~POSIX_SPAWN_JETSAM_MEMLIMIT_ACTIVE_FATAL
;
1630 flags_ext
&= ~POSIX_SPAWN_JETSAM_MEMLIMIT_INACTIVE_FATAL
;
1633 return posix_spawnattr_setjetsam_ext(attr
, flags_ext
, priority
, memlimit
, memlimit
);
1635 #endif /* (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) */
1638 * posix_spawnattr_setjetsam_ext
1640 * Description: Set jetsam attributes for the spawn attribute object
1641 * referred to by 'attr'.
1643 * Parameters: flags The flags value to set
1644 * priority Relative jetsam priority
1645 * memlimit_active Value in megabytes; memory footprint
1646 * above this level while process is
1647 * active may result in termination.
1648 * memlimit_inactive Value in megabytes; memory footprint
1649 * above this level while process is
1650 * inactive may result in termination.
1652 * Returns: 0 Success
1655 posix_spawnattr_setjetsam_ext(posix_spawnattr_t
* __restrict attr
,
1656 short flags
, int priority
, int memlimit_active
, int memlimit_inactive
)
1658 _posix_spawnattr_t psattr
;
1660 if (attr
== NULL
|| *attr
== NULL
) {
1664 psattr
= *(_posix_spawnattr_t
*)attr
;
1666 psattr
->psa_jetsam_flags
= flags
;
1667 psattr
->psa_jetsam_flags
|= POSIX_SPAWN_JETSAM_SET
;
1668 psattr
->psa_priority
= priority
;
1669 psattr
->psa_memlimit_active
= memlimit_active
;
1670 psattr
->psa_memlimit_inactive
= memlimit_inactive
;
1676 posix_spawnattr_set_threadlimit_ext(posix_spawnattr_t
* __restrict attr
,
1679 _posix_spawnattr_t psattr
;
1681 if (attr
== NULL
|| *attr
== NULL
) {
1685 psattr
= *(_posix_spawnattr_t
*)attr
;
1687 psattr
->psa_thread_limit
= thread_limit
;
1694 * posix_spawnattr_set_importancewatch_port_np
1696 * Description: Mark ports referred to by these rights
1697 * to boost the new task instead of their current task
1698 * for the spawn attribute object referred to by 'attr'.
1699 * Ports must be valid at posix_spawn time. They will NOT be
1700 * consumed by the kernel, so they must be deallocated after the spawn returns.
1701 * (If you are SETEXEC-ing, they are cleaned up by the exec operation).
1703 * The maximum number of watch ports allowed is defined by POSIX_SPAWN_IMPORTANCE_PORT_COUNT.
1705 * Parameters: count Number of ports in portarray
1706 * portarray Array of rights
1708 * Returns: 0 Success
1709 * EINVAL Bad port count
1710 * ENOMEM Insufficient memory exists to add to
1711 * the spawn port actions object.
1714 posix_spawnattr_set_importancewatch_port_np(posix_spawnattr_t
* __restrict attr
,
1715 int count
, mach_port_t portarray
[])
1719 if (count
< 0 || count
> POSIX_SPAWN_IMPORTANCE_PORT_COUNT
) {
1723 for (i
= 0; i
< count
; i
++) {
1724 _ps_port_action_t action
= {
1725 .port_type
= PSPA_IMP_WATCHPORTS
,
1726 .new_port
= portarray
[i
],
1728 err
= posix_spawn_appendportaction_np(attr
, &action
);
1737 posix_spawnattr_set_registered_ports_np(posix_spawnattr_t
* __restrict attr
,
1738 mach_port_t portarray
[], uint32_t count
)
1742 if (count
> TASK_PORT_REGISTER_MAX
) {
1746 for (uint32_t i
= 0; i
< count
; i
++) {
1747 _ps_port_action_t action
= {
1748 .port_type
= PSPA_REGISTERED_PORTS
,
1749 .new_port
= portarray
[i
],
1751 err
= posix_spawn_appendportaction_np(attr
, &action
);
1761 _ps_mac_policy_extension_t
*
1762 posix_spawnattr_macpolicyinfo_lookup(_posix_spawn_mac_policy_extensions_t psmx
, const char *policyname
)
1770 for (i
= 0; i
< psmx
->psmx_count
; i
++) {
1771 _ps_mac_policy_extension_t
*extension
= &psmx
->psmx_extensions
[i
];
1772 if (strcmp(extension
->policyname
, policyname
) == 0) {
1780 posix_spawnattr_getmacpolicyinfo_np(const posix_spawnattr_t
* __restrict attr
,
1781 const char *policyname
, void **datap
, size_t *datalenp
)
1783 _posix_spawnattr_t psattr
;
1784 _ps_mac_policy_extension_t
*extension
;
1786 if (attr
== NULL
|| *attr
== NULL
|| policyname
== NULL
|| datap
== NULL
) {
1790 psattr
= *(_posix_spawnattr_t
*)attr
;
1791 extension
= posix_spawnattr_macpolicyinfo_lookup(psattr
->psa_mac_extensions
, policyname
);
1792 if (extension
== NULL
) {
1795 *datap
= (void *)(uintptr_t)extension
->data
;
1796 if (datalenp
!= NULL
) {
1797 *datalenp
= (size_t)extension
->datalen
;
1803 posix_spawnattr_setmacpolicyinfo_np(posix_spawnattr_t
* __restrict attr
,
1804 const char *policyname
, void *data
, size_t datalen
)
1806 _posix_spawnattr_t psattr
;
1807 _posix_spawn_mac_policy_extensions_t psmx
;
1808 _ps_mac_policy_extension_t
*extension
;
1810 if (attr
== NULL
|| *attr
== NULL
|| policyname
== NULL
) {
1814 psattr
= *(_posix_spawnattr_t
*)attr
;
1815 psmx
= psattr
->psa_mac_extensions
;
1816 extension
= posix_spawnattr_macpolicyinfo_lookup(psattr
->psa_mac_extensions
, policyname
);
1817 if (extension
!= NULL
) {
1818 extension
->data
= (uintptr_t)data
;
1819 extension
->datalen
= datalen
;
1821 } else if (psmx
== NULL
) {
1822 psmx
= psattr
->psa_mac_extensions
= malloc(PS_MAC_EXTENSIONS_SIZE(PS_MAC_EXTENSIONS_INIT_COUNT
));
1826 psmx
->psmx_alloc
= PS_MAC_EXTENSIONS_INIT_COUNT
;
1827 psmx
->psmx_count
= 0;
1828 } else if (psmx
->psmx_count
== psmx
->psmx_alloc
) {
1830 if (os_mul_overflow(psmx
->psmx_alloc
, 2, &newnum
)) {
1833 size_t extsize
= PS_MAC_EXTENSIONS_SIZE(newnum
);
1837 psmx
= psattr
->psa_mac_extensions
= reallocf(psmx
, extsize
);
1841 psmx
->psmx_alloc
= newnum
;
1843 extension
= &psmx
->psmx_extensions
[psmx
->psmx_count
];
1844 strlcpy(extension
->policyname
, policyname
, sizeof(extension
->policyname
));
1845 extension
->data
= (uintptr_t)data
;
1846 extension
->datalen
= datalen
;
1847 psmx
->psmx_count
+= 1;
1852 * posix_spawn_destroymacpolicy_info_np
1853 * Description: cleanup the macpolicy struct in posix_spawnattr_t attr
1856 posix_spawn_destroymacpolicy_info_np(posix_spawnattr_t
*attr
)
1858 _posix_spawnattr_t psattr
;
1859 _posix_spawn_mac_policy_extensions_t psmx
;
1861 if (attr
== NULL
|| *attr
== NULL
) {
1865 psattr
= *(_posix_spawnattr_t
*)attr
;
1866 psmx
= psattr
->psa_mac_extensions
;
1871 psattr
->psa_mac_extensions
= NULL
;
1877 posix_spawnattr_setcoalition_np(const posix_spawnattr_t
* __restrict attr
,
1878 uint64_t coalitionid
, int type
, int role
)
1880 _posix_spawnattr_t psattr
;
1881 struct _posix_spawn_coalition_info
*coal_info
;
1883 if (attr
== NULL
|| *attr
== NULL
) {
1886 if (type
< 0 || type
> COALITION_TYPE_MAX
) {
1890 psattr
= *(_posix_spawnattr_t
*)attr
;
1892 coal_info
= psattr
->psa_coalition_info
;
1894 coal_info
= (struct _posix_spawn_coalition_info
*)malloc(sizeof(*coal_info
));
1898 memset(coal_info
, 0, sizeof(*coal_info
));
1899 psattr
->psa_coalition_info
= coal_info
;
1902 coal_info
->psci_info
[type
].psci_id
= coalitionid
;
1903 coal_info
->psci_info
[type
].psci_role
= role
;
1910 posix_spawnattr_set_qos_clamp_np(const posix_spawnattr_t
* __restrict attr
, uint64_t qos_clamp
)
1912 _posix_spawnattr_t psattr
;
1914 if (attr
== NULL
|| *attr
== NULL
) {
1918 if (qos_clamp
>= POSIX_SPAWN_PROC_CLAMP_LAST
) {
1922 psattr
= *(_posix_spawnattr_t
*)attr
;
1923 psattr
->psa_qos_clamp
= qos_clamp
;
1929 posix_spawnattr_get_qos_clamp_np(const posix_spawnattr_t
* __restrict attr
, uint64_t * __restrict qos_clampp
)
1931 _posix_spawnattr_t psattr
;
1933 if (attr
== NULL
|| *attr
== NULL
) {
1937 psattr
= *(_posix_spawnattr_t
*)attr
;
1938 *qos_clampp
= psattr
->psa_qos_clamp
;
1944 posix_spawnattr_set_darwin_role_np(const posix_spawnattr_t
* __restrict attr
, uint64_t darwin_role
)
1946 _posix_spawnattr_t psattr
;
1948 if (attr
== NULL
|| *attr
== NULL
) {
1952 psattr
= *(_posix_spawnattr_t
*)attr
;
1953 psattr
->psa_darwin_role
= darwin_role
;
1959 posix_spawnattr_get_darwin_role_np(const posix_spawnattr_t
* __restrict attr
, uint64_t * __restrict darwin_rolep
)
1961 _posix_spawnattr_t psattr
;
1963 if (attr
== NULL
|| *attr
== NULL
) {
1967 psattr
= *(_posix_spawnattr_t
*)attr
;
1968 *darwin_rolep
= psattr
->psa_darwin_role
;
1975 posix_spawnattr_set_persona_np(const posix_spawnattr_t
* __restrict attr
, uid_t persona_id
, uint32_t flags
)
1977 _posix_spawnattr_t psattr
;
1978 struct _posix_spawn_persona_info
*persona
;
1980 if (attr
== NULL
|| *attr
== NULL
) {
1984 if (flags
& ~POSIX_SPAWN_PERSONA_ALL_FLAGS
) {
1988 psattr
= *(_posix_spawnattr_t
*)attr
;
1990 persona
= psattr
->psa_persona_info
;
1992 persona
= (struct _posix_spawn_persona_info
*)malloc(sizeof(*persona
));
1996 persona
->pspi_uid
= 0;
1997 persona
->pspi_gid
= 0;
1998 persona
->pspi_ngroups
= 0;
1999 persona
->pspi_groups
[0] = 0;
2000 persona
->pspi_gmuid
= 0;
2002 psattr
->psa_persona_info
= persona
;
2005 persona
->pspi_id
= persona_id
;
2006 persona
->pspi_flags
= flags
;
2012 posix_spawnattr_set_persona_uid_np(const posix_spawnattr_t
* __restrict attr
, uid_t uid
)
2014 _posix_spawnattr_t psattr
;
2015 struct _posix_spawn_persona_info
*persona
;
2017 if (attr
== NULL
|| *attr
== NULL
) {
2021 psattr
= *(_posix_spawnattr_t
*)attr
;
2022 persona
= psattr
->psa_persona_info
;
2027 if (!(persona
->pspi_flags
& (POSIX_SPAWN_PERSONA_FLAGS_OVERRIDE
| POSIX_SPAWN_PERSONA_FLAGS_VERIFY
))) {
2031 persona
->pspi_uid
= uid
;
2033 persona
->pspi_flags
|= POSIX_SPAWN_PERSONA_UID
;
2039 posix_spawnattr_set_persona_gid_np(const posix_spawnattr_t
* __restrict attr
, gid_t gid
)
2041 _posix_spawnattr_t psattr
;
2042 struct _posix_spawn_persona_info
*persona
;
2044 if (attr
== NULL
|| *attr
== NULL
) {
2048 psattr
= *(_posix_spawnattr_t
*)attr
;
2049 persona
= psattr
->psa_persona_info
;
2054 if (!(persona
->pspi_flags
& (POSIX_SPAWN_PERSONA_FLAGS_OVERRIDE
| POSIX_SPAWN_PERSONA_FLAGS_VERIFY
))) {
2058 persona
->pspi_gid
= gid
;
2060 persona
->pspi_flags
|= POSIX_SPAWN_PERSONA_GID
;
2066 posix_spawnattr_set_persona_groups_np(const posix_spawnattr_t
* __restrict attr
, int ngroups
, gid_t
*gidarray
, uid_t gmuid
)
2068 _posix_spawnattr_t psattr
;
2069 struct _posix_spawn_persona_info
*persona
;
2071 if (attr
== NULL
|| *attr
== NULL
) {
2075 if (gidarray
== NULL
) {
2079 if (ngroups
> NGROUPS
|| ngroups
< 0) {
2083 psattr
= *(_posix_spawnattr_t
*)attr
;
2084 persona
= psattr
->psa_persona_info
;
2089 if (!(persona
->pspi_flags
& (POSIX_SPAWN_PERSONA_FLAGS_OVERRIDE
| POSIX_SPAWN_PERSONA_FLAGS_VERIFY
))) {
2093 persona
->pspi_ngroups
= ngroups
;
2094 for (int i
= 0; i
< ngroups
; i
++) {
2095 persona
->pspi_groups
[i
] = gidarray
[i
];
2098 persona
->pspi_gmuid
= gmuid
;
2100 persona
->pspi_flags
|= POSIX_SPAWN_PERSONA_GROUPS
;
2106 posix_spawnattr_set_max_addr_np(const posix_spawnattr_t
* __restrict attr
, uint64_t max_addr
)
2108 _posix_spawnattr_t psattr
;
2110 if (attr
== NULL
|| *attr
== NULL
) {
2114 psattr
= *(_posix_spawnattr_t
*)attr
;
2115 psattr
->psa_max_addr
= max_addr
;
2120 static struct _posix_spawn_posix_cred_info
*
2121 _posix_spawnattr_get_posix_creds_info(_posix_spawnattr_t psattr
)
2123 struct _posix_spawn_posix_cred_info
*pspci
= psattr
->psa_posix_cred_info
;
2125 if (pspci
== NULL
) {
2126 pspci
= malloc(sizeof(struct _posix_spawn_posix_cred_info
));
2127 if (pspci
!= NULL
) {
2128 pspci
->pspci_flags
= 0;
2129 pspci
->pspci_uid
= 0;
2130 pspci
->pspci_gid
= 0;
2131 pspci
->pspci_ngroups
= 0;
2132 pspci
->pspci_groups
[0] = 0;
2133 pspci
->pspci_gmuid
= 0;
2134 pspci
->pspci_login
[0] = '\0';
2135 psattr
->psa_posix_cred_info
= pspci
;
2142 posix_spawnattr_set_uid_np(const posix_spawnattr_t
*attr
, uid_t uid
)
2144 struct _posix_spawn_posix_cred_info
*pspci
;
2146 if (attr
== NULL
|| *attr
== NULL
) {
2150 pspci
= _posix_spawnattr_get_posix_creds_info(*(_posix_spawnattr_t
*)attr
);
2151 if (pspci
== NULL
) {
2155 pspci
->pspci_uid
= uid
;
2157 pspci
->pspci_flags
|= POSIX_SPAWN_POSIX_CRED_UID
;
2163 posix_spawnattr_set_gid_np(const posix_spawnattr_t
*attr
, gid_t gid
)
2165 struct _posix_spawn_posix_cred_info
*pspci
;
2167 if (attr
== NULL
|| *attr
== NULL
) {
2171 pspci
= _posix_spawnattr_get_posix_creds_info(*(_posix_spawnattr_t
*)attr
);
2172 if (pspci
== NULL
) {
2176 pspci
->pspci_gid
= gid
;
2178 pspci
->pspci_flags
|= POSIX_SPAWN_POSIX_CRED_GID
;
2184 posix_spawnattr_set_groups_np(const posix_spawnattr_t
*attr
,
2185 int ngroups
, gid_t
*gidarray
, uid_t gmuid
)
2187 struct _posix_spawn_posix_cred_info
*pspci
;
2189 if (attr
== NULL
|| *attr
== NULL
) {
2193 if (gidarray
== NULL
) {
2197 if (ngroups
> NGROUPS
|| ngroups
< 0) {
2201 pspci
= _posix_spawnattr_get_posix_creds_info(*(_posix_spawnattr_t
*)attr
);
2202 if (pspci
== NULL
) {
2206 pspci
->pspci_ngroups
= ngroups
;
2207 for (int i
= 0; i
< ngroups
; i
++) {
2208 pspci
->pspci_groups
[i
] = gidarray
[i
];
2211 pspci
->pspci_gmuid
= gmuid
;
2213 pspci
->pspci_flags
|= POSIX_SPAWN_POSIX_CRED_GROUPS
;
2219 posix_spawnattr_set_login_np(const posix_spawnattr_t
*attr
, const char *login
)
2221 struct _posix_spawn_posix_cred_info
*pspci
;
2223 if (attr
== NULL
|| *attr
== NULL
) {
2227 if (strlen(login
) > MAXLOGNAME
) {
2231 pspci
= _posix_spawnattr_get_posix_creds_info(*(_posix_spawnattr_t
*)attr
);
2232 if (pspci
== NULL
) {
2236 strlcpy(pspci
->pspci_login
, login
, sizeof(pspci
->pspci_login
));
2238 pspci
->pspci_flags
|= POSIX_SPAWN_POSIX_CRED_LOGIN
;
2244 * posix_spawnattr_set_jetsam_ttr_np
2246 * Description: Pass data regarding recent relaunch behavior when jetsammed for the process.
2247 * The recent history is effectively converted into a histogram and the highest
2248 * frequency bucket defines the "type" of the process. The type is passed along
2249 * to the jetsam code as part of psa_jetsam_flags.
2251 * Parameters: count Number of entries in the ttrs_millis array
2252 * ttrs_millis Array of raw data for relaunch behavior
2254 * Returns: 0 Success
2255 * EINVAL Bad attr pointer or empty data array
2258 posix_spawnattr_set_jetsam_ttr_np(const posix_spawnattr_t
* __restrict attr
, uint32_t count
, uint32_t *ttrs_millis
)
2260 _posix_spawnattr_t psattr
;
2263 * Define the bucketizing policy which would be used to generate the histogram. These
2264 * values are based on looking at data from various Avg. Joanna runs.
2266 static const uint32_t relaunch_buckets_msecs
[POSIX_SPAWN_JETSAM_RELAUNCH_BEHAVIOR_BUCKETS
] = {
2271 static const uint32_t relaunch_jetsam_flags
[POSIX_SPAWN_JETSAM_RELAUNCH_BEHAVIOR_BUCKETS
] = {
2272 POSIX_SPAWN_JETSAM_RELAUNCH_BEHAVIOR_HIGH
,
2273 POSIX_SPAWN_JETSAM_RELAUNCH_BEHAVIOR_MED
,
2274 POSIX_SPAWN_JETSAM_RELAUNCH_BEHAVIOR_LOW
2277 /* Make sure the attr pointer is valid */
2278 if (attr
== NULL
|| *attr
== NULL
) {
2282 /* Make sure the count of entries is non-zero */
2287 psattr
= *(_posix_spawnattr_t
*)attr
;
2289 /* Generate a histogram based on the relaunch data while maintaining highest frequency bucket info */
2290 int relaunch_histogram
[POSIX_SPAWN_JETSAM_RELAUNCH_BEHAVIOR_BUCKETS
] = {0};
2291 int max_frequency
= -1;
2292 int highest_frequency_bucket
= -1;
2294 for (uint32_t i
= 0; i
< count
; i
++) {
2295 /* For each data point passed in via launchd, find the bucket it lands in */
2296 for (uint32_t bucket
= 0; bucket
< POSIX_SPAWN_JETSAM_RELAUNCH_BEHAVIOR_BUCKETS
; bucket
++) {
2297 if (ttrs_millis
[i
] <= relaunch_buckets_msecs
[bucket
]) {
2298 relaunch_histogram
[bucket
]++;
2300 /* Check if the bucket is the highest frequency bucket now */
2301 if (relaunch_histogram
[bucket
] > max_frequency
) {
2302 max_frequency
= relaunch_histogram
[bucket
];
2303 highest_frequency_bucket
= bucket
;
2309 psattr
->psa_jetsam_flags
|= relaunch_jetsam_flags
[highest_frequency_bucket
];
2316 * Description: Create a new process from the process image corresponding to
2317 * the supplied 'path' argument.
2319 * Parameters: pid Pointer to pid_t to receive the
2320 * PID of the spawned process, if
2321 * successful and 'pid' != NULL
2322 * path Path of image file to spawn
2323 * file_actions spawn file actions object which
2324 * describes file actions to be
2325 * performed during the spawn
2326 * attrp spawn attributes object which
2327 * describes attributes to be
2328 * applied during the spawn
2329 * argv argument vector array; NULL
2331 * envp environment vector array; NULL
2334 * Returns: 0 Success
2335 * !0 An errno value indicating the
2336 * cause of the failure to spawn
2338 * Notes: Unlike other system calls, the return value of this system
2339 * call is expected to either be a 0 or an errno, rather than a
2340 * 0 or a -1, with the 'errno' variable being set.
2342 extern int __posix_spawn(pid_t
* __restrict
, const char * __restrict
,
2343 struct _posix_spawn_args_desc
*,
2344 char *const argv
[__restrict
], char *const envp
[__restrict
]);
2347 posix_spawn(pid_t
* __restrict pid
, const char * __restrict path
,
2348 const posix_spawn_file_actions_t
*file_actions
,
2349 const posix_spawnattr_t
* __restrict attrp
,
2350 char *const argv
[__restrict
], char *const envp
[__restrict
])
2352 int saveerrno
= errno
;
2355 * Only do extra work if we have file actions or attributes to push
2356 * down. We use a descriptor to push this information down, since we
2357 * want to have size information, which will let us (1) preallocate a
2358 * single chunk of memory for the copyin(), and (2) allow us to do a
2359 * single copyin() per attributes or file actions as a monlithic block.
2361 * Note: A future implementation may attempt to do the same
2362 * thing for the argv/envp data, which could potentially
2363 * result in a performance improvement due to increased
2364 * kernel efficiency, even though it would mean copying
2365 * the data in user space.
2367 if ((file_actions
!= NULL
&& (*file_actions
!= NULL
) && (*(_posix_spawn_file_actions_t
*)file_actions
)->psfa_act_count
> 0) || attrp
!= NULL
) {
2368 struct _posix_spawn_args_desc ad
;
2370 memset(&ad
, 0, sizeof(ad
));
2371 if (attrp
!= NULL
&& *attrp
!= NULL
) {
2372 _posix_spawnattr_t psattr
= *(_posix_spawnattr_t
*)attrp
;
2373 ad
.attr_size
= sizeof(struct _posix_spawnattr
);
2376 if (psattr
->psa_ports
!= NULL
) {
2377 size_t psact_size
= PS_PORT_ACTIONS_SIZE(psattr
->psa_ports
->pspa_count
);
2378 if (psact_size
== 0 && psattr
->psa_ports
->pspa_count
!= 0) {
2383 ad
.port_actions
= psattr
->psa_ports
;
2384 ad
.port_actions_size
= psact_size
;
2386 if (psattr
->psa_mac_extensions
!= NULL
) {
2387 size_t macext_size
= PS_MAC_EXTENSIONS_SIZE(psattr
->psa_mac_extensions
->psmx_count
);
2388 if (macext_size
== 0 && psattr
->psa_mac_extensions
->psmx_count
!= 0) {
2393 ad
.mac_extensions
= psattr
->psa_mac_extensions
;
2394 ad
.mac_extensions_size
= macext_size
;
2396 if (psattr
->psa_coalition_info
!= NULL
) {
2397 ad
.coal_info_size
= sizeof(struct _posix_spawn_coalition_info
);
2398 ad
.coal_info
= psattr
->psa_coalition_info
;
2400 if (psattr
->psa_persona_info
!= NULL
) {
2401 ad
.persona_info_size
= sizeof(struct _posix_spawn_persona_info
);
2402 ad
.persona_info
= psattr
->psa_persona_info
;
2404 if (psattr
->psa_posix_cred_info
!= NULL
) {
2405 ad
.posix_cred_info_size
= sizeof(struct _posix_spawn_posix_cred_info
);
2406 ad
.posix_cred_info
= psattr
->psa_posix_cred_info
;
2409 if (file_actions
!= NULL
&& *file_actions
!= NULL
) {
2410 _posix_spawn_file_actions_t psactsp
=
2411 *(_posix_spawn_file_actions_t
*)file_actions
;
2413 if (psactsp
->psfa_act_count
> 0) {
2414 size_t fa_size
= PSF_ACTIONS_SIZE(psactsp
->psfa_act_count
);
2415 if (fa_size
== 0 && psactsp
->psfa_act_count
!= 0) {
2420 ad
.file_actions_size
= fa_size
;
2421 ad
.file_actions
= psactsp
;
2425 ret
= __posix_spawn(pid
, path
, &ad
, argv
, envp
);
2427 ret
= __posix_spawn(pid
, path
, NULL
, argv
, envp
);